Skip to main content
gamedev.net
🔒 Locked

Recommendations for shadowing algorithm

Started by transwarp Mar 6, 2009 at 6:00 AM 6 replies 1.4k views
Original Post
transwarp
transwarp
Hello everybody, I've read a little bit about Shadow Mapping and Stencil Volume Shadowing, but I have never implemented any form of shadowing myself so far. I'm writing a RTS-Game-Engine using Managed Direct (transitioning to SlimDX) and C# 3.0. Most of the render code including shader and light management is in place and working fine. However, I would appreciate some input on what kind of shadowing method would be the most adequate for the following scenario: Fixed height-map based terrain (will not change during the levels) and two moving directional light sources. My main aim is self-shadowing for the terrain. Having the terrain cast shadows onto movable entities and the other way round would also be nice, but is not my first concern. I also have movable point lights within in the game world, but I don't think considering them for shadowing will be necessary. Looking forward to your ideas and recommendations. Regards, Bastian
FeverGames
FeverGames
do the two directional lights always move in the same pattern?

if not then you need a fully dynamic shadowing technique. What is the max distance your lights will be from the terrain? If it is close to the terrain, you can use lots of shadowing techniques. If it is far (like a sun) you will need cascaded shadow maps.

also i would advise you to make your terrain "lod'able" so you can render a lower quality of mesh for the shadow maps. If you for example use a blur after rendering the mesh, the low quality of the mesh is almost not visible anyway.

It saves you render time ;)
MJP
MJP
Yeah CSM's are the order of the day for outdoor shadows from a directional light source. They require some tweaking though to get a distribution that's good for your scene.

As for the terrain shadows...you have a few options. You can just render it right right into your shadow map so that your terrain has proper dynamic shadows that work with your dynamic geometry. You could also pre-calculate shadow data for the static terrain, and you could even use that data on dynamic geometry if your terrain is just a heightmap.
transwarp
transwarp
The game has a fantasy setting: Two moons orbiting periodically, no sun.
I.e. the light sources are infinitely far away and always move in the same pattern.

Is there some way to pre-calculate shadow maps for this?
MJP
MJP
Well if you pre-calculate shadow information for your static terrain, you're going to need to do it again every time your moons rotate. If they rotate very slowly, you could possibly distribute this calculation across N frames to reduce the performance impact.
Matt Aufderheide
Matt Aufderheide
Quote:
Original post by transwarpIs there some way to pre-calculate shadow maps for this?


Yes but to get smooth transitions between times of day you would need a lot of memory.

For an RTS (overhead) kind of game, you probably don't need CSM or something as complicated. A single shadow map (or two if you have two light sources) with a good frustum that matches the viewing frustum is probably enough.

You can render moving objects into a separate shadow map, and render the terrain into another; that way you can update the terrain shadows less frequently, but still often enough that time of day transitions look smooth.

Unless you terrain has a very high triangle density, it shouldn't be costly to render it every frame though.
InvalidPointer
InvalidPointer
Quote:
Original post by transwarp
The game has a fantasy setting: Two moons orbiting periodically, no sun.
I.e. the light sources are infinitely far away and always move in the same pattern.

Is there some way to pre-calculate shadow maps for this?

Yes. http://http.developer.nvidia.com/GPUGems/gpugems_ch13.html
It's really fast at runtime, too, fairly light on memory consumption IIRC. Should be just what the doctor ordered.

It doesn't work for dynamic entities, though. Has to be static. I would go with a system described by Matt, maybe using something like this: http://appsrv.cse.cuhk.edu.hk/~fzhang/pssm_project/

Combining it would be tricky, but if you're only doing this for one light I can imagine you could just store a mask texture or something and do a multiply/'minimum value' or similar on the results from both passes. Another multiply-add (for sun color and then final light combine) should then be enough to get it into your scene.

Although, now that I think about it, you might end up with a lot of redundant work/double shadowing. In order for terrain to correctly shadow dynamic objects, you'd have to include it in the PSSM. That takes more thought.

clb: At the end of 2012, the positions of jupiter, saturn, mercury, and deimos are aligned so as to cause a denormalized flush-to-zero bug when computing earth's gravitational force, slinging it to the sun.
transwarp
transwarp
Quote:
Original post by InvalidPointer
Yes. http://http.developer.nvidia.com/GPUGems/gpugems_ch13.html
It's really fast at runtime, too, fairly light on memory consumption IIRC. Should be just what the doctor ordered.

This method looks great, however since there is a map editor for normal end-users included with the game, such an extensive pre-procession ray-tracing step is not really practical.
But based on the article I came up with a simplified version of the technique I'd like to share:

Since my terrain is based on a plain heightmap, there are no "holes" in it. For the light-visibility-function this means that the light source becomes visible for each pixel at a certain point of time in the light-movement-cycle and then vanishes at another, with no intermediate on-off-phases.
Also, my two light source both follow the same path, only with different speeds and moving in opposite directions. So instead of having separate light-visibility-functions for the two lights depending on the time I could have one function depending on the vertical light angle.

Based on these simplifications I'd store two additional textures alongside with the heightmap, representing the "Occlusion Interval Map": Basically two grayscale images pixel-wise signifying the lowest and highest light-angle, in-between which the light-sources will be effective (not occluded).
When loading the map files I would transfer this data into the vertex information, instead of sampling it at runtime. The pixel shader would then get two nicely interpolated "Occlusion Interval Border Values" to determine whether a light source is occluded or effective.

As for generating these occlusion maps:
When viewed from the perspective of the heightmap the light sources move on a straight line from left-to-right (or the other way round).
For each pixel of the first occlusion map I move left along the heightmap pixel-by-pixel using basic trigonometry to determine the lowest possible angle for incoming light. In the end I keep the highest angle found for that pixel. This yields the first file.
The same process is repeated now moving right and finding the highest possible angles. Second file complete.

What do you think? A sensible approach?

Regards,
Bastian

Topic Locked

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

Sign in to reply to this topic.