|
Aims | Current state
| Simulation
results and Discussion | Source code
and binaries | References
| email: golas at cs
dot unc dot edu |
Aims:
This assignment had the
following aims:
I've used the photon map approach to add global illumination support to the ray tracer.
The photon map approach is a simple two pass approach to global illumination. The first pass is a forward photon tracing pass. Photon tracing is the same as ray tracing, hence the same architecture can be used for this pass. Photons are emitted from all light sources in the scene, and traced throughout the scene. The only difference from ray tracing is that the originating "photon rays" originate from light sources rather than from the camera, like what is known as "forward ray tracing" (albeit, in more recent terminology, in older terminology, it's backward rt). The so-called photon rays can undergo the same scene interactions as light rays, like specular and diffuse reflections, refractions, and in addition, can get absorbed by the surface. At each interaction we store a copy of the photon to be used in the second pass. For storing photons, we use 2 photon maps, a caustic map for storing photons which have undergone specular reflections and refractions only, and a global map for all other photons. The primary difference between photon tracing and ray tracing is that instead of spawning multiple rays for each interaction, we do a Russian Roulette to choose which interaction to pursue further. The tracing algorithm can be expressed as follows:
algorithm photon_trace {
Until enough photons are stored {
Pick a light source and generate photon
At each step {
If number of intersections of current photon > 1 {
If photon has only encountered specular reflections or transmissions ->
Store copy in caustic map
Else store in global map
}
Do Russian Roulette: Generate random number r in the range [0,1]
If r < kt (transmission coeff) -> Refract photon ray
Else if r < kr + lr -> Reflect ray {
Generate a new random number r' in the range [0,1]
Get probability of Specular reflection Ps, and Diffuse reflection Pd
If r' < Pd -> Diffuse reflect after sampling random direction after
appropriate power scaling
Else if r' < Pd + Ps -> Specular reflect after appropriate power scaling
Else Absorb photon
}
Else Absorb photon (end iterations on this photon)
}
}
}
For emitting photons, I've made a simplifying assumption that all light sources are of the same power. This allows me to use a simple round robin system to choose which light source to emit from, rather than use a complicated probability distribution to ensure fairness and conform to the actual physical phenomena. To emit photon from a light source, the direction is sampled as a point on the surface of a unit sphere. Since I have not added directional light sources, this scheme is sufficient. For point lights, the source of the photon ray is the location of the point light, while for area lights, the source is sampled on the light source disk.
The second pass of the photon map algorithm involves rendering
the scene using the photon map. A Kd-tree is used to optimize nearest neighbor
search that is required to get photons to retrieve the global illumination.
For gathering photons, I use a recursively increasing search radius method as
used in MegaPOV, which starts with a low search radius, and successively increases
the radius if the desired number of photons are not found. The
radiance estimate for a point on screen can be shown to be:
L = Direct
Illumination + Specular/glossy reflection + Diffuse reflections + Caustics +
Refraction
The direct illumination, specular reflection and refraction components can be
efficiently computed by using conventional ray tracing methods, and hence we do
not use photon maps for them. However, diffuse reflections and caustics are
calculated by taking samples from the global and caustic maps respectively.
Simulation
results and Discussion:
To illustrate the global illumination calculation, we can look at the following component images:
+ + + + =
Direct
Specular Diffuse Caustics
Refraction Final
7.33s 13.22s 41.65s
138.95s 6.98s 191.74s
The original image without
global illumination is:
This was rendered in 15.78 seconds when checking till 10 reflections and
refractions. The scene is a modified Cornell Box, in which there is 1
transparent and specular sphere each. The transparent sphere has the refractive
index of glass. The light source is a point light source and is placed on the
left wall. The scene shown above used just 1000 caustic and global photons
each, with 10 photons per sample. For these photons, 100227 photons were shot,
in 0.145 seconds.
From the implementation, I observed that photon mapping is a relatively easy to implement, albeit slow, but very powerful global illumination algorithm. But faster implementations exist, and parallel implementations can make it feasible to use the method. The only downside is the memory requirement for rendering high quality scenes. Moreover, getting the right scaling parameters for photon gathering can be difficult in practice when using filters to improve quality, for example the gaussian or cone filter. However, using a gaussian filter with photon gathering can be used to create somewhat artistic, and interesting artifacts:
Site last updated: Monday, September 8, 2008 12:00 AM