• Advertisement
Sign in to follow this  

Terrain Rendering

This topic is 4259 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've just finished my first terrain renderer! A terrain made of 65536 vertices! In the screenshot you can see a terrain made of 65536 vertices! (And yes, I know I used a ridiculously-looking heightmap.) However, I get 20 FPS max. when I run it, so it's time to start optimizing and I was hoping you people could give me some tips. I have three questions for now: 1. I heard that rendering using triangle strips could improve performance. How is it done? 2. I've read the VBO tutorial on NeHe's site. At the end of the tutorial, the author also mentions rendering using triangle strips, but then says it's beyond the scope of the tutorial. So how do I render the terrain using triangle strips with VBOs? 3. In my renderer, every vertex corresponds to one pixel, so insted of using texturemaps I just set the vertex colors to the corresponding pixel colors. Is that faster than using a texturemap? I thought it obviously is, but just to make sure. Thanks in advance, Mr. Big [EDIT] Wait a second, changing the color per vertex means calling glColor3ub 260,100 times. On the other hand, using texturemaps requires 260,100 glTexCoord2f calls. But then, texture coordinates can be stored in a buffer using VBOs... What about per-vertex colors, can the same be done with them? Would using vertex colors be faster then? I'm confused...

Share this post


Link to post
Share on other sites
Advertisement
If you are using immediate mode to render your terrain, you will get a huge boost by switching to compiled vertex arrrays or VBOs. I haven't used OpenGL in a long time so I don't remember the details. It's not clear which is faster -- an indexed triangle strip vs. an indexed triangle list. So, try an indexed triangle list first because it easier to implement. Using textures is necessary for a good-looking terrain.

Share this post


Link to post
Share on other sites
There are lots of tristrip tutorials on the Net.

1&2. Basically, the first 3 vertices define the first triangle, the fourth vertex define the triangle with the second and the third, and so on. You can easily build a whole terrain like this, row by row. Doesn't differ much from GL_TRIANGLES.
Then just call the vertex pointer with GL_TRIANGLE_STRIP parameter.

Tristrips are faster because you need only one vertex for each new triangle, instead of 3 vertices for GL_TRIANGLES

The one thing you need to know is how to connect the rows.
After the last vertex of a current row (V(n,n)), add vertices (V(n,n), V(n+1,0) ) to your tristrip buffer, and then normally continue with adding the next row vertices. V(n+1,0) is a first vertex in the next row.

This would cause the rows to connect with two invisible triangles, without breaking the strip. Those triangles (V(n,n-1),V(n,n),V(n,n) and (V(n,n), V(n,n), V(n+1,0) are called "degenerated triangles"

3. Put a vertex color inside the vertex buffer too, so you don't have to change glColor each time. Then call it with glColorPointer.

Share this post


Link to post
Share on other sites

You should definitely switch to the VBO approach. Sending that many vertices down per frame is almost certainly your bottleneck.

Using vertex colors, as you're doing, is probably faster than texturing for the number of triangles that you have, but you might get better performance if you used a texture and created fewer triangles (say, one per 4 pixel block).


On modern graphics hardware (ATI at least), strip-ordered triangle lists are just as fast as using the actual strips, because the post transform cache is large enough. I would assume that you'd see a similar thing on Nvidia chips, but I'm not certain. What really matters is not the fact that you're using strips, but the fact that you're drawing triangles in an efficient order. Stripification can give you an efficient rendering order as long as your strips are long enough.

This is assuming you're using VBOs. If you use immediate mode then strips will be faster because you'd have fewer glXXXX() calls, but IMO you should switch to VBOs because they will be faster still.



JB

Share this post


Link to post
Share on other sites
In a real game you probably won't find that you need to render your entire landscape every frame, as the "from outer space" view you've shown here would be very rare.

So normally you'd have a frustum which didn't encompass the entire landscape. If you were in the centre, the first optimisation would be to only draw parts of the landscape in front of the camera. That would immediately cut the number of polys in half anyway.

Then of course you could do better frustum culling, then have a LoD system as well so that further away parts get rendered in lower quality (this is not particularly straightforward, but an OpenGL book I have "OpenGL Superbible" contains a detailed explanation of it).

---

So yes - by all means use the above methods to get verts into the GPU more efficiently. But the most efficient way of saving time is to render less stuff.

Mark

Share this post


Link to post
Share on other sites
Quote:
Original post by mrbig
I have three questions for now:

Fell for all the wrong ideas

Quote:

1. I heard that rendering using triangle strips could improve performance. How is it done?


This is by far the last thing you should try, because a) a triangle list sorted for cache efficiency will be just as good and b) it's not even likely that supplying vertices is the part of the pipeline that's slowing you down. It's like a factory. Whipping that fast guy to work even faster is useless, if that gonzo two places away takes all day to get his screws in.

Quote:

2. I've read the VBO tutorial on NeHe's site. At the end of the tutorial, the author also mentions rendering using triangle strips, but then says it's beyond the scope of the tutorial. So how do I render the terrain using triangle strips with VBOs?


Worry about how to use VBOs and absolutely forget about triangle strips for now. If you tried everything else and you are really SURE that vertex submission is the bottle neck, THEN you can worry about strips.

Quote:

3. In my renderer, every vertex corresponds to one pixel,


That's hard to imagine unless you are using parallel projection or your terrain is absolutely flat and you're looking straight down at it (and in that case, yes, it would be completely dumb to draw a gazillion vertices instead of a textured quad).
Apart from that, vertex colors will be fine, but unless you're aiming for a terrain renderer where you never actually get close to the terrain the simple reason to use texture maps would be the utter lack of detail with only vertex colors.

Without even knowing what you want to use the terrain for, it is pretty impossible to give useful advice, but generally you should cover all the basic "optimizations" before you even worry about strips or whether vertex colors might be .1% faster or slower than a texture. What about culling? And is there even any use for culling or do you plan to always have the whole terrain visible anyway? And in that case: how large do you plan to make it?

How are you drawing it now? The fact that you talk about glColor and glTexCoord calls somehow suggests you are the using the most basic, but also most awefully slow and inefficient hand feeding (ie. immediate mode) and should switch to vertex arrays in the very least (VBO would be better, but if it's too much for you, do vertex arrays first). If the terrain isn't supposed to change you could even try display lists (which are the opposite of flexible, but sometimes even faster than VBO).

Share this post


Link to post
Share on other sites
Original post by Trienco
Quote:
Original post by mrbig
3. In my renderer, every vertex corresponds to one pixel,


That's hard to imagine unless you are using parallel projection or your terrain is absolutely flat.../quote]

He is talking about how the terrain image is stored, not how the result looks on the screen.

Share this post


Link to post
Share on other sites
@trienco: could you please elaborate why index triangle strips optimized for vertex cache efficiency should be the last option for pipeline optimization?

I held a seminar about vertex cache efficient triangle strips last winter and I can t agree with statements that claim that index triangle lists sorted for vertex cache efficiency can perform nearly as fast as optimized tri strips.

There s been an article at toms hardware sometime ago, but his judgement was kind of subjective without scientific value.

The only reason I see that one should start with index tri lists is because almost all index tri strip generators require exactly this storage format for strip generation.

Share this post


Link to post
Share on other sites
So basically, you guys are saying that I should forget about such minor optimizations for now and go do something serious, right?
I know very well about terrain subdivision and frustum culling, but I have good reasons to implement the minor optimizations first:

A. Since I'm doing everything inefficiently, this is exactly the time to test how minor optimizations affect the overall performance.
B. They're simple.
C. If I got it right, using triangle strips and VBOs requires a special arrangement of the triangles. I'd really prefer to do that right away.

Oh and another thing, how do you guys associate a 256x256 texture on a huge terrain with "detail"? ;)
I won't get any detail from such a small texturemap on such a huge mesh, not metter how I use it.
I'm using it merely to define the general colors of the terrain, not for detail, so why bother texturemapping 131,072 triangles?
I'm going to use texture splatting and detail maps, so having defined the general colors of the map also allows me to use greyscales for the textures and detailmaps themselves, which means a little bit less data on the hard-drive and GPU RAM. Oh, there I go again, micro-optimizing...

[EDIT]

Oh, by the way, nobody mentioned backface culling.
Almost forgot about it.

Share this post


Link to post
Share on other sites
I know, but still tend to forget to do it for some reason.

Share this post


Link to post
Share on other sites
well, if you still want to know, the order you would draw it with triangle strips would go something like this:

|/|/|/|
|\|\|\|
|/|/|/|

I know it's a little hard to figure out what that's supposed to be, but pretend this is being drawn in Line mode, and the Top-Left is your first vertex. Then Following the lines would be the way you index the vertices.

I hope that made some sense :P

Share this post


Link to post
Share on other sites
Quote:
Original post by Basiror
@trienco: could you please elaborate why index triangle strips optimized for vertex cache efficiency should be the last option for pipeline optimization?


Because if you did everything else and all the more major stuff, they are unlikely to make any difference. With heavy texturing going on, using VBO, etc. the shortest plank in your barrel is most likely NOT vertex submission and experience usually shows that making the long planks even longer still won't let the barrel hold more water. It's like one part of the pipeline is working like mad, just to get a 5min break after each step to wait for the others to finish their job, too.

Quote:
I held a seminar about vertex cache efficient triangle strips last winter and I can t agree with statements that claim that index triangle lists sorted for vertex cache efficiency can perform nearly as fast as optimized tri strips.


Now, if you're going to say that you used non trivial shaders and not just "naked" unlit and completely "unrealistic" polygons (and probably immediate mode or vertex arrays on top of it), I'm definitely interested in numbers.

But my previous terrain renderes showed exactly no difference between even "non-cache optimized tri lists" and all as one big strip, each row as a strip and everything else I tried, simply because there were about a dozen other places in the pipeline that took longer anyway.

Quote:
The only reason I see that one should start with index tri lists is because almost all index tri strip generators require exactly this storage format for strip generation.


Because it's easier and you won't need to wrap your head around alternating winding orders and placing your degenerate triangles just the right way? You can still start reodering your vertex and index buffers when the terrain is completely finished.



Quote:
Original post by mrbig
A. Since I'm doing everything inefficiently, this is exactly the time to test how minor optimizations affect the overall performance.


And will give you numbers, that are pretty much meaningless for a setup that isn't inefficient to the core. With immediate mode and without any texturing it actually DOES matter to send as few vertices as you can, because your CPU is hand feeding the card and it takes forever. It's the shortest plank and making it longer will make a big difference. In a realistic setting vertex submission most likely won't be the problem and what made things go 300% faster will now make about 0% difference.

Quote:
Oh and another thing, how do you guys associate a 256x256 texture on a huge terrain with "detail"? ;)


I associate either a much larger texture or tiled detail textures with detail. Of course putting a 256x256 texture on a 256x256 terrain is kind of silly, at least if the color is just a function of position (which isn't exactly giving your artists a lot of flexibility)

Quote:
I'm going to use texture splatting and detail maps, so having defined the general colors of the map also allows me to use greyscales for the textures and detailmaps themselves, which means a little bit less data on the hard-drive and GPU RAM.


You need to think a bit further. It means blending together 4 detail textures with a single dot product AND let's you store them all in a single texture, meaning 2 look ups and one dot product, instead of 5 lookups, 1 mul and 3 mads. However, the result tends to look a bit boring, because you can't have colored detail anywhere. No nice green and yellow grass for example and the base texture doesn't remotely have the resolution to pull it off. Clipmapping might be something to look into.

[Edited by - Trienco on June 26, 2006 12:22:38 AM]

Share this post


Link to post
Share on other sites
mrbig: nice terrain anyway :). I'm also working on a terrain generator here. I use triangle strips and Display Lists. First time I read about VBOs and my red book has no index entry to it(!!) but from what I've read from the posts here I understand VBOs are simply to move vertex datas to the graphics card and avoid sending them all the time. So, I suppose this can be mixed with display lists as they are completely different processes. Is this right? Do I have interest to do that mix?

Now a sub-question as we are about terrains: My terrain generator must have a system that provides a stepped coloring depending on height. Simply put: over a certain height, draw in one color, above another one, draw with another color, etc. I tried both vertex coloring (glColor()) and clipping (set a color, draw the scene with a clip removing everything not in the desired height. redo this for another color, etc.) and clipping is really the nicest result. Now, can one think of a cleaner approach, maybe avoiding rendering the scene n times where n is the number of colors?

Share this post


Link to post
Share on other sites
Quote:
Original post by Trienco
Quote:
Original post by Basiror
@trienco: could you please elaborate why index triangle strips optimized for vertex cache efficiency should be the last option for pipeline optimization?


Because if you did everything else and all the more major stuff, they are unlikely to make any difference. With heavy texturing going on, using VBO, etc. the shortest plank in your barrel is most likely NOT vertex submission and experience usually shows that making the long planks even longer still won't let the barrel hold more water. It's like one part of the pipeline is working like mad, just to get a 5min break after each step to wait for the others to finish their job, too.

Quote:
I held a seminar about vertex cache efficient triangle strips last winter and I can t agree with statements that claim that index triangle lists sorted for vertex cache efficiency can perform nearly as fast as optimized tri strips.


Now, if you're going to say that you used non trivial shaders and not just "naked" unlit and completely "unrealistic" polygons (and probably immediate mode or vertex arrays on top of it), I'm definitely interested in numbers.

But my previous terrain renderes showed exactly no difference between even "non-cache optimized tri lists" and all as one big strip, each row as a strip and everything else I tried, simply because there were about a dozen other places in the pipeline that took longer anyway.

Quote:
The only reason I see that one should start with index tri lists is because almost all index tri strip generators require exactly this storage format for strip generation.


Because it's easier and you won't need to wrap your head around alternating winding orders and placing your degenerate triangles just the right way? You can still start reodering your vertex and index buffers when the terrain is completely finished.



In other words, the optimization for indexed vertex cached optimized triangles will hardly pay off since computation necessary to process a vertex is pretty low in static geometry, as long as other parts of your rendering process are complex enough.

Did you do s early z fail pass and several shadowing passes for per object realtime shadowmap? There tri striping and optimizing would certainly pay off depending of mesh complexity


So when rendering pure unlit unrealistic polygons tristriping and optimizing for vertex cache efficiency theoretical should still be faster than vertex cache optimized indexed triangle lists although the speed difference decreases every generation of new 3d accelerators.


Share this post


Link to post
Share on other sites
Quote:
Original post by amnesiasoft
methe: you could try using a shader, that should work nicely for what you're doing.

hmm. I don't think I will dive into the 800pages orange book about shaders sitting on my desk if I don't know whether I'd get significantly faster result. I guess where I loose time is in the clipping mathematics more than drawing the scene 3 times as each time the scene is incomplete (only one color level is drawn). Can you give me good reasons to jump into the shaders book? :)

Share this post


Link to post
Share on other sites
Quote:
Original post by methe
Quote:
Original post by amnesiasoft
methe: you could try using a shader, that should work nicely for what you're doing.

hmm. I don't think I will dive into the 800pages orange book about shaders sitting on my desk if I don't know whether I'd get significantly faster result. I guess where I loose time is in the clipping mathematics more than drawing the scene 3 times as each time the scene is incomplete (only one color level is drawn). Can you give me good reasons to jump into the shaders book? :)


Well for one its the future of gfx programming with GL or DX... and adds so much more control for you to decide what you want to do vs. being dicated by the FFP code path... I recommend reading and moving to GLSL as soon as you can. IMO

Share this post


Link to post
Share on other sites
Quote:
Original post by methe
Quote:
Original post by amnesiasoft
methe: you could try using a shader, that should work nicely for what you're doing.

hmm. I don't think I will dive into the 800pages orange book about shaders sitting on my desk if I don't know whether I'd get significantly faster result. I guess where I loose time is in the clipping mathematics more than drawing the scene 3 times as each time the scene is incomplete (only one color level is drawn). Can you give me good reasons to jump into the shaders book? :)


It actually wouldn't even require the Orange Book at all, I managed to write a shader to light and texture my terrain with some nice fringing after only 2 days of shader work, and I implemented it in HLSL, Cg, and GLSL.

I'd recommend taking a look at Lighthouse 3D to learn some about GLSL, it's a pretty good place, and won't take you too much time. Sure you won't learn really advanced and complex things, but it's a start.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement