Your first statement:
As far as I understand VAO's are just encapsulating the state of VBO's.
is mostly correct, in that VBOs are the most stored type of buffer in an VAO, but any type of buffer associated with vertex processing (i.e., element arrays, indirect draw buffers, etc. depending upon which ones are supported by your version of OpenGL) are also contained within a VAO.
The reason for adding VAOs to the API was to reduce the number of functions calls required to swap data for different objects. In applications with multiple objects that require different sets of vertex attributes, before VAOs, you'd need to call glBindBuffer
for each VBO (including element array buffers) that were required to render that object (the association of a vertex attribute location and a buffer is a property of that buffer, and not of a VAO, in case you ever had that question). VAOs allow all of those bindings to be encapsulated into a single object which can be bound with a single call to glBindVertexArray
, as you mention.
You're also on the right track in swapping between VAOs. In your application's initialization (or whenever you need to add more objects), you'd create and initialize as many VAOs as required, and for each one, bind it, and populate it with all its relevant buffers. When you wanted to use one, you'd merely bind it. It's also worth noting that you can always update the data in a VBO using glBufferData
or similar calls, and that operation will have no effects on the binding contained with the VAO associated with that buffer.