You also need to consider the effect of the depth buffer when determining the correct order. The depth buffer (sometimes called the z-buffer) is usually used for hidden-surface elimination. It keeps track of the distance between the viewpoint and the portion of the object occupying a given pixel in a window on the screen; when another candidate color arrives for that pixel, it is drawn only if its object is closer to the viewpoint, in which case its depth value is stored in the depth buffer. With this method, obscured (or hidden) portions of surfaces aren't necessarily drawn and therefore aren't used for blending.
Typically, you want to render both opaque and
translucent objects in the same scene, and you want to
use the depth buffer to perform hidden-surface removal
for objects that lie behind the opaque objects. If an
opaque object hides either a translucent object or
another opaque object, you want the depth buffer to
eliminate the more distant object. If the translucent
object is closer, however, you want to blend it with
the opaque object. You can generally figure out the
correct order to draw the polygons if everything in the
scene is stationary, but the problem can easily become
too hard if either the viewpoint or the object is
moving.
The solution is
to enable depth-buffering but make the
depth buffer read-only while drawing the translucent
objects. First you draw all the opaque objects, with
the depth buffer in normal operation. Then, you
preserve these depth values by making the depth buffer
read-only. When the translucent objects are drawn,
their depth values are still compared to the values
established by the opaque objects, so they aren't drawn
if they're behind the opaque ones. If they're closer to
the viewpoint, however, they don't eliminate the opaque
objects, since the depth-buffer values can't
change. Instead, they're blended with the opaque
objects.
To control whether the depth buffer is
writable, use glDepthMask(); if you pass GL_FALSE as
the argument, the buffer becomes read-only, whereas
GL_TRUE restores the normal, writable operation.