Shawn Hargreaves Blog
It is possible to use premultiplied alpha with XNA Game Studio, but the bad news is we don't do much to help you with it.
Why not?
Yeah. Our bad. In fact one of my biggest regrets about the design of the XNA Framework is that we didn't do more to make this easier!
To use premultiplied alpha, you must do three things:
Premultiplied alpha blending is configured like this:
graphicsDevice.RenderState.AlphaBlendEnable = true; graphicsDevice.RenderState.SourceBlend = Blend.One; graphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
Or if you are using SpriteBatch:
spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None); graphicsDevice.RenderState.SourceBlend = Blend.One;
Premultiplied blending only works if all your color values are in premultiplied format. But most paint programs and image file formats do not use premultiplied alpha! So we must find a good place to apply this conversion.
For most games, both 2D and 3D, the flow of color data goes something like this:
There are several options for where in this process we choose to convert from conventional to premultiplied format. Two in particular I think can be sensible depending on the situation:
Convert colors at the end of the pixel shader Convert colors in a custom Content Processor Add "result.rgb *= result.a" right before the end of all your shaders Write a PremultipliedAlphaTextureProcessor, which automatically converts all your textures to premultiplied format while they are being built Requires custom pixel shaders Does not require custom shaders, so works with SpriteBatch, BasicEffect, etc. Premultiplication happens after the shader has processed any tint colors, so tints are still specified in conventional, non-premultiplied format All runtime colors, including tint values, are specified in premultiplied format Alpha blending is done with premultiplied colors, so image composition works properly, but texture filtering happens before the premultiply conversion, so alpha cutouts remain a problem All rendering uses premultiplied colors, so both image composition and alpha cutouts work nicely Reasonably easy retrofit to existing code, or even just specific parts of that code, as long as you have custom shaders Affects everywhere you do color math, which may be a lot of places, so it can be a pain to retrofit if you don't plan this from the start
Any time you do computations on color values, you need to use the right math for the type of colors you are dealing with. Some things to bear in mind:
"Affects everywhere you do color math, which may be a lot of places, so it can be a pain to retrofit if you don't plan this from the start"
I was just about to ask you how cumbersome is managing changes in the alpha value fof the premultiplied methodology.
I have a concern with this system. What do you do when you want to gamma correct your textures? Specifically, what happens when you try to gamma correct a filtered value where the alpha was pre-multiplied with the gamma-space color?
> What do you do when you want to gamma correct your textures?
If you are aiming for truly gamma correct rendering, this is trivial. Both filtering and alpha blending are only truly correct in linear color space, so you ideally want to do the gamma correction after all such operations are complete, in which case it makes no difference what alpha format you use prior to this.
You could certainly have problems if you are doing something like filtering linear texture data, gamma correcting, then alpha blending in gamma space. But such a path has lots of other problems already, for instance multisampling can cause all kinds of nasty artifacts.
Hi Shawn,
Thanks for this, it really made a big difference, which I'm very happy about! Here's a before and after shot.
http://img121.imageshack.us/img121/3500/beforepma.png
http://img96.imageshack.us/img96/4927/afterpma.png
No more ugly black pixels, and I can blit to non-integer positions with whatever rotation I like... all the goodness, none of the compromise!
Thanks again!