PDA

View Full Version : glVertexAttribPointer



redphi
05-06-2012, 01:46 AM
According to the specification: http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttribPointer.xml
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.

thokra
05-06-2012, 03:15 AM
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.

Questions?

V-man
05-06-2012, 05:00 AM
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?

thokra
05-06-2012, 05:23 AM
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".

redphi
05-06-2012, 02:56 PM
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.

V-man
05-06-2012, 05:05 PM
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.
http://www.opengl.org/wiki/Tutorial1:_Rendering_shapes_with_glDrawRangeElemen ts,_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.

redphi
05-06-2012, 06:59 PM
OK will do. VAO's are more convenient anyway. What's an IBO? Edit: "Index Buffer Object", got it

thokra
05-07-2012, 03:08 AM
If that is the case, how is it possible to call glVertexAttribPointer is nothing is bound to GL_ARRAY_BUFFER?

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.

redphi
05-07-2012, 01:34 PM
try to not use one VAO for one object if your object count is high

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.)

thokra
05-07-2012, 01:42 PM
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 http://www.opengl.org/sdk/docs/man3/xhtml/glDrawElementsBaseVertex.xml or http://www.opengl.org/sdk/docs/man3/xhtml/glMultiDrawElementsBaseVertex.xml 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?

redphi
05-07-2012, 04:43 PM
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:
http://www.arcsynthesis.org/gltut/Positioning/Tut05%20Optimization%20Base%20Vertex.html
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.