Hardware acceleration for unit highlight effect

Uses some tricks to increase brightness by blitting twice.
This commit is contained in:
Tommy 2022-06-30 22:50:43 +12:00
parent 0fbc12ea01
commit 046f1c932a
2 changed files with 66 additions and 65 deletions

View File

@ -1201,23 +1201,20 @@ void display::get_terrain_images(const map_location& loc, const std::string& tim
}
}
void display::drawing_buffer_add(const drawing_layer layer,
display::blit_helper& display::drawing_buffer_add(const drawing_layer layer,
const map_location& loc, const SDL_Rect& dest, const texture& tex,
const SDL_Rect &clip, bool hflip, bool vflip, uint8_t alpha_mod)
const SDL_Rect &clip)
{
drawing_buffer_.emplace_back(
layer, loc, dest, tex, clip, hflip, vflip, alpha_mod
);
drawing_buffer_.emplace_back(layer, loc, dest, tex, clip);
return drawing_buffer_.back();
}
void display::drawing_buffer_add(const drawing_layer layer,
display::blit_helper& display::drawing_buffer_add(const drawing_layer layer,
const map_location& loc, const SDL_Rect& dest,
const std::vector<texture> &tex,
const SDL_Rect &clip, bool hflip, bool vflip, uint8_t alpha_mod)
const std::vector<texture> &tex, const SDL_Rect &clip)
{
drawing_buffer_.emplace_back(
layer, loc, dest, tex, clip, hflip, vflip, alpha_mod
);
drawing_buffer_.emplace_back(layer, loc, dest, tex, clip);
return drawing_buffer_.back();
}
enum {
@ -1296,18 +1293,27 @@ void display::drawing_buffer_commit()
for(const blit_helper& blit : drawing_buffer_) {
for(texture tex : blit.tex()) {
const SDL_Rect& src = blit.clip();
const uint8_t alpha_mod = blit.alpha_mod();
const bool hflip = blit.hflip();
const bool vflip = blit.vflip();
if (alpha_mod != SDL_ALPHA_OPAQUE) {
tex.set_alpha_mod(alpha_mod);
if (blit.alpha_mod != SDL_ALPHA_OPAQUE) {
tex.set_alpha_mod(blit.alpha_mod);
}
if (src != sdl::empty_rect) {
draw::flipped(tex, blit.dest(), src, hflip, vflip);
draw::flipped(tex, blit.dest(), src, blit.hflip, blit.vflip);
if (blit.highlight) {
tex.set_blend_mode(SDL_BLENDMODE_ADD);
tex.set_alpha_mod(blit.highlight);
draw::flipped(tex, blit.dest(), src, blit.hflip, blit.vflip);
tex.set_blend_mode(SDL_BLENDMODE_BLEND);
}
} else {
draw::flipped(tex, blit.dest(), hflip, vflip);
draw::flipped(tex, blit.dest(), blit.hflip, blit.vflip);
if (blit.highlight) {
tex.set_blend_mode(SDL_BLENDMODE_ADD);
tex.set_alpha_mod(blit.highlight);
draw::flipped(tex, blit.dest(), blit.hflip, blit.vflip);
tex.set_blend_mode(SDL_BLENDMODE_BLEND);
}
}
if (alpha_mod != SDL_ALPHA_OPAQUE) {
if (blit.alpha_mod != SDL_ALPHA_OPAQUE || blit.highlight) {
tex.set_alpha_mod(SDL_ALPHA_OPAQUE);
}
}
@ -1508,8 +1514,8 @@ void display::draw_text_in_hex(const map_location& loc,
for (int dx=-1; dx <= 1; ++dx) {
if (dx!=0 || dy!=0) {
const SDL_Rect dest{int(x + dx*zf), int(y + dy*zf), w, h};
drawing_buffer_add(layer, loc, dest, back_surf,
SDL_Rect(), false, false, 128);
auto& bh = drawing_buffer_add(layer, loc, dest, back_surf);
bh.alpha_mod = 128;
}
}
}
@ -1521,12 +1527,15 @@ void display::render_image(int x, int y, const display::drawing_layer drawing_la
bool hreverse, bool greyscale, uint8_t alpha, double highlight,
color_t blendto, double blend_ratio, double submerged, bool vreverse)
{
if (alpha <= 0) {
return;
}
const point image_size = image::get_size(i_locator);
if (!image_size.x || !image_size.y) {
return;
}
// TODO: highdpi - are x,y correct here?
rect dest = scaled_to_zoom({x, y, image_size.x, image_size.y});
if (!dest.overlaps(map_area())) {
return;
@ -1557,21 +1566,6 @@ void display::render_image(int x, int y, const display::drawing_layer drawing_la
new_modifications += ")";
}
// TODO: highdpi - perhaps this can be done by blitting twice, once in additive blend mode
// Note: this may not be identical to the original calculation,
// which was to multiply the RGB values by (alpha/255).
// But for now it looks close enough.
if(highlight > 0.0) {
const std::string brighten_string = std::to_string(int(highlight*128.0));
new_modifications += "~CS(";
new_modifications += brighten_string;
new_modifications += ",";
new_modifications += brighten_string;
new_modifications += ",";
new_modifications += brighten_string;
new_modifications += ")";
}
// general formula for submerged alpha:
// if (y > WATERLINE)
// then min(max(alpha_mod, 0), 1) * alpha
@ -1604,8 +1598,11 @@ void display::render_image(int x, int y, const display::drawing_layer drawing_la
tex = image::get_texture(i_locator);
}
drawing_buffer_add(drawing_layer, loc, dest, tex, sdl::empty_rect,
hreverse, vreverse, alpha);
blit_helper& bh = drawing_buffer_add(drawing_layer, loc, dest, tex);
bh.hflip = hreverse;
bh.vflip = vreverse;
bh.alpha_mod = alpha;
bh.highlight = float_to_color(highlight);
}
void display::select_hex(map_location hex)
@ -2620,8 +2617,9 @@ void display::draw_hex(const map_location& loc)
&& bool(mouseover_hex_overlay_))
{
const uint8_t alpha = 196;
drawing_buffer_add(LAYER_MOUSEOVER_OVERLAY, loc, dest,
mouseover_hex_overlay_, SDL_Rect(), false, false, alpha);
blit_helper& bh = drawing_buffer_add(LAYER_MOUSEOVER_OVERLAY,
loc, dest, mouseover_hex_overlay_);
bh.alpha_mod = alpha;
}
// Paint arrows

View File

@ -926,30 +926,41 @@ protected:
blit_helper(const drawing_layer layer, const map_location& loc,
const SDL_Rect& dest, const texture& tex,
const SDL_Rect& clip, bool hflip=false, bool vflip=false,
uint8_t alpha_mod=SDL_ALPHA_OPAQUE)
: dest_(dest), tex_(1, tex), clip_(clip), hflip_(hflip),
vflip_(vflip), alpha_mod_(alpha_mod), key_(loc, layer)
const SDL_Rect& clip)
: dest_(dest), tex_(1, tex), clip_(clip), key_(loc, layer)
{}
blit_helper(const drawing_layer layer, const map_location& loc,
const SDL_Rect& dest, const std::vector<texture>& tex,
const SDL_Rect& clip, bool hflip=false, bool vflip=false,
uint8_t alpha_mod=SDL_ALPHA_OPAQUE)
: dest_(dest), tex_(tex), clip_(clip), hflip_(hflip),
vflip_(vflip), alpha_mod_(alpha_mod), key_(loc, layer)
const SDL_Rect& clip)
: dest_(dest), tex_(tex), clip_(clip), key_(loc, layer)
{}
const SDL_Rect& dest() const { return dest_; }
const std::vector<texture> &tex() const { return tex_; }
const SDL_Rect &clip() const { return clip_; }
uint8_t alpha_mod() const { return alpha_mod_; }
bool hflip() const { return hflip_; }
bool vflip() const { return vflip_; }
bool operator<(const blit_helper &rhs) const { return key_ < rhs.key_; }
public:
// Auxiliary parameters, can be modified directly as required.
/** Whether to mirror horizontally on draw */
bool hflip = false;
/** Whether to mirror vertically on draw */
bool vflip = false;
/** An alpha modifier to apply when drawing. 0-255. */
uint8_t alpha_mod = SDL_ALPHA_OPAQUE;
/** Colour modifiers. Multiply colour. 0 = 0.0, 255 = 1.0. */
uint8_t r_mod = 255;
uint8_t g_mod = 255;
uint8_t b_mod = 255;
/** Strength of highlight effect to apply, if any. */
uint8_t highlight = 0;
private:
// Core info is set on creation.
/** The location on screen to draw to, in drawing coordinates. */
SDL_Rect dest_;
/** One or more textures to render. */
@ -957,13 +968,7 @@ protected:
/** The portion of the source texture to use.
* If omitted, the entire source is used. */
SDL_Rect clip_;
/** Whether to mirror horizontally on draw */
bool hflip_;
/** Whether to mirror vertically on draw */
bool vflip_;
/** An alpha modifier to apply when drawing. 0-255. */
uint8_t alpha_mod_;
// TODO: highdpi - colour mod? blend mode? rotation?
// TODO: could also add blend mode and rotation if desirable
/** Allows ordering of draw calls by layer and location. */
drawing_buffer_key key_;
};
@ -987,16 +992,14 @@ public:
* @param alpha_mod An alpha modifier to apply - multiplies
* texture alpha by this value when drawing.
*/
void drawing_buffer_add(const drawing_layer layer,
blit_helper& drawing_buffer_add(const drawing_layer layer,
const map_location& loc, const SDL_Rect& dest, const texture& tex,
const SDL_Rect &clip = SDL_Rect(), bool hflip=false,
bool vflip=false, uint8_t alpha_mod=SDL_ALPHA_OPAQUE);
const SDL_Rect &clip = SDL_Rect());
void drawing_buffer_add(const drawing_layer layer,
blit_helper& drawing_buffer_add(const drawing_layer layer,
const map_location& loc, const SDL_Rect& dest,
const std::vector<texture> &tex,
const SDL_Rect &clip = SDL_Rect(), bool hflip=false,
bool vflip=false, uint8_t alpha_mod=SDL_ALPHA_OPAQUE);
const SDL_Rect &clip = SDL_Rect());
protected: