Skip to main content
GameDev.net gamedev.net
🔒 Locked

Terrain rendering... (again ;))

Started by Freaky Mar 30, 2004 at 2:57 PM 19 replies 2.9k views
Original Post
Freaky
Freaky
Currently i''m implementing a terrain renderer for an outdoor engine and I was wondering if all that CLOD algorithms are usefull as of today. When you just would implement (my current position) a quadtree with in each node a vertex array for that node and finish it up with frustum culling. The FPS currently is quite acceptable. When I push a heightmap of 500+ k polies to the engine the FPS will continuosly float above 35+ fps. I was wondering if it would be useful to implement a CLOD algorithm in the current implementation. Meaning that each patch would adjust it''s vertex count to the distance to the camera. Would this give me even more capacity? How do you feel about this. I think that with current gfx cards this does not deliver that much of a increase of rendering capacity. Not to forget that I do have a single vertex buffer now which I can just shuf to the card for it to be processed. Otherwise I would have multiple arrays and it would require me extra processing power to determine what to render (just to save a couple of polies & fillrate) So, is implementing a CLOD algo worth it? - Freaky
Mister Pink
Mister Pink
It depends what your needs are.

If it''s just a couple thousand triangles and you don''t want to waste time coding anything fancy, you might consider the brute-force approach.

However, for anything half decent, yes, you will need CLOD. Remember that the graphics engine is just on part of the whole game, so it should run much faster than needed "on its own".

There are several techniques out there. The basic old ROAM is defenately obsolete (doesn''t mean that it sucks though), quadtrees are OK but are apparently quite tricky to implement. I defenately recommend using a GeoMipMapping based method, I tried it out and it worked like a dream : easy to implement, easy to optimize and works very well with todays graphic cards. OTOH there''s some new stuff around now since I last played with terrain 3 years ago, like ROAM 2. Dunno what it''s worth, but you might consider looking into it.
Freaky
Freaky
True, but what''s the most efficient way of maintaining buffers with vertices without rebuilding the arrays. Just store a buffer of all possible patch (depending on LOD)?

Doesn''t this take up a lot of space since I can use the memory on other places aswell.

As for the scale. It''s planned for utilization in a large-scale engine. Resources are streamed in when needed. F.ex. geometry blocks & textures.

As of now I can just stream in a patch (quadtree node that is) whenever the camera comes near and it''s needed in the rendering process. During the ''purge'' phase all unneeded resources are purged from memory to make room for other resources.

How would you manage a streaming system with a system like geomipmapping? Anybody any ideas, sources & examples of this?
de_matt
de_matt
I''m building a terrain engine too and I''ve decided to avoid CLOD mainly because it''s over complicated and and it seems to compromise a lot. By this I mean that when you have two quadtrees with different LOD''s you''ve got to make them match up without gaps and that''s tricky and a bit untidy. It''d take a lot of work.

But if your planning on using larger terrain then you may want to do it. Personally I am not going to use it though.

Matt
samgzman
samgzman
That article is crap in my opinion. The guy obviously didnte understand geomipmapping very well with his claims "the would take up tons of precious memory". Think about it for good half an hour and u can figure some clever stuff out. I went with a geomipmapping variant that works great with minimial (relatively speaking) memory usage.
ALX
ALX
Geomipmapping doesn''t take that much more memory, as you can often (but not always) get away with multi resolution index arrays, keeping one single vertex array per tile at the base level.

Anyway, noone would actually precompile all possible mipmaps for all tiles at build time. The idea behind GM is to create the lower levels at runtime, on demand, and store them in some kind of least recently used cache. That doesn''t take much memory at all, and will also work for infinite size procedural (fractal) terrains.
Lutz
Lutz
Is there also a way of doing geo mipmapping if you have a triangular non-regular tesselation? At the moment, I do all the vertex animation stuff by hand, which gets VERY complicated...
Mister Pink
Mister Pink
Basically, what GeoMipMapping is chopping up your huge terrain into smaller chunks, and the LOD-bias is calculated only once for each chunk based on its vertices : you only have to do a division with the distance to get a good-enough LOD at runtime.

You just render it at the appropriate LOD, with an appropriate tesselation along two edges to avoid cracks with neighbouring chunks that have a different LOD. No big issue. The "difficulty" is just in calculating the tesselations, and even that is nothing painstakingly difficult.

If you do any changes to the vertices in the chunk, just recalculate the chunks LOD-bias and voila.

The original paper about this technique was either here on gamedev or on flipcode, can''t remember precisely. The whole thing is so easy even I could code it, and I was a total newbie at the time, never having done any 3D programming

The good things :
- it''s cheap
- its fast : the chunks are rendered as triangle-stripped vertex-arrayed display lists
- it''s easy to implement, despite it not being as intuitive as ROAM. From what I''ve heard its easier than quadtrees.
- no, it doesnt use much memory at all
- you can handle things up to huge distances
- handles seamless terrain changes well
- LIGHTMAPS ! geomipmapping LOVES lightmaps. you can draw beautifully shaded terrain with not many triangles and it looks great.

The bad things :
- your chunks have to be always all the same size
- can''t think of anything else, really.


Just speaking from experience. My engine had visibility up to 64 km with maximum detail of 1 meter, and was very fast, drawing 15k triangles and looked very good. No screenies I''m afraid
Not saying you HAVE to use GeoMipMapping. Unless you plan on large scale terrain (which seems to be the case) it might not be necessary. I''m just saying that for just such a case it''s an ideally suited, tried and proven painless technique
Ysaneya
Ysaneya
Well the good thing with geomipmapping is that it''s a pretty good balance between CPU/GPU, unless ROAM for example (which is shifting all the workload on the CPU). It''s pretty easy to get a performance in the 20-30 millions of tris/second with geomipmapping and a radeon 9700 or geforce fx.

For my planet engine i''m using a geomipmapping-like algorithm (heavily modified, actually i coded it from scratch w/o following any paper, reinvented all the theory), and it has an infinite view distance. All it does is horizon culling (due to the curvature of Earth) but that''s all, no distance-based rejection. I got no performance problem (at least not from that part).

IMO the biggest drawback is that geomorphing doesn''t mix very well with the reduction of details in "flat" areas (like an ocean, doesn''t need the same level of detail than a mountaineous area). If you keep the same details whatever the chunk type is, you''ll have a high polycount (much higher than ROAM) and an average to bad quality around the mountains silhouettes.

Y.
samgzman
samgzman
Exacltly! You dont need a seperate new geometry definition for each LOD level.... all u need is index buffers.

Ysaneya, Im curious as to how much memory ur implementation takes up at and 1 given moment. Is 200MB considered rediculous? Whats a godd target?
Ysaneya
Ysaneya
I''m not the good person to ask because my usage of geomipmapping is not "typical". I have large textures (taking up to 200 Mb of ram), and some of the heights are generated by Perlin noise. But i don''t think the pure geomipmapping part is taking a lot of memory. My index buffers are purely static, and i''m using 17x17 vertices per chunk.

Y.
Mister Pink
Mister Pink
quote:
Original post by Ysaneya
I''m not the good person to ask because my usage of geomipmapping is not "typical". I have large textures (taking up to 200 Mb of ram), and some of the heights are generated by Perlin noise. But i don''t think the pure geomipmapping part is taking a lot of memory. My index buffers are purely static, and i''m using 17x17 vertices per chunk.

Y.



Like Ysaneya says, you only need one set of index buffers, after that you draw any chunk you like. The index buffers take very little memory, not even a couple of megabytes. The LOD-bias is just a float. The memory will mainly be used by your height values, your lightmaps and texture information (usually some kind of alpha map). If you generate your height information on the fly you can pull it off with very little. I didn''t generate it on the fly (except for vertices very close to the camera to make more "lumpiness"), so I roughly used this much memory IIRC :
- close terrain (0 to 2 km distance) : 3x1024x1024 bytes
- far terrain (2 to 32 km distance) : less than 3x1024x1024 bytes
That''s 6 megs
Captian Goatse
Captian Goatse
quote:
Original post by Mister Pink

Like Ysaneya says, you only need one set of index buffers, after that you draw any chunk you like. The index buffers take very little memory, not even a couple of megabytes. The LOD-bias is just a float. The memory will mainly be used by your height values, your lightmaps and texture information (usually some kind of alpha map). If you generate your height information on the fly you can pull it off with very little. I didn''t generate it on the fly (except for vertices very close to the camera to make more "lumpiness"), so I roughly used this much memory IIRC :
- close terrain (0 to 2 km distance) : 3x1024x1024 bytes
- far terrain (2 to 32 km distance) : less than 3x1024x1024 bytes
That''s 6 megs


Where is the logic in that...

1024x1024x(3*32)= 1006632296 bytes /8 = 12.6 megs double that and you''ve got 24 megs. Pls tell me about your compresison technique k? I rely wunt to know it.. D:
Lutz
Lutz
Can you recommend me a good article on geo mipmapping? (But with arbitrary triangulation, not with nice square thingies)

Does it also work if I have very different textures on the different LODs?

BTW: I just noticed that this brute force guy (see article from somewhere above) gets up to -40 FPS with his approach. Damn, that''s really impressive ;-)

Lutz
Mister Pink
Mister Pink
quote:
Original post by Captian Goatse
quote:
Original post by Mister Pink

Like Ysaneya says, you only need one set of index buffers, after that you draw any chunk you like. The index buffers take very little memory, not even a couple of megabytes. The LOD-bias is just a float. The memory will mainly be used by your height values, your lightmaps and texture information (usually some kind of alpha map). If you generate your height information on the fly you can pull it off with very little. I didn''t generate it on the fly (except for vertices very close to the camera to make more "lumpiness"), so I roughly used this much memory IIRC :
- close terrain (0 to 2 km distance) : 3x1024x1024 bytes
- far terrain (2 to 32 km distance) : less than 3x1024x1024 bytes
That''s 6 megs


Where is the logic in that...

1024x1024x(3*32)= 1006632296 bytes /8 = 12.6 megs double that and you''ve got 24 megs. Pls tell me about your compresison technique k? I rely wunt to know it.. D:


Errrmm....
Lets see :
- height information : 1 byte
- light information (light map): 1 byte
- texturing information (alpha map) : 1 byte

2x(1+1+1)x(1024x1024) bytes == 2x(1+1+1) Mb == 2x3 Mb == 6 Mb

I suggest : start->programs->accessories->calculator, and remember that 1 byte == 8 bits

But yeah, you have a point, the lightmap cam be stored in AGP memory and you can use texture compression, depending on how and how often you want to update the lightmap.
sBibi
sBibi
mmh.. I''m afraid you''ll get a very crappy height precision using only 1 byte to store the height, and you''ll get stairs artifacts.
depends on your terrain of course... on the scale but still, even if you store a height offset and heigh scale per patch, it''ll be visible and annoying. but maybe you don''t care. depends on what it''s used for.
JohnBolton
JohnBolton
Here''s some of the pros and cons of the different ways of rendering static terrain:

Brute Force

- Low CPU cost (geometry is pre-built)
- Bus-friendly (vertex and index buffers are static)
- High GPU cost (so many triangles)
- No LOD transitions and no cracks
- Culling is effective
- Pre-computed occlusion culling is possible.


ROAM, CLOD, etc.

- High CPU cost (geometry is built on-the-fly)
- Bus-UNfriendly (vertex and index buffers are built on-the-fly)
- Low (and potentially tune-able) number of DrawPrimitive calls
- Smaller LOD transitions and no cracks
- Culling is effective


Geomipmapping

- Low CPU cost (geometry is pre-built)
- Bus-friendly (vertex and index buffers are static)
- Fixed number (usually higher) of DrawPrimitive calls
- Vertex data is approximately 30% larger (to hold all LODs)
- Cracks and LOD transitions require skirts and morphing
- Culling is effective
- Pre-computed occlusion culling is possible.


Chunked LOD

- Low CPU cost (geometry is pre-built)
- Bus-friendly (vertex and index buffers are static)
- Low number of DrawPrimitive calls
- Vertex data is approximately 30% larger (in order to hold all LODs)
- Cracks and LOD transitions require skirts and morphing
- Culling is less effective (mesh physical size increases as resolution ot the LOD decreases)

In my opinion, Chunked LOD is generally the best of the four.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
sBibi
sBibi
actually, I had the same problems some time ago.
I started with a very simple and stupid way of doing terrain..
I just had a 1024*1024 heightmap, split in 64 * 64 patches, and brute-force rendered all the patches using a LOD and frustum culling. that was horrible, and run at about 5fps, with 4096 calls to glDrawElements.. then it moved to a quadtree based aproach. with one LOD per quadtree patch... ran much better. but too many tris were wasted on flat areas... then I moved to CLOD to tesselate patches. much better, I could get around 30-35 Mtris/sec rendered. then dumped all that into a file, then added patches streaming from the file when they were needed... then realized fixing cracks on the fly during LOD changes was too costly, added skirts built in the patches, and realized it was just the same as chunked LOD... :|

"So, is implementing a CLOD algo worth it?"

if you want huge landscapes, yes. for the same triangle count per patch (around 2000 - 2500 tris max) with CLOD instead of standard simple patch meshes, I got a huge precision increase... so yes, IMHO it's worth it...



[edited by - sBibi on April 1, 2004 6:16:16 PM]
samgzman
samgzman
Damn! About 4 people keep restating the same WRONG thing! The terrain chunks'' geometry is always the same size! that means ur only haveing to mess around with INDEX arrays. u only need to generate indices for all the possible LOD Levels! Memory consumption is faily small here.... maybe u might want to generate the index buffers on the fly.. but they are never 1024... thats just stupid. The geomipmapping paper suggestions a chunk resoultion of 17x17. Im personally using 33x33 and generating the indices on the fly. Im actually working towards a system capable of handling infinitely sized terrain using a terrain paging chunk data streaming scheme having a custom format which stores delta errors, lighting, and geometry, and blending maps.

Please dont respond with the "thats not really infinite tarrain.." arguement.... I''ve read it a million times and it a dumb arguement... I dont want procedural crap cause it limits creativity for the type of terrain. Infinite terrain is just an illusion.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.