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.

Without Supersampling With 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 & Cylinder Primitives Cone and Cylinder Primitives.

Objective two: Phong Shading

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

Without Phong Shading With Phong Shading 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:

Without Mirror Reflection With Mirror Reflection Mirror Reflection.

Objective four: Refraction

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

Without Refraction With Refraction 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.

Without Soft Shadows With Soft Shadows 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 Geomoetry 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.

Without Texture Mapping With Texture Mapping 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.

Without Glossy Reflection With Glossy Reflection 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.

Without Depth of Field Depth of Field - Back Ball

Depth of Field - Middle Ball Depth of Field - Front Ball 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 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 .

Without Schlick Approximation With Schlick Approximation 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.

Without Bump Mapping With Bump Mapping 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.

Without Motion Blur With Motion Blur Motion Blur.

Objective ten: Final Scene

Here is my final scene with all objectives enabled.

Without Motion Blur Final Scene. With depth of field toward center of the room.

With Motion Blur Final Scene.