Advertisement

Color transparency misunderstanding

Started by September 03, 2011 09:44 AM
7 comments, last by jgg 13 years, 2 months ago
Hi there,

I'm new to OpenGL and I'm reading the NeHe's OpenGL tutorials which seem pretty easy to follow and very instructive. I have just read lesson 9, "Moving bitmaps in 3D space", and there is one thing I don't understand.

The program draws some stars which are defined with a specific color. Additionally, you can make them twinkle by pressing the 'T' key. Then, the colors of two different stars are mixed. What I don't understand is how these two colors can be mixed as they are defined for the star texture. I mean, when applied the colors for the two stars to be drawn, the two of them are defined with an alpha value of 255 (1.0f) (check the code below), which means the color should be opaque. So, if they are meant to be opaque, how can they be mixed? Should not the last star to be drawn overlapping the previous one?

Any help would be really appreciated.

Thank you.

...

if (twinkle)
{
glColor4ub(star[(num-loop)-1].r,star[(num-loop)-1].g,star[(num-loop)-1].b,255);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd();
}

glRotatef(spin,0.0f,0.0f,1.0f);
glColor4ub(star[loop].r,star[loop].g,star[loop].b,255);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd();
...
if you look in the function InitGL you will see these two lines

glBlendFunc(GL_SRC_ALPHA,GL_ONE); // Set The Blending Function For Translucency
glEnable(GL_BLEND);

This means that instead of replacing the color when overdrawing it will instead add to the color depending on the color and alpha of the texture your drawing.
Try commenting them out and see what happens.
Advertisement
I understand that these lines enable blending so translucency effect happens, but it seems that the alpha value just changes the brightness of the color.

For example, in lesson 8, the blending enable code is like this:


glColor4f(1.0f, 1.0f, 1.0f, 0.5f); // Full Brightness. 50% Alpha
glBlendFunc(GL_SRC_ALPHA,GL_ONE); // Set The Blending Function For Translucency


If I set the alpha variable in glColor4f to 0.0f the cube becomes invisible, what makes sense as it should be completely transparent. However, when setting alpha to 1.0f, instead of having an opaque cube, it seems to be again 50% transparent but with lighter colors. I know that if I want to get opaque textures I just have to turn off blending (as it is shown in the same code of lesson 8), but what if I want to get a 33% or 85% transparency for example? Setting 0.33f or 0.85f in the 4th argument just makes the transparent cube lighter or darker, no effect on translucency at all.

Probably I'm missing something but, as I said before, I'm a complete newbie and I would like to learn with this; that's why I'm asking smile.gif.

Thank you so much for your help.

I understand that these lines enable blending so translucency effect happens, but it seems that the alpha value just changes the brightness of the color.

For example, in lesson 8, the blending enable code is like this:


glColor4f(1.0f, 1.0f, 1.0f, 0.5f); // Full Brightness. 50% Alpha
glBlendFunc(GL_SRC_ALPHA,GL_ONE); // Set The Blending Function For Translucency


If I set the alpha variable in glColor4f to 0.0f the cube becomes invisible, what makes sense as it should be completely transparent. However, when setting alpha to 1.0f, instead of having an opaque cube, it seems to be again 50% transparent but with lighter colors. I know that if I want to get opaque textures I just have to turn off blending (as it is shown in the same code of lesson 8), but what if I want to get a 33% or 85% transparency for example? Setting 0.33f or 0.85f in the 4th argument just makes the transparent cube lighter or darker, no effect on translucency at all.

Probably I'm missing something but, as I said before, I'm a complete newbie and I would like to learn with this; that's why I'm asking smile.gif.

Thank you so much for your help.

The parameters to glBlendFunc controls how much of the source color (what you draw) is blended with the destination color (what is already in the frame buffer). The first factor, GL_SRC_ALPHA, means the source color is multiplied by the source alpha value. The second parameter, GL_ONE, means the destination color is multiplied by the constant factor 1. These two colors are then added to produce the final color that is written back to the frame buffer.

So if alpha is zero, the final color is srcColor*0+dstColor*1, which is the same as dstColor. The object thus appear invisible, since the result of the blending stage is whatever was in the frame buffer before blending in the second object.
If alpha is one, the final color is srcColor*1+dstColor*1, which is brighter and an equal blend of the source and destination color. The object appears brighter since the total additive factor is 2, and half transparent since the final color is a blend of 1 part source and 1 part destination color. Or, in other words, a 50/50 blending.

What you probably want is to decrease the contribution from the destination color as the alpha increases. Luckily, there is a constant GL_ONE_MINUS_SRC_ALPHA, and I'll let you figure out what it means, where to use it, and how it affects the final blended color.
Thanks for your detailed explanaiton, Brother Bob. Setting this, for example:


glColor4f(1.0f, 1.0f, 1.0f, 0.85f);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

nearly produces the transparency effect I was expecting; I just miss one thing. As the cube is rotating, its sides change their position into the 3D space so, as they are repainted, some weird transparency behavior happens, like the back side being painted "over" the front side. It happens due to the order (always the same) in which the cube sides are painted in the DrawGLScene function, as the front side is the first in code, so every other side coming after will be painted over it. Am I wrong? In order to keep a "logic" transparency process while the cube is rotating, is there any other procedure different than calculating how sides should be repainted according to cube's position?

Thank you again.
That particular blending function is order dependent, which means that the result depends on in which order you draw them. You have to draw from back to front. That means that, depending on how your cube is oriented, you have to draw its faces in different orders to ensure that the back of the cube, as seen from the viewpoint, is drawn before the front of the cube.
Advertisement
Right. And, just to know, is there a different blending function that automatically takes care of this?
There are other blending functions that aren't order dependent, but they do not give you the kind of translucency you're asking for.
Ok, thank you so much for your help!

This topic is closed to new replies.

Advertisement