Lighting and Shadows
- being largely static, terrain usually only needs to have lighting
calculations done when the light moves or the terrain deforms
- for non-colored lights, even with multiple light sources, all that needs
to be computed and stored is a single scalar value, 1 byte per heixel
- the most efficient way to render this is to combine the lighting with
the texture map
Self-Shadowing (Shadows Cast by the Terrain onto Itself)
- Fast
Computation of Terrain Shadow Maps by Mircea Marghidanu
- brief, well-written article shows exactly how to do this with a
heightfield grid
- includes easy-to-follow source code
-
paper
on
Terrain Illumination by
James Stewart
- you can get beautiful soft shadows, perhaps fast enough for
realtime, by pre-calculating the "horizon" for each element of the
terrain
- however, there is a potentially large storage cost
-
Ambient Aperture Lighting (pdf) by Oat and Sander (2007)
- Claims that you don't need to precalculate the entire horizon, you
can get reasonable results by calculating a "spherical cap", which can
be used on the GPU (pixel shader) for realtime lighting. This uses less
memory can still give soft shadows. The spherical intersection
operation can be approximated with the 'smoothstep' function.
Shadows Cast by Objects onto the Terrain
- Jaimi McEntire writes:
- "What I do is to gather the polys around the character, and
project the shadow poly straight down, clipping the shadow poly to each
of the ground polys by using the shadow poly "volume" (which is just
four planes, created from the edges of the shadow poly). This leaves you
with multiple shadow polys that then have to be rendered."
Shadows Cast by the Terrain onto Objects
- objects in the scene (buildings, trees, etc.) also need to be shaded by
the terrain itself
- ray casting
- one approach is to cast rays from the object to the sun, tested for
intersection with the terrain
- moving objects may only need to cast once every few frames, with a
high framerate
- "shadow map"
- in addition to the heightmap, create a second bitmap that stores the
height of the shadow volume at every pixel - i.e. the height at which
the sun becomes occluded and you enter the shadows
- at run-time, compare the height in the shadow map with the actual
altitude of the object - if the object is lower, it's in the shadows
- might take a bit of extra work to make the transition into shadow
smooth
- the shadow map could potentially be lower-resolution or smaller
precision than the heightmap
Optimization
- Real-Time
Photorealistic Terrain Lighting (MS Word doc), Naty Hoffman, Kenny
Mitchell, GDC2001
- looks rigorous, with quite a lot of math, no code
- John Ratcliff says of his approach:
- "Dynamically, mip/map levels of the textures are generated by
combing the source surface texture and the normal map to produce the lit
version of the texture. On a GeForce it would be feasible to use their
normal mapping feature for this effect. The mip/map levels of the
textures are absolutely essential to keep from having 60 to 70 megabytes
of textures in the view frustum at any given moment!! The mip map levels
must be able to be generated dynamically and relatively CPU free. I am
currently using the IPL, which is optimized for MMX to produce the
MIP/MAP levels on the fly, which included making nice smooth looking
light maps from the normal maps which are synthesized on the fly."