views:

315

answers:

3

This is related to my last question. To get this image:

  1. I draw a white background (color = (1, 1, 1, 1)).

  2. I render-to-texture the two upper-left squares with color = (1, 0, 0, .8) and blend function (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA), and then draw the texture with color = (1, 1, 1, 1) and blend function (GL_ONE, GL_ONE_MINUS_SRC_ALPHA).

  3. I draw the lower-right square with color = (1, 0, 0, .8) and blend function (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).

By my calculation, the render-to-texture squares should have color

.8 * (1, 0, 0, .8) + (1 - .8) * (0, 0, 0, 0) = (.8, 0, 0, .64)

and so after drawing that texture on the white background, they should have color

(.8, 0, 0, .64) + (1 - .8) * (1, 1, 1, 1) = (1, .2, .2, .84)

and the lower-right square should have color

.8 * (1, 0, 0, .8) + (1 - .8) * (1, 1, 1, 1) = (1, .2, .2, .84)

which should look the same! Is my reasoning wrong? Is my computation wrong?

In any case, my goal is to cache some of my scene. How do I render-to-texture and then draw that texture so that it is equivalent to just drawing the scene inline?

A: 

Whoops, my computation is wrong! the second line should be

(.8, 0, 0, .64) + (1 - .64) * (1, 1, 1, 1) = (1, .36, .36, .84)

which indeed seems to match what I see (when I change the last square to color (1, .2, .2, .8), all three squares appear the same color).

Jesse Beder
A: 

Regarding your last question: Replacing parts of the scene by textures is not trivial. A good starting point is Stefan Jeschke's PhD thesis.

Malte Clasen
+4  A: 

If you want to render blended content to a texture and composite that texture to the screen, the simplest way is to use premultiplied alpha everywhere. It’s relatively simple to show that this works for your case: the color of your semi-transparent squares in premultiplied form is (0.8, 0, 0, 0.8), and blending this over (0, 0, 0, 0) with (GL_ONE, GL_ONE_MINUS_SRC_ALPHA) essentially passes your squares’ color through to the texture. Blending (0.8, 0, 0, 0.8) over opaque white with (GL_ONE, GL_ONE_MINUS_SRC_ALPHA) gives you (1.0, 0.2, 0.2, 1.0). Note that the color channels are the same as your third calculation, but the alpha channel is still 1.0, which is what you would expect for an opaque object covered by a blended object.

Tom Forsyth has a good article about premultiplied alpha. The whole thing is worth reading, but see the “Compositing translucent layers” section for an explanation of why the math works out in the general case.

Pivot