# CS 688 Final Project - Ray Tracer

Currently, I am in my third term of my Masters of Engineering degree at the University of Waterloo. This term, I decided to enrol in CS 688 - Introduction to Computer Graphics.

As part of the course, we are required to create a project to demonstrate our grasp of computer graphics and implement graphic algorithms. We define our own list of ten objectives.

I decided to create expand on the ray tracer created in Assignment 4 and implement more advanced techniques. Here are a list of the ten objectives (and few extra) that I implemented.

You can download all the images here.

# Objective zero: Jittered Supersampled Antialiasing

The extra feature I implemented for Assignment 4 was jittered supersampling.

*Jittered Supersampling. This was the scene I used for my A4 submission.*

# Objective one: Cone and Cylinder Primitives

Cones and cylinders were added to expand the set of primitives from Assignment 4.

*Cone and Cylinder Primitives.*

# Objective two: Phong Shading

Instead of using the normal of the vertex, the normal was interpolated using barycentric coordinates.

*Phong Shading of a classic Utah Teapot.*

# Objective three: Mirror Reflection

Recursively calculate color contributions from the reflected ray. The reflected ray was calculated using the equation:

*Mirror Reflection.*

# Objective four: Refraction

Recursively calculate color contributions from refraction. The refracted ray was calculated using the equation:

*Refraction. Three glass spheres and a cylinder with an index of refraction of 1.5.*

# Objective five: Soft Shadows

For this objective, I needed to introduce area lighting. From each intersection point, multiple shadow rays would be cast from the intersection to a random point on the area light source.

*Soft Shadows. Used a square area light with a 5x5 grid of jittered shadow rays.*

# Objective six: Constructive Solid Geometry

Union, intersection, and difference operations.

*Constructive Solid Geometry. Union operation on the left, intersection operation on top, difference operations on bottom and right.*

# Objective seven: Texture Mapping

Texture mapping was done by calculating the UV-coordinates for primitives. Bilinear interpolation was used as the filtering method for determining the pixel color.

*Texture Mapping. A texture of a globe on a sphere and a brick on a cube.*

# Objective eight: Glossy Reflection

Glossy reflection was implemented by distributing multiple reflection rays from a reflective surface. Each reflection ray is perturbed following a cosine distribution as follows:

Where is the polar angle, is the azimuthal angle, is the Phong exponent, and and are uniform random numbers between 0 and 1.

*Glossy Reflection. Used 10 perturbed reflection rays at each reflection point.*

# Objective nine: Depth of Field

Depth of field was implemented by distributing rays so that their origin are randomly sampled on a disk at the eye point of a given aperture radius.

In the following images, the aperture radius was set to 25 and the spheres have a radius of 50. 3x3 jittered samples on a disk were generated for each pixel. The eye was placed at a z value of 500. The back ball was placed at -200. The center ball was placed at 0. The front ball was placed at 200.

*Top Left: Without Depth of Field.
Top Right: Focal plane is set so that the back ball is in focus. Focal distance = 700.
Bottom Left: Focal plane is set so that the middle ball is in focus. Focal distance = 500.
Bottom Right: Focal plane is set so that the front ball is in focus. Focal distance = 300.*

# Extra Objective: Multithreading

Multithreading was implemented by parallelizing each pixel. Here’s a graph of the running time versus number of threads for the `macho-cows.lua`

scene in
Assignment 4. It was run in the gl29 computer in the Computer Graphics lab.

*Multithreading. 512x512 rendering of macho_cows.lua on gl29.*

# Extra Objective: Schlick Appoximation

Schlick’s approximation is a formula to approximate the Fresnel factor of specular light. It was applied to the reflected and refracted ray color contributions. It is calculated as follows (from Wikipedia):

where .

*Schlick Approximation.*

# Extra Objective: Bump Mapping

Bump mapping was implemented by reading a normal map and perturbing the normal at each surface point according to the normal map. Code from texture mapping for retrieving a pixel value for a given normal texture was reused.

*Bump Mapping. Applied to same globe and brick objects in the texture mapping objective.*

# Extra Objective: Motion Blur

Motion blur was implemented by giving each ray a random time value and each object a velocity. The time value and velocity together translates the object into a new location. Since we are distributing multiple rays per pixel from anti aliasing already, we get a nice averaging effect for motion blur.

*Motion Blur.*

# Objective ten: Final Scene

Here is my final scene with all objectives enabled.

*Final Scene. With depth of field toward center of the room.*

*Final Scene.*