# Terrain Rendering

## Recommended Posts

Hi, I wanted to ask a question about Terrain Rendering: what kind of terrain LOD scheme is used in games like FarCry1 or Crysis. It looks like Geomipmapping. Click I don't think, they use any kind of streaming system like in Oblivion etc. But some levels in Crysis are very large (island level-> 4096x4096). How can I deal with large datasets (more than 2048x2048) without streaming. Wenn I use Geomipmapping it's stil a storage problem.

##### Share on other sites
This may only solve part of your problem, but I was able to significantly reduce the amount of data I was storing for my terrain by separating the y values from the x and z values of my terrain data. I then created a single base x,z patch which I just reused for every patch of y values I had. This removed quite a bit of my data. I also reused the same set of index buffers per patch as well. I hope this helps, if you search around there are a several posts on this subject on these forums.

##### Share on other sites
Okay, I can store height data seperatly. But then I need to use dynamic vertexbuffer, right? (not static buffers)
Because when I reuse the patches and i need to update the vertices.

And I wanted to know, what kind of LOD System is commonly used in games. The Screenshot above looks like Geomipmapping. But I'm not sure.

##### Share on other sites
The data can be static, you just need two different vertex buffer inputs. You can then send both vertex buffers to the shader as input, one containing just the height information, and another holding the x,z data. You will also want to pass to the shader information regarding the translation of the x,z data so it will map to the correct position in your terrain. You can then output the translated and combined vector to the pixel shader. I developed most of these concepts based on the posts I have read in these forums, and I am certain you could find more detailed information in those posts.

Also, I agree the above post does look like geomipmapping with patch stitching to correct the holes formed between different levels of detail.

I hope that helps.

##### Share on other sites
Storage problem ? You surely dont try to target TNT-class cards with 266 MHz CPUs, right ?
Even 8192x8192x2 is just 128 MB of RAM. And 16384x16384 is still just 0.5GB, which isnt that much these days when you need 3 GB of RAM to play the game and RAM sticks are cheap as never.

But, with terrain streaming, youd actually use much less RAM, since the distant chunks (of which there is majority in scene), would be just some low LOD (i.e. instead of 512x512, youd load just 32x32 for most distant ones). Of course, with DXT1 itd take just 128 MB for 16384x16384.

So, go for terrain streaming. Thats the standard these days. Besides, its a wonderful world to dive into ;-)

##### Share on other sites
I have 8800 GT and 2GB Ram and I think this is the hardware i'm targeting.

But when I create static buffers for each terrain patch, it is a storge problem, because the VRAM is stil limited.

I create system memory copy of the geometry data, for use in simple reads for collision detection etc, but for rendering I use VRAM. Is that wrong what I'm doing? I'm not really familiar with this.

@Valors
I have read some posts and I think reusing a single patch and translating it by using shader seems to be a good idea.

Thanks.

[Edited by - Hiyar on July 25, 2008 3:54:59 AM]

##### Share on other sites
If youre targeting 8800GT and 2 GB RAM, and youre limited by VRAM, then youre doing sth seriously wrong. Storing complete 3D Data for each terrain is a horrible idea. Its good to have it at the begininng, so you always have sth which always works and can test it at any time, but its absolutely unusuable for real-world games.
So, as a next step create a base stream that shall be used for all chunks holding XZ coords and some base UV coords (depending on how you texture the terrain). Then, for each chunk, create a VB of the heightmap values (2 Bytes per coord). Inside Vertex Shader, convert heightmap value to YPOS and take X and Z value of base stream. Use some constant to define offset of current chunk and add it to your vertex position and youre set. Shouldnt take you more than half a day to do it, really.

##### Share on other sites
no response...

can anyone explain, what can I do to reduce the number of draw primitive calls.
I do frustum culling but what can I do for the distant parts of the terrain.

[Edited by - Hiyar on August 7, 2008 6:27:19 AM]

##### Share on other sites
are you using immediate mode in whatever API you are rendering your view(i.e.; glBegin()/glEnd() in OpenGL)? If so, I'd look into vertex buffers and the like, as this will allow you to generate a list of vertices (or indices to vertices), and draw the whole list with one call. This way, if you use a single vertex buffer per cell/quadtree node/whatever, then you only make as many "draw" calls as there are visible cells/whatever.

Note that in OpenGL, for example, you wouldn't render the primitives when doing this, rather call glDrawElements() and its friends on the whole, or part of the, list

##### Share on other sites
I'm using Direct3D. I create a single vertex buffer for a base terrain patch 32x32. Then I use vertex shader for translation.

But my question is:
Here you can see terrain bounding boxes are different sizes. How can I implement this, this way I could reduce drawcalls.

##### Share on other sites
Quote:
 Original post by HiyarI'm using Direct3D. I create a single vertex buffer for a base terrain patch 32x32.
32x32 is awfully small a patch. 2048/32 gives you, how much, 64 patches in each direction ? 64x64 is 4096 DIP calls. Ouch !
I use 256x256 or 512x512, which is 256 times less DIP calls.
But for distant terrain, thats still too low.

So, you need to create another layer of patches. I dont remember right now, if I merged 3x3 or 6x6 or 9x9 patches. Lets say I merged 3x3 patches into 1 megapatch. So, I merged 3x512 into just 512. But now I use 9 times less DIP calls. And am using same Indices array (with same number of LODs as for the regular patches layer).

This will still occupy additional memory (in VBs), though. At the cost of additional 1/9th of your current VB consumption, it gives you a benefit of reducing the DIP call by a factor of 9:1, which I consider fair.

Then, during rendering, you first render those distant megapatches and then those remaining regular patches. If you tweak distances well, and if your texturing is nice and you have some vegetation, the holes between LOD of megapatch to regular patch might not be visible at all. If it is, you should create your Indices in such a way, that you can specify the outer border LOD. That way, you wont have to worry about different details between them.

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628301
• Total Posts
2981913

• 10
• 11
• 11
• 10
• 10