@@ -1811,6 +1811,24 @@ bool TextureSource::generateImagePart(std::string part_of_name,
1811
1811
return true ;
1812
1812
}
1813
1813
1814
+ /*
1815
+ Calculate the color of a single pixel drawn on top of another pixel.
1816
+
1817
+ This is a little more complicated than just video::SColor::getInterpolated
1818
+ because getInterpolated does not handle alpha correctly. For example, a
1819
+ pixel with alpha=64 drawn atop a pixel with alpha=128 should yield a
1820
+ pixel with alpha=160, while getInterpolated would yield alpha=96.
1821
+ */
1822
+ static inline video::SColor blitPixel (const video::SColor &src_c, const video::SColor &dst_c, u32 ratio)
1823
+ {
1824
+ if (dst_c.getAlpha () == 0 )
1825
+ return src_c;
1826
+ video::SColor out_c = src_c.getInterpolated (dst_c, (float )ratio / 255 .0f );
1827
+ out_c.setAlpha (dst_c.getAlpha () + (255 - dst_c.getAlpha ()) *
1828
+ src_c.getAlpha () * ratio / (255 * 255 ));
1829
+ return out_c;
1830
+ }
1831
+
1814
1832
/*
1815
1833
Draw an image on top of an another one, using the alpha channel of the
1816
1834
source image
@@ -1830,7 +1848,7 @@ static void blit_with_alpha(video::IImage *src, video::IImage *dst,
1830
1848
s32 dst_y = dst_pos.Y + y0 ;
1831
1849
video::SColor src_c = src->getPixel (src_x, src_y);
1832
1850
video::SColor dst_c = dst->getPixel (dst_x, dst_y);
1833
- dst_c = src_c. getInterpolated ( dst_c, ( float ) src_c.getAlpha ()/ 255 . 0f );
1851
+ dst_c = blitPixel (src_c, dst_c, src_c.getAlpha ());
1834
1852
dst->setPixel (dst_x, dst_y, dst_c);
1835
1853
}
1836
1854
}
@@ -1853,7 +1871,7 @@ static void blit_with_alpha_overlay(video::IImage *src, video::IImage *dst,
1853
1871
video::SColor dst_c = dst->getPixel (dst_x, dst_y);
1854
1872
if (dst_c.getAlpha () == 255 && src_c.getAlpha () != 0 )
1855
1873
{
1856
- dst_c = src_c. getInterpolated ( dst_c, ( float ) src_c.getAlpha ()/ 255 . 0f );
1874
+ dst_c = blitPixel (src_c, dst_c, src_c.getAlpha ());
1857
1875
dst->setPixel (dst_x, dst_y, dst_c);
1858
1876
}
1859
1877
}
0 commit comments