Rendering Scenes With Translucent Objects:
A (Nearly) Pure GPU Approach

render Methods in SceneElement subclasses

The bulk of the work in this approach is done in the fragment shader which only needs to know whether opaque or translucent pieces are currently being drawn. So the minimal amount of work needed in this approach is to simply set a uniform variable that the fragment shader will see. This code could be placed, for example, in SceneElement::establishView:

ExtendedController* ec = dynamic_cast<ExtendedController*>(Controller::getCurrentController());
glUniform1i(shaderIF->ppuLoc("sceneHasTranslucentObjects"), 1);
if (ec->drawingOpaque())
    glUniform1i(shaderIF->ppuLoc("drawingOpaqueObjects"), 1);
else
    glUniform1i(shaderIF->ppuLoc("drawingOpaqueObjects"), 0);

The GPU fragment shader work

The following shows the rough outline of a fragment shader that can be used with this approach.

…
uniform int sceneHasTranslucentObjects = 0;
uniform int drawingOpaqueObjects = 1;

out vec4 fragColor;

…

void main()
{
    // computeColorAsUsual must:
    // 1. combine Phong color with texture color;
    // 2. set color.a = (texture has alpha) ? f(PPU alpha, texture alpha) : PPU alpha
    vec4 color = computeColorAsUsual();

    if (sceneHasTranslucentObjects == 1)
    {
        if (drawingOpaqueObjects == 1)
            if (color.a < 1.0)
                discard;
            else
                fragColor = color;
        else if (color.a < 1)
            fragColor = color;
        else
            discard;
    }
    else
        fragColor = color;
}

Advantages

Disadvantages