Some questions about VBOs and Vertex Arrays...

Started by
16 comments, last by ogracian 18 years, 10 months ago
Its probably just some internal optimisation in the driver as it knows about the vertex stream you'll be processing.
However, unless you are using something which properly mirrors a vertex format its not a great deal of use [grin]
Advertisement
Unfortunately glInterleavedArrays is not flexible enough for the stuff I do but then again performance gain would be negligible.
[Offtopic] Yay for 1800 rate points my buddy Phantom [/Offtopic]
Hello,

Thank you people for your help, and based on your post I noticed that in my code I am calling glVertexPointer() FIRST, which as you say is a bad thing (I
need to test moving it to last).

And about interleaved data, let me see if I got it, so I pack all my models data in a single VBO using a method like JavaCoolDude show me here.

Then to render, when I set my gl*Pointer functions instead of call it with the array pointer, I call it with the OFFSET in the VBO where my data lives, right?

Last but no last : ), so using this method, when I need to send a mesh to shaders with just Position + TexCoord0, use the same aproach just disabling the
color part using glDisableClientState(GL_COLOR_ARRAY) before I render my mesh:

So to close, the order to use it is as follows:

- Pack ALL my model vertex data in a single VBO (like JavaCoolDude show here)
- Bind the VBO, set all gl*Pointers using offset instead pointer, calling
glVertexPoiner last to avoid NVIDIA troubles. Ex:

   vertexSize = sizeof(float)*12;   glBindBufferARB( GL_ARRAY_BUFFER_ARB, myVBO );      glNormalPointer(GL_FLOAT, vertexSize, (float *)NULL + 3);   glTexCoordPointer(2, GL_FLOAT, vertexSize, (float *)NULL + 6);   glColorPointer(4, GL_FLOAT, vertexSize, (float *)NULL + 8);   glVertexPointer(3, GL_FLOAT, vertexSize, NULL);   


- Disable any vertex data that is not needed by shader, like color, using
glDisableClientState befor I render it.

- Render my mesh using glDrawRange elements.


Thanks in advace,
Oscar
Sounds like you've got it down pat! One thing that I want to mention, though: Most of the documents I've seen don't treat it as such, but under windows you need to register glDrawRangeElements as an extension (It actually comes through in my program as "glDrawRangeElementsEXT").

Also, just a quick blurb from the nVidia VBO whitepaper, to help explain the glVertexPointer thing:

Quote:Avoid Calling glVertexPointer() more than once per VBO
The glVertexPointer function does a lot of setup in VBO, so to avoid
redundancy.
The most efficient way to do is to bind the VBO buffer, setup various array pointers (glNormalPointer etc) and then call glVertexPointer(). glVertexPointer should be called one time for one VBO.
You might think the essentials of VBO management are done in glBindBufferARB(), but its the opposite. VBO systems wait for the next upcoming important function (like glVertexPointer).
The binding operation is cheap compared to the setup of various pointers.
This advice fits any other function working in the same manner as glVertexPointer().


Good luck, and let us know who it works out for ya!
// The user formerly known as Tojiro67445, formerly known as Toji [smile]
Cool!, I really appreciate all your help here, now just have to implement it : )

Ah! before I forget to ask it, this method looks preatty stright forward but for STATIC data, but what about DYNAMIC data, how can it be handle if all is
packed in same VBO?

For example, in my current code, some times I need to modify the color array
using a wave function, so the way I modify it is filling a temporal array (sctarch buffer) with the new color data, then I use the following code to
build a new VBO for the modified data:

 sglBindBufferARB(GL_ARRAY_BUFFER_ARB, newVBO); sglBufferDataARB(GL_ARRAY_BUFFER_ARB, numVerts * sizeof(byte) * 4, newColorArray, GL_STREAM_DRAW_ARB);


So as you can see this method dose not seems to work with the packed data
because I will need to rebuild the entire VBO again, maybe I could "Map" the buffer but I really not sure how to handle it.

Regards,
Oscar
You may want to look into mapping, yes, but I'm afraid I've never used it so I wont be of much help. It essentially gives you a short term pointer to the array for easy editing, but I doubt that will help with extracting the interleaved data.

I guess this is where functionality and speed begin to butt heads. As far as I can see the easiest way to keep things interleaved would be to keep the original data handy, rebuild the interleaved array, and upload it to the card every frame. Not pretty >_<

What may be a better, if ever so slightly slower option would be to interleave the static data (vertex, normal, etc) and then place any data that you need to update frequently into a straight array appended at the end of the buffer (use the SubBufferData function. It's slower than a basic BufferData, but I think it would be faster than a constant rebuilding of the entire buffer). So in memory your buffer now looks like this:

|------Vertex/Normal/Texture--------|--Color Data--|

Memory pointers still work the same, just with a different offset and for the color data the stride would be 0. It's not going to be quite as fast as a fully interleaved buffer, but at least everything is still in VBO form.

If anyone has a better suggestion I'd love to hear it!

EDIT: @Ademan - Heh, I guess I should have been a little more clear about that. You definately would want to specify the buffer as dynamic whenever you're going to be changing any of the data in it with any regularity. How much that helps, though, is a simple matter of driver implementation. The drivers can completely ignore your usage hints if they want to. Still, thanks for pointing that out Ademan.

[Edited by - Toji on June 1, 2005 9:00:54 PM]
// The user formerly known as Tojiro67445, formerly known as Toji [smile]
Hrm, i like your idea there Toji, but unfortunately i dont think that would be practical, because if both are stored in the same vertex buffer, then you would be bound by the usage of the buffer, which would be sub-optimal for one of the vertex attributes, if you were to keep everything in a dynamic or streaming VBO, that would eliminate the point of having them in a VBO at all (well, most likely it would, what the driver does with your buffer is actually up to it) since you're moving to a VBO so that you can keep the static data server side (card) rather than client side. But if you kept everything in a static VBO the dynamic data's access might be so slow it would negate all advantages. (the best way to find out however, would be to try it)

I think either what toji said (with a dynamic or static draw or copy VBO (my moneys on static, provided you use a buffer sub data)
OR
2 VBOs, static data in one (obviously with a static usage) and a second dynamic VBO (dynamic or stream usage, this could also be replaced by just a vertex array if you ask me)

hope that helps
-Dan
When General Patton died after World War 2 he went to the gates of Heaven to talk to St. Peter. The first thing he asked is if there were any Marines in heaven. St. Peter told him no, Marines are too rowdy for heaven. He then asked why Patton wanted to know. Patton told him he was sick of the Marines overshadowing the Army because they did more with less and were all hard-core sons of bitches. St. Peter reassured him there were no Marines so Patton went into Heaven. As he was checking out his new home he rounded a corner and saw someone in Marine Dress Blues. He ran back to St. Peter and yelled "You lied to me! There are Marines in heaven!" St. Peter said "Who him? That's just God. He wishes he were a Marine."
Hi,

I really appreciate all your help!, I learned a lot about it, and about the dynamic data management, in my current implementation (separate VBOs), I use a similar aproach to what Ademan555 says, I mean, I use a second VBO with
GL_STREAM_DRAW_ARB usage, then I use sglBufferDataARB to load my modified data on it.

I will try both methods (Toji and Ademan555) and see how thing go : )

Best Regards,
Oscar

This topic is closed to new replies.

Advertisement