1. Shadow mapping is a technique for rendering shadows from point and distant light sources based on rendering an image from the light source’s perspective that records depth in each pixel of the image and then projecting points onto the shadow map and comparing their depth to the depth of the first visible object as seen from the light in that direction. This method was first described by Williams (1978), and Reeves, Salesin, and Cook (1987) developed a number of key improvements. Modify pbrt to be able to render depth map images into a file and then use them for shadow testing for lights in place of tracing shadow rays. How much faster can this be? Discuss the advantages and disadvantages of the two approaches.
  2. Through algebraic manipulation and precomputation of one more value in the constructor, the SpotLight::Falloff() method can be rewritten to compute the exact same result (modulo floating-point differences) while using no square root computations and no divides (recall that the Vector3::Normalize() method performs both a square root and a divide). Derive and implement this optimization. How much is running time improved on a spotlight-heavy scene?
  3. The functionality of the SpotLight could be replicated by using a suitable image in conjunction with the ProjectionLight. Discuss the advantages and disadvantages of providing this specific functionality separately with the SpotLight class.
  4. The current light source implementations don’t support animated transformations. Modify pbrt to include this functionality, and render images showing off the effect of animating light positions.
  5. Modify the ProjectionLight to also support orthographic projections. This variant is particularly useful even without an image map, since it gives a directional light source with a beam of user-defined extent.
  6. Write an AreaLight implementation that improves on the DiffuseAreaLight by supporting spatially and directionally varying emitted radiance, specified via either image maps or Textures. Use it to render images with effects like a television illuminating a dark room or a stained-glass window lit from behind.
  7. Many of the Light::Power() method implementations only compute approximations to the actual emitted power for their lights. In particular, all of the lights that use images (ProjectionLight, GonioPhotometricLight, and InfiniteAreaLight) all neglect the fact that for each of them, different pixels subtend different solid angles and therefore contribute differently to the emitted power. Derive accurate models for the emitted power of these light sources, and implement them in pbrt. How much error do the current implementations have when used in some of the pbrt example scenes? Can you construct contrived scenes to show the maximum error introduced by the current implementation?
  8. Read some of the papers in the “Further Reading” section that discuss the shadow cache, and add this optimization to pbrt. Measure how much it speeds up the system for a variety of scenes. What techniques can you come up with that make it work better in the presence of multiple levels of reflection?
  9. Modify pbrt to support the shaft culling algorithm (Haines and Wallace 1994). Measure the performance difference for scenes with area light sources. Make sure that your implementation still performs well even with very large light sources (like a hemispherical skylight).
  10. Read the paper by Velázquez-Armendáriz et al. (2015), and implement their method for efficiently rendering scenes with complex light sources. Create or find models of a few complex lights, including many shapes that exhibit specular reflection and/or transmission. Compare results using your implementation to renderings using one or more of the bidirectional integrators from Chapter 16 (which are best suited to handling this challenge). Note that you may need to set very long maximum integrator path lengths for the current implementation of pbrt to be able to render these scenes at all. How much more efficiently does your implementation render images of scenes lit by these lights than the built-in integrators? Do results from the two approaches match?