PDA

View Full Version : Avoid Blending with Background when Blending Quads



Aboleoneo
09-05-2017, 01:56 PM
I am looking for a way to blend smoothly between 2 overlapping textured quads. The textures are subsequent sprite animation frames. These textures have a fully opaque area in the middle, with the pixels near the border being transparent.

I would like to blend between the images in such a way that at every step when blending from the first to the second texture, the place where the opaque regions on both textures overlap have no influence of the background showing through.

If I blend both quads like this:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);

then the overlapping opaque areas loose their full opacity, because the background gets blended in. If both textures are at 0.5 opacity, then the background has an influence of 0.25 on the image, because the first blend was with the background.

I could create a frame buffer, on which I could draw the first quad full opacity, and then blend the second quad with the first, and then render the frame buffer to a texture full opacity on the original scene.

Is there another way to do this?
Thanks.

Dark Photon
09-05-2017, 04:54 PM
I am looking for a way to blend smoothly between 2 overlapping textured quads. The textures are subsequent sprite animation frames. These textures have a fully opaque area in the middle, with the pixels near the border being transparent.

...

I could create a frame buffer, on which I could draw the first quad full opacity, and then blend the second quad with the first, and then render the frame buffer to a texture full opacity on the original scene.

Is there another way to do this?

With a different blend function, yes.

If I understand correctly, you're saying you can definitely do A @ ( B @ C ), where A is the background, B is quad1, C is quad2, and @ is the blend operator. But really you'd like to skip the intermediate framebuffer and do ( A @ B ) @ C instead. Right?

Ok:
A @ ( B @ C ) = ( A @ B ) @ C


is the definition of the associative properly, which means this will only work if @ is an associative blend function.

(SRC_ALPHA, ONE_MINUS_SRC_ALPHA) is not an associative blend function.
(ONE, ONE_MINUS_SRC_ALPHA) is an associative blend function.

The latter is also called the "pre-multipled alpha" blend function.

So I would consider changing your blend function to pre-multiplied alpha (both for the RGB and the A components). Then you can do this.

On Tom Forsyth's blog (LINK (http://eelpi.gotdns.org/blog.wiki.html)), there are two good posts on this blend function. In the right-hand pane, click on the "Premultiplied alpha" and "Premultiplied alpha part 2" page links and read through them. In particular, note the mentions about "associativity" and about "particle systems".