Alpha Bleeding

"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

  • 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:

Bug caused by lack of Alpha Bleeding visible in CGE editor

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:

Alpha Bleeding example - back image Alpha Bleeding example - front image (incorrect)

Here's an analysis (investigating colors in GIMP) of the colors:

Investigating Alpha Bleeding in GIMP 1 Investigating Alpha Bleeding in GIMP 2 Investigating Alpha Bleeding in GIMP 3 Investigating Alpha Bleeding in GIMP 4

Where the opaque light yellow changes into transparent, you have

  1. opaque (alpha = 1) pixels, with RGB color (in hexadecimal notation) fecb5d
  2. partially transparent (alpha = 73,3%) row, with RGB color again fecb5d
  3. transparent (alpha = 0) rows, with RGB color being just 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.

  1. E.g. if you use Spine to export texture atlases, it has a ready "Alpha Bleed" option at export.

  2. Or use our castle-view-image:

    1. Open the image in castle-view-image

    2. Uncheck "View -> Use Image Alpha Channel" (optional, it will allow you to see effect of "alpha bleeding" in the next step)

    3. 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.

    4. 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.

    Fixing Alpha Bleeding in castle-view-image: before Fixing Alpha Bleeding in castle-view-image Fixing Alpha Bleeding in castle-view-image: after
  3. Or you can write your own code to perform this operation. Just call TCastleImage.AlphaBleed to do the same thing that castle-view-image 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.

Alpha Bleeding example - front image (fixed)

Here's the result of mixing the 2 images, now correct, in the CGE editor.

Fixed problem, visible in 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.