I have a heightmap terrain that is currently using a big fat glDrawElements having set vert and tex coords pointers and such.
The terrain does continuous lodding and based on a detail threshold I could be rendering anything between 30K and 80K tris.
Because of the continuous lodding, as the camera moves, verts keep getting added/removed.
Will I see any performance gains moving my code to use VBOs for this? I’m guessing I’ll have to use the STREAM_ flag that is a 1-to-1 update-to-draw (according to the docs I read).
No, I don’t think (but it’s just an opinion, not a fact) that it will give you more speed if you need to rebuild your vertex array every frame anyway.
If you have a vertex array implemented properly, then you shouldn’t see any significant performance gain.
k_szcheck thx for your response.
What do you mean by having a vertex array “implemented properly”?
My terrain is stored as a quadtree and I start from the root node updating nodes recursively. Rendering is done in the same way (i.e. from the root node recursively).
During my update I see what nodes will be “enabled” and during rendering I construct the vert array using the “enabled” nodes.
Every 250 quads (i.e. approx 2000 tris (since there is a max of 8 tris per quad)) I call glDrawElements. Then I carry on until I go through the whole quadtree.
(I’ve read somewhere that something between 2000 and 2500 tris is the “optimal” amount to send in a glDrawElements call…Not sure how true that is btw).
What I meant was not enabling/disabling the array and setting new pointer too often.
As for glDrawElements, I’m using different approach to terrain rendering, but I don’t want to go through details since it’s not important here. At first I had sectors, each one with 128 triangles - frustum culling decided which sectors to render and then I called glDrawElements for every sector that should be rendered.
Then I’ve decided to put everything into one array and for each sector that should be rendered I copied it’s index array to global index array. This way I had static vertex array and dynamic index array. Copying indices and calling glDrawElements once was 30% faster than not copying them and calling glDrawElements multiple times.
The point is that every OpenGL command that starts rendering (such as glBegin or glDrawArrays) is expensive, so there should be as little of them as possible.
u could gain performance with VBOs if you just updated ur terrain-VBOs every 5th or 25th frame. I think terrain is not that fast changing to notice any difference between every-frame-updates and every-5th-frame-updates.
you could also use doublebuffering for the VBOs, so while rendering from one buffer, u could update progressivly parts of the other every frame and switch them when done.
You would probably get a performance boost by using a ring of VBOs such that only one VBO is used per frame. Each frame you could map the next buffer and write into it. This would alleviate the main problems with dynamic VBOs, having to call BufferSubData in order to update which causes a memcpy, or worse a stall, and the glMapBuffer stall so that all commands using that VBO are flushed out to the GPU and then waited for completion. Using multiple VBOs in a ring would get you on a fast path.
80k tris is very little for a terrain
in my opinion its best if u ditch the LOD and just store the terrain at the highest resolution
devide the terrain into say 8x8 patches
pros - less cpu work, no popping, better looking, perhaps faster
cons - none
the only time for a terrain u would want LOD is if it had many millions of tris