"Alpha Bleeding" is an operation you sometimes need to perform on your images to make blending work as you expect.
"Blending" means that you use partial transparency when rendering your image. It means that the alpha channel of your image contains any values within the range 0..1 (not just only 0 or 1). Alpha equal 0 means "completely transparent", alpha equal 1 means "complately opaque", values in-between mean "partially transparent". For example alpha value 0.25 means that when rendering, we should take 1/4 from the image color, and mix it with 3/4 of the current screen color at this place.
Blending makes sense both for user-interface (like images you place in TCastleImageControl
), 2D games and 3D games (e.g. textures on your 3D models, that you load to TCastleScene
). More info about blending in CGE is here.
To avoid rendering artifacts, sometimes you need to proces your images with "alpha bleeding". Why?
When the image is scaled, we typically apply a filtering operation on the image pixels, that essentially averages a few image pixels (all the channels, so both RGB and alpha).
Such filtering is done e.g. when
TCastleImageControl.SmoothScaling
is true
(in this case we do bilinear filtering),
TDrawableImage.SmoothScaling
is true
(again, in this case we do bilinear filtering),
TCastleScene
with default texture properties (see TextureProperties
node to customize how texture filtering is done), in which case we use bilinear or trilinear (bilinear with mipmaps) filtering.
It means that RGB values from the pixels that you see (in e.g. GIMP) as completely transparent, are, counter-intuitively, affecting the rendering output.
Essentially, it means that you need to fix RGB values in your image, for transparent pixels.
Here's an example of a rendering bug caused by this, from this Trello ticket:
In the above example, one image is rendered in front of another. The front image has, however, black transparent pixels (RGBA = (0, 0, 0, 0)) very near the opaque light yellow pixels (RGB = light yellow, A = 1). And in effect they get averaged into dark yellow (black is averaged with light yellow). Which results in a dark smudge on the forehead of the character. Here are the actual images, the back and (incorrect) front:
Here's an analysis (investigating colors in GIMP) of the colors:
Where the opaque light yellow changes into transparent, you have
fecb5d
73,3%
) row, with RGB color again fecb5d
black
(000000
in hex).
AD 1, AD 2 are OK.
AD 3 is bad — these black RGB values get mixed into the final output.
The solution is called alpa bleeding. It means that you fill the RGB values of transparent pixels with sensible values, taken from neighboring non-transparent pixels.
In general, you can do this in various ways, various software for 2D image creation/processing can perform this.
E.g. if you use Spine to export texture atlases, it has a ready "Alpha Bleed" option at export.
Or use our Castle Image Viewer:
Open the image in Castle Image Viewer
Uncheck "View -> Use Image Alpha Channel" (optional, it will allow you to see effect of "alpha bleeding" in the next step)
Use "Edit -> Alpha Bleeding (Slow but Correct Algorithm)". As the menu caption says, our "alpha bleeding" implementation is rather slow, but OTOH it is really correct, trying hard to fill all RGB colors on transparent pixels.
Save resulting image (replace the old image, or create a new image -> whatever is more comfortable for you; take into account you will need to repeat this process in the future in case the source of this image changes), and use it.
Or you can write your own code to perform this operation. Just call TCastleImage.AlphaBleed
to do the same thing that Castle Image Viewer does.
Note: We heavily advise to not do TCastleImage.AlphaBleed
during actual loading of your game (even though, technically, you can). As the process is really slow and needs to be performed only once for a given image. It should be done as a pre-processing step that you run once over your data, before packaging it.
Here's the resulting, fixed front image. You cannot really see a difference from the previous, incorrect image, by a human eye — you'd need to investigate the transparent pixels in GIMP to see the change.
Here's the result of mixing the 2 images, now correct, in the CGE editor.
There's an alternative to this: you can also use filtering that doesn't average pixel colors. Just
set TCastleImageControl.SmoothScaling
to false
,
or set TDrawableImage.SmoothScaling
to false
,
or use nearest filtering for textures in TCastleScene
.
This is good for pixel-art games usually (where you actually want to see "big pixels"), but not in general
(you usually want smooth scaling, in most cases).
See this Trello ticket for a similar description, that also contains sample application with invalid image to play with.