While the phong shading model aims for a photorealistic lighting model, there are several other lighting models that aim to produce non-photorealistic effects. Gooch shading and Toon shading are both examples of popular non-photorealistic lighting models.

Gooch Shading

The purpose of Gooch shading is to emulate technical illustrations. The technique draws black edge lines and adds warm and cool colors to more clearly show the luminance and curvature of the object. Warm colors are used to indicate surfaces facing the light source and cool colors are used to indicate surfaces facing away from the light source. The following equations are used to calculate the luminance range and the final color of each pixel is linearly interpolated by using the dot product of the normal and the direction of the light source[1].

$$ k_{cool} = k_{blue} + \alpha k_d $$ $$ k_{warm} = k_{yellow} + \beta k_d $$ $$ (\frac{1 + N \cdot L}{2})k_{cool} + (1 - \frac{1 + N \cdot L}{2})k_{warm} $$

There are several techniques for drawing the edge lines and the one used in my program will be discussed further below. The following are comparisons of the output from my program for two different 3d models using both the Phong shaders and Gooch shaders.

Toon/Cell Shading

Toon Shading or Cell Shading is another non photorealistic shading technique that attempts to create a render in a style that looks cartoonish. Unlike phong shading that interpolates the colors based on the normal, toon shading renders discrete regions rather than continuously. This can be done by setting thresholds for the dot product of the normal and light direction and for each range having a consistent tone [2].

Below is the output of my program's toon shader on two different 3d models.


This final shader is based on stippling or shading using small dots [4]. All the dots are generated using the diffuse color and some factor of randomness. The shader generates more distinct dots in the darker regions by weighing the random part more based off of the dot product of the normal and light direction.

Edge Lines

The implementation of edge lines used in my program was to render another copy of the 3d model. This copy would be slightly enlarged and rendered completely in black. It would be rendered with front face culling so that only the surfaces facing away would be rendered. This would allow the original model to be rendered on top of some slightly enlarged back surfaces in the shape of the original model creating edge lines for most of the model. This technique doesn't work perfectly especially in places where there's a lot of overlap between parts of the 3d model.

The copy of the original model was enlarged in the vertex shading with the following equation where \(\alpha\) is some very small constant. The larger the constant is the thicker the edge lines become. This works by moving the vertex from the original position along the direction of the normal some small amount.

$$ gl_{Position} = vertex_{position} + \alpha * normal $$

Another technique that would get rid of the z-fighting issue with the previous technique is to use multi-pass rendering. The first pass would determine the colors and instead of rendering to the screen it would output the results to a framebuffer that is passed into another shader. This second shader would run an edge detection algorithm such as the Sobel filter[3] and render the scene with edge lines where detected by the algorithm.

Summary and How to Run Program

The program is built on top of the skinning project. It runs on the lab machines and is compiled the same way as the skinning project. The only difference is that the "F" key when pressed changes the shader program that is being used. The program has a phong, gooch, cell, and stippling shader.