Open GL : Using Vertex Array Objects to Organize Your Buffers

- How To Install Windows Server 2012 On VirtualBox
- How To Bypass Torrent Connection Blocking By Your ISP
- How To Install Actual Facebook App On Kindle Fire
9/9/2012 9:42:26 PM

You just read about vertex buffer objects. Each vertex attribute has an offset within a buffer and a set of other state such as data type and stride. Each one also has an associated buffer, which can be different for each attribute. Calling glVertexAttribPointer sets all of this state, including the buffer binding for the attribute. If you have a fairly complex scene with several objects in it and each object keeps its vertex data in its own VBO, then that is a reasonable amount of state per object. If the application is well-written, drawing one of these object may end up as simple as a single call to a function like glDrawElements or glDrawArrays.

Even if the layout of data is the same between objects (it probably will be for many applications) and the offsets of the data are the same (maybe all data starts at offset zero, for example), it is still necessary to call glVertexAttribPointer for every vertex attribute. For an object that has, say, eight vertex attributes, this means at least one call to glBindBuffer (possibly up to eight if all the vertex attributes are in separate buffer objects), and eight calls to glVertexAttribPointer. If you’re using indexed vertices, you also need to bind your GL_ELEMENT_ARRAY_BUFFER. All this to prepare for a single call to glDrawElements. This is a lot of state to set, a lot of error checking that the driver has to do, and a lot of information that the application has to look after.

To help organize all this information, OpenGL provides an object called a vertex array object (VAO). A VAO is a container that packages together all of the state that can be set by glVertexAttribPointer and a few other functions. When using a VAO, all state specified through a call to glVertexAttribPointer is stored in the current VAO. There is no default VAO in OpenGL. This means that before you can even specify your vertex pointers, you need to create and bind a VAO. For simple applications, it may be sufficient to create a single VAO, bind it, and leave it bound for the lifetime of the application (as we did when we introduced VBOs earlier). However, an application can create as many VAOs as it needs and use them to manage all of the array state. When it’s time to draw using a particular set of vertex attributes, simply bind the VAO containing that set of state and start drawing. This allows each object in a scene to manage its own vertex buffers by creating a VAO to maintain its state and binding it before drawing. That way, the object won’t upset the vertex array state of any other object in the scene.

To create one or more VAOs, call

void glGenVertexArrays(GLsizei n, GLuint *arrays);

Like most other OpenGL objects, VAOs are referred to by name represented as unsigned integers. The glGenVertexArrays function creates n vertex arrays and places their names in the array arrays. If glGenVertexArrays fails to allocate a VAO for some reason, it returns zero for its name. A well-written application should always check for this condition before trying to use the result. Like buffer objects, the VAO name zero is reserved by OpenGL to mean “no VAO.” Again, when no VAO is bound, glVertexAttribPointer will not work and will generate an error if you call it. To delete VAOs, call

void glDeleteVertexArrays(GLsizei n, GLuint *arrays);

This function deletes the n VAOs whose names are in arrays. It is important for your application to clean up after itself. If arrays has an element containing the name zero, that will be ignored. This means that you can safely pass an array previously written to by glGenVertexArrays to glDeleteVertexArrays without worrying whether some of the names might be zero (due to an error during the execution of glGenVertexArrays, for example). To start using a VAO, call

void glBindVertexArray(GLuint array);

This makes array the current VAO. When a new VAO is bound for the first time, it contains all of the default state that would be present in a freshly created context. From now on, any time you call a function that accesses the vertex array state, it will access the state contained in the currently bound VAO. This includes functions that set state, such as glVertexAttribPointer; functions that implicitly use that state, such as glDrawArrays or glDrawElements; and functions that explicitly read vertex array state, such as glGetIntegerv.

Now that we have a VAO, we can set as much state on it as we like. We can call glVertexAttribPointer as many times as we need and the state will be stored in the VAO. If we call glBindBuffer followed by glVertexAttribPointer, the buffer binding will also be stored in the VAO. Note, though, that while the buffer binding associated with the vertex attribute is stored in the VAO, binding a new VAO does not change the current buffer bindings. That is, the actual state of the currently bound buffers is not stored in the VAO. To return to the example at the start of this section—the object with many vertex attributes, each with different state and buffer bindings—we can improve the performance of this greatly using VAOs.

Instead of calling glBindBuffer and glVertexAttribPointer many times right before drawing the object, we can do it at initialization time. When it is created, the object can generate a VAO, bind it using glBindVertexArray, and set all of its vertex array state as if it were about to render itself. After initialization, return OpenGL to having no VAO bound by calling


Now, when the object is about to be rendered, call glBindVertexArray again with the object’s VAO, and then call the rendering functions such as glDrawArrays. Thus, rendering a complete object that has many vertex attributes, all stored in a collection of VBOs with different parameters, can be as simple as two function calls—glBindVertexArray and glDrawElements, for example. This is also beneficial for layered libraries, scene graph managers, and middleware that might want to render without disturbing the current OpenGL state. If the normal behavior of the environment is to have no VAO bound, then each object binds its own VAO, renders itself, and then binds VAO zero, resetting everything.

Top 10
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
Video Sports
- The Banner Saga 2 [PS4/XOne/PC] PC Launch Trailer
- Welkin Road [PC] Early Access Trailer
- 7th Dragon III Code: VFD [3DS] Character Creation Trailer
- Human: Fall Flat [PS4/XOne/PC] Coming Soon Trailer
- Battlefleet Gothic: Armada [PC] Eldar Trailer
- Neon Chrome [PS4/XOne/PC] PC Release Date Trailer
- Rocketbirds 2: Evolution [Vita/PS4] Launch Trailer
- Battleborn [PS4/XOne/PC] 12 Min Gameplay Trailer
- 7 Days to Die [PS4/XOne/PC] Console Trailer
- Total War: Warhammer [PC] The Empire vs Chaos Warriors Gameplay Trailer
- Umbrella Corps [PS4/PC] Mercenary Customization Trailer
- Niten [PC] Debut Trailer
- Stellaris [PC] Aiming for the Stars - Dev. Diary Trailer #1
- LawBreakers [PC] Dev Diary #4: Concept Art Evolutions
programming4us programming4us