The required features are:
Features like refraction, texture mapping, antialiasing and intersections of objects are optional...but make for cool pictures.
The simple ray tracer casts a ray through every pixel in the image plane. The image plane lies in the plane z=-1, and the viewpoint is at the origin. The sphere you see is centered at (0,0,-2) and has radius 1.
The raytracer uses OpenGL only to put up a window; it draws an array of pixels into the window, and YOU are responsible for coloring the pixels one by one to make the image. The function drawPixel writes single pixels to the array.
Here's what the symbols mean.
Let p be the point on a surface seen by ray r.
This required lighting model handles shadows, diffuse reflectance and reflective surfaces. You can improve the model by implementing distance attenuation, a local specular reflectance term, colored light, and refraction as additional features
You want each of the R,G and B components of the final pixel color to come out between zero and one, so all the material parameters above should be chosen between zero and one as well. When calculating cosines, set any value less than zero to be zero. Otherwise, for instance, strange things show up near the boundary of the sphere. Here are some formulas that might come in handy.
As usual, you should take it step by step.
It's easier to use a directional light source (position is a point at infinity); handling point light sources at a finite point is optional.
DO NOT define the light source in OpenGL; since you're not using OpenGL to draw any polygons, this will not have any effect! Make a data structure of your own to represent the light source, with a position and intensity. Then use that information to compute the diffuse component of the lighting at each pixel according to the lighting model equation above.
You have to modify trace whenever you add a new object - otherwise it doesn't test for intersections with the new object.
You might run into this common bug: when p lies on the surface of an object, trace returns that object as the first thing hit, because of roundoff error. You can fix this by checking that the parameter t along the ray is actually somewhat greater than zero (define some small tolerance value) in trace.
Make one of the surfaces in the scene reflective. You find the reflection ray at a point p by reflecting the ray from p to the viewpoint (which is (0,0,0)) across the surface normal at p. Compute the color seen along the reflection ray by recursivly calling rayColor. Be careful to limit the number of levels of recursion.