Homework 1
VS 2005
Finishing this assignment proved to be more of a test of my software building skills than anything else. Since I recently got VS 2005 I had to rebuild both OpenEXR and pbrt itself to get everything running. Naturally this introduced a bunch of minor issues regarding code compatibility (the new 'safe mode' printf calls, some altered Win32 API macros etc, see also kd-tree below) that needed attention, but after a night's work I think I got everything right. At least it runs.
Scene setups
Setting up the scenes was reasonably simple, once I got the coordinate systems straightened out and realized which of the lights in configuration 4 needed to be area lights and which ones needed to be spotlights. Obviously I lowered the resolution and sampling settings while working in order to facilitate speedier renderings. The rest of the work just required a bit of patience, something I've come to understand is a very valuable commodity in the rendering business.
kd-tree bug (VS 2005)
While doing the below extra work, I discovered what I believe might be a 'bug' in the KdTree class. However, the build (1.02) is the most recent one from the webpage and has been around for about a year, making me suspect that this is an issue with VS 2005.
When calling the recursiveBuild() method from the constructor, a std::vector is provided, and as 'end' argument _its size_. Since recursiveBuild() tries to access the end:th element in the vector when calling std::nth_element() (and 'end' is out of range by 1), an exception is thrown and the application crashes. The way later recursions are called lead me to the conclusion that it's the initial call that's faulty, not the way the argument is handled, so I did a quick fix by adding a -1 after nNodes at line 77 in kdtree.h. As I said, I find it really hard to believe that this issue has been appearing in other compilers, so I guess this is more of a heads-up than a bug report.
Take a look at the (original) code and see what you think:
73 vector<const NodeData *> buildNodes;
74 for (u_int i = 0; i < nNodes; ++i)
75 buildNodes.push_back(&d[i]);
76 // Begin the KdTree building process
77 recursiveBuild(0, 0, nNodes, buildNodes); // nNodes == buildNodes.size() ?
78 } // end of KdTree CTOR
79 template <class NodeData, class LookupProc> void
80 KdTree<NodeData, LookupProc>::recursiveBuild(u_int nodeNum,
81 int start, int end,
82 vector<const NodeData *> &buildNodes) {
(...)
96 std::nth_element(&buildNodes[start], &buildNodes[splitPos],
97 &buildNodes[end], CompareNode<NodeData>(splitAxis)); // end is unaltered at this point
Extra 1 - photon mapping
Instead of doing the suggested inter-surface reflections using photon mapping, I decided to try out the much more spectacular-looking caustics effects. I switched to a near-perfectly transmissive glass material, and altered the scene settings to facilitate my objective.
Result
This is the final result, using 500k photons for caustics. The algorithm has converged to a pretty believable image. See below for some intermediate steps.
Intermediate 1
Using only 10k photons for caustics, the map gets far to crude an the artifacts plenty.
Intermediate 2
Stepping up to 100k photons, things begin to look better, but the sharp details are still missing.