Premultiplied alpha in XNA Game Studio 4.0

Originally posted to Shawn Hargreaves Blog on MSDN, Thursday, April 8, 2010

As of Game Studio 4.0, the default alpha blending mode is now premultiplied rather than interpolative.

 

Why?

I was fed up of repeating this conversation:

Customer: Why do I see ugly borders around the edges of my sprites?

(or sometimes: Why does rendertarget blending not work like I expect?)

Me: To make that work right, you need premultiplied alpha.

Customer: Ok, how do I do that?

Me: Read this lengthy article. First, you need to run all your textures through a special content processor, which is not built into Game Studio. Then, change your color math to work a different way, using operations that are not built into the Color struct. Finally, change your blend renderstates to a custom configuration, which is not built into the SpriteBlendMode enum. Oh yeah, and you can no longer use BasicEffect specular lighting or fog on translucent objects.

Customer: Yikes! How come this isn't easier?

Me: Sorry. Our bad.

To be clear: premultiplied alpha is not a perfect panacea for all problems (Kris commented on my blog with an article listing some cons). Expert graphics programmers can be expected to understand multiple color formats, and choose the appropriate one for different situations. Game Studio 4.0 continues to support interpolated alpha blending, just like previous versions supported premultiplied alpha. So we are really just dealing with two questions here:

  1. What is the default alpha format? When a developer who does not yet understand the blend equation, color math, and texture filtering, loads a sprite and draws it to the screen, which are they using?

  2. What do more experienced developers have to do if they want something other than this default?

The second was a no-brainer. Changing alpha format was too hard in previous Game Studio versions, and should be made easier.

The first was not such an obvious decision. We felt that premultiplied alpha would be a better default, as it avoids several problems that have proven to be both common and extremely confusing. But this would be a major breaking change for people who are used to doing things the old way, and are maybe already partway through creating a game. Starting from a blank slate, premultiplied versus interpolative color math are roughly equal in complexity, but it can be painful to change format in mid stream!

In the end, two things made up our minds:

 

What changed?

The blend state now defaults to premultiplied:

By default, the Content Pipeline now converts all textures into premultiplied format. If you do not want this, or if your source texture files are already in premultiplied format, turn off the "Premultiply Alpha" processor parameter:

Untitled

We tweaked the Color struct to better support premultiplied math:

BasicEffect, and its four new built-in sibling effects, assume premultiplied alpha in all the places where this makes a difference:

 

How do I upgrade my code?

For most games, only one code change is needed to switch from interpolative to premultiplied alpha. Everywhere that you used to call:

    new Color(color, alpha)   // where alpha is a byte ranging 0-255

Change this to:

    color * alpha   // where alpha is a float ranging 0-1

The bad news is you might have to change this in a lot of places! But the good news is, since we removed that Color constructor overload, you will get helpful compile errors any place you forget to do this :-)

If you have textures that encode data other than transparency into their alpha channel (for instance if you are using alpha to store a gloss map, or a displacement for parallax normal mapping), you should turn off their "Premultiply Alpha" content processor parameter.

 

How can I get the old behavior back?

If you prefer to continue using interpolative alpha like in previous Game Studio versions, you must do three things:

Blog index   -   Back to my homepage