I think I understand how to use Vertex Array Objects (VAOs) and how data is stored and how the pointers in OpenGL work but there are a few things I'm things I'm fuzzy on. I was hoping someone could confirm my understanding and correct anything that's wrong.
I managed to find this and this article which is where I got most of my information from but was still a bit uncertain about how long the Vertex Buffer Object (VBO) needs to be bound to the Array Buffer binding point and when VAOs need to be bound and rebound. I also have never used old OpenGL so a lot of the references in the second link made little sense to me. This is how I understand things at the moment:
The first step is to put the data in a VBO:
glGenBuffers
glBindBuffer(GL_ARRAY_BUFFER, ...)
glBufferData(GL_ARRAY_BUFFER, 100, pointer-to-data, ...)
This sends 100 bytes of data into the VBO that's bound starting with the data at the address pointed to by the pointer. Then to specify what data needs to be sent to which inputs in the shader when rendering happens we use:
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 3, GL_FLOAT, ..., 6, (void*)5)
This starts at 5 bytes in from the start of the data in the VBO, takes 3 floats as the vertex values and then steps 6 bytes to get to the next piece of data*. I take it if you have a VAO bound then the VAO stores the information about how to access the data to be sent to attribute 0, and the data is stored somewhere in the graphics memory.
As far as I can tell once glVertexAttribPointer has been called you can then bind a new VBO and enable and set the vertex attribute pointer for other attributes, attribute 1, 2 etc.
(This is the part I am the most uncertain about) However if you want to render a second model calling glVertexAttribPointer for attribute 1 will override the current settings. In order to draw the second model you either need to:
- Draw the first model and then set the attribute pointer, OR
- Store the attribute calls in a VAO by binding it before making the calls, and then re-binding the appropriate VAO before each draw call.
I understand the the second option is preferable, and that the first is sort of like binding everything to the default VAO and changing the attribute pointers all the time.
Is this more or less correct?
*EDIT :
From derhass's comment, in glVertexAttribPointer( , size, type, , stride, ) if stride = 0 then the ith element will be at position offset + i * size * sizeof(type)
but if stride is anything else then the ith element is at offset + i * stride
?