CMSC 435/634: Introduction to Computer Graphics

Assignment 1
Ray Tracing
Initial submission September 9, 2014
Due September 16, 2014

Before you start

You will be doing your work this semester in a class git repository. Before you get started on any of the assignments, you should fetch yourself a copy of your personal repository following these directions. Your personal class respoitory on the UMBC GL/Linux systems is /afs/

To make sure you do not have last-minute problems, you must commit and push something to your repository by Tuesday, September 9th. This be anything from an update to the readme to the completed project.

The Assignment

For this assignment, you must write a C or C++ program that will render triangles using ray tracing and the barycentric coordinate intersection method. The input is in a simple text format called NFF, containing information about the view and objects in the scene. You will read an NFF scene from a file or stdin, and ray trace the single image described there. Rays that hit an object should be rendered in the triangle color, while rays that do not hit any object should use the background color of the scene. Do not try to include any of the more advanced ray tracing features you may read about (shadows, reflection, refraction, lights, etc.), we will get to those later. Your output should be an image file in PAM format.

tetra -s 3


For the base assignment, you should be able to trace tetra-3.nff, which is checked into your assn1 directory. Additional NFF format scenes can be generated using a set of programs called the 'Standard Procedural Databases'. A copy of these programs may be found in ~olano/public/spd3.14/. While NFF format is relatively simple, it does contain many features we will not be using in this assignment. You should be able to read any NFF format file, but ignore anything you do not implement. For the basic assignment, you should at least handle the "v" viewing specification, "b" background color, "f" object material specification (just the r g b color part, ignore the rest), and "p" polygon specification. "c" and "pp" are all multi-line, so you will at least need to recognize enough of those to know how much to skip.

Split any polygon with more than three vertices into a fan of triangles: given vertices 0,1,2,3,4, the triangles would be (0,1,2), (0,2,3), (0,3,4)

Since the SPD programs produce their output on stdout, if your ray tracer takes its input on stdin, you can pipe them together:

~olano/public/spd3.14/tetra | ./trace

Since that has 4096 triangles and can be slow to raytrace, using the -s option can yield a simpler models. For example, tetra-3.nff with 64 triangles was generated with

~olano/public/spd3.14/tetra -s 3 > tetra-3.nff


We are using PAM because it is an exceedingly simple format to write. See the netpbm PAM page for more details. PAM files can be viewed directly or converted to other image formats for viewing. On the linux systems, you can use "display" to view these files or "convert" convert them into most other image formats.

To create a PAM file, first you should store your image in an array of bytes in y/x/color index order:

unsigned char pixels[HEIGHT][WIDTH][3];

When filling in this array, remember that it is in y/x order, not the more familiar x/y order, with 0,0 in the top left corner of the image. The third index of the array is the color component, with red=0, green=1 and blue=2. Color values range from 0 to 255. Color values in your ray tracer should be floating point fractions, so you will need to scale to convert them to a byte. Be careful to check for overflow or underflow when mapping floating point values into a byte. For example, this would store a floating point color value g into the green component of the pixel at x=50 and y=25:

pixels[25][50][1]= (g<0) ? 0 : (g>1) ? 255 : (unsigned char)(g*255);

Once you've filled in the pixels array, actually writing the PAM file is quite simple. It is just a text header consiting of the characters, "P7" (identifying a PAM file), text lines containing information about the image. The header is followed by the raw binary data. Here's the complete C code necessary to write a PAM file:

FILE *f = fopen("trace.pam","wb");
fprintf(f, "P7\n");
fprintf(f, "WIDTH %d\nHEIGHT %d\nDEPTH 3\n", WIDTH, HEIGHT);
fprintf(f, "MAXVAL 255\nTUPLTYPE RGB\nENDHDR\n");
fwrite(pixels, 1, HEIGHT*WIDTH*3, f);
gears -s 1

634 only

Splitting polygons into a fan of triangles only works for convex polygons. Instead, use the test-ray method to handle arbitrary concave polygons. Try the "gears" SPD program to generate a scene with some pretty complex polygons.

balls -s 3

Extra Credit

For up to 10 points of extra credit, implement spheres too. Try the balls SPD program for a scene with lots of spheres.

Other people's code

Ray tracing is a popular rendering technique, and the internet contains lots of resources for ray tracers in general and things like ray-object intersection in particular. Other than the PAM snippet above, YOU MAY NOT USE ANY OUTSIDE CODE. All code that you use must be your own.


This is a big assignment. Start NOW, or you will probably not finish. No, really, I promise you will not be able to do it in the last two days. Even before we get to all of the details of the ray tracing itself, you can still start working on your file parsing.

I have created a separate page with some additional development suggestions.

What to turn in

Turn in this assignment electronically by pushing your source code to your class git repository by 11:59 PM on the day of the deadline. Do your development in the assn1 directory so we can find it. Be sure the Makefile will build your project when we run 'make' (or edit it so it will). Also include a README.txt file telling us about your assignment. Do not forget to tell us what (if any) help did you receive from books, web sites or people other than the instructor and TA.

Check in along the way with useful checkin messages. We will be looking at your development process, so a complete and perfectly working ray tracer submitted in a single checkin one minute before the deadline will NOT get full credit. Do be sure to check in all of your source code, Makefile, README, and updated .gitignore file, but no build files, log files, generated images, zip files, libraries, or other non-code content.

To make sure you have the submission process working, you must do at least one commit and push one week before the deadline.