For my final project I added the following features to the Miro ray tracer:
Depth of field
Attenuation of light using Beer's Law
Unfortunately, not all of these are used in the final image, due to not having time to render with all of them turned on. The final image is rendered without depth of field, because it seemed like the least important feature for this scene, and without the diffuse-diffuse term of the rendering equation, due to the cost of rendering this and the fact that I don't think it's working completely yet. Some worthwhile optimizations for this set of features would be irradiance caching to speed up calculating the diffuse-diffuse contributions, the use of shadow photons to cut down on wasteful shadow rays, and use of a projection map to speed up building the caustics photon map.
The first features I implemented were antialiasing and depth of field. For antialiasing I am using a simple 4x4 grid sampling scheme. I have yet to try out other sampling patterns, such as the honeycomb, quincunx, or jittered samples, mainly because I was pretty happy wit hthe regular 4x4 when I got it going and felt there were more important things to work on, such as depth of field.
I felt depth of field was a good feature to implement because it is a pretty strong visual cue for people when viewing recorded images. I compared several different sampling schemes, namely direct disk sampling, disk rejection sampling, concentric disk sampling and stratified concentric disk sampling. Stratified concentric disk was easily the winner. At half as many samples it looked as good if not better than the other sampling methods. It is also easier to implement than stratified version of the other sampling methods, at least in my opinion, since it nicely maps stratified samples in the unit square to the unit disk.
32 DOF samples/AA sample, Rejection Sampling
32 DOF samples/AA sample, Concentric Disk
16 DOF samples/AA sample, Stratified Concentric Disk
36 DOF samples/AA sample, Stratified Concentric Disk
As you can see from these test images, stratified sampling does just as well as the non-stratified cases with half the samples. At a comparable number of samples it looks much smoother.
Next up was photon mapping. I used Dr. Jensen's book on global illumination with photon mapping to add photon mapping to my program. I currently have separate global and casutic photon maps, though in the image only the caustic photon map is used due to render tiem constraints. The caustics photon map is generated by spewing photons out randomly until enough of them hit specular objects. While easy to implement this makes generating the caustics photon map take much longer than it "should." In the final image I am only using photon mapping to generate caustics. This is due to both lack of time to render the image with full global illumination and also because I haven't finished testing it yet. Below is an image showing the direct visualization of the global photon map for the cornel box with specular spheres. You can see the color bleeding on the ceiling from the colored side walls.
After I got photon mapping working I added support for attenuation of light based on Beer's Law to my specular material shader. I used trial, error, and educated guesswork to come up with attenuation coefficients which produced a reasonably convicing wine bottle and white wine color. I also added support for Beer's Law effects in the photon hit handlers so that photon's refracted through specular materials would have their colors altered according to the attenuation of the material. This is what creates the colored caustics seen in the final image.
The final step in getting this image ready was to implement a bumpmapped texture for the counter top which the wine glass and bottle rest on. I wanted something that looked like a mosaic of clay pieces because I find mosaics appealing. I found a picture of such a mosaic online and used a color picker to sample some of the colors to use for the different regions in the Worley noise. In retrospect I probably should have picked a few more colors with some more inbetween the darkest and lightest shades, because as it stands I think the pattern is a bit too "clumpy," with too many groups of the same color tile stuck together. There's also a bit of perlin noise added to try to give the tile a slightly rough feel. The texture is bump mapped such that the sections of grout are "lower" than the tiles, though it really isn't noticable in the image. Zoomed in you can tell, as in the image below.
I had originally planned to add a subtle bump mapping to the wine bottle as well, to throw off the perfection of it's surface appearance, since this sort of "unnatural" perfection is often a giveaway for computer generated imagery. This also could perhaps be accomplished with a glossy reflection model. Either way I didn't end up implementing either.