Terrain

Started by
4 comments, last by RobM 2 years, 4 months ago

I'm rendering a dynamic terrain shadow map (using cascaded shadows), and I need to work out which terrain tiles I need in the shadow map. My terrain is a standard quadtree based terrain, with 32mx32m tiles being the smallest drawn, up to 1024m x 1024m (with a max terrain size of 8192m x 8192m). When working out which tiles to choose for normal rendering, I just do the standard frustum culling approach, i.e. check if the parent patch is in the frustum, then split into the children, and so on. I then do a distance calculation to each of the children to check if I should traverse further down - this all works nicely.

My question is, how should I traverse the terrain quadtree in order to find which tiles to draw in the shadow maps? My current implementation takes the sun position and does a ray intersect between the sun's direction vector and the ground plane. I then use that as the effective viewer position and apply the same logic to when normal rendering in order to get a list of caster terrain tiles. Is this how it's normally done or is there a better way?

edit: that’s not the title I entered for this post!

Advertisement

You could form a frustum from each cascaded SM projection and reuse your camera frustum culling code. (Just an idea - no experience myself)

@JoeJ Thanks Joe. That's pretty much what I'm doing already. I cull the terrain patches/tiles against the light's frustum. But in order to cull and select the relevant terrain tiles (i.e. which tiles should draw at 32x32, which at 64x64, 128x128 and so on), I need a distance from the patch. When rendering the terrain normally, this distance comes from the x/z position of the camera, to the edge of the patch..

When deciding which tiles to render in the shadowmap, however, I'm struggling to work out what I should measure the distance of the patch to. At the moment, I'm projecting a ray from the centre of the light's frustum [cacade], in the direction of the sunlight downwards and intersecting that with the imaginary ground plane at zero (with normal 0, 1, 0). Problem is, the terrain at this position may be 300 units above in the Y direction meaning it'll almost certainly give the wrong size of terrain tile as it's likely to be further away. What I suppose I need to do is intersect that ray with the terrain, but that's going to be slow. Here's a side on view of the issue. If I used the black distance marker, terrain tiles in the centre of the light frustum would be smaller and match the actual terrain (which is what we want). However, I'm currently using the blue marker, which is a fair distance from the camera meaning the tiles I draw in the light frustum are too big for the actual terrain, i.e. they don't match.

Actually, thinking about it, I only need to do the terrain intersection once per frame so maybe it might not be so bad. I'm sure this isn't the ‘normal’ way to do it though…

Hmmm - eventually you could precalculate the average height for each quadtree node, and use this to calculate a center point at runtime. Distance from this point to camera would define the LOD to render. You have to make sure this point is calculated using the exact same math, no matter if traversing fro camera or for shadows. Otherwise various cascades might select a different LOD due to floating point issues.
Not sure if respecting height is needed. As terrain is usually quite flat, using the same 2D metric for both should be good enough or even more robust against LOD popping. A working 2D metric would be projecting terrain and camera down to the same plane. Your image maybe implies you forgot to do this for the camera as well.

Thinking of this, a traversal for each cascade is probably a waste. I guess it's faster to traverse only once for camera, store the LOD cut in a list, and then for each SM cascade iterate the whole list to cull tiles which are not in the cascade frustum.
Oh no - this would miss shadow casters which are not visible for the camera. So you do need to traverse per cascade to be save.

Edit:
> As terrain is usually quite flat, using the same 2D metric for both should be good enough

… makes sense only if player keeps close to surface of the terrain. If you have airplanes, the 2D method would waste detail on the aera below the plane.

Thanks Joe

Actually, just using the camera position as the centre point works pretty well.

This topic is closed to new replies.

Advertisement