# Does premultiplied alpha give order independent transparency?

I've heard that pre-multiplied alpha gives you order independent transparency but when I sit down and do the math, it doesn't seem to be working.

Is that untrue, or am I doing something incorrectly?

The formula I'm using is:

$out_{rgba} = in_{rgba} + out_{rgba} * (1 - in_a)$

where $in$ is premultiplied alpha. In other words, taking a "normal" color in RGBA, i multiply RGB by a. 30% opaque white would start out as (1, 1, 1, 0.3) but would become (0.3, 0.3, 0.3, 0.3) as premultiplied alpha.

After getting the wrong answers when working it out by hand, I wrote the C++ program below and am still getting the wrong results.

After execution:

$out1 = (0.738, 0.913, 0.3, 1.0)\\ out2 = (0.738, 0.875, 0.113, 1.0)$

Can anyone explain why?

#include <array>

typedef std::array<float, 4> RGBA;

void PremultiplyAlpha (RGBA& rgba)
{
rgba[0] *= rgba[3];
rgba[1] *= rgba[3];
rgba[2] *= rgba[3];
}

RGBA BlendPremultipliedAlpha (const RGBA& dest, const RGBA& src)
{
RGBA ret;
ret[0] = src[0] + dest[0] * (1.0f - src[3]);
ret[1] = src[1] + dest[1] * (1.0f - src[3]);
ret[2] = src[2] + dest[2] * (1.0f - src[3]);
ret[3] = src[3] + dest[3] * (1.0f - src[3]);
return ret;
}

int main(int argc, char **argv)
{
RGBA greenGround = { 0.0f, 1.0f, 0.0f, 1.0f };
PremultiplyAlpha(greenGround);

RGBA red25PercentOpaque = { 1.0f, 0.0f, 0.0f, 0.25f };
PremultiplyAlpha(red25PercentOpaque);

RGBA white30PercentOpaque = { 1.0f, 1.0f, 1.0f, 0.3f };
PremultiplyAlpha(white30PercentOpaque);

RGBA yellow50PercentOpaque = { 1.0f, 1.0f, 0.0f, 0.5f };
PremultiplyAlpha(yellow50PercentOpaque);

// one way
RGBA out1;
{
// start with the green ground and blend in 25% opaque red
out1 = greenGround;
out1 = BlendPremultipliedAlpha(out1, red25PercentOpaque);

// then blend in 50% yellow
out1 = BlendPremultipliedAlpha(out1, yellow50PercentOpaque);

// then blend in 30% opaque white
out1 = BlendPremultipliedAlpha(out1, white30PercentOpaque);
}

// other way
RGBA out2;
{
// start with the green ground and blend in 30% opaque white
out2 = greenGround;
out2 = BlendPremultipliedAlpha(out2, white30PercentOpaque);

// then blend in 25% red
out2 = BlendPremultipliedAlpha(out2, red25PercentOpaque);

// then blend in 50% yellow
out2 = BlendPremultipliedAlpha(out2, yellow50PercentOpaque);
}

return 0;
}


Premultiplied alpha itself does not give you order independent transparency, no.

This page talks about how it can be used as part of an order independent transparency solution however: http://casual-effects.blogspot.com/2015/03/implemented-weighted-blended-order.html

Other benefits of premultiplied alpha include:

Alan, Jim Blinn's compositing article also explains why premultiplied is the correct way to do any filtering of transparent images.

From the proof of premultiplied alpha blending, there is an assumption that "the operator must respect the associative rule." So, it may lead to confusion of the order of process.

Since this is not the commutative rule, blend(a,b) is not same as blend(b,a).

Hence, blend(blend(a,b),c) returns same value of blend(a,blend(b,c)). but, blend(blend(a,b),c) does not return same value of blend(blend(b,a),c) like your example.