Skip to content

3D Rendering with VBOs

wasalski edited this page May 25, 2012 · 1 revision

Vertex Buffer Objects were introduced in OpenGL 2.x and were made standard in OpenGL 3.x. They provide an efficient method of rendering thousands of vertices by copying the vertex array and index array over the GPU side memory once and rendering the information multiple times instead of copying the data over to the GPU on every frame.

The snogoggles package's VBO class provides an object oriented wrapper on the OpenGL methods needed to utilize vertex buffer objects. It is highly recommended that all 3D rendering done in snogoggles is done through this class. However, a basic understanding of the processes occurring behind the scenes of this class is necessary to facilitate proper usage.

Using a VBO is superior to rendering in immediate mode for 2 reasons. Firstly, it minimizes the number of GPU/CPU sync points (points at which the CPU is unable to do meaningful work until the GPU completes its task) . The more times the CPU and GPU need to sync up, the worse the performance of the application gets. For example, glBegin() and glEnd() calls used in immediate mode rendering are sync points. This is the biggest performance increase. Secondly, copying data over from the CPU to the GPU is slow. Vertex buffer objects only copy over data when explicitly told to, and store the data otherwise.

Example code utilizing the snogoggles VBO class follows below.

A. Example code creating and binding a vertex buffer object:

VBO vbo;              // Creates vbo object
vbo.Clear();          // Clears all data from vertex list and index list

Clearing the VBO removes all of the data stored in the vertex and index arrays; without this you will be adding to the end of the list with every call. Now we will set up the data to draw a red triangle. The list of indices provides a memory efficient way to be able to use the same vertex for more than one polygon.

// Sets up vertices for a red triangle
vbo.AddVertex( Vertex( TVector3(1,1,0), Colour(255,0,0) ) )
vbo.AddVertex( Vertex( TVector3(-1,1,0), Colour(255,0,0) ) )
vbo.AddVertex( Vertex( TVector3(-1,-1,0), Colour(255,0,0) ) )

// Set up the index list - the order in which the vertices should be rendered
vbo.AddIndex(0);
vbo.AddIndex(1);
vbo.AddIndex(2);

Now that we're done loading our geometry data into the vertex buffer object, its time to copy the data over to the GPU side memory, which is done with the command

vbo.Bind();           // Binds data to GPU buffers

This is an expensive call and should only be invoked when the data that you want to render changes.

B. Example code for rendering a vertex buffer object:

Now that our vertex buffer object is initialized and the data is bound to OpenGL buffers, to render the triangle:

vbo.Render( GL_TRIANGLES );

Where the parameter for the render call takes an OpenGL primative to render (GL_LINES, GL_TRIANGLES, GL_QUADS, etc.) Easy, right?