Is that a correct usage of VAOs?
No1.
glVertexAttribPointer
uses the buffer object that was bound to GL_ARRAY_BUFFER
at the moment the function was called. So you can't do this:
glVertexAttribPointer(...);
glBindBuffer(GL_ARRAY_BUFFER, bufferObject);
glDrawArrays(...);
This will not use bufferObject
; it will use whatever was bound to GL_ARRAY_BUFFER
when glVertexAttribPointer
was originally called.
VAOs capture this state. So the VAO will, for each vertex attribute, store whatever buffer object was bound to GL_ARRAY_BUFFER
when it was called. This allows you to do things like this:
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, buffer1);
glVertexAttribPointer(0, ...);
glVertexAttribPointer(1, ...);
glBindBuffer(GL_ARRAY_BUFFER, buffer2);
glVertexAttribPointer(2, ...);
Attributes 0 and 1 will come from buffer1
, and attribute 2 will come from buffer2
. VAO now captures all of that state. To render, you just do this:
glBindVertexArray(VAO);
glDraw*();
In short, if you want to change where an attribute's storage comes from in OpenGL, you must also change it's format. Even if it's the same format, you must call glVertexAttribPointer
again.
1: This discussion assumes you're not using the new ARB_vertex_attrib_binding. Or, as it is otherwise known, "Exactly how Direct3D does vertex attribute binding." If you happen to be using an implementation that offers this extension, you can effectively do what you're talking about, because the attribute format is not tied with the buffer object's storage. Also, the tortured logic of glVertexAttribPointer
is gone.
In general, the way we solve this in the OpenGL world is to put as many things as possible in the same buffer object. Failing that, just use one VAO for each object.