Lesson 16: Backface Culling

Backface Culling

Backface culling is one of the easiest ways to speed up an OpenGL program. The idea is that when we draw a closed surface, we actually don't have to draw any of the faces that are facing away from the camera. Such faces are always covered by faces that are facing towards the camera. If we skip these faces, we only have to draw roughly half as many polygons.

The way we can do this in OpenGL is when we have closed surface, we just specify the vertices in counterclockwise order, when facing the polygon. Then, whenever OpenGL wants to draw a polygon, it knows that the polygon is facing away from the camera if the vertices are in clockwise order. If backface culling is enabled, OpenGL will just cull, or not draw, those faces.

Adding Backface Culling to the Spinning Cube

Let's add backface culling to the spinning cube program. We're going to add a little code to the initRendering function.

void initRendering() {
    //...
    glEnable(GL_CULL_FACE);
    //...
}

Whew! Hard work! Let's take a nice, long coffee break. When you come back from the break, try running the program. Since I was careful to specify the vertices on the cube in counterclockwise order, the program looks exactly the same, but it runs a little faster. OpenGL only has to draw about half as many faces as before. For a simple scene like this, it doesn't make much of a difference, but for more complicated programs, backface culling gives a serious boost.

You can also have OpenGL draw only the back faces by calling glCullFace(GL_FRONT). Why would you want to do that? Well, if you did the lesson on alpha blending, I mentioned that there's a trick using backface culling that lets you have transparency without complicated sorting of faces. We need to be able to cull front faces for this trick to work. You can make the cube transparent by following these steps:

  1. Cut all of the code in the drawScene function for drawing the cube (not including functions such as the ones used for transformation).
  2. Add a function drawCube(GLuint textureId) right after the line where we set BOX_SIZE, and paste the code for drawing a cube there.
  3. Change _textureId in the function to textureId.
  4. Change the calls to glColor3f to calls to glColor4f, and add the parameter 0.6f to the end of each.
  5. Add calls to glEnable(GL_BLEND) and glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) to the end of initRendering. Leave in the call to glEnable(GL_CULL_FACE).

Then, add the following code to drawScene where the code for drawing the cube was:

    glCullFace(GL_FRONT);
    drawCube(_textureId);
    glCullFace(GL_BACK);
    drawCube(_textureId);

Once we do this, we'll be drawing all of the polygons facing away from the camera, then drawing all of the polygons facing towards the camera. This will make it so that we draw all of the faces in the back before the faces in the front, which is exactly what we need for alpha blending. This technique works for any convex shape, but may not work for concave shapes. If you run the program, it will look just like the transparent cube from the alpha blending lesson. And we did all that without any complicated face sorting.

This explains how to use backface culling for alpha blending or for speeding up a program.

Next is "Lesson 17: Display Lists".