Adding shadows is one of the most effective ways of adding realism to a computer-generated image. The human visual system uses shadows to determine depth, light location, and direction, as well as spatial relationships between objects. PhotoRealistic RenderMan supports shadows using a shadow map algorithm. This algorithm is a compromise between shadow quality, ease of use, and rendering efficiency. Using a ray tracing algorithm to make shadows offers greater ease of use and higher quality, but at a price of slow execution speed and incompatibility with the other PhotoRealistic RenderMan rendering algorithms. Other algorithms, such as drop shadows (computing the shadow projection onto a surface, and adding dark-colored geometry to represent the shadow), are more efficient but much less flexible than shadow mapping.  The shadow map algorithm offers significantly more efficiency if multiple frames are to be rendered that have the same light locations and attributes.
The basic shadow map method is relatively easy to use, but it is not automatic. For each light that casts a shadow a shadow map image must be rendered. This image is rendered from the location of the light source. The image is then converted into a format suitable for use by special light shaders that can use the map to selectively light the scene. This selective lighting produces shadows. The basic approach is shown in Figure 1, below.  Each type of light must be handled differently to ensure that proper shadows are produced.
For lights that have a direction (such as spotlights and distant lights), the view for the shadow image is in the light direction. Point lights are handled differently, as will be explained later.
Listing 1 shows placecam.c, a simple program used to calculate the RenderMan transforms needed to place the camera at the light position and point it in the proper direction, given a location and aim point. These transforms are used as the camera transform for the map image. For lights with only a location (point lights) a translation to place the light at the origin is needed. This translation is simply the negation of the light's location components. The direction is computed in a special way described later.
The placecam program can also calculate the required field of view for a spot light using the above formula.
Lights that come from a direction but have no location, such as distant lights, should have their shadow maps rendered using an orthographic projection. Orthographic projections have no field of view, so the area covered by the shadow map image is controlled by the ScreenWindow setting. ScreenWindow values are easy to calculate because they are just the extents of the scene in the camera space x and y directions. A description of setting a distant light map image ScreenWindow appears later in this document.
When a shadow image is rendered, the zfile display driver is used to write a depth image of the scene. This image contains the depth of the first surface encountered at each image pixel. The format of the z file must be changed to a shadow texture file format before it is used to make an image. The image is reformatted using MakeShadow during rendering or using the txmake utility with the -shadow option from the command line.
Finally, special shadow light shaders must be used to access the shadow map during final image creation. These shaders use the shadow() shading language function to access the map. See Listing 2 (the shader code for the shadowdistant light shader) for an example of accessing a shadow map. Three shadow light shaders are provided with Developer's RenderMan: shadowdistant, shadowspot, and shadowpoint. Implementing the above procedure to produce shadows in your images will work, but it will not produce the highest image quality or be as efficient as possible. Several more complex issues must be addressed to produce optimal shadows.
There are two major quality issues to be addressed when making images with shadows: self-shadowing and shadow map resolution. The former can actually affect the appearance of the object that casts the shadow; the latter affects the shadow's edges. There are also ways to create shadow maps as efficiently as possible.
Self-shadowing occurs when, because of numerical inaccuracies or other problems, shadows are incorrectly produced on the object that should be casting the shadow. In PhotoRealistic RenderMan, self-shadowing is avoided by having a "tolerance" around objects. No shadow will be cast on a point inside this tolerance. The tolerance is called the shadow bias. While there are two RIB calls used to set the bias, for our purposes they should both use the same value. Shadow bias must be set correctly or two different types of artifacts can be produced. If the bias is too small self-shadowing will occur and spots of shadow will appear on objects in the scene at inappropriate locations. If the bias is too large shadows will appear to be detached from objects. This is especially noticeable when an object is resting on and casting shadows on the same surface. To see examples of these two problems, render the file biasshad.rib to produce the required shadow map and then bias.rib with each of the five bias values in the RIB file.
The number of pixels in a shadow map controls both the quality of the shadows in an image and the rendering time for the map. If there are too few pixels the individual shadow pixels will be visible in the image. This will give the shadows a jagged appearance or it will cause the edges of the shadow to be ragged. If the resolution is too high time is wasted rendering unnecessary pixels. Render resshad.rib with each of the resolutions given in the file and, for each new map, render res.rib to see the effect of the map resolution. The lowest-resolution map also shows that the correct bias value depends on the resolution of the map. For this reason, it is a good idea to test shadow bias at the resolution of the final image.
When making a shadow map we want to use as many of the calculated pixels as possible; it makes no sense to spend time rendering pixels we won't use. This means we should only include an object, or part of an object, in the shadow map if it casts a shadow visible in the final image. We can control the absolute resolution of a shadow map using the Format statement, as with any RenderMan image. We control the objects included in the shadow map using either the "fov" parameter when using perspective projection, or the ScreenWindow parameters when using orthographic projection.
For additional efficiency you can, of course, remove objects from a RIB file when making the shadow maps. This will prevent these objects from casting shadows. Removing objects, especially if they cover a large area of the screen, can decrease rendering times substantially. This technique is often useful for objects that form the background in an image, since they usually cast no shadows and often cover large areas of the screen. Notice that the background patch in resshad.rib has been removed to speed up the shadow map rendering. Various special effects also require removing objects from the shadow map RIB files.
Listing 8 (noshad.rib) is a RIB file with a distant, a spot and a point light, but no shadows. Listing 9 (allshad.rib) is the same, but includes the shadows. The RIB files distant.rib, spot.rib, and the set pointpx.rib, pointpy.rib, pointpz.rib, pointnx.rib, pointny.rib, and pointnz.rib show examples of making shadows for all three basic light types. All of these images show nine cylinders in a corner formed by three bilinear patches. A distant light comes from the top front right corner. A spot light with a 24° cone angle is located near the top front right corner. A point light is located where the middle pin in a setup would be, at a height of about two units above the floor patch.
For each shadow map we use the same rendering parameters and we remove all the shaders (Surface and LightSource statements) from the file. As a result, we'll get the maximum rendering speed without affecting the shadow quality. If there were displacement shaders we would leave them in the shadow map files because they would change the geometry of the scene and might affect the shadow map images. The zfile driver is used in each Display statement. At the end of each shadow map file, after WorldEnd, we added a MakeShadow statement to convert from the z file format to the shadow map file format. When examining the camera transforms in the RIB files, remember that transforms are applied in bottom-to-top order in RenderMan.
First, let's examine how we set up the shadow RIB file for the distant light. First we calculated the camera transform to make the shadow map. This was easy in our example because the distant light was in world space, so all we had to do is run the placecam program with the distant light "from" and "to" parameters. If any transforms had been active for the LightSource statement we would have had to apply these transforms to the "from" and "to" parameters before using placecam. We then added the orthographic projection needed for a distant light camera.
The hardest part of setting up the distant light shadow was to limit the view of the camera to cover only the objects that should cast shadows. We used a trial-and-error method to determine the parameters needed by the ScreenWindow statement. First we tried a default ScreenWindow of -1 1 -1 1. This was too small because it didn't cover all the cylinders. Next we tried -2 2 -2 2; this was too big on the right and bottom and too small on the top. We tried -2 1.8 -1.8 2.2; not too bad, but still too big on the right side. Finally we settled on -2 1.3 -1.8 2.2, which fits the cylinders well. We tried all these tests displaying to a framebuffer, using a very small window (64x64) after commenting out the MakeShadow statement.
Now that we had a shadow RIB file with the correct camera setup and rendering parameters (after we restored the Display and MakeShadow calls), we needed a first estimate for the image size to use for the shadow map generation. A good first try is a map size similar to the image size, in this case 256x256. Remember, a shadow map's size must be a power of two in both directions.
The shadow map RIB file for the spot light was generated in a similar manner, except it was easier to get the correct field of view for the camera. First we calculated the camera parameters using placecam and the "from", "to", and "coneangle" values from the spot light statement. The statements from placecam were used directly in the RIB file, as indicated in Listing 12, spot.rib. We started with a Format statement of 256 256 1 again as a first estimate for the correct shadow map size.
The RIB files used for point light shadows were easy to build, but we needed six of them, one for each major world space direction (negative and positive x, y, and z). The camera transform for a point light consists of a Rotate statement to point the camera in the correct direction and a Translate statement to place the camera at the point light location. The Translate call simply negates the "from" coordinates of the point light source, moving the camera back to that point. The Rotate calls were described above. The shadow maps were made with a "perspective" projection and an "fov" greater than 90°. We used 95° here.
At this point we had files to make the shadow maps, but we still needed to modify the image file to use these maps. For the distant light we replaced the shader name "distantlight" with "shadowdistant" and added a "shadowname" parameter with the correct shadow map name. For the spot light we replaced the shader name "spotlight" with "shadowspot" and added the correct "shadowname" parameter. Finally, for the point light we replaced "pointlight" with "shadowpoint" and added the six file name parameters "sfpx", "sfnx", "sfpy", "sfny", "sfpz" and "sfnz".
The eight files (six for the point light, and one each for the spot and distant lights) are all the basic RIB files we need to create and use the shadow maps for our demonstration images, but we still needed to do some test renderings to determine the correct shadow bias value and map resolutions for good image quality.
A rule of thumb for setting the bias is to use 1% of the largest extent of the objects included in the image, measured in camera space. Unfortunately this number may be difficult to calculate for RIB files with complex geometry. A trial and error method is often best. Remember, bias too large will cause shadows to be "separated" from their objects and a bias too small will cause random dark spots on objects. We used a trial-and-error method and found a value of 0.1 to be correct for this image.
During our test rendering we found the shadow from the distant light to be of low quality because the map resolution was too low. We increased the resolution to 512x512 and this improved the shadow quality. The resolution of the spot light map seemed to be reasonable, and the resolution of the point light map was quite good.
We have now described and given examples for using the PhotoRealistic RenderMan shadow capabilities for an end user with access to RIB files. It was never intended for end users to have to follow this procedure, because we hoped all modeling program writers would include support for automatically making shadows in their programs when they added RenderMan support. Modeling programs have access to all of the model data and the power of the computer allowing them to use even more powerful techniques to produce shadows using RenderMan.
*    for a scene. This routine must be called before RiWorldBegin().
*    might be in negative z, but not afterward.
* component, and the rotated x,z vector from above.
**secrets of Pixar.  Reverse engineering of object code is prohibited.
**Technical Data and Computer Software clause at 252.227-7013.
#transform to place camera at distant light "from" and aim at "to"
#transform to place camera at point light "from"
 REEVES, WILLIAM T., SALESIN, DAVID H., and COOK, ROBERT L., "Rendering Antialiased Shadows with Depth Maps," Computer Graphics (SIGGRAPH '87 proceedings) 21(4) (July 1987).