Back to index

Tutorial 2: Vertex Buffer Objects

Before starting this tute, make sure you have SDL working and can at least display a set of axes using OpenGL+SDL.

Axes and a grid

Use the following framework code which draws a wireframe grid using immediate mode and triangle strips.

Storing the Data

The grid is rendered using triangle strips in Immediate Mode. For this tute we will modify this to render using stored coordinates, then using stored coordinates and indices, then Vertex Arrays (VAs) and finally Vertex Buffer Objects (VBOs).

First modify the program to use display the grid using the stored vertex data. Study the way the coordinates are computed and stored. Notice that whilst the grid drawing code duplicates vertices for each unique position in the grid. each vertex coordinate is only stored once. Then if a coordinate needs to be used multiple times it can be accessed via its array index. Moreover, all the indices needed to render the grid can also be stored in an array - the index or element array. The size of the vertex array will need to be equal to the number of vertices (n_vertices), and is (rows+1) * (cols+1) (one unique vertex for each position). The size of the index array is basically the number of vertices * 2 (as vertices are repeated in neighbouring strips).

The program uses a vec3f struct that contains x,y,z floats, and a Vertex struct which has a vec3f for the vertex coordinates. Later we will add a normal to the Vertex struct, which could also contain other data such as texture coordinates also. The coordinate data is an array of Vertex, consisting of tightly packing float data.

After allocating the two arrays of the correct size, they are initialised with the correct data. It is fairly obvious what data should go into the vertex array, not quite as obvious what should go in the index array.

After changing the program to use the stored vertex data (which still uses Immediate Mode i.e. glVertex) try modifying it to use both the stored vertex and index data from the index and vertex arrays.

Vertex Arrays

Now that the arrays have been created, we can attempt to render them as vertex arrays:

If we were rendering triangles, we could send all the indices in one batch, however since we are rendering a series of triangle strips, multiple draw calls in a loop are used, eg:

	for (int i = 0; i < cols; i++)
	  glDrawElements(GL_TRIANGLE_STRIP, (rows + 1) * 2, GL_UNSIGNED_INT, &indices[i * (rows + 1) * 2]);
	
      

A grid should render that matches the immediate mode grid.

The loop with multiple draw calls could be eliminated and replaced by a single draw call using glMultiDrawElements, although internally this may be implemented internally using a loop anyhow.

Note that although the number of vertices is the same, there is fewer indices using strips than individual triangles, It is not obvious which approach is faster, as unlike immediate mode, the vertices themselves are only processed once.

Vertex Buffer Objects

Now that we have VAs working correctly, we can attempt to render using VBOs. The advantage of this rendering technique is that vertex data does not need to be sent to the GPU each frame, only when we want to change it.

Rendering is performed in the same way as using Vertex Arrays, but in addition we need to do the following when creating the data:

Now each time we want to render the VBO, we need to: