Sign in to follow this  

Distant Terrain Rendering

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

I have been doing a little personal project with the goal of rendering as realistic looking terrain as possible. At the moment I'm using a simple smallish heightmap and blending three different textures (grass, rock, snow) by an amount depending on the height to simulate mountains. I'm performing this blending in the pixel shader, along with detail mapping, bump mapping and simple lighting. I'm implementing fog in the vertex shader. I'm using an adaptive LOD algorithm based on computing Binary Triangle Trees of the terrain at initialisation. At each frame the tree is traversed in order to determine which level of detail is drawn, this computation uses the distance of the tree node to the viewer and the error metric computed at the beginning. After much tweaking, this seems to be working just fine. I do notice some 'vertex popping' as the distance changes to certain features, but the tweaking has minimised this effect to an acceptable level for me. I thought about interpolating between the two levels of detail in the vertex shader, but I'm not sure how to go about this yet. My main question relates to how I should go about rendering very distant terrain. I want to achieve a similar effect to Oblivion, which involves something like a 16km^2 map and you can see the mountains in the distance from very far away, whilst the detail of the immediate neighbourhood remains very high. I know this probably couldn't be achieved by a heightmap alone, as when you set the far clip plane to a value sufficient to display far terrain, your resolution/granularity is decreased to the point where you can't display fine detail at small distances. I don't know exactly how oblivion achieves the awesome distant landscape effect, but I know it involves pre-generating some LOD meshes and distributing those with their heightmaps. Does anyone know more detail on how Oblivion achieves distance landscape rendering? Also, are there any other good methods of achieving this? I've been researching this for the last couple of days but haven't been able to find any papers/web resources that describe 'exactly' what I want. I think first I need to generate a heightmap far bigger than the one I have now, as I can almost see one corner from the diagonally opposite corner at the moment. But how do I actually render it such that it will not be clipped for being too far away, without having to increase the far clip plane (as that would reduce the granularity of the depth buffer and thus the detail at close distances)? Following are 3 screenshots of my terrain renderer so far: With texturing: The same view as wireframe, to see the LOD algorithm in action: Moved slightly forward from previous position, note the slight increase in detail at the bottom of the slope at the center of the scene as the camera has moved closer to it: EDIT: Oh, During my research I did find out how oblivion handled distant objects/meshes (such as the main tall tower in the middle, for those who have played the game) - they have a separate lower-detail mesh that is rendered when the 'far view distance' option is enabled. They don't perform collision detection or anything on this mesh. I do not know how they handle distant landscape though, that is what I am interested in for now.

Share this post


Link to post
Share on other sites
I dont know how it's done in oblivion, never played it.
But as you said, either use a terrain lod scheme which handles very large datasets well (e.g. geoCLipmapping) or render far away landscape into a cubemap which gets updated every now and then (every 20 frames or so...). Distant level geometry was done that way in shadow of the collossus (ps2).

The Making Of "Shadow Of The Colossus"

Edit: typo geomipmapping -> geoclipmapping

[Edited by - stephanh on June 24, 2008 7:53:39 AM]

Share this post


Link to post
Share on other sites
Thanks for the response, the cubemap method sounds exactly the kind of thing I need. I don't think its possible to use a terrain LOD scheme to render really distant land, as the vertices for this terrain will need to be beyond the normal clipping distance (perhaps even 10 times the clipping distance or so). The only solution for that problem (that I can see) seems to be substituting a texture for the distant land, such as you suggested, and rendering that texture just inside clip range.

Since I posted my original question I found a similar previous question posted here last year, and one of the suggested solutions was to render distant landscape to the skybox which sounds quite similar to what you suggest.

I'm not sure how to actually go about this though. After doing a quick google search I came across an article indexed on IntroGameDev.com in 'Game Programming Gems 2' - the article is called 'Rendering Distant Scenery with Skyboxes', which is exactly what I want. The problem is I cannot find an online version of this article, it seems to be available only in printed form and for a price - anyone know if this is available online and free anywhere?

Does anyone know of any good online resources that will help me render distant landscape to a texture? I have quite limited experience with 3D graphics, and I have never used anything other than standard 2D textures and techniques no more complicated than detail/bump mapping and texture splatting.

At the moment I'm distributing the LOD mesh calculation over several frames, as it is just too expensive and unneccesary to perform every frame. I guess this method would probably also need to be distributed, and if so then the framework for that is already in place, which is good :)

I had a quick look at the Shadow of Colossus screenshots, and it looks like the distant terrain is clearly separate from the foreground. Whilst it still looks quite nice, whatever technique oblivion uses creates a pretty much seamless transition between foreground and distant background. They may use a texture-based approach to rendering distant land, but it seems like the main problem with that approach is the seam created between foreground and background and, if they are using that method, then they manage to solve this problem extremely well!

EDIT:
Here is a link to a screenshot showing an example of distant terrain in Oblivion: http://planetelderscrolls.gamespy.com/screenshots/?ss=919&view=ss&page=1&cat=4
Note how the mountains in the far distance on the horizon seamlessly blend with the closer terrain at the foot of the mountain, and how there is less fog applied at the foot of the mountain than towards the top, which further gives the impression of volume. If they are using a texture to render the distant land, then they are doing it pretty much seamlessly, and the texture itself really gives the impression of volume. I wonder if I can turn on wireframe mode in Oblivion which may give me some clue as to how it works. I'll try that now :)

EDIT 2:
Ok, I tried wireframe mode in oblivion and the results surprised me - they aren't using any kind of texture to show distant terrain, they are actually rendering distant landscape and stuff using a terrain lod scheme that relies on precomputed low triangle count meshes that are substituted in when the landscape is far away. More surprising was that the area of terrain immediately around the camera was shown in full detail, i.e. even when flat-ish terrain could be vastly simplified into like 100 times less triangles, it still renders each and every small triangle instead of trying to compute a low-error simplification of the immediate area. This might partially explain the bad framerates I'm getting with the game, as they could do some optimisation on the immediate area's mesh.

The problem I've been getting with actually rendering distant terrain using vertices is that to give the impression of vast scale I have to have the camera close to the surface, lower the movement speed, and apply a fine detail map to the immediate area. This means I have to have a 'near clip plane' of like 0.01f, or when I look down at my feet the terrain will disappear as it gets clipped for being too close, whilst I still need a far clip plane of like 100.0f or the distant terrain gets clipped. Having a very far far plane and a very near near plane means the granularity of the 16 bit depth buffer gets decreased and you notice Z-fighting and other problems, and I'm not sure how to get round these.

[Edited by - EvilDonut on June 23, 2008 7:33:45 AM]

Share this post


Link to post
Share on other sites
The far clip plane matters surprisingly little concerning depth precision. You can even push it to infinity.
I usually keep my near plane around 1.0 - 1.5 for a human-sized observer and push the far plane as far as necessary.

Rendering such large terrain, assuming with 16km^2 you mean a ~ 16k*16k heightfield, it's more a storage problem. You are dealing with 1GB of raw float-height samples then. Data has to be paged-in on demand using a LOD-scheme supporting some kind of out-of-core rendering. Additionally it might be wise to compress that data.

Your LOD sounds like chunked-lod which should be able to handle such amounts of data (with paging).

But i doubt the terrain is that detailed in oblivion, ground clutter and close object meshes do their share do conceal nearby terrain detail. And simple fog or atmospheric effects provide a good depth impression.

How large is your current heightmap? What hardware do you target?

Share this post


Link to post
Share on other sites
Yeah, the terrain LOD in Oblivion is a ridiculously simple two-level scheme--the high detail terrain is just a regular heightmap and the low-detail is highly simplified. The simplicity of it is mainly just disguised by the really fantastic work the artists did (and, as stephanh pointed out, the large amount of clutter helps to hide the transition).

I actually wanted to do a much more sophisticated scheme but time was really limited. :) I'm very excited to see how people react to Fallout 3's terrain/object LOD scheme since it's quite a bit more awesome.

I think the main point to take from Oblivion, though, is that fantastic artwork goes a long way to making something look next gen and high tech, even when (as in the case of the distant terrain) it's actually pretty simple under the hood.

Share this post


Link to post
Share on other sites
Yes, the amount of clutter in outdoor areas really masks the low terrain detail. I tried turning on noclip so I could fly to about 100 metres above the surface, then turning down the foliage/object render distance as low as I could. I was then high enough to see the neighbouring low-detail patches clearly, and they have a very low triangle count. Also, when I flew towards them so that the high detail patch was loaded the terrain would suddenly and quite significantly change, an effect which is hardly observable when at normal heights above the land due to the foliage etc.

I think the prettiness of oblivion's outdoor areas is very much related to the foliage (SpeedTree powered) and nice skybox/lighting, and if I could make a terrain renderer half as good as Oblivion then I'd consider this project a success :)

My previous heightmap was only 512x512, but I'm now attempting to use Oblivion's heightmaps instead as its a convenient source of large prebuilt height data. Oblivion uses tiled heightmaps, each of size 1024x1024, of which there are 14 for the main outdoor world. Each of these tiles appears to be further divided into 32x32 cells, each cell 32x32 pixels in the heightmap. I believe their coarsest LOD simplifies each cell into a single quad, but I may be wrong there as I've not investigated it that closely. I will be trying to combine my CLOD method with these heightmaps and see what happens.

Fallout 3 sounds interesting, are you able to give some kind of overview of the terrain LOD method being used or is that still hush hush for now? :)

stephanh: I'm developing on what is now a fairly low end machine - Athlon XP 3800+, 2GB RAM, GeForce 7600 GS. I'm getting about 45fps at the moment which is pretty poor for such a small heightmap. However, I haven't yet implemented any frustum culling stuff, and my LOD calculations consider the entire terrain, not just the terrain that is currently visible - so there are plenty of optimisations yet to make. I started this project over a year ago and am only just picking it up again. At the moment I'm spending most of my time trying to remember what the various pieces of code did, as I'm not big on commenting my own code :)

I'll try setting the near clip plane a little closer to 1.0, and increasing the far clip plane. I will then need to raise the camera off the ground and rescale the terrain to compensate for this.

Thanks for the help!

Share this post


Link to post
Share on other sites
I was reading a few months ago that John Carmack for their new engine found LOD pretty much a waste of CPU cycles and that just blasting all the triangles to the card was faster anyways. You might actually want to try removing your LOD code and see if it's that much slower. I've tried doing this and ended up gaining quite a few FPS. I even had 2-3 different LOD techniques in the code I could swap between and all were slower then just rendering all the polygons which surprised me. Just depends on how your code works. Inefficient code (not saying yours is) with great LOD is still inefficient and slow. Might be an interesting test for you.

Share this post


Link to post
Share on other sites
I had tried that a while ago, and without any LOD at all I get 60 fps (I capped it at 60 and just slept for any extra spare time), but with LOD I got 45fps - so yes, its a big speedup using no LOD at all :) But that was with 512x512=262144 vertices, and I even had to spread my LOD updates over like 20 frames. The heightmaps I'm using now consist of about 14M-verts in total, and I really don't fancy sending all that to the gfx card without any LOD, even with frustum culling. I think my code is also fairly inefficient, as it is the result of a sort of evolutionary design process and as such contains a lot of redundant code.

I think John Carmack is right to some degree, but I think there exists a tradeoff between how much effort you put into LOD and how much you just brute force. As cards get better, that tradeoff gets pushed towards the 'brute force' end of the scale, but then you eat up a large portion of your triangle count which could be better used on the various models etc in your environment. I would certainly want to at least have two levels of LOD, like Oblivion, with near terrain at maximum detail and far terrain at minimum detail.

I'm now attempting to implement geoclipmapping with the Oblivion landscape, as that seems to be fairly cutting edge and suitable for large terrains. It actually looks fairly simple too, I don't have to mess around as much with recursively subdividing triangles and maintaining loads of pointers between neighbouring triangles and ensuring that they perfectly tesselate, etc, as I was doing with my previous LOD scheme - that was a massive pain to implement.

Share this post


Link to post
Share on other sites
I partly agree with Carmack. I don't think he's dealing with datasets as large as we are--when your game area is measured in miles on each side, you need SOME kind of geometry LOD, or you very quickly end up vertex-limited, not to mention filling up tons of memory with distant vertices that make little to no contribution to the scene.

I do think that continuous LOD schemes are essentially a waste of time on modern hardware. You always want to be focusing on blasting big batches to the video card. The point of LOD is to reduce (1) the number of triangles by VERY BIG amounts, since small tricount optimizations make essentially no difference in rendering time, and (2) the number of batches, if you're using some kind of hierarchical scheme. And of course (3) to reduce memory usage.

So yeah, I'm a big fan of chunked LOD and related schemes, in case it's not obvious.

(Can't really talk about Fallout LOD at this point, obviously. But try going into wireframe once the game comes out and it'll be pretty easy to see how it works. :)

Share this post


Link to post
Share on other sites
Quote:
Original post by lancekt
So yeah, I'm a big fan of chunked LOD and related schemes, in case it's not obvious.


I`m extremely glad to see there are pros that still think that chunked LOD is a usable alternative (with proper tweaking).

To OP: The whole "huge terrain distances" feature is actually just a hack, an effect.
Consider the following terrain (16x16 km, 32768x32768 heightmap - i.e. 2 billion triangles). With properly chosen chunks (i.e. VB/IB pair), the framerate skyrockets to over 3000 fps (on 7950GT and 1.6 GHz CPU).


Terrain Shot 2

It`s all just an illusion and depends on how you define your terrain - i.e how it looks - if it does create the impression of huge terrain or not. The above shot shows that you can easily have an overview of 16x16 km, but if necessary, down there you can have a detail of 0.5m per vertex, just switch to proper LOD Indices/Vertices. Of course, with such amounts of data, you need to hold only 16-bit value of YPOS and calculate the rest inside shader.

Share this post


Link to post
Share on other sites
I'm not sure your best target would be Oblivion. Having played the game I can say the LOD transition looks horrible and the pre-computed LOD meshes would give problems with changes in the heightmap. I've heard that Crysis actually uses a voxel system for distant terrain, though that could be wrong.

Share this post


Link to post
Share on other sites
Yep, I agree the transition looks pretty bad - I'm trying to use an entirely different LOD scheme though, just witht the same heightmaps. I'm not even using their distant LOD meshes and will instead calculate my own for whatever scheme turns out to work. I'm looking at geoclipmaps at the moment, not sure if I actually 'need' that many levels of detail though.

Share this post


Link to post
Share on other sites
Hi all

Very interesting posts from everyone. I have a couple of simple questions:

a) How do you go into wireframe mode in Oblivion? Are you using the PC version or XBox360?
b) EvilDonut, are you working towards any kind of game idea? Or is this just an experimental project?
c) (not so simple) - is geomipmapping the way forward? Based on the presumption that brute-force rendering is becoming a better option than progressive and dynamic LOD techniques.

Share this post


Link to post
Share on other sites
Quote:
Original post by RobMaddison
a) How do you go into wireframe mode in Oblivion? Are you using the PC version or XBox360?
b) EvilDonut, are you working towards any kind of game idea? Or is this just an experimental project?
c) (not so simple) - is geomipmapping the way forward? Based on the presumption that brute-force rendering is becoming a better option than progressive and dynamic LOD techniques.


a) 'twf' in the console, accessed with the ~ key (PC only).
c) I wouldn't call any single technique 'the way forward' but at least on current-gen hardware, techniques that provide optimal brute-force rendering are definitely preferable. That said, I suspect that once some of the new DX10 capabilities (e.g. geometry shaders) are faster and more widely available, lots of things will change in ways we haven't even thought of yet. :)

Share this post


Link to post
Share on other sites
a) I'm on the PC, so I just bring up the console and type 'twf' for toggle wireframe mode, and 'tcl' for toggle clipping (fly mode). I don't know if you can do this on XBox, but I'd be surprised if there was no way of entering some kind of debug mode.

b) No specific game idea in mind. I'm just playing around with computer graphics in general to gain experience in the field. My immediate goal for this project is to make a great terrain renderer, and in the future I may try some kind of free MMORPG if I get a lot more experience and can be bothered.

c) I don't know if its the way forward, but brute force is just not an option with massive landscapes. Infact, I don't think brute force will ever be a realistic option. As power of cards increases, so to does the realism of the scenes. But the realism of the scenes is always achieved by squeezing the maximum possible out of the graphics card, and you can't do this if you're wasting triangles on far-away detail that may only account for a few pixels of screen-space. Even a simple LOD scheme can cut the terrain triangle count by say 90% of brute force, so for the tiny amount of effort it takes to implement LOD you get so much more resources available for this 'other stuff' like actor detail, foliage, shadows, advanced atmosphere stuff - all of which will contribute more to the scene than slightly more detail a kilometer away. As for geoclipmapping specifically, I don't know if that is the best choice for the kind of data I'm dealing with, but right now I don't know of any better solution. One advantage of geoclipmapping is it is relatively easy to shift a lot of the work into the vertex shader, which is generally good for any graphics algorithm.

Share this post


Link to post
Share on other sites
I have a question which is related to this thread but slightly off the track, and aimed mostly at lancekt I'd guess.

If we were to develop our game idea on a PC with a view to eventually getting it onto next-gen consoles (Xbox360 in particular), do you have to factor in at the early design stage which terrain implementation you use? I'm still deciding between chunked LOD (geomipmaps) and geoclipmaps for our idea, but I'm airing towards chunked LOD at the moment.

If we do work on the terrain implementation, is it work that will be wasted when we come to port to the XBox360? I know the architectures are very different, but I don't really want to spend a fair amount of time getting the terrain looking right on the PC when it's really the XBox I'm aiming at.

Having been involved on Oblivion, would you say implementations between the PC and XBox360 versions were _that_ different?

I'd be really interested in any tips you can give for this particular area of development.

Share this post


Link to post
Share on other sites
Quote:
Original post by RobMaddison
I have a question which is related to this thread but slightly off the track, and aimed mostly at lancekt I'd guess.

If we were to develop our game idea on a PC with a view to eventually getting it onto next-gen consoles (Xbox360 in particular), do you have to factor in at the early design stage which terrain implementation you use? I'm still deciding between chunked LOD (geomipmaps) and geoclipmaps for our idea, but I'm airing towards chunked LOD at the moment.

If we do work on the terrain implementation, is it work that will be wasted when we come to port to the XBox360? I know the architectures are very different, but I don't really want to spend a fair amount of time getting the terrain looking right on the PC when it's really the XBox I'm aiming at.

Having been involved on Oblivion, would you say implementations between the PC and XBox360 versions were _that_ different?

I'd be really interested in any tips you can give for this particular area of development.


Practically speaking, the differences aren't really high-level enough to affect the implementation of something like terrain that you choose, if that makes sense. If you pick a method that's efficient and functional on a DX9-level PC, it will be fine on the 360 too. Really the only difference that may affect you significantly is that you have much more limited memory on a 360 than on a typical PC.

All of the methods you suggest should work just fine, although chunked LOD or geomipmaps would probably be quite a bit easier to implement than geoclipmaps. :)

Share this post


Link to post
Share on other sites
Quote:
Original post by lancekt
I partly agree with Carmack. I don't think he's dealing with datasets as large as we are--when your game area is measured in miles on each side, you need SOME kind of geometry LOD, or you very quickly end up vertex-limited, not to mention filling up tons of memory with distant vertices that make little to no contribution to the scene.


Actually if you look at Rage the new game they're making it's quite large worlds available (also the MegaTexture is pretty sweet imo). I think using model LOD is of greater benefit then terrain. But then again most of my terrain experiments ended with a few hundred thousand tri's or so, if I recall correctly. Then again it was on cards over 4 years old at this point too. I think at one QuakeCon he said [Carmack] he was working with 16km x 16km datasets. But his discussion of brute forcing it was from a year or so earlier so he may have changed his mind (oh no flip-flopping!? ;-))

Honestly I'd just brute force it until it became an issue to get further into development. But it was, at the same time, fun playing with all the different LOD options out there. But I find it is more of a Time vs Distance issue in my situation, where others are waiting (Time) for me to get to the point where they can use the features (Distance) they need so I have to sprint in some areas then crawl in others. So I think its a matter of your situation also.

Share this post


Link to post
Share on other sites
Some great replies...

For my requirements (4km x 4km), I've decided to go with a hybrid of chunked LOD and brute force. Here's my plan:

I keep the 4096x4096 heightmap data in memory (~33mb). As a pre-processing stage, I split up the heightmap into 3 levels. This will give me:

Level 1: 4 quad-tree nodes, each of 256x256 at a stride of 8 heightmap pixels. This will mean if you're stood at one corner of the map and looked at the opposite side, one triangle at full distance would span 8 metres - perfect for hills, etc. At this level, I will store 4 textures at 512x512x16 (~2mb) which should provide a nice coverage from distance. I see this level taking up ~4.5mb.

Level 2: 16 quad-tree nodes, each of 64x64 at a stride of 4 heightmap pixels. This will mean triangles rendered using this level would span 4 metres. At this level, I will store 16 textures at 256x256x16 (~2mb + mipmaps). I see this level taking up ~22mb.

Level 3: 64 quad-tree nodes, each of 256x256 at a stride of 2 heightmap pixels. This will mean triangles rendered using this level would span 2 metres. At this level, I will store 64 textures at 256x256x16 (~8mb + mipmaps). I see this level taking up ~95mb.

For level 4, the final level (1 sample per metre), it would take up too much memory to statically store this level (335mb at 20bytes per vertex), so some kind of dynamic buffer generation might be the way. For each level 3 node, there will be 64 (8x8) 65x65 vertex patches. Each of these will be frustum culled and then probably brute force drawn using a bank of static vertex buffers - probably using vertex texture lookups in the shader. For this level, I probably envisage using texture splatting for the main texture detail. For odd areas of texture detail, I will splat on a per vertex quad basis - so it should be possible to have lots of various detail all over the terrain. I just treat these as static objects that follow the slope of terrain, and infact use the same vertices.

All in all, I'm estimating static goemetry and base textures taking up ~150mb. Is this far too much for xbox360 (which is where I ultimately would like this to go)? It has 512mb system mem so I assume it's fine.

Does this sound like a feasable approach to anyone? Or am I completely barking up the wrong tree. Any comments for improvement most welcome!

Thanks

Share this post


Link to post
Share on other sites
Why would you need to store 20 Bytes per vertex for Level 4 ? A height should be enough, meaning just 2 Bytes per vertex. You`ll use another stream with precalc`ed UV and XZ coords. This stream can be used with any chunk, no matter how big your terrain is.

Also, it`s not completely obvious if you`re just keeping separate Index Buffers per each LOD Level, or if you`re again keeping separate Vertex Buffers per each LOD.

As for the 4096x4096 heightmap, it doesn`t have to occupy 33 MB. If you plan on using vertex texture lookups in shader, why not compress it into DXT and have it occupy just 8 MB (4096x4096x0.5) ?

Share this post


Link to post
Share on other sites
That's true, I hadn't thought of using vertex streams yet, thanks.

Regarding the index buffers, I have one per level which is used for each chunk in that level so the footprint is relatively low. I am having to use 32 bit index buffers though (for the minute), as some of my chunks are 257x257 meaning over 65536 indices. It's been a couple of years since I've done any work on this and, at that time, it was considered best practice to split up index buffers if they went over 65536. I may do that at some point because using 32 bit buffers for a buffer only slightly over the max seems like a bit of a waste of memory.

I can't really compress the heightmap as I need the values to be exact and DXT is a lossy compression IIRC (although I appreciate it would be lossy in the vertex shader as well as CPU_. The reason for this is I need the ability to quickly pull out arbitrary heights from the map in order to a) create sporadic splatted textures and b) calculate accurate sloping (for the player(s)).

Thanks for the advice (I realise this thread is now slightly dissimilar to the title).

Share this post


Link to post
Share on other sites
I haven't actually implemented such a scheme, but as I was reading through all of these great replies, it occurred to me that dual paraboloid mapping would work great in this circumstance. The far away terrain mesh is inherently overly complex - or put another way it is highly tesselated with respect to the viewpoint.

This is exactly what paraboloid mapping needs, which would allow you to render the distant terrain into the paraboloid maps == two render passes with highly complex terrain. However, since the terrain is far away you would only need to render it once in a while due to the spatial coherence in the viewer's position with respect to the terrain. So the two extra rendering passes would be highly amortized over several hundred frames or more, and there wouldn't be any tesselation issues with the DPM generation.

Has anybody tried this out before? The distant geometry rendering basically becomes a simple lookup (similar to the cube mapping example mentioned above), and you could dynamically decide the near and far clipping planes to allow for very good depth resolution in the mid range. I'll have to add this to the list of things to try out...

Share this post


Link to post
Share on other sites
Quote:
Original post by stephanh
I dont know how it's done in oblivion, never played it.
But as you said, either use a terrain lod scheme which handles very large datasets well (e.g. geoCLipmapping) or render far away landscape into a cubemap which gets updated every now and then (every 20 frames or so...). Distant level geometry was done that way in shadow of the collossus (ps2).

The Making Of "Shadow Of The Colossus"

Edit: typo geomipmapping -> geoclipmapping




Hmmm cube map OR skydome (if theres an issue with the corners)

Thats an interesting idea to optimize even intermediary ranged scenery for long views....

Share this post


Link to post
Share on other sites
Quote:
Original post by RobMaddison
Some great replies...

For my requirements (4km x 4km), I've decided to go with a hybrid of chunked LOD and brute force. Here's my plan:

All in all, I'm estimating static goemetry and base textures taking up ~150mb. Is this far too much for xbox360 (which is where I ultimately would like this to go)? It has 512mb system mem so I assume it's fine.


Just had a look at my old geomipmap terrain and plugged in a pieced-together 4096x4096 version of the Oblivion map. Total memory usage is 100MB with a chunk size of 64x64 and no textures.

Thinks to do:

-just store height values in buffers and offsets for chunks (you'll probably have to use 4byte floats anyway, so unfortunately you waste about 3byte per vertex). Put them together in a shader.

-for the tree, don't use any pointers and text book tree traversal. Ugly overhead. Instead, exploit the fact that your tree will be complete. Store it as an array (level for level). Moving to the child/parent is a matter of a simple bitshift on the current index and "collecting" all leaf nodes is a matter of calculating the offset and number, then just fetch them (in nice, cache friendly order, as they are all in one consecutive block)

-just use spheres for culling. They aren't precise, but they are good enough and fast

Rendering the whole thing (view is corner to corner) is 2,5 million triangles at 70fps (7900GT). Fiddling with the lod threshold etc. and reducing it to a sane amount should be good to go. Though I wouldn't recommend geomipmapping for really large terrain with "infinite" view distance.

Also, did you consider a method to hide the gaps between different lods? Skirts seem to be pretty accepted, though after stumbling over a chinese-wall-like monster skirt from hell in Oblivion, I'm not so happy with them. All V or U like terrain can look pretty bad. On the other hand, I hate my code to automatically create index buffers for all linking pieces and it means a lot of extra render calls.

Share this post


Link to post
Share on other sites
I've changed my original terrain renderer to use the Oblivion heightmaps with procedurally generated texturing to determine what areas are grass/sand/rock/snow/water. The LOD method I'm sing is completely different to my first attempt, as that was unneccesarily resource-hungry. Following are some shots:



The terrain is divided into 'patches', each corresponding to a 1024x1024 heightmap (as output by Oblivion's construction set), each of which are further divided into 'cells' of size 128x128 (this size was used as it was the highest power of 2 that could be used with 16 bit index buffers after skirts were added to each side). LOD meshes are computed for each cell by generating a mesh for each of the heightmap mipmap levels, so the highest LOD is 128x128, then 64x64, and so on. There were 8 LOD meshes for each of the 896 cells, each of which was saved as a .x file in a Data folder - so quite a lot of them!

Each heightmap patch has its normals computed and saved in a 1024x1024 texture, which is used in the pixel shader lighting function. Each heightmap patch also has two 'terrain textures' of size 512x512 (gonna try 256x256 as there was almost no quality loss from halving it from 1024 to 512), each color channel of which is used to represent a single terrain type (grass, rock, etc). I tried using bitfields so I could compress several terrain types into a single color channel, the interpolation didn't quite work though. The values of each channel are used as blending factors for the individual terrain textures in the pixel shader.

For visibility determination I'm doing a ridiculously simple method involving a spherical interesction test between each cell and the view frustum - there is no quad tree of cells (although there could easily be) as looping through all 900 cells doing this very simple test is pretty quick.

Water is done by drawing a very big quad over each cell. The quad is planar and has a Y value of 0, so using this method there is no way of getting rivers at different heights :( Implementing this would require something clever be done to construct the vertices representing the surface of the water. The big water quad does a texture lookup to determine its alpha factor, which allows me to give the smooth transition between sand and water rather than an instant change as you see in many older games.

Next on the to-do list is to improve the water by bump mapping it with a water-like texture which will change over time in some way so as to simulate waves/ripples/motion on the water surface. Once I add sky boxes I will do some very simple skybox reflection, but doing some kind of environment-based reflection involving local/global terrain will probably be more challenging considering the vast amount of terrain.

I tried implementing Screen Space Ambient Occlusion and made pretty good progress but it began to really harm the framerate when I tried to get antialiasing working - i was using render-to-texture for the scene (you can't do antialiasing with render-to-texture, so you have to render to a really big texture then shrink it down which involves 4x more calls to your pixel shader function), storing linear z values in the alpha channel, then passing this texture to a SSAO shader that operates on a full screen quad. The results were kind of what SSAO should look like, except for auras above some peaks, but I suspect large scale terrain is not the best way to test an SSAO shader - a small enclosed scene with models, e.g. people, would be far better.

EDIT: See how much better a bit of bump mapping makes water look? :) The screenshots don't show it, but the normal map is animated so as to simulate a rippling/wavy/choppiness effect - the animation is done entirely in the pixel shader which is parameterised by a 'water phase' variable (-1 to +1, increments slightly every frame) that is used in some trig equations that are applied to the normals. I don't think I've got specular lighting working properly yet though, you can't see any at all when you are at the waters edge.


[Edited by - EvilDonut on July 7, 2008 8:52:26 PM]

Share this post


Link to post
Share on other sites

This topic is 3446 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.

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