*Write a distribution ray tracer, similar to the one described in [Cook84].
(assignment)*

I extended the classical raytracer that I implemented for the first assignment. I added support for triangles, and I implemented antialiasing, soft shadows, image texturing and blurred reflection.

For antialiasing, I used the following approach: if the color computed for the current point is significantly different from its upper and left neighbors (since tracing is done left to right and top to bottom), I recomputed the color at the three points. The new color was computed as the weighted average between the old color ("central" sample, 60%) and an additional number of samples obtained by tracing random rays close to the central one (40%). The weights of the additional samples was inversely proportional to the distance in image space from the central sample point.

For soft shadows, I implemented "extended" light sources, specified by a point and a radius. I traced an additional number of rays between the point whose color was being computed to some random point on the light source. I then counted the number of rays that actually hit the light source, without intersecting another object (thus assuming no attenuation from the center of the light to its edge). The final energy contribution of the light source was then multiplied by the ratio of unobstructed rays to the total number of rays traced.

I implemented image texturing differently for triangles and spheres. For triangles I used barycentric coordinates, as presented in the book. For spheres I used Paul Rademacher's approach described in "Ray Tracing: Graphics for the Masses".

For blurred reflection, I simply replaced the reflected ray with the weighted average of the "central" sample (60%) and some number of rays traced in random directions close to the direction of the central ray (40%).

While not justified mathematically or physically, the weights I used in the program produce visually-pleasing results.

I also implemented a very simple motion blur (just one object) by just modifying the position of an object along a trajectory before tracing each ray and averaging the samples using equal weights.

Since I did not implement an object hierarchy, I could not use the second model provided. Also, rendering was very slow because I did not implement any acceleration structure (bounding volumes, etc.) for computing intersections. This prevented me from using even part of the model (e.g., the teapot), because the number of triangles was too high to compute the image in a reasonable amount of time.

Below are some screenshots produced by my program:

A screenshot the first model, with an extended light source for soft shadows. |

A screenshot of the same model, with blurred reflections. |

Another screenshot of my own model, with antialiasing, texture mapping and motion blur. |

- header definition file: rayTracer.h
- C++ program: rayTracer.cpp
- main program file: main.cpp