Since OpenGL 4.3 most of the VAO states can be set using direct state access. Have a look at the following functions:
void glVertexArrayAttribBinding (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
void glVertexArrayVertexBuffer (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
void glVertexArrayBindingDivisor (GLuint vaobj, GLuint bindingindex, GLuint divisor);
void glEnableVertexArrayAttrib (GLuint vaobj, GLuint attribindex);
void glDisableVertexArrayAttrib (GLuint vaobj, GLuint attribindex);
void glVertexArrayAttribFormat (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
void glVertexArrayAttribIFormat (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
void glVertexArrayAttribLFormat (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
You can find some examples on how to use them in this thread.
In principle "old" VAO code can be translated 1-1 to DSA code. Assume we have an example like this
glBindVertexArray(vao);
glEnableVertexAttribArray(att_idx); //att_idx comes from shader
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(att_idx, 4, GL_FLOAT, GL_FALSE, sizeof(vec4), 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
then this could look in DSA code as follows
//glBindVertexArray(vao);
//No translation needed, since we don't want to bind :)
//glEnableVertexAttribArray(att_idx);
glEnableVertexArrayAttrib(vao, att_idx);
That was the easy part.
//glBindBuffer(GL_ARRAY_BUFFER, vbo);
//glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glVertexArrayVertexBuffer(vao, 0, vbo, 0, sizeof(vec4));
Specifies the binding-point <-> buffer correspondance. Here the second parameter is a binding point. You can choose here basically what you want as long as it is < GL_MAX_VERTEX_ATTRIB_BINDINGS. But I normally recommend to use the same index that the attribute has. Parameter 3 and 4 (Stride, Offset) are the same values as in glVertexAttribPointer
. Note, that glVertexArrayVertexBuffer
does, in contrast to glVertexAttribPointer
, not allow a stride of 0 to indicate tightly packed data. Even when the data is tightly packed, the stride has to be specified in bytes.
glVertexArrayAttribFormat(vao, att_idx, 4, GL_FLOAT, GL_FALSE, 0);
This defines the format of an attribute. Values 3-5 are similar to their correspondances in glVertexAttribPointer
. The last parameter is the relativeoffset between elements in the buffer.
glVertexArrayAttribBinding(vao, att_idx, 0);
This line creates a correspondence between the attribute index and the binding point used in glVertexArrayVertexBuffer
.
The last thing missing is the index buffer:
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glVertexArrayElementBuffer(vao, ibo);
Now the vao should be in the same state as it was with the old code.