My code is working as it should but it might be a coincidence and I don't want to dwell on a bug later so I'm trying to keep it as clean as possible:
I do the following for initializing a mesh:
From my understanding, the VAO will store the state of the vertex attribute arrays that I enabled. It will also store both the VBO and the IBO that I bound. Since I "closed" all actions on the VAO by binding the Vertex Array back to 0, I make sure no other code is going to mess my VAO. So if this is all right, all I need to render is:
And this should bring both the AttribArray states as well as the VBO and IBO stored. My questions are:
A. Do I need to bind the IBO after I set the VertexAttribPointers? If so, why?
B. Does the VAO really store both the VBO and the IBO? I've heard it only stores the last buffer that was bound, meaning I have to render like this:
But this makes no sense, why use VAOs when they don't store both buffer objects? Wouldn't it be just the same as binding VBO and IBO and then drawing elements without ever binding the VAO?
Thank you in advance for helping.
Code is as follows:
Initialisation
// generate VBO
glGenBuffers(1, &m_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, m_vertices.size()*sizeof(GLfloat), m_vertices.data(), GL_STATIC_DRAW);
// generate IBO
glGenBuffers(1, &m_ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indices.size()*sizeof(unsigned short), m_indices.data(), GL_STATIC_DRAW);
// generate VAO
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
// set the vertex attribute pointer
glEnableVertexAttribArray(0);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,vertexSize,reinterpret_cast<const GLvoid*>(0));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo);
glBindVertexArray(0);
Drawing
glBindVertexArray(m_vao);
glDrawElements(GL_TRIANGLES,size,GL_UNSIGNED_SHORT,reinterpret_cast<const GLvoid*>(0));
glBindVertexArray(0);
Also, isn't it cleaner if I put it like this:
Seems cleaner, but I don't know if the result is the same, specially for the lack of a IBO binding between steps 4 and 5.
Binding to a VAO then also automatically binds that EBO. A VAO stores the glBindBuffer calls when the target is GL_ELEMENT_ARRAY_BUFFER . This also means it stores its unbind calls so make sure you don't unbind the element array buffer before unbinding your VAO, otherwise it doesn't have an EBO configured.
A Vertex Array Object (VAO) is an OpenGL Object that stores all of the state needed to supply vertex data (with one minor exception noted below). It stores the format of the vertex data as well as the Buffer Objects (see below) providing the vertex data arrays.
Addressing your questions:
A. Do I need to bind the IBO after I set the VertexAttribPointers? If so, why?
No. You could bind the element array (IBO in your terminology) first, and do the vertex attributes later, but generally speaking, they're separate bindings within the VAO. For example, you could bind your IBO as well as several VBOs, and render with either glDrawElements
(and variants) using the data in the IBO, or using glDrawArrays
(and variants) using only the sequential vertex data in your VBOs - the rendering command determines if the IBO is used or not.
B. Does the VAO really store both the VBO and the IBO?
Yes. A VAO can store the binding information for a single IBO, and at least 16 VBOs.
I've heard it only stores the last buffer that was bound, meaning I have to render like this:
Bind VAO
Bind VBO
Draw Elements
Unbind VAO
As you surmised in your original post, this statement is incorrect, and the binding of the VBO you include is unnecessary. A VAO can store up the implementation-dependent maximum (which is at least 16) number of VBOs, each of which can be bound to a vertex attribute.
Also, isn't it cleaner if I put it like this:
- Gen and bind VAO
- Gen and bind IBO and BufferData
- Gen and bind VBO and BufferData
- EnableVertexAttribArrays that I need and set VertexAttribPointers
- Unbind VAO (binding to 0)
Yes. As you point out, that allows you to bind, render, and clean-up in only three commands.
Really, that's the entire point of VAOs, to collect all those binding and vertex attribute associations so you can do all the plumbing once, and then fire-and-forget later.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With