0

I am currently learning OpenGL and VAO's are confusing me. As far as I understand VAO's are just encapsulating the state of VBO's.

Bind VAO
load buffer data
Disable VAO

and then you can draw it like

activate VAO
DrawArray ...
deactivate VAO

But I am not sure if this is really useful in practice. Let's say I have a really huge scene that I want to render. Maybe 10km² and I obviously don't want to load every object to the GPU at one time, I probably want to separate the scene into different chunks.

Now I am moving around and at one point I have to load another chunk of objects to the GPU right? But as far as I know I can't change a VAO and I would have to create a new VAO every time something changes in my scene.

So what in my scene would be a VAO? Would the entire scene be a VAO? Or would every object be a VAO?

And for me to have multiple VAO's doesn't make too much sense because I can't compose the VAO's together I can only draw them on top of each other like this

activate VAO1
DrawArray ...
deactivate VAO1

activate VAO2
DrawArray ...
deactivate VAO2
Maik Klein
  • 15,548
  • 27
  • 101
  • 197

2 Answers2

3

You cannot enable or disable a VAO, they are a class of objects in OpenGL known as containers (same as FBOs). They provide the context for vertex array drawing operations and the state necessary to describe them. You most certainly can change a VAO, they are just state containers... bind it and then change one of the states it stores. Whether you use one VAO for your entire scene or multiple is up to you, but keep in mind in a core OpenGL 3.2 context, you cannot issue any vertex drawing commands without at least some VAO bound.

Also, VAOs have nothing to do with currently bound buffer objects per-se, except for the element array buffer. VAOs store vertex array pointers, which may be directly or indirectly (see: GL_ARB_vertex_attrib_binding) bound to a VBO, but the VAO does not care at all about what VBO is currently bound to GL_ARRAY_BUFFER. It is different for the element array buffer as I mentioned, VAOs do track the currently bound element array buffer so that a call to glDrawElements (...) will have consistent behavior merely by binding a VAO. Without this property, you would have to bind a VAO and then also bind an element array buffer before you could issue an indexed drawing operation.

Andon M. Coleman
  • 42,359
  • 2
  • 81
  • 106
  • 1
    Sorry, but you have a few errors in your response. VAOs became mandatory in OpenGL 3.1 core profiles. Also, VAOs store the bindings to any type of buffer object needed for vertex processing, and don't do anything special for element-array buffers like you suggest. Assuming the VAO contains all the VBOs, an EBO (only one element-array buffer can be bound at a time, while at least 16 VBOs can be active at one time), binding the VAO will bind all its attached buffers. Sorry for correcting you, Andon, normally your answers are spot on. – radical7 Jan 03 '14 at 18:29
  • 2
    @radical7: There is no such thing as a 3.1 core profile, core/compatibility was introduced in GL 3.2. Also, VAOs do not store vertex buffer bindings; they store pointers (which may be relative to a VBO). They **do**, however, remember what element buffer is bound. You can only ever have one type of a buffer object bound at any given time and this is precisely why VAOs do not track VBO bindings, the only time the VBO binding matters is immediately before `glVertexAttribPointer (...)` and friends are called (again, because the pointer's address space is defined by the bound VBO **at that time**) – Andon M. Coleman Jan 03 '14 at 23:40
  • 1
    @radical7: I believe some of your confusion around VBO bindings has to do with the behavior of `glVertexAttribPointer (...)`. Typically when binding an object in OpenGL is necessary in order to make an API call it is because that API call will setup some state within the object you just bound. VBOs turn this paradigm on its head, in that the only reason you have to bind a VBO before calling `glVertexAttribPointer (...)` is because the **offset** you pass is relative to the bound VBO. This whole confusion really stems from reusing the old client memory vertex pointer system. – Andon M. Coleman Jan 04 '14 at 00:33
0

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.

radical7
  • 8,957
  • 3
  • 24
  • 33
  • I would suggest you have a look at [this](http://www.opengl.org/wiki/Vertex_Specification#Index_buffers) part of the OpenGL wiki. If you do not want to dig through the official OpenGL specification to see why VAOs do not store VBO bindings but do store element array buffer bindings (IBOs as they are sometimes called). I would highly recommend you look at the official specification, however, as the language in that part of the Wiki is terribly unprofessional (e.g. *"I know that's confusing, but that's the way it is."*). The information in the Wiki is accurate, just presented poorly. – Andon M. Coleman Jan 03 '14 at 23:57