CS 351: Assignment #8


Due before Thanksgiving break. Picture 1 is due Friday, November 18.

For this assignment you will implement Gouraud shading for polygons with ambient and point light sources. The end result will be a complete 3D z-buffer rendering system with lighting and shading. If you decide to implement Phong shading as an extension, you may skip the Gouraud shading step and just go straight to Phong shading.


Here is the new Graphics System Specification.

The major steps are as follows.

  1. Create the light source data type and supporting functions. The Lighting_shading function should calculate the appearance of a surface given its parameters and all of the lights. This test program should create this output. The first light line is the contribution of the ambient illuminant. The second light line is the combined ambient and point lighting. These results use the equation in the graphics specification and approximate H as (L+V)/2.

    As a second test of your Lighting_shading function, you can run this program, which generates the image below. It does not use your modeling system, only the Lighting_shading function.

  2. Update your Polygon_drawShade algorithm to do Gouraud shading, and test it on a hand-created polygon to see if the colors interpolate cleanly. Calculate the colors using an ambient and a point light source and the shading function defined in the prior step.

    The updates are primarily in the makeEdgeRec, fillScan, and updateActiveList functions. You will need a new field in the Edge data structure to hold a color and a dColorPerScan. If you call them cIntersect and dcPerScan, they will act similarly to xIntersect and zIntersect. You will need to add two Color arguments to makeEdgeRec: c1, and c2. They should mirror lower and upper, and reflect the colors at those two vertices.

    To account for perspective projection, calculate dcPerScan using the color value divided by the depth value, as below. edge->dcPerScan.c[0] = ( c2.c[0]/upper.val[2] - c1.c[0]/lower.val[2] ) / dscan;

    Similarly, calculate the initial cIntersect as the initial color value divided by the initial z value. In your fillScan function, you will need to multiply c/z by z to get the true color value.

  3. Create the function Polygon_shade that calculates the color at each vertex of the polygon given a DrawState and Lighting structure. Use the Lighting_shading function above to do the actual color calculations. The function should allocate and fill out a color array as part of the Polygon data structure. In addition, write the utility functions Polgyon_setNormals, Polygon_setColors, and make sure your Polygon_clear, Polygon_copy, Polygon_setNULL, Polygon_set, and other utility functions properly handle the new color field and oneSided field. The Matrix_xformPolygon should also do a Matrix_xformVector on the surface normals.
  4. Add the functions to the Module class for handling body and surface colors and the surface reflection coefficient. These additions will also involve changes to the Element_init function.
  5. Update your Module_draw function to handle Gouraud shading. The main change is in the ObjPolygon case.
  6. To implement Gouraud shading for polygons, you need to calculate shading at the vertices of the polygon. The simplest way to do this is to place the light sources in world coordinates and make the color calculations after multiplying the polygon by the LTM and GTM matrices. Therefore, your polygon case will end up looking something like the following.

    case ObjPolygon:
      Copy the polygon data to a temporary polygon P
      Transform P by the LTM
      Transform P by the GTM
      If doing Gouraud shading
        Call Polygon_shade to calculate the color at each vertex using P
      Transform P by the VTM
      Homogenize the X and Y coordinates
      If doing Gouraud shading
        Call Polygon_drawShade with P, the draw state and the lighting

    Note that your Polygon_drawShade function does not need to use the lighting, only the DrawState. If you implement Phong shading, you will need the lighting information.

  7. Test your system to this point using a simple cube.

  8. You can test your system further using the X-wing scene from last week.

  9. A third test program makes use of the files linked below. Run the example program test8c.c using the command:
  10. ./test8c starfury.ply 30

    The first linked code is the test program, the second goes in your library and enables your system to read in .ply files, and the third is the .ply file itself. Note, you may have to modify the read function depending upon the specific fields in your polygon structure. Also, the program makes a system call to convert, so if your system does not have the ImageMagick package installed, either install it or reduce the size of the image from 2000x2000 to 500x500 using a different image reduction tool.

    Feel free to create your own .ply models. Several of the Stanford models are available in that format. To obtain the models, you can peruse the Stanford 3D Scanning Repository. Also, 3D modeling programs like Blender3D (which is freely downloadable), can save models in the .ply format.

  11. The required creative image for this assignment is to create your own 3D model and place at least three copies or variants of it into a scene with at least one point light source, an ambient light source, and shading. Each person should create their own scene.



Make a child wiki page from your main CS 351 wiki page. Give it the label cs351f11project8. Please follow the format below.

  1. Abstract: 200 word description (at most) of what you did and a picture to go along with it.
  2. Description of the task, in your own words. Be brief, but write it as though explaining it to a fellow student not in the course.
  3. Description of how you solved the task, including any key equations or algorithms. You should also include algorithms or descriptions of what you did for any extensions. Include pictures here.
  4. More pictures. Please put a caption on each picture explaining something about it. If you have nothing else, give it a name and indicate whose picture it is.
  5. Summary of what you learned.


Put your code files in your private handin folder as a single zip or tar file. Put your writeup on the wiki. Give it the label cs351f11project8.