Depth Map Based Ambient Occlusion

May, 2003

template:ambocc.slim

Introduction

PRMan11 provides a raytraced occlusion shadeop to render ambient occlusion, but I don't think most people have enough time and resources to pay the price. When the model gets a little heavier, it is opten hard to tell how long the render will take.

Thanks Andrew Whitehurst for his great tutorial about Depth Map Based Ambient Occlusion Lighting, we get a faster non-raytrace alternative.

I modify his shaders a bit and give a guide to use them.

The Test Scene

Inspired by T3 trailer, I took time to model the copter and I hate to test a cool shader on boring sphere or box. You can download the model (1.94MegaByte) here.

I set up a simple lighting with an ambient light and a shadow-casting distant light.

The traditional ambient light is quite boring since it simply throw a flat color onto the surface, discarding too much details. It must be attenuated properly.

Shadow Buffering

The basic idea of depth map based solution is to make a dump of the shape of geometry with a number of depth(shadow) maps shot from different viewpoints(spotLights). Like shooting random sample rays in a hemisphere as we do in the ray-traced solution, we need a dome of spotLights. You can download them here. I have 250 spotLights in it, but I think much less number of lights such as 180 also works.

Each of them is attached to a special light shader "domeSpot", which does not actually light things up, and it just tell the surface shader which shadow map should be used. And a shadow map generator is also attached to them.

If your model is stationary within the animation, the map generation frequency may be set to "Once Per Job", or you must use "Every Frame".

Import the light dome and transform the group to let every light's cone tightly fit the copter so more pixel of the shadow maps will be useful.

If you launch render now, you will have to wait a very long time until any render begins because there are 250 RIB file for shadows, around 700 MegaByte, data to write! So you must use RIBBox here.

Hide all the lights and set Renderer to "none" and do not Cleanup "rib" and "map", then launch render-- nothing happened but a new RIB appeared in the /rib directory in your project.

Open it with some editor and delete the last two line.

Find the line:

Surface "defaultsurface"

and delete it with all lines before it.

Delete all Surface declarations, so this RIB only contains geometry description. Save it in /rib directory and name it "copter.rib". You can download it here(right-click and save target).

Create a RIBBox and type:

ReadArchive "rib/copter.rib"

in it. Name the box "world" to let RIB generation insert the RIB archive into the "world" coordinate system, so that huge amount of data will not have to appear in every RIB.

Now turn off "Primary Visibility" of the copter in the scene and turn on the light dome.

It's time to render the shadow maps! You can simply change renderer to "prman" or "netrender" and launch render. But I don't use Alfred here because "server busy" or "server in use" seems inevitable. I still set "none" and use a DOS command line instead.

MEL:rmanrenderer.rar

It is a MEL script can start prman.exe to render selected RIB(s).

Click "+" to pick up a shadow RIB.

Delete characters after "_". Because the shadow map generation frequency is "Every Frame" and current frame is one, the map extension is ".shd.0001.rib". If "Once Per Job" is used, use ".shd.rib" instead.

Set the start and end of the dome lights, and in this case we use 0 and 249. A DOS window will splash out when you click "r".

It takes a PIII 550 MHz CPU around 80 minutes to render all those 250 shadow maps with 1024 resolution. I think the speed is acceptable.

Baking Occlusion and Bent Normal Data

When the shadow map render is done, make sure to turn on "Laziness" of the domeLight shadow generator! You can keep reusing those maps--for this frame at least.

Create an Ensemble and name it "world".

Rename RIBBox "world" to "copter", and connect it into the ensemble. Plug a surface shader "amboccD" in the "Surface" line.

The "bias" control is a small distance to eliminate incorrect self-shadow.

When the light dome is visible, invoke a lower Shading Rate like 4, render the scene.

Wait a monent, we get the black-and-white occlusion data representing how much ambient light hits on specific surface point. Save it as occlusion pass in tiff format.

Turn on "Do bentNormal" and launch render again, and this time is the colorful bent normal data representing the difference between Surface Normal and "average light direction".

Save it as bentnormal pass in tiff format.

These passes will be projected to "NDC" coordinate of the active camera to affect abient light, and they are never viewpoint-independent. So you will have to re-render them if camera is changed.

Ambient Lighting

Create an "OccAmbient" light in palette and attach it to a Maya ambient light. Load occlusion pass, bent normal pass and environment map in it.

Connect a "Matte" into "world" ensemble, hide the light dome, then launch render.

This is ambient light only.

Add on a shadow-casting distant light.

Most common shading models has the Ambient() call, so you can apply any textured shader on the model, but remember to set "Ka" high enough, or the ambient light will be invisible.

Advantage and Disadvantages

The most time-consuming shadow buffering is viewpoint-independent, which is the most advantage that depth map based ambient occlusion has over a ray-traced solution. We can quickly change the camera and re-render occlusion and bent normal pass, then the final lighting, just use the shadow maps again and again.

It is a very suitable way to match the lighting for stationary model such as architectures. For animated models, shadow buffering has to be done at a per-frame frequency! If the model is not quite complex and covers not too much pixels of the image, try a raytraced occlusion render first! And it can not handel any indoor scene.

Depth map based solution cantains three stages of render, and each of they requires using special shaders and a lot of tricks. If you haven't any idea of what shader, map, NDC, RIB or ambient occlusion is, please try some more basic tutorials first. If you have gotten really tired to fuss about Pixar's occlusion shader, I hope it useful to help you get things done.