### CS488 Raytracer Final Project

This project was done for my final project for the Winter 2018 offering of CS488 at the University
of Waterloo.

### Objective 1 - Extra Primitives

Extra cone and cylinder primitives were implemented by obtaining intersection points from corresponding
parametric equations. The caps of the cylinder and cone were intersected against halfspaces.
As for side intersections, the cylinder equation is x^2 + y^2 = r and the cone equation is
x^2 + y^2 = z^2

### Objective 2 - Texture Mapping

Texture mapping was implemented by mapping 3d surface coordinates to 2d texture coordinates and
applying the specified texture colour to the object's diffuse component. For basic triangles,
barycentric coordinates were used to interpolate the texture coordinates.

### Objective 3 - Bump Mapping

Bump mapping was implemented using normal maps which specified the normal vectors at points on
the surface. The normal, tangent and bitangent vectors at the intersection point were used
to convert the normal map's tangent normal to a model space normal.

### Objective 4 - Refraction

Refraction was implemented by recursively casting secondary rays based Snell's law which defines
a relationship between refractive indices, incident vector and refracted vector. Fresnel
equations were used to compute the reflectance for a given refractive material.

### Objective 5 - Reflection

Mirror reflections was implemented by recursively casting secondary reflected rays from intersection
points on reflective objects.

### Objective 6 - Phong Shading

Phong shading was implemented by interpolating vertex normals based on barycentric coordinates.
Custom vertex normals were generated by taking the average of every vertex's intersected
face normals. The result is a smoother looking surface using less vertices.

### Objective 7 - Perlin Noise

A sample of 2D perlin noise was used to generate a heightmap mesh. By taking the negative abs()
of the noise, ridged noise was able to be produced allowing for sharper peaks.

### Objective 8 - Soft Shadows

Soft shadows was implemented by casting multiple shadow rays arranged in a uniformly distributed
grid. Based on the fraction of rays which were obscured, the shadow intensity was altered.

### Objective 9 - Depth of Field

Depth of field was implemented by creating and taking the average of multiple passes of the image
with slightly modified eye positions. The modified eye positions were sampled from a jittered
grid.

### Objective 10 - Final Scene

All prior objectives are present in this image. Can you spot them all?

### Extra Objective 1 - Adaptive Anti-aliasing

Adaptive anti-aliasing was implemented by first sampling 5 rays per pixel and recursively subdividing
and producing more rays depending on the difference of sub-pixel colours. This allowed for
reduction of edge "jaggies" while also salvaging performance.

### Extra Objective 2 - Cel Shading

Cel shading was implemented by grouping together gradients of specular and diffuse light within
thresholds. Edges were identified and coloured black by using a Sobel filtered version of
the original image.