Lesson 17: Display Lists

Display Lists

An easy way to speed up OpenGL programs is to use display lists. The idea is that we have a sequence of OpenGL commands that we want to execute a lot, for instance, commands for drawing a particular object. We save all of the commands in a display list, and whenever we want to draw the object, we just call the display list.

This speeds things up because if, for example, there are calls to glVertex3f in the display list, we may only have to send the vertex coordinates for the object to the graphics card once. Whenever we call the display list, the coordinates may already be on the graphics card, and we don't have to waste time sending them to the graphics card again.

Adding Display Lists to the Spinning Cube

We'll use a display list to speed up the spinning cube program. First, we put all of the code for drawing a cube into a drawCube function. Then, we add a GLuint variable called _displayListId that will store the id of the display list. Then, we go down to initRendering to set up the display list.

void initRendering() {
    //...
    
    //Set up a display list for drawing a cube
    _displayListId = glGenLists(1); //Make room for the display list
    glNewList(_displayListId, GL_COMPILE); //Begin the display list
    drawCube(_textureId); //Add commands for drawing a cube to the display list
    glEndList(); //End the display list
}

First, we make room for one display list by calling glGenLists(1), which returns the id we can use for our display list. You can make room for multiple display lists at once by passing a number other than 1 to glGenLists, in which case the id of the first display list would be _displayListId, the id of the second would be _displayListId + 1, the id of the third would be _displayListId + 2, and so on. But for this program, we only need one display list.

Next, we want to tell OpenGL the sequence of OpenGL commands that are in the display list. We do this by calling glNewList(_displayListId, GL_COMPILE). Any OpenGL command that appears between a call to glNewList and glEndList will be put in this display list. In this case, we have a call to drawCube, so the display list will contain all of the OpenGL commands for displaying a cube.

void drawScene() {
    //...
    
    //Call the display list for drawing a cube
    glCallList(_displayListId);
    
    //...
}

In drawScene, we insert a call to the display list using the function glCallList, to instruct OpenGL to draw our cube.

If we run the program now, it looks the same as the spinning cube program, but it runs a little faster. The speedup doesn't matter a whole lot for a simple program like this, but for more complex 3D scenes, display lists are really useful for speeding things up.

There's one other thing I'd like to note. You can have a call to a display list inside of another display list. For example, we could have something like this:

GLuint displayListId = glGenLists(1);
glNewList(displayListId, GL_COMPILE);
drawObject();
glCallList(otherDisplayListId);
glEndList();

This does NOT insert the commands for the other display list into the new display list. Rather, it inserts a call to the other display list. If we were to change the other display list later, the changes would be reflected in the display list with id displayListId.

This explains how to use display lists to speed up an OpenGL program.

Next is "Lesson 18: Normalizing Normals".