According to the specification:
You can call this function when nothing is bound to GL_ARRAY_BUFFER, as long as your “pointer” or offset parameter is NULL. What does this do then? I thought whenever you called glVertexAttribPointer, whether you are using them in conjunction with a Vertex Array Object or not, there needs to be a vertex buffer object bound to GL_ARRAY_BUFFER, so that this generic vertex attribute “belongs” to a certain VBO.

First, you’re mixing up the concepts of a VAO and a VBO. A VBO is merely a data store for some arbitrary vertex data. The VAO is used to not only store data, but to associate data and state. Therefore, when a vertex array object is currently bound and you call glVertexAttribPointer() the state you set with the call, if it is valid, will be stored as the specific state for the active VAO. This is NOT the case if you bind only a VBO. ATM I’m not quite sure if this also applies to the enabled/disabled state of generic vertex arrays (glEnabelVertexAttribArray() etc.).

Second, the spec says that a non-zero VBO needs to be bound to GL_ARRAY_BUFFER if pointer is not NULL. Think about it. Since pointer is interpreted as a byte offset into a specific memory range, e.g. the space allocated for a specific buffer object, it would be rather undefined what such a pointer would mean if no buffer was bound. On the other hand, you can safely assume that an offset of NULL will have the attrib pointer point to the first element in the buffer. If you maintain different buffer objects for vertices, normals, tex coords and so on, this is not a problem. If, however, you want a single buffer with packed or interleaved data, you’ll need a valid offset and possibly a stride to point to the correct sequence of elements in the buffer’s memory.


If pointer is not NULL, a non-zero named buffer object must be bound to the
GL_ARRAY_BUFFER target (see glBindBuffer),
otherwise an error is generated

According to them, if pointer is not NULL, you need to have a VBO bound?
It seems to be suggesting that you can’t source a RAM location.
In GL 3 core, you can’t use a RAM location?

You can, but as I said before: What’s the use of accessing some arbitrary location via a byte offset, if you have no idea if the corresponding address will be in the allocated space of the buffer object? It would be typical “undefined behavior”.

Thanks for the responses, I really appreciate it.

I don’t think I’m mixing up VAO’s and VBO’s, but I may have not been clear in my original post. Here is what I mean. Let’s say you have interleaved data in a VBO. You create a VAO, bind it, then calls to glVertexAttribPointer will both specify the format of the data (how many attributes, the type/size/number/stride/offset/etc. of each attribute), but also where that specific data is, the VBO currently bound to GL_ARRAY_BUFFER. You may unbind the VAO at this point.

Now, when you want to render the model contained in that VBO, you bind the VAO to get the correct attributes, and do your draw call (glDrawArrays or whatever), then you can unbind the VAO or just go ahead and bind a new VAO to render a different model. No need to bind any VBOs at this point, because the correct VBO is stored as part of the VAO. This is what I mean by VAO’s “belonging” to a certain VBO (edit: or set of VBO’s, if you use separate VBO’s for different attributes).

So, that means, I can’t do something like use one VAO to render many VBO’s with similar attribute properties, right? Because each VAO is only associated with one (or one set) of VBO’s.

With that said, I’m guessing using glVertexAttribPointer without VAO’s is similar. Each vertex attribute “belongs” to a certain VBO. If that is the case, how is it possible to call glVertexAttribPointer is nothing is bound to GL_ARRAY_BUFFER?

Sorry if I’m fundamentally misunderstanding something.

Yes, a VAO object tracks the pointers and also the VBO and IBO bound.
You just bind the VAO and call glDraw_whatever.
That’s what I demonstrated in this tutorial.,_VAO,VBO,shaders%28C%2B%2B/_freeGLUT%29

The case of VBO only, the states should be tracked as well.

However, it sounds like you are coding for GL 3 and above, so you should always use VAO.
Starting with GL 3.2 core, you no longer have a choice. You must use VAOs.

OK will do. VAO’s are more convenient anyway. What’s an IBO? Edit: “Index Buffer Object”, got it

Because in that case the state of the attrib pointer is simply used for every subsequently bound VBO. The obvious drawback is that every buffer needs to be layed out to exactly match the pointer attributes. At least that’s the way I understand this whole thing. To get around that, do what V-Man suggested (and is sound advice since VAO can significantly reduce API calls). However, be careful not to bind your VAOs to often and try to not use one VAO for one object if your object count is high (meaning more than a hundred or so) since VAO changes are supposedly expensive - at least time measurements if done using NVIDIA’s Parallel Nsight suggest that.

Since a VAO tracks the pointers of certain, specific VBO’s and IBO’s as V-man said, how do you render two VBO’s with one VAO? Or are you saying use the same VBO/VAO for multiple copies of the same object (though with possibly different positions, orientations, etc.)

You don’t. You still have one VBO, one VAO and one IBO. The difference is that the buffers store information of multiple objects. Then you can use or to render multiple objects with very few API calls. During all this you bind the VAO only a single time as long as you render objects from that buffer. One thing to be aware of is that you should only accumulate objects for a single draw call if they share the same shader which will further reduce API calls.

Be aware however: This adds complexity to your code and it’s usually not worth it when you object count is low enough. If you get to a few hundred or thousand it will most likely be worth the trouble. It can dramatically reduce API calls if done right. What’s the worst case scenario you need to be able to handle?

I’m just learning OpenGL for fun, don’t have any specific project in mind. But thank you very much, thokra. I remember reading about BaseVertex here:
It kind of went over my head and I did not really see the point of it, but I do now. It makes a ton of sense now.