Vertex Specification Best Practices

From OpenGL Wiki
Revision as of 18:16, 9 February 2009 by V-man (talk | contribs) (New page: VBO = Vertex Buffer Object, a GL 1.5 feature<br> IBO = same as VBO, but it stands for Index Buffer Object. They are both essentially the same thing.<br> === Size of a VBO/IBO === How smal...)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

VBO = Vertex Buffer Object, a GL 1.5 feature
IBO = same as VBO, but it stands for Index Buffer Object. They are both essentially the same thing.

Size of a VBO/IBO

How small or how large should a VBO be?
You can make it as small as you like but it is better to put any objects into one VBO and attempt to reduce the number of calls you make to glBindBuffer and glVertexPointer and other GL functions.
You can also make it as large as you want but keep in mind that if it is too large, it might not be stored in VRAM or perhaps the driver won't allocate your VBO and give you a GL_OUT_OF_MEMORY.
1MB to 4MB is a nice size according to one nVidia document. The driver can do memory management more easily.

Vertex, normals, texcoords

Should you create a separate VBO for each? Would you lose performance?
If your data is static, then make 1 VBO for best performance. Be sure to interleave your data and make it a multiple of 32 bytes for good cache line coherence. See the other VBO page because it explains these details.

If one of them is dynamic, such as the vertex, you could store this in separate VBO.
By dynamic, we mean that you will be updating the VBO every frame. Perhaps you want to compute the new vertices on the CPU. Perhaps you are doing some kind of water simulation.
No, you don't lose too much performance if you use separate VBOs. It would be on the order of 5% but your test might show otherwise.
Example:

 //Binding the vertex
 glBindBuffer(GL_ARRAY_BUFFER, vertexVBOID);
 glVertexPointer(3, GL_FLOAT, sizeof(float)*3, NULL);  //Vertex start position address
 //Bind normal and texcoord
 glBindBuffer(GL_ARRAY_BUFFER, otherVBOID);
 glNormalPointer(GL_FLOAT, sizeof(float)*6, NULL); //Normal start position address
 glTexCoordPointer(2, GL_FLOAT, sizeof(float)*6, sizeof(float*3);  //Texcoord start position address

Dynamic VBO

If your VBO will be dynamic, should you call glBufferData or glBufferSubData?
If you will be updating a small section, use glBufferSubData. If you will update the entire VBO, use glBufferData.
The above information comes from a nVidia document

Another thing you can do is double buffered VBO
This means you make 2 VBOs. On frame N, you update VBO 2 and you render with VBO 1.
On frame N+1, you update VBO 1 and you render from VBO 2. This also gives a nice boost in performance for nVidia and ATI/AMD.