Shadows

CS 381 Lecture, Dr. Lawlor

Here are a bunch of ways to represent shadows.  Try them out in my "shadow" example program (Zip, Tar-gzip)

Shadows in General

Shadows are an important aspect of our perception of a scene.  Without shadows, objects seem to "float" above the ground, because we can't relate the position of the objects and the ground. No shadows

No Shadows

Unrealistic Shadows

Lots of totally fake shadow algorithms exist.  With these algorithms, objects never cast shadows on themselves or other objects, just a pre-defined "ground" object.
Decal shadows: draw something dark (usually an alpha-blended textured quad) on the ground plane beneath each object.
  • Advantages:
    • Very easy and fast.
    • Can be made to work on non-planar surfaces (sort of).
    • Trivially allows soft shadows, by just using a blurry decal texture. This soft shadow can be more attractive than hard shadow maps/volumes.
  • Disadvantages:
    • Shape of shadow is not related to the shape of the object.  At all.  This is clearly silly, since a teapot should cast a teapot-shaped shadow, not a fixed splooch.
    • It can be tough to avoid z-buffer fighting when drawing the decal.  One method is to draw the ground, turn off Z buffer tests and writes, draw the decals, then draw everything else.  Another method is to draw the decals normally, but shift their geometry slightly off the ground.
shadow maps

Decal Shadows

Projected shadows: squish actual world geometry down onto ground plane, and draw it dark.
  • Advantages:
    • Very easy: just need a projection matrix to squish geometry to plane.
  • Disadvantages:
    • Where two objects intersect, you'll draw dark geometry twice, which gives ugly darker regions where two shadows overlap.
    • Difficult to make it work on non-planar surfaces.
    • Doubles amount of geometry.
    • Same z-buffer problems as with decal shadows.
Projected shadows

Projected Shadows

Projected shadows with stencil: like projected shadows, but avoids drawing the same part of the ground twice by first rendering the geometry to the stencil buffer, then drawing where the stencil is set. stencil shadows: stencil buffer
Stencil shadows: color

Stencil buffer
Projected w/ Stencil Shadows

Point Light Shadow Algorithms

These algorithms can cast shadows from curved objects onto themselves or each other.  The big remaining limitation is that the shadows have hard edges--they're shadows cast by a point light source.
Shadow maps: render world from point of view of light source, storing the depth to the topmost (and only lit) object.  When rendering, check the depth to the light source: if on top of the shadow map, you're lit, if beneath, you're in the dark.
  • Advantages:
    • Works with curved surfaces and shadow receivers.
    • Easy enough: render world from light source is just another render.
  • Disadvantages:
    • Depth is discretized--must choose resolution and coverage (almost never good enough!)
    • Draw everything twice (once from light source, again from camera).

Here's a nice tutorial on shadow mapping from CMU, with more pictures.
Shadow Map Depth Image
Shadow map: depth image
Shadow Map Color Image
Shadow map: color image

Stencil shadows: color


Shadow Map Shadows

Shadow volumes: extrude ``shadow silhouettes'' from the boundary of each object (as seen from the light source), and render those silhouettes onscreen.  For conventional shadow volumes, increment the stencil buffer on the *front* faces, and decrement on the *back* faces.  After doing this, the stencil buffer contains the number of shadows entered but never exited--this is hence a count of the number of shadows each piece of geometry is in.  If you're inside at least one shadow (i.e., your stencil buffer value is nonzero), you are hence in shadow.


Shadow Silhouettes
Shadow Volume Silhouette Buffer Values
Shadow Volumes

Shadow Volume Silhouettes
Shadow Volume Stencil Buffer Totals
Shadow Volume Shadows

Carmack Shadow Volumes: just like normal shadow volumes, but when drawing the silhouettes, invert the sense of the depth test, and increment *back* faces and decrement *front* faces.  This has the advantage that it even works when the camera starts off inside a shadow volume.

Area Light Shadow Algorithms

Real distributed light sources cast soft shadows.  There are many algorithms out there to compute soft shadows.  The oldest method is to cast many rays to the light source--the fraction of rays that reach the light source gives the approximate fraction of the light source that is visible, and hence the fraction of light that reaches the point.  For simple scenes (e.g., one spherical lightsource and one occluding sphere or polygon), it's actually possible to analytically compute this fraction of illumination; for complicated scenes, we really don't have much hope of getting shadows exactly right--because occluding geometry can act like a pinhole camera, and hence expand an abitrarily complicated shadow pattern from any point in space.

Modern methods to approximate soft shadows include a shadow volume-like "silhouette wedge" method, primarily by Assarson; and several extended shadow map generation techniques, like Chan and Durand called Smoothies.  All of these have advantages and disadvantages, which are still being sorted out in the literature and in research labs.

I actually wrote a little paper on "penumbra limit maps", a fairly cheap way to get soft shadows on the graphics hardware.

I've also written a little global illumination system based on a conetracing-like idea, but for polygons.  The shadows look great, but they're about the limit of scene complexity the system can handle at reasonable speed!

Sunlight
Sunlight Sunlight
"Sun" light: small orange light source
Sun and sky together
"Sky" light: big blue source