**Final Project: the Outer Limits**
Student name: Yaorui Zhang
(##) Implementation
I tried to implement photon mapping, environmental map, bump map, field of depth and participating media.
### Photon Mapping
See integrator.h & photonmap.cpp
For this part, I mostly followed the instructions of the slides and used the kd-tree provided on Piazza to store the photons. There are many details that I had to be very careful of.
Firstly, I created a new integrator (inherited the integrator class) named "PhotonMap".
Then I implemented functions to generate photons and trace photons. I chose to add the photon num by one every time I call the function 'generate photon map'.
Since there's only a quad light in my scene, I only wrote the function to get photon from a quad light.
I generated photons of a certain number (M), but the number of the photons actually stored can be different, especially when there's occlusion between the light source and my main scene.
I would store the photon when it's not a specular surface, and the Russian Roulette method determines when to end the recursion and ensure the photons carries the same amount of power.
**Testing**
To test if the photon map I stored is correct, I wrote a function in camera.h to project the points on the screen, and then generated a image of photons.
I compared the photon map with that shown on the slides, and they look very similar.
Photon Map I generated
Photon Map on the slide
Then I added the Li function for the photon map integrater so now it can trace the ray once and calculate the density of the photons at the hit point.
With more photons, the result becomes clearer and the color color also become more realistic.
After that, I implemented final gather so now I'm using MIS path tracing together with photon mapping. This largely reduced the bias and spotches of photon mapping.
FinalGather
The caustic map looks like this:
Caustic map
After that, I implemented progressive photon mapping.
I wrote a function called new run, in which I clear all the photons and change the radius.
The result is shown as follows:
When I set the ior to zero and count only the direct light and caustic map, the result is shown as follows:
Probably due to some sort of round-off errors (if it's perfectly transparent sphere the edges shouldn't show up when it's only direct light), the shadow doesn't disappear completely, but it's already hard to notice.
When comparing my result using photon mapping to mis path tracing, I found the picture a bit brighter, especially for the shadows and caustics.
### Bump Mapping
See material.cpp (for Lambertian & metal)
In short, for this task I'll have to change the shading normal of hit points according to the gradient of the corresponding point on the bump map.
I rotated the offset vetor so it's parpendicular to the geomatry normal to make sure it works in all directions.
Since the effect doesn't seem to be very clear for bump maps without clear edges, I multiplied the gradient of the bump maps by 20 when applying them.
I added a new variable named bump to lambertian and metal materials and allowed them read the image file from json.
Here are some example results:
Using a mud bump
Using a seed bump
### Sky Box
See scene.cpp, Color3f Scene::background(Vec3f direction)
The main idea for implementing the sky box is to add an infinite sphere with texture to the scene.
To do this, I modified the function named background() so it can return the background color at a certain direction (similar to the uv mapping of a sphere, calculate the shpere coordinate of the direction).
During ray tracing process, when a ray hits nothing, we would call that function.
The sky box
### Depth of field
The idea is to set an offset to the origin (sample on the aperture, which can be considered as a disk)
### Volumetric Path tracing (for homogeneous media)
See integrator.h & integrator.cpp (a new class named vPT)
I only implemented volumentric path tracing for homogeneous media without boundary by free path sampling, following the instuctions from the slides.
When the ray hits something in the media, the direction of the scatter ray is equally distributed in all directions. So I just sampled on a unit sphere to determine the new direction.
I also tried to distinguish if the ray is inside an object by computing the dot product of the normal and the ray direction, so inside the normal we'll just use the normal path tracing.
When the ray hits nothing, instead of just return the background color, we would continue path tracing. Because of this, the program can be really slow and the background is always blurred.
Here are some example images:
I don't have a validation for this part, but we can already get a feeling (though not very obvious for the volumentric light).
It might be a good idea to set a boundary for the ray, so if it hits some particles very far away, we don't have to continue tracing it.
### Volumetric Photon Mapping (not working)
See integrator.h & vPM.cpp
I don't have time to finish this part. The furthest step I got was to generated a photon map.
The process is very similar with the volumetric path tracing.
Volumetric Photon Map
(##) Limitations and future work
Recently the skybox is also a “light” but I couldn't generate photons from it. It would be really nice if I can importance sample the environmental map.
Also I didn't get the participating photon mapping work well, which I would really want to get done in the future.