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. Let us know if you have any questions.
The entries for the optional rendering contest can be seen here. They look great; congratulations to everyone that entered!
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-s04/photonMappingStarterSpr04.tar.gz
(due to the restrictions noted below, we cannot post it on the web).
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.
Caveat #2: this code is a bit of a mixed bag; at various points in time dozens of Washington undergraduate and graduate TAs have made changes to this code, without any sort of unifying style guidelines. I apologize for the lack of coherency; however, the code is fairly well documented. I have also spent the last couple of weeks rewriting and shaking out all the bugs that I could find in the code (and will continue to do so), but if you find any please let me know ASAP so that I can alert the class! Thanks.
Update 26 April 2004: There was a small but significant error in the diffuse scattering derivation which has been fixed; the 2π normalizing term should have been just π (thanks to Jernej for pointing this out). Obviously since this was my mistake you won't be penalized for using the incorrect scaling term (and you'll get perfectly reasonable looking images either way). My apologies for any confusion this may have caused. I'd also like to take this opportunity to remind you of the usefulness of Philip Dutré's online Global Illumination Compendium, which contains the correct normalization term. I've added references to this and other useful pubs at the bottom of this page, but you should still consider Doug's page to be the master list.
Update 26 April 2004: I've updated the sample solution again slightly to correct for an underestimate in diffuse-diffuse transfer. The correct formula is derived on the FAQ page, I strongly suggest taking a look at this if your diffuse-diffuse transfer doesn't look as you expect it to.
Update 23 April 2004: The sample solution had a bug in the Fresnel code that caused it to reflect twice as much radiance at normal incidence than it was supposed to. This has been fixed now in the version in the class directory.
Update 23 April 2004:
For cornellBoxSpheres.ray
, you'll get a prettier picture if you
crank the reflective
coefficient of the first sphere to
(1,1,1) and the transmissive
coefficient of the second sphere
to (1,1,1) (this will make the scene look a little brighter).
Update 22 April 2004:
A quick tip: If you're seeing a lot of totally blown out
photons in your map, consider the possibility that you have a divide by
zero somewhere in your code. I find it helpful to sprinkle my code liberally
with assert
s to catch these as close as possible to the
place they occur.
Update 21 April 2004: FLTK seems to have mysteriously vanished from the lab machines, so I installed it in the class directory. Let me know if you have any problems with it.
Update 19 April 2004: I have added the beginnings of a FAQ here; please take a look at it if you have any questions about the assignment.
Update 19 April 2004: I've created another test scene with water caustics (see above right); you can download it here. Thank Maya for the watery displacement map. Note that this scene uses a polymesh for caustics, so if your code only handles spheres this may be a problem (and hence it is not required that you be able to render it). If you want to, though, it's pretty easy to build the caustic map using simple rejection sampling.
Update 15 April 2004:
Quick tip on Henrik's photon map implementation: don't forget to call
Photon_map::balance()
after you've stored all your photons
because I don't think it will return correct radiance estimates otherwise.
Update 11 April 2004:
I've posted a sample solution at
/afs/cs.cmu.edu/academic/class/15864-s04/photonMappingSolution
(or photonMappingSolution.exe
for Windows users).
Note that you have to set the depth to at least 1 to get it to sample the
diffuse reflections rather than read the irradiance directly from the photon map
(and you'll want to send out more than 1 sample/pixel to get any decent
images).
Update 10 April 2004:
For those who were unhappy that the BSP tree code wasn't working, I've posted another
patch that replaces the BSP code with my own acceleration code (it's an axis-aligned
bounding box heirarchy, and due to some fancy template stuff it now uses the same
code that the trimesh acceleration code uses). As I noted below it won't make a
difference on your standard trimesh type stuff but it might make a difference
if you decide you want to find out what caustics a sphereflake has. The
patch can be found at
/afs/cs/academic/class/15864-s04/patch-photonMappingStarter-p2
and instructions for its use can be found in the same location,
here.
Update 9 April 2004: I've added a project roadmap here. Also, please disable BSP tree acceleration whever you're doing renders; I have my own acceleration code in there which should be plenty fast enough and I seem to have broken the older BSP tree code during the rewrite. I'll post the solution tomorrow, I just need to test it in the lab.
Update 9 April 2004: When you add in the proper falloff term for the area light source, you will probably find that due to the relative sizes of the geometry everything will be much too dark. I recommend setting the light intensity to 250.0 like this:
// light translate( 2.78, 5.48, 2.295, scale( 1.3, 1.0, 1.05, rotate( 1.0, 0.0, 0.0, 1.5708, square { material = { emissive = (250.0, 250.0, 250.0); } } ) ) )I haven't updated the code in the source directory because I want people to be able to at least render the sample scenes out of the box.
Update 8 April 2004: I have updated the starter code significantly, most especially with respect to the user interface which now contains a variety of options which may help make testing easier. In particular, this update includes:
You can either download the new updated code, or if you've already started
working on the project I've posted a patch which you can apply to your
existing code base at
/afs/cs/academic/class/15864-s04/patch-photonMappingStarter-p1
.
Intructions to use this patch can be found here.
.cshrc
(or
.login
) file to get Linux to find all the runtime libraries:
% setenv LD_LIBRARY_PATH /afs/cs/academic/class/15864-s04/lib/
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 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,
Almost too many to list here. See also all the slides and references on the course webpage.
Questions? Contact Christopher Twigg.