Wednesday, November 18, 2009

Premultiplied alpha

If You don't know what's premultiplied alpha and why it solves all the world's problems, just read Tom Forsyth on premultiplied alpha or Shawn Hargreaves on premultiplied alpha.

Pros:
1. Better quality for textures with sharp alpha cutouts.
2. Removes some blending state changes (which can be important if You are coding for a PC).
3. Can mix additive blending with alpha blending without a state/shader/texture change.

What are the hidden cons, which aren't mentioned by Tom or Shawn?
1. Fixed pipeline fog doesn't work with it.
2. Worse quality for smooth alpha with DXT5 compression.

Why premultiplied alpha doesn't work very well with DXT5 for textures with smooth alpha gradients? In DXT5 texture is divided into the 4x4 pixel blocks. For every block, colors (and alphas) are approximated with equidistant points on a line between two end points (using some index table). Color end points are quantized (5:6:5 bits) and alpha end points are saved with 8 bit precision. This means that for the most textures we get better precision for the alpha channel than for the color channel.

Furthermore compressing values of a broader range gives us better precision. For example if we have alpha filled with 1/255 and RGB values in range [0; 1] then premultiplied texture RGB channels will contain only two different numbers - 0 or 1/125. This means that by using standard alpha blending we get better precision in case we would like to multiply RGB by a factor greater than 1 or tonemap final results.

Standard alpha blending:
    srcAlpha = Compress_color( src.rgb ) * Compress_alpha( src.a )

Premultiplied alpha blending:
    srcAlpha = Compress_color( src.rgb * src.a )

Let's see how does it look in practice. I created a sample texture with a "lighting" gradient in RGB channels and smoke puff in alpha (from left to right: RGB, alpha and premultiplied RGB by alpha):










Now let's alpha blend two compressed textures (DXT5), zoom and compare results (left image - standard alpha blending, right - premultiplied alpha blending):

















This looks like a small difference, but can be quite visible in a real game - especially when smoke particles are big or their color is multiplied by a factor greater than 1 or when using some kind of tone-mapping.

BTW there is interesting feature/bug in NVIDIA Photoshop texture tools. You can't save DXT5 with full black alpha (it just creates a DDS without alpha channel). This ensures that those lazy artists use DXT1 compression for additive premultiplied alpha blending :).

2 comments:

  1. Aslan Dzodzikov18/8/10 19:18

    It seems to me, the main cause of quality degradation in your sample is color range decrease. You should scale premultiplied image to full range in order to have better compression.

    ReplyDelete
  2. Yes, You are right that most of the quality degradation comes from range decrease. I didn't think about it when I wrote this post. Scaling could work, but it would require a change of texture pipeline (16 bit source textures, some tool or smart artists).

    ReplyDelete