PDA

View Full Version : Blending on render to texture alpha problem



STTrife
07-21-2014, 01:00 PM
Hi there,

For a GUI system I render parts to a buffer/texture first (I call them a canvas), and then rendered the texture to the screen.

For example

-create buffer/texture
-draw rectangle with texture to it
-draw a label (text) on top of that
-draw a quad with the texture-buffer on screen.

(the reason I want to do it this way, instead of rendering directly to screen, is so that I can cut off GUI elements that are too large)

Now the buffer/texture has a alpha component too, because it must be able to handle some transparency.

What goes wrong:
when I draw the full solid rectangle on the buffer/texture all alpha values go to 1 (this is good)
then I draw the label, but it uses antialiasing and therefor it uses blending. Now it also blends the alpha value! Thus introducing unwanted transparency in the texture/buffer (it was solid before, and it shouldn't have any transparency when a label is rendered on it).

It seem that with the blending functions, you can't separate what happens with the rgb values from what happens to the alpha values... if you blend, it also blends alpha values the same way (right?)

What I wanted, and what I assumed would happen is that if the background alpha is already 1, it would not lower that alpha value, because it was already solid... but that I guess that was wishful thinking...

any idea how to solve this issue?

thanks!

carsten neumann
07-21-2014, 01:20 PM
I think you are looking for glBlendEquationSeparate (http://www.opengl.org/sdk/docs/man/html/glBlendEquationSeparate.xhtml) and glBlendFuncSeparate (http://www.opengl.org/sdk/docs/man/html/glBlendFuncSeparate.xhtml).

STTrife
07-21-2014, 04:22 PM
that is it, thanks!

Actually: In my situation ideal would be: overwrite alpha (with source alpha) if it's larger than the destination alpha, but I don't think that is an option in OpenGL, is it???
Anyway, the glBlendFuncSeparate works fine, as long as I draw a solid background behind the label first, but that was my plan anyway.

carsten neumann
07-22-2014, 01:51 AM
Actually: In my situation ideal would be: overwrite alpha (with source alpha) if it's larger than the destination alpha, but I don't think that is an option in OpenGL, is it???


Sounds like you want the max of source alpha and dest alpha, so perhaps something like:



glBlendFuncSeparate( **, **, GL_ONE, GL_ONE);
glBlendEquationSeparate( **, GL_MAX);

STTrife
07-22-2014, 03:24 AM
I see.. yes this is exactly what I need, thanks!
I suppose GL_FUNC_ADD would be appropriate for the first argument? If I use SRC_ALPHA and ONE_MINUS_SRC_ALPHA in the blending function?

or actually... imagine: first a 50% transparent texture is placed on the canvas (then it should be 50% transparent)..
then a 30% transparent texture is put on top of that. What should the total transparency be then? 80%? Or less?
How does it work in real life if you place transparent layers on top of each other?


Sounds like you want the max of source alpha and dest alpha, so perhaps something like:



glBlendFuncSeparate( **, **, GL_ONE, GL_ONE);
glBlendEquationSeparate( **, GL_MAX);

carsten neumann
07-22-2014, 05:09 AM
The reference pages I linked to above have the formulas that get applied. Roughly what happens is that source and destination RGB and A values are weighted with the factors set by glBlendFunc/glBlendFuncSeparate and then the function selected with glBlendEquation/glBlendEquationSeparate is applied. One thing to consider when rendering (transparent) layers is that you possibly want to disable depth writes and/or the depth test or make sure your layers have depth values that correspond to their "ordering". And of course as always when dealing with blending: a number of blend modes are not commutative meaning the order you render things in matters.

STTrife
07-22-2014, 07:13 AM
Thanks, I read and think I understand the formulas that opengl uses, that was very helpful. I have also ensured that the render order of the layers is correct, but my question is now more general:

If I have a piece of glass that is 50% transparent, and another one that is 30% transparent, and I glue them together, how transparent is the result? (talking about the real life physics rules here)

Am I correct if I say 15%?

So in my open gl case, an alpha of .50 and an alpha of .70 should result in an alpha of 0.85 right?




The reference pages I linked to above have the formulas that get applied. Roughly what happens is that source and destination RGB and A values are weighted with the factors set by glBlendFunc/glBlendFuncSeparate and then the function selected with glBlendEquation/glBlendEquationSeparate is applied. One thing to consider when rendering (transparent) layers is that you possibly want to disable depth writes and/or the depth test or make sure your layers have depth values that correspond to their "ordering". And of course as always when dealing with blending: a number of blend modes are not commutative meaning the order you render things in matters.

carsten neumann
07-22-2014, 11:28 AM
From my very limited understanding, what is called transparency in computer graphics is really lumping together a whole bunch of physical effects (where you have reflection and refraction happening at the surface, absorption inside the material and a second set of reflection and refraction on the other side surface of the object). That being said, I agree that your calculations should produce a reasonable looking approximation ;)