Ambient occlusion is a technique that appeals to many CGI enthusiasts. Scenes
rendered using this technique are often visually appealing. Typically, such
scenes are rendered using the ray tracing features of a renderer. Although it
is often assumed that ray tracing produces photo-realistic images, in
the case of ambient occlusion such an assumption is wrong. The shading effect
achieved with ambient occlusion is not dependent on the light sources in a scene.
Infact, occlusion ordinarily does not even require a scene to have any light sources!
Ambient occlusion has more in common with techniques used by illustrators than photo-realists.
The basic code for listing 1 was taken from Pixar's Application Note #35 "Ambient Occlusion, Image Based Illumination, and Global Illumination". It can be found at
within the Pixar directory.
In the code for their first sample occlusion surface shader they refer to a function
The sample code on this page does not rely on their header file but, instead,
The gather() function shoots
a number of rays, defined by
Rendering the rib file with a higher sampling rate improves the image quality (figure 2) but at a considerable cost in rendering time.
Listing 3 gives the code for an improved version of occlusion shader.
It uses a shading language function called
The value hilited in red is the value that controls occlusion quality. Smaller values give better results (figure 4), but again, at the cost of rendering speed.
Using either the occlude1 or the occlude2 shader prevents shadows being rendered because neither shader takes direct lighting into account. Figure 5 shows the effect of a shadow casting spotlight when the occlude3 shader (listing 4) is used.
The apparent color of the surface (
LightSource "shadowspot" 1 "intensity" 55 "from" [-1 5 5] "to" [0 0 0] "shadowname" ["raytrace"] "samples" 64.0 "width" 8
Figure 6 shows the effect of using the occlude2 shader on the box while using the new occlude3 shader on the ball and floor.
The following code snippet shows how a shader can test if it is currently shading the interior or exterior face of a surface.
/* we're shading the outside of a surface - ignore diffuse() */ if(n == nf) Ci = (1 - occ) * Cs * Oi; else /* we're shading the inside */ Ci = (1 - occ) * Cs * Oi * Kd * diffuse(nf);
In figure 7 we see the effect of switching diffuse() "off" on outward facing surfaces.
© 2002- Malcolm Kesson. All rights reserved.