Project 5
CS354: Computer Graphics
Due Dec 3rd, 11:59pm

Instructions

In this project, you will work on a simple ray tracer. Please do this project ALONE. As usual, implementing the required features well will get you about a B, and to get an A you'll need to implement some optional features.

The required features are:

  • Add a light source and a diffuse component to the lighting model.
  • Add a new kind of object - your choice - to the scene.
  • Cast shadow rays to make shadows.

    Features like refraction, texture mapping, antialiasing and intersections of objects are optional...but make for cool pictures.

    Starting off

    Here are the files to make a primitive raytracer: When you compile it, you should get an executable that draws a picture of a dark red circle on a black background: a ray-traced picture of a red sphere in dim ambient light.

    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.

    Lighting model

    Here is the simple lighting model you are required to implement.

    Here's what the symbols mean. Let p be the point on a surface seen by ray r.

  • ambg is the general ambient lighting level (scalar)
  • ambm is the ambient reflectance of the surface (scalar)
  • vis(i) is zero if light source i cannot be seen from p, 1 otherwise
  • theta is the angle between the ray from p to light source i and the surface normal
  • difm is the diffuse reflectance of the surface (scalar)
  • intensityi is the intensity of the light source (scalar)
  • colorm is the color of the material (an RGB value)

    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.

    Step 1

    Define a light source (coming from over your left shoulder is traditional) and get the diffuse reflectance component of the lighting model working.

    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.

    Step 2

    Make some more objects and add them to your scene. At least one new kind of object is required. A halfspace under the sphere is a good idea. Boxes are easier to implement than general intersections of halfspaces. Cylinders, cones and other quadric surfaces like paraboloids and hyperboloids are easy and fun. Try varying the material properties to get a nice looking scene. For every object you'll need a function to find the first intersection of a ray with the object, and a function to find the normal on the object at a point.

    You have to modify trace whenever you add a new object - otherwise it doesn't test for intersections with the new object.

    Step 3

    Add shadows by defining the function Vis(i). You decide whether a point p on the object surface is in shadow by casting a ray from p to the light source i. If trace returns a point other than p, then the object lies between p and i, p is in shadow, and Vis(i)=0. If not, then p is visible from i, and Vis(i)=1.

    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.

    Step 4

    Note: This is optional.

    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.

    Turning it in

    Please make at least one .tif or jpg file of your final raytraced image. As usual, put your name on all files, write a README, and email it to me.