Simple Ray Tracer

Coded in C++ | December 15, 2011
Ray tracing is a technique in computer graphics to generate an image by tracing a light ray onto an image plane and computing the effects of its encounter with an object. However, it comes at a high computation cost. As part of an advanced C++ laboratory class, I implemented a ray tracer from scratch, using guidelines from the instructor.

Shapes and Objects

My ray tracer can represent basic geometries such as planes, spheres, and cylinders. The math involved with a plane is simple, since it is a flat surface. It is more complicated for a sphere and cylinder, since there are two intersection points between a ray and a sphere/cylinder. These points can be calculated using the quadratic formula. By finding the location of the intersection, we can compute the color needed at that point.
Some extra work is needed to find the intersection of a ray and a cylinder, since cylinders don't always come upright. To make the math easier, we transform the coordinate system into one where the cylinder is oriented along the positive y-axis. A sphere with the same radius is centered at specific points such that finding the ray's intersection with the sphere is the same as finding the intersction with the cylinder (but the math is easier).
  
Above are images of a cylinder and a sphere sitting on a plane, as produced by the ray tracer. Both also have four lights of various colors shining on them.

Reflection

A ray tracer would not be complete without reflection! Reflectivity can range from 0 (no reflection) to 1 (total reflection). The reflection computation occurs at the same time as the actual object's color computation. When a light ray hits an object, a reflected ray is generated. This is offset by a small delta compared to the incident ray, which makes it look better.
This reflected ray is traced back and forth (so it is reflected multiple times) in order to calculate the final reflected color. Ultimately, there is a limit to the depth of recursive calls required for the reflectivity calculation.
  
The results of implementing reflection can be seen above. The first image has a plane with a reflectivity of 0.1, and the other has a plane with a reflectivity of 1.

Rendering an Image

The ray tracer renders an image by writing out each individual pixel to a text file. I use the ASCII PPM (Portable PixMap) format, which is formatted as follows:
P3 width height 255
r1 g1 b1
r2 g2 b2
...
The first line is a header with the width and height of the image, and the following lines are the red, green, and blue values for each pixel. These values range from 0 to 255 (as indicated by the 255 in the PPM image header). These are then converted to PNG since PPM images take up a lot of space.