diff options
author | Warr1024 <warr1024@gmail.com> | 2019-10-18 13:17:35 -0400 |
---|---|---|
committer | SmallJoker <SmallJoker@users.noreply.github.com> | 2019-10-18 19:17:35 +0200 |
commit | 15b6922ae6e3d4807e709fcfea0615595f6f765e (patch) | |
tree | 9de54ed3d4cc29d2e9e51c268d099de4f9d1046b | |
parent | b7e358703fd6f828423c2e6622c0740669eb1d7a (diff) | |
download | minetest-15b6922ae6e3d4807e709fcfea0615595f6f765e.tar.gz minetest-15b6922ae6e3d4807e709fcfea0615595f6f765e.tar.bz2 minetest-15b6922ae6e3d4807e709fcfea0615595f6f765e.zip |
Correction for alpha blending issues in texture mod compositing (#9029)
-rw-r--r-- | src/client/tile.cpp | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/src/client/tile.cpp b/src/client/tile.cpp index 3d9e2470a..3189ab28c 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -1812,6 +1812,24 @@ bool TextureSource::generateImagePart(std::string part_of_name, } /* + Calculate the color of a single pixel drawn on top of another pixel. + + This is a little more complicated than just video::SColor::getInterpolated + because getInterpolated does not handle alpha correctly. For example, a + pixel with alpha=64 drawn atop a pixel with alpha=128 should yield a + pixel with alpha=160, while getInterpolated would yield alpha=96. +*/ +static inline video::SColor blitPixel(const video::SColor &src_c, const video::SColor &dst_c, u32 ratio) +{ + if (dst_c.getAlpha() == 0) + return src_c; + video::SColor out_c = src_c.getInterpolated(dst_c, (float)ratio / 255.0f); + out_c.setAlpha(dst_c.getAlpha() + (255 - dst_c.getAlpha()) * + src_c.getAlpha() * ratio / (255 * 255)); + return out_c; +} + +/* Draw an image on top of an another one, using the alpha channel of the source image @@ -1830,7 +1848,7 @@ static void blit_with_alpha(video::IImage *src, video::IImage *dst, s32 dst_y = dst_pos.Y + y0; video::SColor src_c = src->getPixel(src_x, src_y); video::SColor dst_c = dst->getPixel(dst_x, dst_y); - dst_c = src_c.getInterpolated(dst_c, (float)src_c.getAlpha()/255.0f); + dst_c = blitPixel(src_c, dst_c, src_c.getAlpha()); dst->setPixel(dst_x, dst_y, dst_c); } } @@ -1853,7 +1871,7 @@ static void blit_with_alpha_overlay(video::IImage *src, video::IImage *dst, video::SColor dst_c = dst->getPixel(dst_x, dst_y); if (dst_c.getAlpha() == 255 && src_c.getAlpha() != 0) { - dst_c = src_c.getInterpolated(dst_c, (float)src_c.getAlpha()/255.0f); + dst_c = blitPixel(src_c, dst_c, src_c.getAlpha()); dst->setPixel(dst_x, dst_y, dst_c); } } |