Using "indexed vertex rendering" with VBOs?

Started by
5 comments, last by Dragonion 13 years, 7 months ago
Hello Forum,

A VERY COMPACT DESCRIPTION OF THE OBJ FILE FORMAT
A mesh in a Wavefront OBJ file is stored as collections of faces (triangles), where each face is represented by three index references to arrays containing vertex position-, normal-, and (sometimes) texture coordinate data. For example, each side of a cube mesh would consist of two triangles and consequently each corner vertex would be referenced by no less than six different triangles. A single triangle could then be stored as [1,2,3] in the OBJ file meaning "use vertex entity number 1, 2, and 3 to draw this triangle".

THE CURRENT SITUATION
So, I wrote a small program to convert an OBJ file to the file format used by my engine and voila; I got the Blender mascot (Suzanne) spinning on my screen. However, the way I am currently doing it is by simply creating a VBO containing each vertex in each face (had it been a cube instead of Suzanne the total number of vertices doing it this way would have been 36: 3 vertices per triangle times 2 triangles per side times 6 sides) and render them with a single call to glDrawArrays.

THE QUESTION
While this is the intuitive way of doing it for me, the idea of using a single vertex for multiple triangles as done in OBJ files is much more economical memory-wise. So my question is this: Is it possible to perform "indexed vertex rendering" (in lack of a better word) with VBOs? Or perhaps in some other way?

Edit:
* Changed the title to match the question a little better.
* Added another question.

[Edited by - Dragonion on September 1, 2010 4:45:30 PM]
Advertisement
Well there's two issues here.

If you want to do indexed rendering with VBOs, you can do it with glDrawElements instead of glDrawArrays.

HOWEVER:

You won't be able to use OBJ data out of the box with VBOs. In a OBJ a vertex can have a separate index for positions, normals, and uvs. You can't do this with VBO, as every element of the vertex must have the same index. (You can't use normal #5 with uv #8). To render a OBJ as a VBO you'll have to duplicate a lot of vertices to make this happen.

If you search there are hundreds of similar questions asked here, you'll find as much information as you want.
[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game
Quote:Original post by karwosts

If you want to do indexed rendering with VBOs, you can do it with glDrawElements instead of glDrawArrays.


Aha! Thanks a lot for the tip -- I guess it has just become a habit of mine to use glDrawArrays. If it's not too much trouble, do you know if there is a performance penalty using glDrawElements compared to glDrawArrays?

Quote:Original post by karwosts
HOWEVER:

You won't be able to use OBJ data out of the box with VBOs. In a OBJ a vertex can have a separate index for positions, normals, and uvs. You can't do this with VBO, as every element of the vertex must have the same index. (You can't use normal #5 with uv #8). To render a OBJ as a VBO you'll have to duplicate a lot of vertices to make this happen.

If you search there are hundreds of similar questions asked here, you'll find as much information as you want.


I know, I just simplified my explanation to better be able to explain what I was trying to achieve to the reader. But thanks for pointing it out.
I would guess you're not going to find a clean answer to that anywhere. It will depend on number of triangles, driver, amount of repetetion, and several other factors. Probably either will work for you, glDrawElements should allow you to have smaller VBOs, but you probably will not notice much difference in perf. Profile it for yourself on your own meshes if you're curious about performance.
[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game
Quote:Original post by karwosts
I would guess you're not going to find a clean answer to that anywhere. It will depend on number of triangles, driver, amount of repetetion, and several other factors. Probably either will work for you, glDrawElements should allow you to have smaller VBOs, but you probably will not notice much difference in perf. Profile it for yourself on your own meshes if you're curious about performance.


Fair enough, I guess in the end concrete benchmarking is always the best and most reliable way to evaluate performance.
If anything glDrawElements should be faster overall, as it saves on bandwidth by reducing the number of vertexes sent to the GPU (not really an issue with a VBO however) and enables your hardware's vertex cache to actually work (by caching a small amount of recently used vertexes so that they don't need to be re-transformed if reused - this one is important).

It also enables construction of larger vertex batches: a group of polygons sharing a common state can be drawn with a single glDrawElements instead of multiple glDrawArrays (or a single glDrawArrays with degenerate triangles - yuck). This is also very important, but perhaps more important with D3D than with OpenGL.

You won't however notice much if any perf difference with low poly renders, it's only when you get to huge polycounts that the real advantages kick in. How huge is "huge"? Depends on your hardware and the quality of your driver.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Quote:Original post by mhagain
If anything glDrawElements should be faster overall, as it saves on bandwidth by reducing the number of vertexes sent to the GPU (not really an issue with a VBO however) and enables your hardware's vertex cache to actually work (by caching a small amount of recently used vertexes so that they don't need to be re-transformed if reused - this one is important).

It also enables construction of larger vertex batches: a group of polygons sharing a common state can be drawn with a single glDrawElements instead of multiple glDrawArrays (or a single glDrawArrays with degenerate triangles - yuck). This is also very important, but perhaps more important with D3D than with OpenGL.

You won't however notice much if any perf difference with low poly renders, it's only when you get to huge polycounts that the real advantages kick in. How huge is "huge"? Depends on your hardware and the quality of your driver.


Thanks a lot - that feedback was tremendously useful! It certainly does make good sense that glDrawElements could actually surpass glDrawArrays in performance the way you explain it.

This topic is closed to new replies.

Advertisement