Working in RGBA Mode
OpenGL can work in both RGB or RGBA mode. Under the new RGBA mode, transparencies can be encoded as a fourth component, so colors are blended together depending on their assigned alpha values. As a rule of thumb, an alpha of 0.0 means totally transparent, whereas an alpha of 1 means totally opaque.
But working with alpha values is a bit more involved than that. Water, glass, and fire are all semitransparent, but their optical properties are very different. Luckily, OpenGL supplies us with a set of calls that can simulate many different phenomena. Let's do an overview of OpenGL's RGBA functionality, and then look at some specific examples.
OpenGL offers two subsets of RGBA calls: blending or testing. Alpha blending refers to the color mixing process that takes place between translucent materials, such as stained glass. The resulting color is a combination of the colors of the different surfaces. Alpha testing, on the other hand, is a binary process by which a pixel is either fully opaque or fully transparent, so no blending takes place. A good example of alpha testing is a fence, where the geometry is just a quad with an alpha-tested texture map laid on top. Alpha testing is significantly faster than alpha blending because many fragments can be rejected early in the pipeline, and the remaining fragments do not have to compute pixel arithmetic (as opposed to the blending routine in the alpha blending mode).
Whichever the case, both alpha blending and testing must be enabled and disabled by using the following OpenGL tokens:
glEnable(GL_BLEND); (...) glDisable(GL_BLEND);
glEnable(GL_ALPHA_TEST); (...) glDisable(GL_ALPHA_TEST);
All code within an Enable/Disable scope will be treated accordingly. Let's first examine OpenGL's alpha testing routines. You first need to supply a texture that has an alpha channel. Then, you can tell OpenGL to accept or discard fragments depending on their alpha value. The syntax is as follows:
glAlphaFunc(glenum type, glfloat threshold);
The first parameter indicates the type of test we will perform, and the second parameter is a threshold value that is usually related to the type of test. For example, the following line sets a threshold value of 0.5, and tells OpenGL that fragments greater than that value should be painted; and fragments with alpha values lower than or equal to 0.5 should be discarded:
glAlphaFunc(GL_GREATER,0.5);
Alpha values for the test can either be passed per pixel, as part of an alpha channel bundled with the texture map, or per vertex in a glColor4f call. In the latter case, per-vertex alpha values are modulated by per-pixel texture values, so the resulting alpha value is passed through the test.
Alpha blending is a much slower and complex process, but results are very attractive. Here we will need to specify alpha values, either per vertex or per pixel, and a blending equation that determines how translucent objects will interact. The blending equation is specified with the following call, which determines how the source and destination fragments are combined:
glBlendFunc(glenum src, glenum dest);
Source means whatever graphic primitive you are about to paint. It is the source of new data. Destination is where the new data will be added—thus, the contents of the frame buffer. The two parameters allow you to specify what computation will be performed every time a source fragment is combined with a destination. Possible values for both parameters are
GL_ZERO GL_ONE GL_DST_COLOR GL_ONE_MINUS_DST_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA GL_DST_ALPHA GL_ONE_MINUS_DST_ALPHA GL_SRC_ALPHA_SATURATE
The trick here is to learn which parameter combination is needed to render certain effects. To make your life easier, I'll now cover the most widely used combinations. Many times you will need to create semitransparent objects such as glass or clouds, which filter light but do not act like light sources. For this case, the parameter combination is
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
so that you pass alpha values to primitives you want to render transparent. Another typical scenario is rendering objects that, being semitransparent, do add illumination to a scene. Some examples are a bonfire, a lens flare effect, or a laser beam. In these cases, what you need is an additive blend, which is achieved by
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
Many interesting effects can be created with more exotic parameter combinations. Make sure you understand the two examples provided in this section, and you will be able to think of new uses yourself.
|