2
votes

I've been working in opengl for a while relatively smoothly, but recently I've noticed that when I render a primitive with a transparent texture onto my fbo texture (custom frame buffer) it makes the fbo texture transparent at the pixels the primitive's texture is transparent. The problem is that there are things behind this primitive (with solid color) already rendered before the transparent one. So the fbo texture should not be transparent at those pixels - blending a solid & transparent color should result in a solid color, shouldn't it?

So basically, opengl is adding transparency to my fbo-texture just because the last primitive drawn has transparent pixels even though there are solid colors behind it already drawn into the fbo texture. Shouldn't opengl blend the transparent texture with the fbo's existing pixels, and result in a solid color if the fbo texture is already filled with solid colors before rendering the transparent primitive?

What happens when I render my fbo texture to the default frame buffer, is that the clear color bleeds through parts of it - where the last drawn texture is transparent. But when I render the same scene straight to the default opengl frame buffer, the scene looks fine and the clear color is not bleeding into the transparent texture.

What's even more interesting is that the glClearColor - color is only visible where the primitive's texture's alpha has a gradient - the clear color has no influence on where the texture alpha is 1.0 or 0.0... is this a bug? It seems to affect the primitive's texture the most at pixels with 0.5 alpha. Then going further above or below decreases the glClearColor influence.

I know it's a bit of a complex question/situation, I honestly tried my best to explain

I'm using:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

to draw both the partly transparent primitive into the fbo-texture, and then the fbo texture to the default framebuffer

This is what the fbo-texture drawn into the default opengl fbo looks like:

glClearColor is set to red.

1
Before drawing the fbo's texture to the screen, do you remember to reset the blending? Also any code or a screenshot of it happening would be nice.vallentin
Have you verified that GL_BLEND is enabled?Matteo Mecucci
Screenshot added :) I don't want to reset the blending because I do want to have transparent fbo-textures, the problem is that the fbo-texture is transparent where it's not supposed to be, blending with the clear color of the default frame bufferHelloWorldCpp
Where do you see transparency, where it isn't supposed to be? Couldn't this just be the result of filtering? (When the fbo's texture is applied to the quad)vallentin
It seems like the clearColor is (red) is affecting the fbo-texture where the quad's texture has a gradient, the fully opaque parts are correct (left of the image) and the fully transparent parts are also correct, blending with the background completely (right side) - the gradient inbetween however is affected by the clearcolorHelloWorldCpp

1 Answers

1
votes

blending a solid & transparent color should result in a solid color, shouldn't it?

Only if your blend mode tells it to. And it doesn't:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

This applies the same blending operation to all four components of the colors. This causes the final alpha to be the result of multiplying the source alpha by itself and adding that to the destination alpha times 1-src alpha.

Now, you could use separate blend functions for the color and the alpha:

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);

The last two parameters specify the blending for just the alpha, while the first two specify the blending for the RGB colors. So this preserves the alpha. Separate blend functionality is available on GL 3.x and above, but is also available as an extension on older hardware.

But it seems to me that you probably don't want to change the alpha at all. So simply mask alpha writes when rendering to the texture:

glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);

Don't forget to undo the alpha mask when you want to write to it again.