Terrain LOD
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]
Yeah... some of these ideas are not very good. You only load the terrain once, and that's at level initialization time.
The terrain can be very large and will not necessarily be entirely loaded at once. With a structure like this, the index buffers of the leaves can be reused because chunks are loaded in leaves.
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.
With modern hardware, which is the target platform, it is faster to do a bit more calculations then to transfer larger amount of data. This is especially true when loading out of core data in the background.
You're making 3D terrain. You don't use quad trees for 3D environments, you use octrees.
The quadtree is the data structure used for culling and lod selection. Each node will contain the maximum and minimum height of the terrain for the area covered by the node.
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.
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.
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
Culling is done via the quad-tree.What would be a good way to impose this restriction ?
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
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.
Thank you, i am very interested by the approach.
Here you go:
Happy to explain any of it if you get stuck, although it's been a while...