Schabby's Blog
Reserve Orbital Defence Commander

This post is a brief tutorial on how to use display lists in OpenGL. An working and self-contained example is given below using LWJGL.
Display lists are an essential feature of OpenGL to improve the rendering performance of your application. You can think of them as kind of a macro for OpenGL commands that you name, record and call at some point in your game. More specifically, you assign an integer handle to a sequence of OpenGL commands and call the commands identified by that handle when you need them.

The advantage is mainly rendering speed which is greatly improved as you don't pump your geometry into the rendering pipeline through individual glVertex, glNormal etc. commands in every render pass. Instead, you render your potentially complex geometry into a display list once and call ist every time you want the geometry to be rendered. This becomes enormously beneficial in a Java environment where you want to use as few JNI calls as possible.

The disadvantage is that a display list is fixed once it is uploaded to video memory. That means you cannot modify the order or geometry data after you compiled your list. Even if you only need to change one single glTranslate parameter, you would need to delete the entire list and create a new one.

So far for dry theory, let's look at the example. Please note that this example makes use of my LWJGL example base class which I recommend to copy first so that the example runs out of the box.

We start with setting up the example class as follows. The setUp method is responsible for recording the GL commands into the "macro".

public class DisplayListExample extends LwjglExampleBase
{
	// handle (id) of the display list to be generated
	private int displayListHandle = -1;
 
	// angle in degrees required for rotating the cubes
	private float rotationAngle = 0;
 
	/**
	 * Sets up LWJGL and OpenGL and renders the 
	 * display list.
	 */
	public void setUp() 
	{
		// Set up LWJGL and OpenGL using the
		// base class.
		super.setUp();
 
		// Generate one (!) display list.
		// The handle is used to identify the
		// list later.
		displayListHandle = glGenLists(1);
 
		// Start recording the new display list.
		glNewList(displayListHandle, GL_COMPILE);
 
		// Render a single cube
		renderCube(1);
 
		// End the recording of the current display list.
		glEndList();
	}

Setting up a display list is a simple as that. Note the parameter GL_COMPILE. It tells OpenGL to only compile the list and not to draw it at the same time. Alternatively,
one could use GL_COMPILE_AND_EXECUTE which would render the result while recording.

Lets us have a look into the renderCube() which basically contains the OpenGL commands to render a simple cube (without normals because we dont have lighting).

	public static void renderCube(float size)
	{
		final float HALF = size/2;
		glBegin(GL_QUADS);
 
		glColor3f(0, 0, 1);
		glVertex3f(-HALF, -HALF, -HALF); 
		glVertex3f(-HALF, size-HALF, -HALF); 
		glVertex3f(size-HALF, size-HALF, -HALF); 
		glVertex3f(size-HALF, -HALF, -HALF);  
 
		glColor3f(0, 1, 1);
		glVertex3f(-HALF, -HALF, size-HALF);  
		glVertex3f(-HALF, size-HALF, size-HALF);  
		glVertex3f(size-HALF, size-HALF, size-HALF); 
		glVertex3f(size-HALF, -HALF, size-HALF);  
 
		glColor3f(1, 0, 1);
		glVertex3f(-HALF, size-HALF, -HALF);  
		glVertex3f(size-HALF, size-HALF, -HALF); 
		glVertex3f(size-HALF, size-HALF, size-HALF); 
		glVertex3f(-HALF, size-HALF, size-HALF); 
 
		glColor3f(1, 0, 0);
		glVertex3f(-HALF, -HALF, -HALF);  
		glVertex3f(size-HALF, -HALF, -HALF); 
		glVertex3f(size-HALF, -HALF, size-HALF); 
		glVertex3f(-HALF, -HALF, size-HALF); 
 
		glColor3f(1, 1, 0);
		glVertex3f(-HALF, -HALF, -HALF);  
		glVertex3f(-HALF, size-HALF, -HALF); 
		glVertex3f(-HALF, size-HALF, size-HALF); 
		glVertex3f(-HALF, -HALF, size-HALF);  
 
		glColor3f(0, 1, 0);
		glVertex3f(size-HALF, -HALF, -HALF);  
		glVertex3f(size-HALF, size-HALF, -HALF); 
		glVertex3f(size-HALF, size-HALF, size-HALF); 
		glVertex3f(size-HALF, -HALF, size-HALF); 
 
		glEnd();
	}

Now comes the interesting part of calling the display list. To illustrate its usefulness, I draw a grid of 5x5 of the same cube and only change its position and rotation.

	/**
	 * Render 5x5 cubes centered around the origin. Each
	 * cubes has a slightly different rotation to make this
	 * example look more interesting.
	 */
	public void render() 
	{
		// In each render pass, add one degree to rotation
		// angle.
		rotationAngle += 1;
		for( int x = 0; x < 5; x++ )
		{
			for( int z = 0; z < 5; z++ )
			{
				// Save current MODELVIEW matrix to 
				// stack.
				glPushMatrix();
 
				// position next cube
				glTranslatef(x*2 - 4,0, z*2 - 4);
 
				// rotate next cube
				glRotatef(x*z*10+rotationAngle, 1, 1, 1);
 
				// Call the display list which renders
				// the cube.
				glCallList(displayListHandle);
 
				// Remove current MODELVIEW Matrix from
				// stack.
				glPopMatrix();
			}
		}
	}

And that's it! Pretty easy, huh? To conclude the example I provide the main() method necessary to run the example. Also, please bear in mind that you need LwjglExampleBase to run the example.

	public static void main(String[] argv) 
	{
		DisplayListExample example = new DisplayListExample();
		example.setUp();
		example.gameLoop();
	}
}

Alright, we are done with the tutorial. If you liked the post, please leave a comment and let me know if you have questions or found a bug.

Cheers, Johannes


Post Comment

Please notice: Comments are moderated by an Admin.