CS40: Computer Graphics, Lab 9

Lighting and Shading

By Jeff Kaufman

In this lab I extended the graphics library I started in lab 2 by adding support for lighting and shading.

Gouraud Shading

In the Gouraud method of shading polygons you do color calculations only at the verticies and then interpolate those colors over the polygon in the scanline fill algorithm.

Color Calculations

The Phong reflection model is used to determine colors. It involves summing the contributions of each light in the scene. Lights can be ambient, points, or spots. Ambient light has no position, only intensity and color, and makes things look more realistic by approximating the light due to reflections off objects.

Point lights have a position and the light due to each point is considered in body and surface components. The body component does not depend on the viewer because it represents light that goes into the object a small ways, bounces around unpredictably, and comes out again just as likely to be going towards the viewer as any other point. The intensity of the body reflection depends only on the surface normal and the direction from the surface to the light source. When these vectors are paralell the reflection is at its highest and when they are orthogonal it drops to zero. In the Phong model we approximate this relationship with the cosine function which we can get from taking the dot product of the normal and the unit vector in the direction of the light source. The product of this scalar, the body color of the object, and the color of the point light gives us the body component.

Reflection_body = Color_body * Color_light * (surfaceToLight . surfaceNormal)
The surface component corresponds to the portion of the light that will bounce off the surface of the object and go towards the viewer. If the object is completely matte this will be zero but many real objects, especially plastics and metals, show small highlights. Because many objects have a clear layer above their pigment and we're modeling the light that bounces off this layer we need to have a separate color to prepresent the surface reflection color. For plastics this will likely be white while for metals it will be the color of the metal. Having a separate color also allows us to vary the intensity of the reflection by decreasing the color values.

To calculate the surface reflection we first find the vector half way between the vector from the surface to the viewer and the vector from the surface to the light source. The closer this vector is to the surface normal the brighter the reflection should be. We use the cosine function again to approximate this, but this time we raise the result to a power that represents how tight the highlights should be. This should depend on the surface, and nominally models roughness, but doesn't do a good job of making surfaces look more rough or smooth.

Reflection_surface = Color_surface * Color_light * ( normalize(surfaceToLight+surfaceToViewer) . surfaceNormal)^roughness

Spot lights are a simple modification of point lights to give them a direction and a dispersion angle. The color value is multiplied by the negative dot product of the direction from the surface to the light and the light's direction, raised to a power. This power represents the tightness of the spot.

Color = Color * (-light.direction . surfaceToLight)^tightness
The image and movie below show a spotlight moving across a phong shaded cube.

Color Interpolation

Once we have colors for the normals we can color the rest of the polygon. Just like we interpolated inverse Z values we can interpolate the color values. It's a matter of interpolating along the edges of the polygon and then across between the edge colors. Below we have a rotating triangle where the verticies have all been set to promary colors colors and those colors are being interpolated across the triangle.
We can also do this with other shapes, such as octogons (shown below), but this doesn't work properly for conceptual reasons. At most four verticies determine what range of colors a scan line will take on, so if you have many verticies most will be ignored horizontally. This actually looks interesting (very shiny) but to properly support larger polygons I would need a different algorithm.
We also have a problem because we divided our coordinates out by Z to make a perspective projection. We can fix this by interpolating Color/Z instead of Color and then multiplying by Z (which we've been interpolating) later to get the real colors.

Phong Shading

Calculating color values and interpolating works ok, but it does not deal well with cases where light should be acting substantiall differently on part of the polygon. We can instead do calculations at each pixel. This is slower, but can look much nicer. Our color calculations need to know both the world coordinates of the point and the normal at that point so we need to interpolate these. Interpolating them is just like interpolating colors.

Below are two images of a cube with an offest point light just in front of it, one rendered with Gouraud shading and one with Phong, showing how Gouraud shading can be quite inaccurate. The linked movies show the light moving from left to right across the cube.
We can also do pretty stuff with spheres and multiple lights:

Test Image

Something is still funny in my renderer. The image on the left uses the estimated normals that the origonal test code used, giving sharp lines, while the image on the right uses the normals specified by the model, looking much smoother. The coloring and shading, the whole point of this lab, are wrong though.

Extentions

I implented phong shading and spotlights, both of which worked well, as well as making several animations.


Jeff Kaufman : 2006
cbr at sccs dot swarthmore dot spam edu. Remove spam.

main page