PhotoRealistic
RenderMan
Application Note #26
Soft Shadows in PhotoRealistic RenderMan
August, 1998
Figure 1: Soft Shadows
Introduction
PhotoRealistic RenderMan has always supported shadow computations
through the use of prerendered shadowmaps, which can determine
shadowing information for a single light source point. Unfortunately,
such shadows have hard boundaries and are characteristic of computer
graphics (see figure 2). More realistic shadows
come from light sources that aren't a single point; the RenderMan spec
defines the use of area lights but they aren't implemented in PRMan.
Shadow computations from area light sources require visibility checks
with more than one point on the light source. One way to approximate
area shadows is by rendering multiple shadowmaps from various points on
the light source, and averaging their shadow contributions. (see figures 3 and 4). If we were able to render an
infinite number of shadowmaps, this would converge to the answer we
seek. This is infeasible, of course, so we would like a solution which
can approximate soft shadows without requiring a large number of
shadowmaps.
PRMan 3.8 provides such a solution. The shadow shadeop has a
new form which accepts multiple shadowmaps and a specification of the
"area light's" shape. Since this only affects shadow computations, you
don't get other phenomena associated with area light sources (such as
non-point highlights), but the softening of shadows goes a long way to
make illumination more realistic.
How to use them
Before you can render an image with soft shadows, you must render
shadowmaps which will provide the renderer with visibility information
for the occluding objects. While normal shadows require only one
shadowmap rendered from the light source's location, soft shadows
require multiple shadowmaps from various points on the light source's
area. The arrangement of the shadowmaps is up to the user, but in
general a few shadowmaps from evenly-spaced points on the light source
will produce the best results.
IMPORTANT: There are currently two restrictions which must be followed
when rendering these shadow views:
- Currently PRMan requires that all of the geometry which will cast
shadows from a given light source must be contained in every
shadowmap which is supplied to the shadow call. Clearly, each
view will have different information (because of the shifted view
position), but the volume of the occluding objects must be
contained in the view frusta of every shadowmap.
- The shadowmaps must be in a new, special shadowmap format called
minmax shadowmap. This format contains a hierarchical min-max
tree of occlusion information which allows the soft shadow computation
to be more efficient. These minmax shadow files are computed either by
the RiMakeShadow call or with the separate utility
txmake. (See below.)
Once you have multiple shadowmaps providing various views of the
occluding objects, you can use them in a shadow call to render
soft shadows. There are a few differences between the soft-shadow form
of shadow and the normal case:
- The "name" parameter can be a comma-separated list of filenames
rather than a single filename. This is where you list the various
views you've rendered.
- The new "source" parameter lets you specify the location and
shape of the area light source. We never had to specify this before
because the location was implicitly the origin of the shadowmap's
view; since we have multiple shadowmaps now, we must be more explicit.
The "source" keyword must be followed by one, two, three, or four
points (which must be uniform and in current space),
which will specify a point, line segment, triangle, or quadrilateral
light source; if using a quadrilateral light source the points must be
specified in "bowtie" order (in the same way that the points are
ordered for a bilinear patch). The renderer will integrate its
lighting computations over this area. It is generally advisable that
your shadowmaps are rendered from various points on this
surface.
- The new "gapbias" parameter tells the renderer how to infer
connectivity information in the shadowmaps. Adjacent pixels whose z
values are within "gapbias" of each other will be assumed to be part of
the same object. Sometimes experimentation may be necessary to find
the right gapbias value, but a good starting point (and often a good
enough value) is the shadow bias number.
As before, the bias parameter specifies how far to shift samples
towards to the light source to prevent self-shadowing of objects.
The samples parameter still specifies how many samples to cast
when performing the shadowmap computation. Larger values will produce
less noisy output and smoother shadows, but are proportionally more
expensive to compute.
Example
Suppose you have rendered the four shadow views from figure 3 into the zfiles "light1.z", "light2.z",
"light3.z", and "light4.z". Before you can use these for soft shadows,
you must convert these into minmaxshadow files. This can be done in
one of two ways:
txmake -minmaxshadow light1.z light1.shad
txmake -minmaxshadow light2.z light2.shad
txmake -minmaxshadow light3.z light3.shad
txmake -minmaxshadow light4.z light4.shad
Alternately, you can place a MakeShadow call in the RIB stream
after each shadow pass. For example, in the RIB that creates
"light1.z",
MakeShadow "light1.z" "light1.shad" "minmax" 1
will create the minmax shadow file "light1.shad".
Next, we must write a shader that will make use of multiple minmax
shadow files. Here's an example:
light arealight(color lightcolor = color(1,1,1);
float intensity = 1;
string maplist = "";
float numsamples = 1;
point Pl1 = point(0, 0, 0);
point Pl2 = point(0, 1, 0);
point Pl3 = point(0, 0, 1);
point Pl4 = point(0, 1, 1);
float shadowBias = 0.001;
float gapBias = 0.01) {
varying float attenuation;
illuminate ((Pl1+Pl2+Pl3+Pl4)*0.25) { /* base illumination at average */
/* of light positions */
attenuation = shadow(maplist,Ps,"source",Pl1,Pl2,Pl3,Pl4,
"samples",numsamples, "bias",shadowBias, "gapbias", gapBias);
Cl = lightcolor * intensity * (1-attenuation);
}
}
Note that this shader expects the comma-separated list of shadow views
to be passed through the parameter "maplist." To use this shader in a
final render, we make a light source in RIB that uses the above
shader. For this shader, we pass in the list of views and the four
corners of the light source:
LightSource "arealight" 1 "intensity" [1]
"maplist" ["light1.shad,light2.shad,light3.shad,light4.shad"],
"Pl1" [1.15622 -8.83187 4.78469]
"Pl2" [0.191448 -6.11682 8.94722]
"Pl3" [5.9265 -7.13679 4.78469]
"Pl4" [4.96173 -4.42175 8.94722]
"gapBias" [0.03]
"shadowBias" [0.3]
"numsamples" [36]
Figure 2: Hard shadow
Figure 3: Four shadowmaps
Figure 4: Averaging the results of four shadowmaps
Pixar Animation Studios
(510) 752-3000 (voice)
(510) 752-3151 (fax)
Copyright © 1996-
Pixar. All rights reserved.
RenderMan® is a registered trademark of Pixar. |