Project 3: Ray Tracing

Due: Wednesday, March 16, 2005, 11:59pm


Objective

The goal of this project is to write a ray tracing renderer. Your program should be able to read scene data from a file according to a defined scene description language. From this, your program will then render an image of the scene and write out the image to a file. In this project we will use just two geometric primitives: spheres and cylinders. We will implement shadows and reflection, but not refraction.


Scene Description Language

fov  angle
Specifies the field of view (in degrees) for a perspective projection. The viewer's eye position is assumed to be at the origin and to be looking down the negative z-axis (giving us a right-handed coordinate system). The y-axis points up.

background  r g b
Background color. If a ray misses all the objects in the scene, the pixel should be given this color.

light  x y z [r g b]
Point light source at position (x,y,z). Its color is optional (the default is white). Your code should allow up to 10 light sources. Any objects in your scene should cast shadows from these light sources, of course.

surface  Kar Kag Kab  Kdr Kdg Kdb  Ksr Ksg Ksb  N  Krefl
This command describes the reflectance properties of a surface, and this reflectance should be given to the objects that follow the command in the scene description, such as spheres and cylinders. The first three values are the ambient coefficients (red, green, blue), followed by diffuse and specular coefficients. Next comes the specular power N (the Phong exponent), which says how shiny the highlight of the surface should be. The final value is the reflection coefficient (0 = no reflection, 1 = perfect mirror). Usually, 0 <= Ka,Kd,Ks,Krefl <= 1.

sphere  x y z radius
A sphere with its center at (x, y, z).

cylinder  x y z  height  radius
A vertical cylinder with the center of its base at (x,y,z) and a given height and radius. This command will only allow us to make cylinders that have an axis parallel to the y-axis.

write  filename[.ppm]
Ray-traces the scene and saves the image to a PPM image file.
Note on color specification: Each of the red, green, and blue components range from 0.0 to 1.0.


Code Provided

All the provided source code that you will need for this assignment can be downloaded here: prog3.zip. We have supplied two utility packages that you should use to complete this assignment. The first of these is a set of Command Language Interface routines (CLI). These are provided so that you do not have to write a parser for the scene description language. See below for more details on the CLI routines.

The second set of routines that we provide are for writing a pixel in a window and for writing an image to a file. You used these routines for your first assignment. There are just a few routines that you'll need to use:

gtBeginGraphics (xsize, ysize);
This command creates a framebuffer of the given size. If you are linking to the SGI routines, this actually creates a window on the screen. If you are on a different kind of workstation, it simply allocates the necessary memory.

gtWritePixel (x, y, r, g, b);
This command writes a pixel to the screen at integer locations (x,y). The color of the pixel is (r,g,b), where these are integers from 0 to 255 for each of red, green and blue.

gtWriteFramebuffer(filename);
Write the contents of the framebuffer to a PPM file.

gtEndGraphics();
Deletes the framebuffer.

You can find a program called "irect.c" that uses these routines. This program allows you to type commands such as "rect 0 0 50 50" to draw a rectangle. It demonstrations how to use the CLI routines.


CLI Routines

The command line routines (CLI) provide a simple way to write and extend an interpreter of ASCII files. The CLI routines automatically understand the command "read". If you type the command "read rect_test" after running the program "irect", it will read the commands in the file "rect_test.cli" and execute them. Look at the contents of the file "rect_test.cli" to see what a CLI command file looks like. This particular file draws two rectangles and writes them to the file rect.ppm. In this same way we will assemble our scenes to be ray traced. Reading in the commands from a file saves us from having to type in the scene descriptions each time. When you run irect, if you type "help" or "?", it will print out a list of commands that you may type. You can add new commands to the program by adding lines such as:
  COMMAND ("sphere  x y z radius") {
    float x,y,z;
    float radius;
    get_real (&x);
    get_real (&y);
    get_real (&z);
    get_real (&radius);
    create_sphere (x, y, z, radius);  /* your own sphere-creation code */
  }
You will need to create CLI commands for each of the commands in the scene description language.


Scene Files

In the directory "results" are several test scenes that are described by .cli files. Also in that directory are the images that should be created by these scene files. The file "t0.cli" is perhaps the most simple image, and you might use this scene as a starting point.


Suggested Approach

It is probably best to begin by making small changes to the "irect.c" program to see how to add new commands to the CLI interpreter. After you feel comfortable with this, then you can make dummy routines for each of the commands that your ray tracer should understand. Then replace each of the dummy routines with real code and you will be done! :-)

Once the shell of the program is ready, we suggest creating the main loop that creates the primary rays (those from the eye). Start by printing out the information about these rays to make sure that the numbers make sense. Once you've got this loop working, then start on the ray/sphere intersection routine. Don't bother shading the sphere correctly at first-- just color it anything other than the background color. Once you've got a round object on the screen, then work on the shading of the sphere. Finally, work on ray/cylinder intersection.


Authorship Rules

The code that you turn in must be entirely your own. You are allowed to talk to other members of the class and to the instructor and the TA about high-level questions about the assignment. It is also fine to seek the help of others for general C programming questions. You may not, however, use code that anyone other than yourself has written. Code that is explicitly not allowed includes code taken from the Web, from books, or from any source other than yourself. The only exception to this rule is that you should use the routines that we provide. You should not show your code to other students. If you need help with the assignment, seek the help of the instructor or the TA.