Rendering Techniques Assignment 1:

Writing a Ray Caster

Assigned: Monday, September 20, 1999
Due: Monday, October 4, 1999 (before the start of class - no extensions)

Overview

For this assignment, you will write your own ray casting program. Your program will be capable of rendering Phong-illuminated, shadowed spheres. You will be developing the program entirely from scratch, so be prepared to get your hands dirty. If all goes well, you will achieve very satisfying results and produce some pretty pictures of your own design.

The program should be written in C++.  I will be compiling and running your programs using g++, so whatever platform you use to develop it, it should make sure it compiles and runs correctly with g++ before you turn it in (that will put your instructor in a good mood just before grading your assignment).

You might want to take a look at Paul Heckbert's “Writing a Ray Tracer,” which is Chapter 7 of Glassner's An Introduction to Ray Tracing, on reserve at MSE. If you read it, pay special attention to section 3, and try not to be overwhelmed by the number of possible options and optimizations for a ray tracer.  You do not have to do things exactly as presented in the article of course; it’s just a model in case that is useful.

Design your program in an object-oriented fashion from the start - we will be making extensions to this program in future assignments. You should have simple classes for vectors, rays, images, and rendering objects (sphere is child class) as a minimum. Do not get too carried away using all possible C++ features. Just keep it simple. Note that the vector class is important. I don’t want to see you doing your vector computations one component at a time, which leads to more code, more bugs, and more difficult reading for your instructor. Be safe – use vector addition, subtraction, dot product, cross product, scaling, and normalization functions (inline, if you care about speed).

Program Description

The ray caster will read a simple scene description from an input file (format specified below).  It will support spotlights and spheres, using Phong illumination (single-sided).  You may specify all your lights and spheres directly in eye coordinates, so you do not need to perform any transformations.  This is a ray caster, so you do not need to trace reflection or transmission rays.  However, I would like you to trace shadow rays.  Because there is no transparency, each light is either fully visible or occluded to a particular surface point.  The program should create a PPM format image file (described below), which is easy to generate. Typical programs for viewing .ppm files on Unix systems include ‘xv’ and ‘display’. You should convert your files to lzw-compressed tiff files to save space (saves space in your account, and smaller for you to submit to me). The pbmplus set of utilities include the program pnmtotiff. Freeware programs to view/convert .ppm files under Windows may be found at:  http://perso.wanadoo.fr/pierre.g/download/viewer/Xnview-gb-win.zip. If you find other useful tools, let me know and I’ll pass the information on to the rest of the class.

The executable should be called `raycast` and should be callable with the simple command:

raycast <scene description filename> <image output filename>
(If it's useful to you, you could also consider allowing the input file to come from stdin and the output file to go to stdout, but you must support the above form as well.)

Included with this homework assignment is a sample scene description and the corresponding rendered image. You should test your program on this file as well as many other test cases you devise to ensure that your program functions properly in all tricky circumstances.

Place some lights and spheres in an interesting arrangement to create an image at a moderate resolution (512x512, perhaps).  I will obviously try some my own scene descriptions to test out your program.

You do not need to perform speed optimizations.

Suggested Approach

Here’s one path you might take to completing the project. I don’t want to see all the intermediate results of these steps, but this should give you an idea of how I would approach the project.
  1. Start early. I have given you enough time for this assignment, but it will take you the entire time. Starting early will give you time to ask me questions about those crucial details that you didn’t even realize existed until you tried to write the program. Remember – no extensions will be granted (without dean’s excuse). You should be generating some sphere images without illumination by the end of the first week to ensure timely completion.
  2. Start with image class and writing ppm files. Test with simply created images like solid color, checkerboard, etc. Make sure you understand your image coordinate system.
  3. Write file parser, and necessary data structures for storing information.
  4. Write main loop to generate eye rays for entire image. (As a handy debugging trick, you can scale/bias your ray direction’s x, y, and z components and store into r, g, and b of an image. Viewing the image and examining particular values can help you verify that your eye rays are correct. Storing intermediate values as colors like this is a often useful way to debug your program's operation on an entire image at once.)
  5. Write sphere intersection routines and use with eye rays. Set image colors to sphere diffuse color. Don’t do any illumination. Your image should thus contain solid-colored ellipses indicating which spheres are visible at each pixel. Run on my test scene and compare images.
  6. Add purely local Phong illumination computation.
  7. Add shadow rays to determine which lights contribute to each pixel’s illumination.
  8. Come up with your own test cases and debug.
  9. Design extremely cool demonstration image.
You could choose to postpone the parsing until later in the development, using hard-coded tests until then. However, if you choose to do it early on, you can immediately start testing any cases you think might give your code trouble.

Deliverables

E-mail me a single .zip file (uuencode the file or do mime attachment) containing the following: Please do not invent a new, clever way to turn in the assignment, and do include all of the above items (I have many assignment to review, so submitting them in a fairly uniform way makes the process much smoother).

PPM Format (extension .ppm)

PPM format has ASCII and binary variants. I’ll first describe the ASCII version:
P3
xres yres
255
r g b r g b r g b r g b
r g b r g b r g b r g b


P3 is a magic number that identifies the file type. xres and yres are integers specifying the image resolution. 255 is the maximum color value. r, g, and b are the color values of the pixels. They are each an integer in the range [0, 255]. You can place carriage returns wherever you like in the list of pixel values. Comment lines starting with # are also allowed in the ASCII format.

The binary format is almost the same, except the magic number is P6 and the rgb values in the file are written out as byte values instead of ASCII strings (comments, spaces, etc. are not allowed in this portion of the file).

You should probably start with the ASCII version to test things out, then convert to the binary version, which occupies several times less space.

Scene Description Format (extension .rt1 – that’s a number 1)

Numbers in angle brackets are real numbers, in square brackets are integers
Naturally, the brackets do not appear in the actual file (but the colons do).
Blank lines and white space should be ignored
Lines with a ‘#’ as the first character are comments and should be ignored.
Colors should be specified in the range [0.0, 1.0]
Angles should be in degrees, and refer to the full angle (as opposed to the half angle)
 
# comment lines start with # and may appear anywhere
RESOLUTION: [x resolution] [y resolution]
FIELD_OF_VIEW: <full x field-of-view>
BACKGROUND: <red> <green> <blue>
NUM_LIGHTS: [number of lights]
LIGHT
 POSITION: <x> <y> <z>
 DIRECTION: <x> <y> <z>
 INTENSITY: <red> <green> <blue>
 EXPONENT: <exponent>
 CUTOFF: <angle>
ENDLIGHT
LIGHT
ENDLIGHT
LIGHT
ENDLIGHT
#in other words, one LIGHT…ENDLIGHT block for each light
NUM_SPHERES: <number of spheres>
#similarly, one SPHERE…ENDSPHERE block for each sphere
SPHERE
 CENTER: <x> <y> <z>
 RADIUS: <radius>
 DIFFUSE_COLOR: <red> <green> <blue>
 DIFFUSE_COEFFICIENT: <coefficient>
 SPECULAR_COLOR: <red> <green> <blue>
 SPECULAR_COEFFICIENT: <coefficient>
 SPECULAR_EXPONENT: <exponent>
ENDSPHERE
SPHERE
ENDSPHERE
SPHERE
ENDSPHERE


I have made this format as simple as possible to parse, with little room for variation except white space and number of lights, spheres, etc. You can write your parser by hand or use lex/yacc to generate a parser. If you use lex/yacc, do include the properly-generated .c and .h files with your program source as well as the original lex and yacc input files.

Final Words of Encouragement

Good luck on your first assignment. I hope that in addition to being a lot of work, it provides you with some fun and satisfying moments. Remember that I'm available to answer questions in class, by e-mail, or by appointment.


Home
September 20, 1999