Does/can the VAO store an id for an EBO and why?

The reason I ask this question is because I notice in the code from my tutorial that when setting up a mesh I have to Bind VAO, VBO and EBO, but when drawing I have to bind both VAO and EBO first. I realize that one VBO could have the need to be used with more than one EBO and that is why I am guessing the EBO needs to be bound again so as to specify, but if I am correct on that then I am unclear on if it matters or not whether a VAO and VBO are bound when an EBO is set up.

Thanks

What tutorial is that?

In any case, the element buffer binding point is part of the VAO’s state. This is more clear when using the direct state access API, as glVertexArrayElementBuffer is the function you use to attach a buffer to the VAO’s element buffer binding point.

It is actually a Udemy course called “Computer Graphics with Modern OpenGL and C++” by Ben Cook but it is 4 years old and version is 330. It is a great course in some ways as he knows a lot. And the parts that are not great are also a great learning experience as well. I am actually going back and forth between it, Cherno’s YT stuff, Victor Gordon’s YT stuff and learnopengl.com. Everyone is doing basically the same things just in slightly different ways and not in the same order. This course went over a basic camera and basic transformations and is just now going to do textures for example. But I keep wanting to go over the basics a lot before going on as there are many moving parts for me to be acquainted with.
glVertexArrayElementBuffer looks like it is only available starting at OpenGL 4.5? So does that mean that an EBO could not be part of the VAO’s state at the OpenGL 3.3 stage like this stuff I am doing?

Update, as I have been looking into this and it looks like I should not have to bind EBO again before drawing even in OpenGL 3.3. So I will try and debug my code later and see what the issue is. Will update here then.

No. The GL_ELEMENT_ARRAY_BUFFER binding is stored in a VAO in all versions which have VAOs (3.0 and later).

The Direct State Access (DSA) API was added in 4.5. That allows operations which manipulate VAOs to manipulate a specific VAO rather than the currently-bound VAO. It doesn’t change what data is stored in VAOs, it just provides an alternative mechanism for manipulating them.

All other buffer bindings are context state.

If you’re having to re-bind the EBO before drawing, that implies that it’s being unbound elsewhere. The most likely reason is having setup code which does:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, ...);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

When issuing commands which operate upon “object bound to target”, it’s typical to unbind the object once the call has been issued. Prior to 3.0, this would be logical for the EBO as the binding was context state like the other buffer bindings. With VAOs, the binding is stored in the VAO and shouldn’t normally be unbound.

Also, since 3.0 you have to consider which VAO is bound when binding a buffer to GL_ELEMENT_ARRAY_BUFFER. If you just want to update the buffer contents and don’t want to use the DSA API (glNamedBufferData etc), note that the choice of binding point doesn’t matter. You could bind to GL_COPY_READ_BUFFER or GL_COPY_WRITE_BUFFER, which have no specific purpose other than to provide targets to which buffers can be bound without affecting any of the binding points which do have a specific purpose.

Thank you so much! You just saved me a lot of debugging time. I seriously just now sat down to start trying to figure this out. This here like you said is exactly what was in my code.

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, ...);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

In fact the last 3 lines of the createMesh() method they give is this:

    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); 
    glBindBuffer( GL_ARRAY_BUFFER, 0 );
    glBindVertexArray( 0 );

Based on your response, I have now changed it to just the bottom line. This is adding to the things I have had to change in this course. They were adding new where it wasn’t necessary in one place and in another place they were not distinguishing direction and front in the camera code. I only figured that out because I was comparing different tutorials and saw the difference.

In other ways though the course is pretty good though so I still like using it along other materials. Again thank you very much.

Unbinding GL_ARRAY_BUFFER is reasonable, as that binding only affects glVertexAttribPointer (and similar); it doesn’t directly affect draw calls. If you have more than one VBO, you have to bind the correct VBO before each glVertexAttribPointer call so there’s not much to be gained by leaving a specific VBO bound.

Thank you very much. You have all been very helpful. Expect me to continue bugging you all in the future. After I have done an exhaustive search of already answered questions of course ;-).