Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the formula for alpha blending for a number of pixels?

I have a number of RGBA pixels, each of them has an alpha component.

So I have a list of pixels: (p0 p1 p2 p3 p4 ... pn) where p_0_ is the front pixel and p_n_ is the farthest (at the back).

The last (or any) pixel is not necessary opaque, so the resulting blended pixel can be somehow transparent also. I'm blending from the beginning of the list to the end, not vice-versa (yes, it is raytracing). So if the result at any moment becomes opaque enough I can stop with correct enough result. I'll apply the blending algorithm in this way: ((((p0 @ p1) @ p2) @ p3) ... )

Can anyone suggest me a correct blending formula not only for R, G and B, but for A component also?

UPD: I wonder how is it possible that for determined process of blending colors we can have many formulas? Is it some kind of aproximation? This looks crazy, as for me: formulas are not so different that we really gain efficiency or optimization. Can anyone clarify this?

like image 364
avp Avatar asked Sep 30 '08 17:09

avp


2 Answers

Alpha-blending is one of those topics that has more depth than you might think. It depends on what the alpha value means in your system, and if you guess wrong, then you'll end up with results that look kind of okay, but that display weird artifacts.

Check out Porter and Duff's classic paper "Compositing Digital Images" for a great, readable discussion and all the formulas. You probably want the "over" operator.

It sounds like you're doing something closer to volume rendering. For a formula and references, see the Graphics FAQ, question 5.16 "How do I perform volume rendering?".

like image 149
Adrian Avatar answered Oct 17 '22 10:10

Adrian


There are various possible ways of doing this, depending on how the RGBA values actually represent the properties of the materials.

Here's a possible algorithm. Start with final pixel colours lightr=lightg=lightb=0, lightleft=1;

For each r,g,b,a pixel encountered evaluate:

lightr += lightleft*r*(1-a)
lightg += lightleft*g*(1-a)
lightb += lightleft*b*(1-a)
lightleft *= 1-a;

(The RGBA values are normalised between 0 and 1, and I'm assuming that a=1 means opaque, a=0 means wholly transparent)

If the first pixel encountered is blue with opacity 50%, then 50% of the available colour is set to blue, and the rest unknown. If a red pixel with opacity 50% is next, then 25% of the remaining light is set to red, so the pixel has 50% blue, 25% red. If a green pixel with opacity 60% is next, then the pixel is 50% blue, 25% red, 15% green, with 10% of the light remaining.

The physical materials that correspond to this function are light-emitting but partially opaque materials: thus, a pixel in the middle of the stack can never darken the final colour: it can only prevent light behind it from increasing the final colour (by being black and fully opaque).

like image 26
Chris Johnson Avatar answered Oct 17 '22 10:10

Chris Johnson