Sign in to follow this  
Hiyar

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 this post


Link to post
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 this post


Link to post
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.


PS: Sorry for bad english

Share this post


Link to post
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 this post


Link to post
Share on other sites
Storage problem ? You surely don`t 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 isn`t 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, you`d 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, you`d load just 32x32 for most distant ones). Of course, with DXT1 it`d take just 128 MB for 16384x16384.

So, go for terrain streaming. That`s the standard these days. Besides, it`s a wonderful world to dive into ;-)

Share this post


Link to post
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 this post


Link to post
Share on other sites
If you`re targeting 8800GT and 2 GB RAM, and you`re limited by VRAM, then you`re doing sth seriously wrong. Storing complete 3D Data for each terrain is a horrible idea. It`s good to have it at the begininng, so you always have sth which always works and can test it at any time, but it`s 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 you`re set. Shouldn`t take you more than half a day to do it, really.

Share this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by Hiyar
I'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, that`s still too low.

So, you need to create another layer of patches. I don`t remember right now, if I merged 3x3 or 6x6 or 9x9 patches. Let`s 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 won`t have to worry about different details between them.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this