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]
Some questions about VBOs and Vertex Arrays...
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]
[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:
- 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
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:
Good luck, and let us know who it works out for ya!
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!
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:
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
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]
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]
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
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
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
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
Popular Topics
Advertisement