Photon Mapping

CS 580 Programming Assignment 4


by Elshad Kasumov

Description

This program is an implementation of a photon mapping renderer for triangular, planar, and spherical models. The implementation is closely modeled on
Jensen, Realistic Image Synthesis Using Photon Mapping, AK Peters Ltd, ISBN 1568811470

Photon mapping is a rendering technique that uses emitted (as well as refracted and reflected) photons to calculate the illumination of a particular
location; it allows for such effects as caustics and soft shadows, which are simply not available to non-distributed ray tracing and are possible, but very
costly with distributed ray tracing.

A photon is a structure with a position, a splitting plane (used for splitting kd-trees), an incoming direction denoted by angles theta and
phi, and power.

This is a C++ implementation of the photon map. It will execute on CSA with the included Makefile.

The basic photon mapping algorithm consists of two steps:

  1. Photon Casting
  2. Rendering
Photon casting uses a basic ray-tracing approach to cast out photons from a light source (only point light sources in this particular implementaiotn); upon hitting
a surface, the photon is either reflected or absorbed - decided by a Russian roulette - and, depending on factors such as the reflectivity of the surface, etc., is
stored in the photon map.

Rendering, described very simply, is casting a ray from a view point into the scene (very similar to the ray tracing procedure), and, upon hitting a surface, computing
the radiance at that location by processing n nearest photons and interpolating their power with a BRDF.

Pseudo Code

Photon Casting

  1. Initialize the scene and the light sources
  2. For every light source:
    1. Emit photons
      • while (number_of_emitted_photons < MAX_PHOTONS)
        • x = E 1
        • y = E 2
        • z = E 3
      • dir = normalized (x, y, z)
      • p = light source position
      • cast out the photon from p in direction dir and, if connects, store in the photon map
      • increment number of emitted photons
      • scale power of stored photons with 1/ne (number of emitted photons)
    Where E is a uniformly-distributed random number in the range [-1, 1]
Rendering

For every pixel (i, j) in the projection screen:

  1. Compute primary ray from the view point in the direction of (i, j)
  2. Get the closest intercept point, as well as the surface normal at that location, and the index of the object that was intersected
  3. Call the irradiance_estimate 1 function of the photon map class to compute radiance at that location
  4. Add in the ambient lighting component of the intersected object
  5. Set the pixel into the ppm buffer
Functions:
irradiance_estimate (x, w, n) {
locate n nearest photons r = distance to the nth nearest photons
sum(flux) = 0
for each photon p do {
pd = photon direction
phip = photon power
sum(flux) += fr(x, w, pd ) * phip
}
Lr = sum(flux)/(2pi r2)

fr(x, w, pd ) = Il,diff = kdIl (N . L), where L = -pd

Module Diagram

Screenshots

Source Code

Acknowledgements:   C++ code for the ray tracer employed in this assignment provided by Jing Zhong, and may not be used without permission. Modified slightly
                for purposes of assignment.

                Photon Map C++ code based almost entirely on that provided in the appendix of Realistic Image Synthesis Using Photon Mapping.