In this assignment, you will learn about monte carlo sampling for solving the rendering equation and acceleration techniques.
The assignment description can be found in PDF form here. There is also this project roadmap. Let us know if you have any questions.
There will be a rendering contest at the end of the assignment.
We are providing you with a large code base to start from that should
be of significant help. It can be found at
/afs/cs.cmu.edu/academic/class/15864-s05/photonMappingStarter2005.tar.gz
(due to the restrictions noted below, we cannot post it on the web).
The code will build under both Linux and Windows. The Linux Makefile
should already point to all the correct libraries which have been
installed in /afs/cs.cmu.edu/academic/class/15864-s05.
For the Windows version, you will need the following libraries:
To save you the trouble of building all this, I have placed the file
photonMappingLibrariesWindowsVS71.zip in the class directory
(/afs/cs.cmu.edu/academic/class/15864-s05), just unzip it and
point Visual Studio toward the appropriate directories. Those who prefer
to roll their own (or are using an older version of VS.net) can obtain
the correct versions of both GSL and VL in the class directory by themselves,
FLTK and boost can be retrieved from their respective websites.
Note: Please do not distribute this code. Various portions of this code are provided courtesy of the University of Washington graphics group and Henrik Wann Jensen, and they have requested that we make it available only for the purposes of this class.
The major components of the code consists of (1) a parser, which converts .ray files into scene graphs, (2) a user interface, which you can use to adjust various ray tracer parameters and also to visualize the scene, and (3) the actual ray tracer implementation itself, which is a full recursive ray tracer in the style of Whitted.
The parser reads in .ray files, which are unfortunately a
rather proprietary format, but which luckily support most of the stuff
you would hope for including nested transforms, full scene graphs,
arbitrary Phong materials and texture mapping, etc. The full documentation
for this format is available here, but the
best way to learn is by looking at the supplied samples. In particular,
pay attention to the various Cornell box scenes that can be found in
the scenes/photonMapping directory in the source code
distribution.
The user interface for the ray tracer uses the Fast Light toolkit. This is a cross-platform toolkit that allows for the use of OpenGL. It's also a little bit ugly (both in terms of the code you write and the look of the interface) compared to e.g. QT but its license is significantly less encumbered.
I have provided a couple of buttons and sliders in the UI for supporting both photon mapping and distribution ray tracing. In particular, you can select how many samples you want to cast per pixel (use the "samples/pixel edge" slider) and how many photons to send into the scene (use the "photons/light source" slider). The "Recompute photon map" button calls the recomputePhotonMap() function in Scene, which you have to implement. If you need to add any more sliders, you should add them in the GraphicalUI constructor and have an appropriate callback function (use the existing sliders/buttons as examples). Full documentation for FLTK 1.1 is also available on their web site.
The second (and most glamorous) part of the user interface is the debugging
view, which you should hopefully find very useful. Most of the code that you
might want to touch is in the DebuggingView::draw() function.
A write-up giving more details for this interface can be found
here.
Most of the action in the ray tracer itself happens in the
RayTracer::traceRay function. This implements
a full recursive Whitted ray tracer with reflection and refraction
and you should use this code as a reference while you are working
on extending it to handle photon mapping. In particular, it
makes extensive use of the Scene::intersect function,
which casts a ray into the scene and returns with both the location
of the intersection, a pointer to the intersected object, and the
surface material.
The RayTracer::tracePixel function samples the pixel
using stratified sampling as a proper distribution ray tracer should.
It calls RayTracer::traceRay to get irradiance estimates
for a given ray direction.
For other details on the code, please see this code roadmap.
At center, the photon map for the Cornell box scene; at left, rendering the scene using the 2-pass algorithm suggested in Henrik's book; at right, the "official" rendering of the Cornell box, from this page. I'm not sure what is causing the differences between my box and the official rendering, but I suspect they are in part due to our use of a very simple RGB color model as opposed to a proper spectral model.
Henrik has graciously provided us with his photon map implementation.
You can find it in photonmap.h and photonmap.cpp.
All the documentation we have for this is in the header file; more details
may appear later.
I will periodically be adding assignment tips below.
Here is a debugging trick to see if things are working. Suppose you shoot a bunch of photons into the scene and store them in the photon map, but don't allow them to bounce. Now, suppose you estimate the direct illumination at each point in the scene using just the visibility term and the falloff term. Given an infinite number of photons and an infinite number of visibility rays, this estimate and the radiance estimate from the photon map should converge to the same value (the photon map like any kernel density estimator introduces a bias towards smooth functions, but this should become negligable in the limit). We can take the difference between these two quantities and plot a histogram; this histogram should be centered around 0. Here's what I get when I do this,
Sponza Atrium model courtesy Marko Dabrovic. .ray file here.
Almost too many to list here. See also all the slides and references on the course webpage.
Questions? Contact Christopher Twigg.