
How do VAOs introduce an improvement to VBOs?
Posted Wednesday, 10 March, 2010 - 09:54 by pontifikas inI've been trying to figure out VAOs.
From what I read, VAOs store an array of vertex attributes.
What is not clear is how is this done and how is it beneficial?
I will write what I think is happening according to what I've read and please correct me if I'm wrong so I can develop full understanding on this matter.
1)Create the VAO
2)Bind it to make it current
3)Point to some attributes known to reside in the shader, and set some values to them using VertexAttribPointer()
!!--> The moment you do that, the VAO is updated as far as these attributes are concerned.
4) In the function were you do your drawing, berfore binding your VBOs first bind the VAO to make it current and activate
the values of the vertex attributes it contains.
5)Draw your scene using your VBOs.
BENEFIT: You only have to assign values to attributes once. At each drawing the program will refer to the VAO for the values of the attributes.
Thank you in advance.


Comments
Re: How do VAOs introduce an improvement to VBOs?
That's how I understand it, too:
Without VAOs you have to re-issue VertexAttribPointer calls every time you bind a VBO with a different layout. With VAOs, you encapsulate the layout information in a VAO object (at load time) and you simply bind the correct VBO, VAO and render.
It's cleaner and potentially faster.
Re: How do VAOs introduce an improvement to VBOs?
iirc you don't need to bind vbo if you use vao
Re: How do VAOs introduce an improvement to VBOs?
There was large discussion over at opengl.org on how VAOs actually work. The extension spec is somewhat fuzzy on the details, but the 3.2 PDF spec cleans things up: according to table 6.6 (pg 271), the VBO is not part of the VAO state, while the EBO
is(table 6.5).For clarity's sake, by VBO I refer to the current ARRAY_BUFFER_BINDING, while by EBO to the current ELEMENT_ARRAY_BUFFER_BINDING (called
ArrayBufferBindingandElementArrayBufferBindingin OpenTK).Re: How do VAOs introduce an improvement to VBOs?
Thank you for the forum link Fiddler. It was very enlightening.
So to sum it up and make the corrections should anyone else bump on this thread searching for info:
1)Create the VAO
2)Bind it to make it current
3) Create some VBO(vertex buffer object)
4) Bind that VBO to make it current
5) Put data into that VBO using BufferData function
6) Point to some attributes known to reside in the shader, and set some values to them using VertexAttribPointer(). This binds the VBO
with some attribute index(0-15). The moment you do that, the VAO is updated, as far as these attributes are concerned.
7) In the function were you do your drawing, Bind the VAO (to make sure it is current, though it may already be).
8)Draw your scene using your DrawElements functions.
I have two last questions though. I OpenTK we have an overload of VertexAttribPointer() that takes as last argument an int (offset).
Unfortunately no documentation is yet provided. How does it work?
Also, is binding vertex buffer object before calling VertexAttribPointer() with IntPtr.Zero as last argument like telling VertexAttribPointer "Associate an attribute index with the data of the currently bound VBO"?
While specifying some array as last argument is like telling VertexAttribPointer "Regardless of the currently bound(current-active) VBO associate the attribute index with THAT set of data"
Re: How do VAOs introduce an improvement to VBOs?
The int overload for VertexAttribPointer is there for convenience. Internally, it simply calls
VertexAttribPointer(..., new IntPtr(offset)). (Historical note: older versions of OpenTK usedobjectparameters instead of generics, which meant you could pass a plaininteven if such an overload did not exist: OpenTK would 'helpfully' take its address and pass that to OpenGL, resulting in crash later on. This bug was common enough that explicitintoverloads were added as a workaround).Filed a bug on the missing documentation as #1623: Convenience overloads are not documented
VertexAttribPointer works differently depending on whether GL.GetInteger(GetPName.ArrayBufferBinding) is zero or not:
I'd suggest avoiding legacy VAs and the array-based overloads completely. They have no place in modern OpenGL apps and don't get along well with the .Net GC.
Re: How do VAOs introduce an improvement to VBOs?
...according to table 6.6 (pg 271), the VBO is not part of the VAO state, while the EBO
is(table 6.5).I want to comment on this, it is right that "VBO binding" is not the part of VAO state, but how I had understood the VAO is parallel to the nvidia (I have a radeon too but did not test this yet) drivers (I have dx10 capable quadro and mobile) such that when VAO is bound your AttribPointer calls are recorded in a way that you dont need to bind VBOs again. In state tables, it is declared that AttribPointer is held but type is undefined. It is the case that (I have tested this by binding zero buffer to ARRAY_BUFFER before VAO, so it is only emprical not relevant to specs) when I bind VAO I don't need to bind VBO again. So, this gives me the option to hold different attributes on different buffers but I don't need to bind them again and again. One of the posts on the thread on the forum you pointed gives such usage scenario:
//initiate vbo, vao etc. bind textures bind vao make draw calls bind textures bind vao make draw calls ...Note: before this post I did not know that EBO is part of VAO, it seems good to have that, but it could be of more use if we could store EAO with draw calls similar to IndirectCall mechanism introduced in OpenGL 3.3
Re: How do VAOs introduce an improvement to VBOs?
This is what I also made out from this thread. It is the call to VertexAttribPointer that binds the VBO to the VAO at a specific index. From that point on, VAO knows from which VBO to fetch data for each vertex attribute index. That is why in my second list of actions I dont include binding the VBO at the drawing function.
Re: How do VAOs introduce an improvement to VBOs?
Note: before this post I did not know that EBO is part of VAO, it seems good to have that, but it could be of more use if we could store EAO with draw calls similar to IndirectCall mechanism introduced in OpenGL 3.3
When you say that EBO is part of VAO you mean that, in order for the VAO to Draw the EBO must be Created, Bound and Populated after the target VAO is made current? I'm referring to creation in particular.
Re: How do VAOs introduce an improvement to VBOs?
As I understand it, it means the last EBO you bind is "latched" into the VAO state. Next time you bind that VAO, it should automatically bind that EBO, too.
Creation itself shouldn't play a role, only the last call to
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ...)for any given VAO.(Haven't tried this myself, though).
Re: How do VAOs introduce an improvement to VBOs?
True, according to http://www.opengl.org/wiki/Vertex_Array_Objects
"Let us say that you are issuing a glDrawElements command while a particular VAO is bound. In our pseudo-code, let us say that the VAO binding is called pVAO. Here is what will happen, relative to our pseudo-code definition.
The pVAO->pElementArrayBufferObject is the buffer object from which vertex indices will be pulled. If this is NULL (ie: bound to zero), an error is raised: you can use glDrawArrays, but not glDrawElements without an element buffer. "
"The VertexArrayObject::pElementArrayBufferObject is controlled by the binding of GL_ELEMENT_ARRAY_BUFFER. Calling void glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferObj) will set this field of the VAO"
"Changing the GL_ARRAY_BUFFER binding does not affect VAO state. This is different from the GL_ELEMENT_ARRAY_BUFFER binding, which is directly part of VAO state. It is only when calling one of these two functions that the GL_ARRAY_BUFFER binding matters to the VAO. "
So, glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferObj) changes incapsulated in binded VAO EBO state to current GL_ELEMENT_ARRAY_BUFFER, VertexAttribPointer is the only function that changes VAO's VBO state to current GL_ARRAY_BUFFER.