### RSLPoint Clouds & Brickmaps for Ambient Occlusion

#### Introduction

This tutorial introduces the use of point clouds and brick maps for occlusion shading. The shader, listing 1, applies unusual color tinting to the occlusion that it assigns to a surface - figure 1.

Listing 1

 ```surface tinted_occlusion (float samples = 32, sampleangle = 90.0, maxdist = 1000000; string bakename = "", channels = ""; color camera_color = 1; output varying float _occlusion = 0; output varying color _Cs = 0; ) { normal n = normalize(N), nf = faceforward(n, I); float d; Oi = Os; // We have the brickmap with the pre-calculated // occlusion values... if(match("bkm\$", bakename)) { texture3d(bakename, P, n, "_occlusion", _occlusion, "_Cs", _Cs); } else // we have to calculate the occlusion { if(rayinfo("depth", d)) { if(d == 0) // ...I've been hit by a camera ray { color hitc = 0; gather("illuminance", P, n, radians(sampleangle), samples, "surface:Cs", hitc) { _occlusion += 1; _Cs += hitc; } else // gather failed to hit a surface _Cs += 1; // Calculate the averages... _occlusion = 1 - _occlusion/samples; _Cs =_Cs/samples; if(bakename != "") bake3d(bakename, channels, P, n, "_occlusion", _occlusion, "_Cs", _Cs); } } } // Note: Cs is not used Ci = Os * camera_color * _occlusion * _Cs; } ```

In addition to calculating an occlusion value - or reading a previously saved value from a brickmap - the `tinted_occlusion` shader averages the colors of the surfaces that occlude the surface being shaded. Thus a red sphere on a white polygon causes reddish occlusion to appear on the polygon. The color assigned to an object, say,

```    Color 1 0 0
Sphere 1 -1 1 360```

does not effect the color of the object as seen by the camera but, instead, causes another surface that is occluded by the object to be tinted. The shader provides a parameter called "camera_color" and it is the color assigned to this parameter that controls the visual coloration as "seen" by the camera.

The shader either reads a brickmap, if the parameter "bakename" has the file extension "bkm", or it writes data to a point cloud. The two output variables "_occlusion" and "_Cs" are provided so that secondary images ie. render passes, can be generated. The names "_occlusion" and "_Cs" have been chosen because rib files produced by mtor/maya have default display channels with these names.

The scene must be rendered twice. A pre-pass render generates a point cloud file that is subsequently converted to a brickmap in preparation for the second render - the beauty pass. The point cloud or the brickmap can be viewed using ptviewer or brickviewer. Again, Cutter is setup to automatically use these utilities. Select the name of the map you wish to view. A right mouse click or control click (OSX) will popup the menu shown in figure 2.

#### Avoiding Gaps in the Point Cloud Data

To ensure all the occlusion data will be available for later use, the "bake-camera" must be setup not only so that it views as much of the scene as necessary but that three rib `Attributes` are set to ensure the "bake-camera" does not ignore rear-facing or hidden surfaces. When baking the point cloud the following must be active.

```    Attribute "cull" "hidden" [0]
Attribute "cull" "backfacing" [0]
Attribute "dice" "rasterorient" [0]```

If they are not present in a rib file their default value is `[1]`. Figure 3 shows a point cloud rendered using the attributes shown above. Figure 4 shows gaps in the point data because is was rendered with the default attribute values for "hidden", "backfacing" and "rasterorient".

 Because the `camera_color` parameter to the shader in listing 1 plays no part in the tinting of the occlusion some unusual beauty pass renders can be achieved by setting `camera_color` to a color that do not correspond to the true color of an object. For example, in figure 5 the yellow sphere is producing a blue tinted occlusion on the poly-plane. Listing 2 shows a sample rib file for the bake-pass. The point cloud will be saved to the same directory as cutter.jar. Use a full path to save the point cloud to your preferred directory. Listing 3 shows the rib file for the beauty pass.

Listing 2 (bake pass)

 ```DisplayChannel "color _Cs" "quantize" [0 0 0 0] "dither" [0] DisplayChannel "float _occlusion" "quantize" [0 0 0 0] "dither" [0] Display "tinted_occlusion" "it" "rgb" Format 400 400 1 Projection "perspective" "fov" 40 ShadingRate 100 Translate 0 0 10 Rotate -90 1 0 0 Rotate 0 0 1 0 Scale 1 1 -1 WorldBegin Attribute "visibility" "trace" [1] Attribute "visibility" "transmission" ["opaque"] Surface "tinted_occlusion" "samples" 32.0 "sampleangle" 90.0 "bakename" ["test.ptc"] "channels" ["_occlusion,_Cs"] # no spaces "camera_color" [1.0 1.0 1.0] # overrides true surface color Attribute "cull" "hidden" [0] Attribute "cull" "backfacing" [0] Attribute "dice" "rasterorient" [0] TransformBegin Scale 10 10 10 Polygon "P" [-0.5 0 -0.5 0.5 0 -0.5 0.5 0 0.5 -0.5 0 0.5] "st" [0 0 1 0 1 1 0 1] TransformEnd TransformBegin Translate -1 0.5 0 Color 0.956 1.0 0.2 ReadArchive "pCube.rib" TransformEnd TransformBegin Translate 1 1 0 Color 1.0 0.4 0.2 Sphere 1 -1 1 360 TransformEnd WorldEnd System "brickmake ./test.ptc ./test.bkm" ```

Listing 3 (beauty pass)

 ```DisplayChannel "color _Cs" "quantize" [0 0 0 0] "dither" [0] DisplayChannel "float _occlusion" "quantize" [0 0 0 0] "dither" [0] Display "tinted_occlusion" "it" "rgb" Format 400 400 1 Projection "perspective" "fov" 40 ShadingRate 100 Translate 0 -0.5 7 Rotate -90 1 0 0 Rotate 0 0 1 0 Scale 1 1 -1 WorldBegin Attribute "visibility" "trace" [1] Attribute "visibility" "transmission" ["opaque"] Surface "tinted_occlusion" "samples" 32.0 "sampleangle" 90.0 "bakename" ["./test.bkm"] "channels" ["_occlusion,_Cs"] "camera_color" [1.0 1.0 1.0] TransformBegin Scale 10 10 10 Polygon "P" [-0.5 0 -0.5 0.5 0 -0.5 0.5 0 0.5 -0.5 0 0.5] "st" [0 0 1 0 1 1 0 1] TransformEnd TransformBegin Translate -1 0.5 0 Color 0.956 1.0 0.2 ReadArchive "pCube.rib" TransformEnd TransformBegin Translate 1 1 0 Color 1.0 0.4 0.2 Sphere 1 -1 1 360 TransformEnd WorldEnd```