Jump to content
  • Advertisement
Sign in to follow this  
Laval B

Terrain LOD

This topic is 1216 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

Hello everyone.
 
I'm an currently working on the design of a terrain system for my engine.  The goals are to be able to render large terrains with good quality in real time. I'm mostly working on the geometry pipeline so far. The literature is quite abundant but i mostly retained the ideas from the following papers :
 
 
 
So far the geometry pipeline will looks like this :
 
- Terrain will be rendered using a heightfield (texture).
- The terrain grid will be a minimal vertex buffer containing only the x and z coordinates.
- The displacement will be done in the vertext shader.
- Vertex normals will also be computed in the vertex shader.
- The redering will be done using a quadtree that will be used for both culling and lod selection. The quadtree is basically only managing index buffers.
 
In order to avoid T-Junctions between adjacent nodes with different lod, a certain number of index buffers permutations will be used (9 of them) just like it is described in [1].
The problem is that for this algorithm to work, the difference in lod level between two geometrically adjacent nodes on the terrain must must be at most 1.
 
What would be a good way to impose this restriction ? Right now, i'm out od ideas or at least good ones ...
Edited by Laval B

Share this post


Link to post
Share on other sites
Advertisement

Yeah... some of these ideas are not very good. You only load the terrain once, and that's at level initialization time. If you're pulling the height information from a height map, there's no reason why you can't just set the exact world coordinates for each terrain vertex. If you do this for every frame inside of the vertex shader, your GPU is going to be doing a lot of unnecessary processing work which could just be avoided by placing the XYZ coordinates at load time. Multiply that by every vertex in your terrain, and its going to add up.

 

The same applies to vertex normals. There's no reason why you can't just get this info at load time and store it in a custom vertex object for each terrain vertex. In fact, if you're going to be creating a height map texture for your terrain, you can also create a normal map texture for your terrain.

 

You're making 3D terrain. You don't use quad trees for 3D environments, you use octrees.

 

To avoid the T-junctions, you want to use skirts. The LOD level of a terrain chunk should NOT be influenced by the LOD level of an adjacent terrain chunk. In my terrain system, I had four LOD levels, and I had to be able to skirt lower LOD's to higher LOD's. Check out this wireframe to see what I mean:

[attachment=28739:TerrainLOD.png]

Share this post


Link to post
Share on other sites

If you're using DirectX 11-grade graphics cards, doing the LOD tessellation in the Hull/Domain shader stages is fairly neat, and avoids some of the difficulties of having to patch up T-junctions between LOD levels.  I've played around with it both this way, and more the way you are describing:

Not the greatest screenshot, but this is from my hardware-tessellated version.  I'm sure that I'm not doing things in the most optimal way, but on the hardware I was using(GTX560), the hardware-tessellated version was considerably faster.

 

 

Yes, hardware tessellation is something i need to investigate more. I have toyed a bit with a terrain tessellation demo that was published in GPU Pro 4 and it looked very neat indeed. The performace were very good on my development machine (GTX 780 Ti x2). When i tried it on a smaller card (Quadro 600) which has DX11 feature level but much less cores, it was running fine but very close to the minimum frame time with only the terrain.

 

I'm thinking tessellation might be good for smaller tasks like morphing in character animation when the character is close to the camera. 

 

Tessellation is indeed interesting for very dynamic surfaces like character's faces and water simulation. Like i told you, i need to get a good grip of it and the associated cost.

 

I may also have to support DX10 level hardware so i will need a falback.

 

Tank you for your post, i will read your references when i get back home.

Edited by Laval B

Share this post


Link to post
Share on other sites
I do a similar style terrain to what you're proposing. I stitch terrain patches with different lods together in the vertex shader by simply moving the edge-in-question vertices of the higher LOD patch to match those of the lower LOD patch. Performance is great.

I have made one or two posts on the subject on this forum a few years ago, I'll see if I can dig them out

Share this post


Link to post
Share on other sites

What would be a good way to impose this restriction ?

Culling is done via the quad-tree.
With proper memory management, you can jump directly to adjacent cells, as well as up and down LOD levels.
When beginning the search through the quad-tree, perform a standard parent-child iteration over the tree, but select child nodes in order of closest-to-camera first.
This allows you to find the chunk closest to the camera and its appropriate LOD level.

From here, change your search method so that it branches out and away from that chunk, and for each node you pass a minimum and maximum search depth. For each neighboring node, you may only go up or down one level in the tree.

As for proper memory management, this method becomes possible if you lay out all nodes sequentially in RAM and hold an array of pointers to the start of each level. To go from Node [X, Y] to its parent, simply go up one level (use the array of pointers to the starts of each level) and index into that array of nodes [X>>1, Y>>1]. Nodes on a level will be organized like a bitmap, so you can also easily go left, right, up, and down from any given node on the same level, allowing to traverse from any node directly to any other node.

You would organize your quad-tree this way for best cache usage anyway.


L. Spiro

Share this post


Link to post
Share on other sites

I have made one or two posts on the subject on this forum a few years ago, I'll see if I can dig them out

 

Thank you, i am very interested by the approach.

 

 

Culling is done via the quad-tree.

With proper memory management, you can jump directly to adjacent cells, as well as up and down LOD levels.
When beginning the search through the quad-tree, perform a standard parent-child iteration over the tree, but select child nodes in order of closest-to-camera first.
This allows you to find the chunk closest to the camera and its appropriate LOD level.

From here, change your search method so that it branches out and away from that chunk, and for each node you pass a minimum and maximum search depth. For each neighboring node, you may only go up or down one level in the tree.

As for proper memory management, this method becomes possible if you lay out all nodes sequentially in RAM and hold an array of pointers to the start of each level. To go from Node [X, Y] to its parent, simply go up one level (use the array of pointers to the starts of each level) and index into that array of nodes [X>>1, Y>>1]. Nodes on a level will be organized like a bitmap, so you can also easily go left, right, up, and down from any given node on the same level, allowing to traverse from any node directly to any other node.

You would organize your quad-tree this way for best cache usage anyway.


L. Spiro

 

 

Thank you very much for the detailed explanation.

Share this post


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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!