RSL
Selective Occlusion


return to main index



Introduction

This tutorial presents a method for rendering ambient occlusion for scenes that have a mixture of fixed and moving objects. The occlusion for the fixed objects is pre-baked into a point cloud and subsequently converted to a brickmap. The pre-bake can be done with a regular occlusion shader (listing 1) or a point-based occlusion shader (listing 2).

The beauty pass relies on the use of trace-sets (refer to the subset tutorial). The shader in listing 3 combines the occlusion from the pre-baked brickmap with on-the-fly occlusion calculations for the moving objects. Compared to the brute force method of rendering an animation entirely without the use of a pre-baked occlusion, the selective technique is very efficient.


Bake Pass

The first shader, listing 1, calculates ray traced occulsion. For simplicity it has few parameters. The second shader, listing 2, uses point-based occlusion. Either shader can be used with the rib file in listing 3.


Listing 1 (ray traced occlusion)


surface
rt_occlusion(string bakename = "",
                    subset = "";
             float  samples = 256,
                    coneangle = 80;
    output varying float _occlusion = 0)
{
normal n = normalize(N);
  
_occlusion = 1 - occlusion(P, n, samples, 
                        "coneangle", radians(coneangle),
                        "subset", subset);
if(bakename != "")
    bake3d(bakename, "_occlusion", P, n, 
                     "_occlusion", _occlusion );
Oi = Os;
Ci = Oi * Cs * _occlusion;
}


Listing 2 (point based occlusion)


surface 
pt_occlusion (string bakename = "";
              string hitsides = "front";
              float  maxdist = 1e15, 
                     falloff = 0, 
                     falloffmode = 0,
                     samplebase = 0,
                     clampocclusion = 1, 
                     maxsolidangle = 0.05;
    output varying float _occlusion = 0)
{
normal n = normalize(N);
normal nf = faceforward(n, I);
  
_occlusion = occlusion(P, nf, 0,     
     "pointbased", 1,            // no raytracing required
     "hitsides", hitsides,       // "front","back" or "both"
     "maxdist", maxdist,         // normally a large distance
     "falloff", falloff,         // reduction  with distance
     "falloffmode", falloffmode, // rate of change of darkness
     "samplebase", samplebase,   // jittering
     "clamp", clampocclusion,    // prevent "blow-out"
     "maxsolidangle", maxsolidangle);
if(bakename != "")
    bake3d(bakename, "_occlusion", P, n, 
                     "_occlusion", _occlusion );
Ci = (1 - _occlusion) * Os;
Oi = Os;
}


Listing 3 (bake-pass)


DisplayChannel "float _occlusion"
  
Display "untitled" "framebuffer" "rgb"
Format 427 240 1
Projection "perspective" "fov" 40
ShadingRate 1
  
Translate  0 0 10
Rotate -30 1 0 0
Rotate 0   0 1 0
Scale 1 1 -1
WorldBegin   
    # The next two attributes can be commented if pt_occlusion
    # is used instead of the rt_occlusion shader
    Attribute "visibility" "trace" [1]
    Attribute "visibility" "transmission" ["opaque"]
    Attribute "cull" "hidden" 0
    Attribute "cull" "backfacing" 0
    Attribute "dice" "rasterorient" 0
    # All objects share the same shader
    Surface "rt_occlusion"  "bakename" ["./occ.ptc"] 
                                    "samples" 256
                                    "subset" ["fixed,floor"]
    # Only fixed, non moving, objects are described in this file
    AttributeBegin  # LEFT SPHERE
        Attribute "grouping" "membership" ["fixed"]
        Translate -4 1 0
        ReadArchive "pSphere.rib"
    AttributeEnd
    AttributeBegin  # RIGHT SPHERE
        Attribute "grouping" "membership" ["fixed"]
        Translate 4 1 0
        ReadArchive "pSphere.rib"
    AttributeEnd
    AttributeBegin
        Scale 10 10 10
        Attribute "grouping" "membership" ["floor"]
        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]
    AttributeEnd
WorldEnd
System "brickmake ./occ.ptc ./occ.bkm"

The attributes cull:hidden, cull:backfacing and dice:rasterorient ensure occlusion for rear facing surfaces is baked into the point cloud. Ideally, the pre-baking scene should be setup so the entire polygon is within the picture frame. Because point-based occlusion does not require ray tracing the attributes visibility:trace and visibility:transmission should be commented or deleted if the pt_occlusion shader is used for the pre-bake.


Beauty Pass

The beauty pass rib file, listing 5, differs from the pre-bake rib file in that it includes a sphere tagged as "moving" (line ??). Also, each object has been assinged an instance of the "selective_occlusion" shader - listing 4. Had this shader used point-based occlusion the beauty pass could be rendered without ray tracing.


Listing 4


surface
selective_occlusion(string bakename = "";
                    string subset = "";
                    float  samples = 256,
                           coneangle = 80;
     output varying float _occlusion = 0)
{
normal     n = normalize(N);
  
if(match("bkm$", bakename)) {
    texture3d(bakename, P, n, "_occlusion", _occlusion);
    
    // Perhaps we also need to find the occlusion from an
    // object that was NOT in the original brickmap.
    float additional = 0;
    if(subset != "") {
        additional = 1 - occlusion(P, n, samples, 
                            "coneangle", radians(coneangle),
                            "subset", subset);    
        _occlusion  = _occlusion * additional;
        }
    }
else
    {
    _occlusion = 1 - occlusion(P, n, samples, 
                        "coneangle", radians(coneangle));
    if(bakename != "")
        bake3d(bakename, "_occlusion", P, n, 
                "_occlusion", _occlusion );
    }
Oi = Os;
Ci = Oi * Cs * _occlusion;
}



Figure 1


Figure 2




© 2002- Malcolm Kesson. All rights reserved.