Tutorial 16 : Display Lists

Tutorial Advanced Download Section

Display lists are used to optimize performance of rendering (ie rendering faster). They are mostly used for rendering larges objects, which requieres a large number of glVertex calls. Keep in mind the call glVertex is SLOW.

Display list is not the only technique to improve rendering speed. There are other rendering techniques such as vertex array, vertex buffer object (known as VBO) and frame buffer object (know as FBO). For what I've experienced for large objects, VBO is faster than display list which is slightly faster or equivalent to vertex array. FBO is know to be faster than VBO, I don't have tried it yet.

I've made few comparisons between display lists and classic rendering (glVertex), to view the speed-up obtained with display list.
During these comparisons, we will show that display lists are a lot faster than glVertex for large objects. The results are comparable for tiny objects.
 

Display lists (DL) can store on the GPU a list of OpenGl command. Any OpenGl command can be stored in a display list. At the display list creation, those command are compiled in the display list.
Afterwards, those commands can be called lots of time in a faster way (datas already sended to the GPU) than the classic rendering (direct mode)..
 

A display list is refered by an ID like for textures. This ID is create with :
    int listId = gl.glGenLists(1)
We can generate more than one ID, the parameter is the number of list to create. If more than one display list is created, each display list ID are contiguous, this means the first list id is listId, the second list ID is listId+1 and on ...

At its creation the list is empty. To initialize it, we will use the block glNewList / glEndList. This block is similar to the block used for rendering primitive objects (glBegin / glEnd).
In this block, we can call any OpenGl commands. We can also use all java syntaxe like for loop, function call ...
    gl.glNewList(list, mode)
        ...                    //OpenGl call Code to stored into the display list
    gl.glEndList()
list is the reference to the list
mode is the mode of creation of the display list : GL_COMPILE, GL_COMPILE_AND_EXECUTE. GL_COMPILE compile the display list ie the OpenGl calls are stored in the display list. GL_COMPILE_AND_EXECUTE compile the display list and execute the OpenGlcommands.

After a display list has been initialized, it can't be modify. This means a display list can't be dynamically updated for animated objects.
 

We have seen how to creates a display list.
You should now want to use it :
    gl.glCallList(list)

You probably wants to call multiple lists :
    gl.glListBase(listBase)
    gl.glCallLists(nbLists, type, referenceOffsets)
The first method select the display list refered by listBase as the base list. Indices in the referenceOffsets array are counter by considering that listBase is 0.
nbLists is the number of lists that should be called.
type is the type of information stored in referenceOffsets. It is typically : GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT or GL_UNSIGNED_INT.
indiceOffset is an array that holds offset reference to the desired list to call by comparison to listBase (Ex: if listBase = 100 and you want to draw a list refered by 103, its offset reference is 3).

You will see a usefull application of this in Tutorial 18 to draw text using a display list for each characters.
 

To know if a display list ID is valid (ie is a DL), we can use :
    gl.glIsList(list)

When a display list is unecessary, the memory of the GPU can be free by destroying the DL :
    gl.glDeleteLists(list, numList)
list is the first display list ID to destroy.
numList is the number of display list to destroy (from the first ID).
 

The goal of this tutorial is to draw simple shapes (a textured cube) with a high number of repetition, and compare the result betwen direct mode and display lists.

The scene is composed of 'pyramids' made of 10 cubes, which will be drawn lot of times :


Association of cubes

The display list used is composed of 4 'pyramids', ie 40 cubes. This list will be called many of times.
 

Creation of a display list

/*****************************************
 * Initialize all display lists          *
 *****************************************/

private void initDisplayList(GL gl)
{
    /***************************
     * NEW * Display List ?    *
     *******************************************************************************************
     * Display list (DL) store OpenGl code for a later use. This is used when some OpenGl      *
     * commands are called lot of times.                                                       *
     * For the drawing of a lot of identical or large objects, DL is more efficient than using *
     * glVertex (less time for sending datas to GPU and then for rendering).                   *
     *                                                                                         *
     * First, we start with creating a new empty list. The glGenList method creates            *
     * contiguous lists.                                                                       *
     * final int LISTS = gl.glGenList(numberOfDL);                                             *
     * LISTS is the first DL, LISTS+1 is the second ...                                        *
     *                                                                                         *
     * To initialize the list, we only need to put the code to execute into the block          *
     * glNewList/glendList like :                                                              *
     * gl.glNewList(LISTS, GL_COMPILE); //or GL_COMPILE_AND_EXECUTE                            *
     * ... //OpenGl commands to store in the DL                                                *
     * gl.glEndList();                                                                         *
     * Note: after the list is initialize, it can't be changed/updated.                        *
     *                                                                                         *
     * We can execute the DL with glCallList :                                                 *
     * gl.glCallList(LISTS);                                                                   *
     * Note: glCallLists can also be used to call many DL, this will be used in Tutorial 20.   *
     * To destroy the DL from the GPU memory :                                                 *
     * gl.glDeleteLists(LISTS, numberOfDL)                                                     *
     *******************************************************************************************/


    //Generates a new reference for a display list that will holds the drawing of a cube
    OBJECT_DL = gl.glGenLists(1);
    gl.glNewList(OBJECT_DL, GL.GL_COMPILE);
        //Objects drawn on the screen, set of glNormal/glTexCoord/glVertex calls
        drawGeometry(gl);
    gl.glEndList();

    //Here is an example of creating 3 contiguous DL
    //The next 3 DL will not improve the rendering, it is just given as an example

    TEXTURES_DL = gl.glGenLists(3);
    gl.glNewList(TEXTURES_DL, GL.GL_COMPILE);
       gl.glBindTexture(GL.GL_TEXTURE_2D, texture[0]);
    gl.glEndList();
    gl.glNewList(TEXTURES_DL+1, GL.GL_COMPILE);
       gl.glBindTexture(GL.GL_TEXTURE_2D, texture[1]);
    gl.glEndList();
    gl.glNewList(TEXTURES_DL+2, GL.GL_COMPILE);
       gl.glBindTexture(GL.GL_TEXTURE_2D, texture[2]);
    gl.glEndList();
}

Note: The display list which binds the texture ID are shown here as an illustration of generating contiguous lists. This will not improve the rendering here (glCallList is probably slowest than glBindTexture). For more information on this, look at tutorial 20.
 

Here, we will see the performances of our display list. We will compare the FPS (frames per second) of the application either in display list mode and in direct mode. For those two modes, the object rendering is exactly the same. Higher the FPS is, faster the scene is rendered. So, the best mode is the mode for which the FPS is higher.

Those comparisons are made with an ATI Radeon 9600 graphic card (my computer) using the JOGL.
 

This first comparison will compare the FPS obtained for a high number of vertice drawn, light is disabled :
 

Number of pyramids 4 12 20 36 100 200 500 1000
FPS using display list 980 812 742 668 478 312 152 83
FPS using direct mode 747 486 356 233 100 52 21 10

This first comparison will compare the FPS obtained for a high number of vertice drawn, light is enabled :

Number of pyramids 4 12 20 36 100 200 500 1000
FPS using display list 908 798 694 564 322 194 88 46
FPS using direct mode 712 450 330 214 90 48 19 9

Note: A pyramid is made of 10 cubes, a cube is made of 24 vertices => a pyramid is made of 240 vertices.

We can see the huge gain obtained with display list. Higher the number of vertices is, bester is the rendering with display list.
The scene remains interactive (fluid) even for a large number of vertices. In direct mode, for the highest number of vertices, the goes very low (mouvement is slightly jerky).

Next, we will see if the display lists are best for low number of vertice ?
 

The second test will compare the result for a low number of vertice drawn, light is disabled :

Number of cubes 1 2 3 4
FPS using display list 1290 1254 1190 1176
FPS using direct mode 1172 1052 880

812

and with light enabled :

Number of cubes 1 2 3 4
FPS using display list 984 983 980 978
FPS using direct mode 984 974 964

954

Note: A cube is made of 24 vertices.

Even for a low number of vertices, display list are better but with a soft gain.
 

Display lists are faster than calling successively the glVertex calls. Display list is the easiest way to improve performance of your application. Other techniques like vertex array, VBO or FBO needs are a little more complicated.

Use display list where you can !
 

Look at the Tutorial 20 to know more about this.
 

This little utility will manage the display list for you. You can see how it is easy to use
 

DisplayListHelper


    //An helper to use display list
    DisplayListHelper dl = new DisplayListHelper(new ActionListener(){
        public void actionPerformed(ActionEvent e)
        {
            //OpenGl commands to be compiled in a display list
            ...
        }
    });

    ...

    //Render the display list
    dl.renderInDL();

    ...

    //Destroy the display list
    dl.release();

 

D : switch between display lists / direct mode
+ - : increase/decrease the number of vertice drawn
L : enable/disable lighting
T : select a texture filter

You can also use directional keys or the mouse to mouse the scene.
 

Remember to download the GraphicEngine-1.1.2 to run this tutorial !


If you've got any remarks on this tutorial, please let me know to improve it.
Thanks for your feedback.
 

Previous Tutorial

Back

Next turorial

Copyright © 2004-2012 Jérôme Jouvie - All rights reserved. http://jerome.jouvie.free.fr/