Due Friday 28 April 2017
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.
The final assignment will be to pick one more capability and add it to your system. That could be shadows, area lighting, texture mapping, a complex 3D model representation, or some other extension of your choice. As you complete this assignment, you may want to consider what capability you want to build out and start that process in parallel.
Here is the final Graphics System Specification.
The major steps are as follows.
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 (note that my
lighting_add function prints out the sum of all the shading calculated
so far). 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.
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, cIntersect, 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 start and end parameters, and specify 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 = ( c2.c/end.val - c1.c/start.val ) / 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.
- 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_init, polygon_set, and other utility functions properly handle the new color field and oneSided field. The matrix_xformPolygon should also call matrix_xformVector on each surface normal.
- 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.
- Update your module_draw function to handle Gouraud shading. The main change is in the ObjPolygon case.
Test your system to this point using a simple cube.
You can test your system further using the X-wing
scene from last week.
- A third test program makes use of the files linked below. Run the example program test9c.c using the command:
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.
./test9c 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. In particular, if you are using doubles for your Point/Vector data structure, you will need to modify the fscanf call for those to %lf instead of %f. 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.
- Implement Phong shading instead of Gouraud shading. This requires interpolating the surface normals and surface locations (in world coordinates) across the polygon.
- Implement spotlights.
- Implement area lighting.
- Create a scene like a lamp with a lampshade using combinations of standard lights, as we discussed in class.
- Make an example that would be a useful demonstration of the shading concepts.
- Build a full scanline rendering system that executes all polygons in one pass.
- Build an A-buffer system instead of a z-buffer system so you can do transparency (and shadows).
- Make interesting models, like planets and spheres.
- Make cool pictures and animation sequences.
- Handle aliasing issues at boundaries by using the centroid value of polygons to determine which of two polygons of similar depth is really in front.
Make a child wiki page from your main CS 351 wiki page. Give it the label cs351fs17project9. Put up your required and portfolio images along with brief descriptions and relevant information.
Put your code on the handin server. Put your writeup on the wiki.