<< marc ten bosch
© 2004-2009, all rights reserved
Some content © 2005 DigiPen (USA) Corporation, all rights reserved

Non-photorealistic Shading

January 2005

Non photorealistic Shading Models

Goal: Implement as many NPR shading techniques as possible, discuss efficiency, find common patterns and expand on them.

Techniques implemented: Celshading, Celshading with specular highlights, Simple hatching, "Blended" Hatching, Gooch ("Cool to Warm") shading, Gooch/Rademacher shading, Goochel shading (A combination of Gooch and Cel Shading), Anisotropic lighting.

Tools used: Vertex and Pixel shaders (Via OpenGl and Cg)

Celshading can be implemented efficiently using vertex shaders for per vertex lighting, or using fragment shaders for per pixel lighting. My implementation uses vertex shaders to support more graphics cards. The idea is to compute the diffuse component at each vertex in the vertex shader and then send that value as a texture coordinate of a 1D texture. This 1D texture contains the step function that defines the celshaded areas. This maps the continuous amount of light (as the dot product between the normal to the surface and the light vector) to a set of fixed values (usually between 2 and 4).


The Pen and Ink Hatching implemented here is based on the same concept. For celshading, we define regions with constant light intensity across the model. In pen and ink hatching, we define similar regions, but instead of coloring each of them with a specific constant color, we perform a lookup to a specific texture in normalized screen space (using normalized screen coordinates).

My implementation of Blended Hatching extends this concept by using the continuous version of the light intensity to linearly interpolate between the different textures.

Gooch shading can also be implemented only in vertex shaders. This shading technique defines two colors in addition to the model color: a cool (like yellow) and and warm color (blue etc..). Phong lighting clamps the dot product between the normal to the surface and the light vector to the 0 to 1 range and scales the color of the object by that amount. In contrast, Gooch shading takes that dot product (with values in the -1 to 1 range), and scales it to 0 to 1, in order to retain the maximum amount of information. It then uses that value to linearly interpolate between the cool and the warm color, just after adding the model color to both of them (to have a sense of model color). I also implemented extensions and variations, and in particular, Gooch/Rademacher shading.

Goochel shading (I made that name up) is combination of Gooch and cel shading. It applies the celshading step function to the full range lighting dot product (as opposed to the clamped one).


Anisotropic lighting was implemented just like celshading but with a texture mimicking metal.

It is interesting to try to generalize the functions that can be applied to the lighting dot product (clamping, step, etc...).