Terrain Optimization...

Hi all

I was wondering what some different methods of optimaztion could be used in drawing terrain. All i have heard of is Tesselation, and a method where the farther out the poly is, the bigger it gets, thus reducing the poly count. The second methos i said works very nicly, but when i do per-vertex lighting it starts looking very bad.

Thank you for any ideas and suggestions
Zix

p.s. i am using very large terrain (2000x2000) to (4000x4000) units

Visit Google.com with the search phrase ‘ROAM’

Good luck.

Don’t use per-vertex lighting…

-Ilkka

Geomipmapping is better suited to current hardware than ROAM. Google will reveal more.

I agree on the per vertex lighting, thingy. Set all the vertex normals to face straight up and use a normal map, just like if you were doing bump-mapping on a flat surface.

EDIT: In my own terrain renderer it was even worse since I was using per-vertex colouring instead of using a colour map. Hehehe. . .

[This message has been edited by Ostsol (edited 08-12-2003).]

what’s wrong with per-vertex lighting?

Originally posted by JanHH:
what’s wrong with per-vertex lighting?

When you bring the terrain down to a lower polygon count you have less vertices to work with. As a result, you lose alot of the finer detail in the shading (in addition to the loss of polygon detail). By using a normal map, the only detail you really lose in in the terrain’s sillouette – and a good tesselation algorithm can minimize that, anyway.

Originally posted by bunny:
Geomipmapping is better suited to current hardware than ROAM. Google will reveal more.

I am not really sure of that (reading about Geomipmapping right now). I agree that there are algorithms avaiable which works nicely when “small enough” terrains are getting rendered but here zix is using a 4000x4000. I am also doing a large terrain renderer and most algorithms around the net does not feel attractive (my crash test is 12000x8000).
Now, the terrain map itself is, for zix 4000x4000 = 15.2MB if he’s using 8bit samples. Expand that to a 16bit only and 30MB are gone away (for height only). Add eventual GeoMipMaps and stuff like that. I feel there is the need to manage memory very effectively here.

I must thank you anyway for the hint provided about geomipmapping. I am very interested on that topic. I’ll keep an eye on it (reading a paper right now).

I would recommend what I think is being called,‘chunked LOD’. I presume it’s not the same as geomipmapping or is it?

Basically break your terrain up into chunks e.g. 128x128, then calculate the LOD based on distance from the viewer.

You can use a cacheing system to only store the vertex array data for visible chunks of vertices. You only need to regenerate the vertex data when a chunk becomes visible or changes LOD. This keeps memory/cpu usage low.

This is imo the fastest,most memory effecient way of rendering terrain on modern hardware.

This screenshot shows a wireframe view of chunked LOD terrain with a 4kx4k dataset. http://www.adrian.lark.btinternet.co.uk/MarsExWF.JPG

Edit: Image updated to show newer version of the software running at 51MPolys/sec. With fog off it runs at 82MPolys/sec on a GF5900u)

[This message has been edited by Adrian (edited 08-12-2003).]

Originally posted by Adrian:
[b]I would recommend what I think is being called,‘chunked LOD’. I presume it’s not the same as geomipmapping or is it?

Basically break your terrain up into chunks e.g. 128x128, then calculate the LOD based on distance from the viewer.

You can use a cacheing system to only store the vertex array data for visible chunks of vertices. You only need to regenerate the vertex data when a chunk becomes visible or changes LOD. This keeps memory/cpu usage low.

This is imo the fastest,most memory effecient way of rendering terrain on modern hardware.

This screenshot shows a wireframe view of chunked LOD terrain with a 4kx4k dataset. http://www.adrian.lark.btinternet.co.uk/MarsExWF.JPG [/b]

Exactly the same idea.

I’m currently working on a variation of this, where the patches are stored in quad-tree nodes, and all are the same fixed resolution. The advantage of this is that the fixed chunk size is the optimal amount of vertex data to send to the graphics card in a single burst. Although it’s not as flexible as the standard approach.

Thank you all for your suggestions. Right now i am using something similiar to ‘Chunked LOD’, but with texture maps. I will go look at Geomipmapping and see what it does, it might be perfect for what i am doing.

Thanks again, and if anyone has a better idea i would be happy to hear it
ZIX

I just want to know if i’m geting the idea about geomipmapping…

I found this site here and read a little about it. It sounds like i’m already doing. Here are two images…

normal image
In mesh

it looks fine (excluding the texture map is pretty bad when it comes to shadows, i found a free one on the internet)

Thanks for advide, ZIX

EDIT: darn UBB code…

EDIT: darn UBB code TIMES 2…

[This message has been edited by zix99 (edited 08-12-2003).]

[This message has been edited by zix99 (edited 08-12-2003).]

Basically break your terrain up into chunks e.g. 128x128, then calculate the LOD based on distance from the viewer.

Fundamental problem: how do you guarentee that the edge cases work correctly? Since they can’t be using the same vertices, how do you handle the possibility of possibility of seeing small gaps between edges?

Also, how do you deal with visible LOD popping?

Fundamental problem: how do you guarentee that the edge cases work correctly? Since they can’t be using the same vertices, how do you handle the possibility of possibility of seeing small gaps between edges?

Yes, a thorny problem. Edge strips and corners have to be tesselated so that there are no T-junctions. The solution is outlined here. http://www.flipcode.com/cgi-bin/msg.cgi?..um=askmid&id=-1
Solving this for the corners was even worse and by far the hardest part of the engine.

Also, how do you deal with visible LOD popping?

With 250,000 polygons per frame popping is virtually unnoticeable. These days popping/geomorphing should be avoidable.

In case you downloaded my demo and noticed seaming, IIRC the seaming was only fixed in the second demo(Melas). http://www.adrian.lark.btinternet.co.uk/PWMarsExplorer3.htm

[This message has been edited by Adrian (edited 08-12-2003).]

Originally posted by Korval:
[b] Fundamental problem: how do you guarentee that the edge cases work correctly? Since they can’t be using the same vertices, how do you handle the possibility of possibility of seeing small gaps between edges?

Also, how do you deal with visible LOD popping?[/b]

Where the neighbouring patches levels are different, you render the higher resolution mipmap edge to match the lower resolution edge using triangle fans.

See the method (and diagram) here

You can deal with popping by setting the error metric to be very low, so that only small errors are allowed when changing levels. If that’s not good enough, you can do vertex blending between two detail levels. This is dealt with in the paper I linked to above (they refer to it as trilinear geomipmapping).

Originally posted by zix99:
I just want to know if i’m geting the idea about geomipmapping…

A few things I noticed from your mesh:

  1. You jump from a low LOD to a high LOD which was 4x more detailed in each direction. It would be better to get your LOD algorithm to do a more smooth transition between the LOD levels.

  2. You will get seeming issues because you have T-junctions in your mesh, refer to flipcode link I posted higher up.

  3. Your not using many polys you will likely have severe popping issues, how many polys are you rendering per frame?

[This message has been edited by Adrian (edited 08-12-2003).]

Having implemented geomipmapping in my engine, I can say that if you use a pixel error metric of 3.0 then popping is almost unnoticeable. Getting a 3.0 pixel error required rendering on average 150,000 polys per frame for my test terrain, which is quite attainable at decent speeds on even a radeon 7500 when you use large batches, as GMM forces you to. I used “skirts” to make the T-junctions and seaming disappear, and used the same texture across the entire mesh to avoid texture seams. For calculating pixel error, I used the same formula as discussed in the chunked LOD paper, but you can specify a fixed screen width if you don’t want your LOD selection to be resolution-dependent.

And for some eye candy, here’s a pic of my terrain running, with a 1024^2 puget sound heightmap and a custom 2048^2 texture made by Devon Zachary. 112 is the framerate, and 216910 is the polycount. Running on a Radeon 9500 pro, 1GHz duron. And it uh… uses a direct3d driver, but the same stuff should apply to an opengl backend.

[edit] I should point out that GMM doesn’t scale very effectively. I can load a 2048^2 heightmap, but with my current implementation it takes about 30 seconds to load and chews up 1.5GB of memory. Chunked LOD addresses this problem by only loading the vertices needed by a [soon to be] visible LOD mesh, and storing distinct vertices for each LOD level - this also allows for optimization of the meshes such as using VIPM. Chunked LOD takes quite a bit more preprocessing than GMM though, especially if you go for unique texturing (not splatted) - GMM can be loaded directly from a heightmap, but Chunked LOD requires some custom-formatted data structures that are all ready to stream into memory off disk.

[This message has been edited by Assassin (edited 08-12-2003).]

One of very few topics I see Assassin around so just wanted to say hi.

  • BlueDev

[This message has been edited by VC6-OGL (edited 08-12-2003).]

Originally posted by Assassin:
[edit] Chunked LOD takes quite a bit more preprocessing than GMM though, … GMM can be loaded directly from a heightmap, but Chunked LOD requires some custom-formatted data structures that are all ready to stream into memory off disk.

Why do you have to preprocess for chunked LOD? I calculate vertices from the heightmap at runtime and store them in a cache just keeping those that are part of visible tiles, no preprocessing is necessary. (apart from indice arrays for the different LODs)

[This message has been edited by Adrian (edited 08-12-2003).]

how would you guys render a very large terrain? at least 1000 x 1000 km in real, and probaly larger? I think a normal map with a lot of details for such a size is rather inappropriate, isn’t it? we have a standard triangle mesh with per vertex lighting and no tricks at all and it looks very bad, compared to the screenshot above, and it’s already about 1.000.000 poly in the whole terrain, and a large amount of texture data… any hints?

thanks
Jan