Programming Assignment 1: Ray Tracer for Planes and Spheres

comp238-assn1.cpp

    I built a ray tracer that renders spheres and planes and accounts for reflections and
refractions.  Here are some pretty pictures from hand-input models.  Once I get the
input file parser working, I would be able to show more pictures.

The code:

    My ray tracing model is the One True Way.   Basically, a center of projection, a
direction of view, and a focal length (and an assumption of 36x36 mm image plane)
provide a basis such that a ray cast from the eye through a pixel (i,j) on the film is of
the form :
            cop + (vector to lower left of film) + i*a + j*b
where a and b are orthogonal vectors that span the film.  Then it's a simple double
for loop.
    I have one RayTrace function that can call itself recursively (if the reflection index
or transparency is non-zero).  Starting at a point, and extending along a vector, it
computes the minimum positive (up to machine error) scaler to extend the vector to
hit the closest object.  It does this by iterating through all the objects in the scene
(ouch).  The function then computes lighting for the closest object hit, or returns the
background color if nothing was hit.  If there are reflection and/or refraction compon-
ents, the function is called recursively for them, and the returned colors are factored
into the final color returned.
    After some issues with specular highlighting (as described below), the lighting at a
pixel is now just about:
            [1-(transparency + reflection)]*(diffuse and ambient)
            + transparency*(color from transparency ray)
            + reflection*(color from reflection ray).
Then I add to that the specular component computed from the material properties.

Notes:

    This was a lot of work, mostly in the bug fixing area.  One peculiar example was
the eleven hours I spent finding the source of intricate designs in transparent objects.
What was happening was my rays were getting stuck on the inner surface of the
object intersected.  So for example I shoot a ray that hits a transparent sphere.  Since
there's a non-zero transparency, I then shoot a ray--independent of all others ever
shot--starting at one side of the sphere, in the direction of the other side, to get more
color components.  But when I compute the minimum positive intersection distance
of a ray with a sphere, I sometimes return a number that's just barely positive, like
10^-15.  So my ray would go nowhere during all the recursions, and black would
end up as the color of the first transparency ray.  Since there are only two cases, I
would get either a nicely colored ray that got through, or one that got stuck, but in
a very deterministic pattern if I aligned the sphere in just the right way with the axes.
I haven't recreated the pictures since I fixed the problem for lack of time.
    There was also an interesting hack that I used to get spcular highlights to show up
on the completely reflective balls picture above in the point light source environment.
The typical reflection ray off of one of these balls would not pass through the point
light source.  But it may pass at a close enough angle so that a piece of the light's
color should come back as part of the returned color for the ray.  So separate from
other things going on in the ray trace function, I check the angle of the current ray
compared to the other light sources.  If the angle is within ~20 degrees and the light
is not occluded by an object, I'll add a piece of the light proportional to the dot of
the light vector and the current ray raised to some power.  I only add a piece of the
light with the closest angle.  Below is an example of how this might go wrong.
    What I've ended up doing about the lighting hack is leaving it only when I am
otherwise going to return a background color for the ray (the light is outside the
scene).  In order to get specular highlights on a reflective or transparent object, I
don't temper the specular computation by the reflection and refraction amounts
(see above).
 


Notice on the left, lights aren't rendered.  My hack for adding light color to a ray, rather than rendering the
light explicitly, made this scene look awful (on right).  In general the lights should be outside of the scene for
this method to look reasonable.


Here, the camera is actually inside a sphere with a refractive index of like 1.5.  You can
see some distortion, but my intuition as to why there isn't more is: The image plane is
very close to the surface of the surrounding ball, not leaving much room for distortion.
Also, this model is lit with the final version of my lighting (namely, adding the specular
component after all else has been factored into the color returned).