Adding an occlusion pass

Air’s surface shaders provide a consistent set of output variables for common rendering passes such as diffuse, specular, reflection, and per-light channels.  Any or all of these values can be saved during a single invocation of the renderer, either to separate image files or as individual layers in a multi-layer OpenEXR file.  What if we need to save an additional pass, such as occlusion, as part of the rendered image set?

If we were rendering each pass with a separate invocation of the renderer, we could use one of Air’s command filtering options to override the surface shader assignments with a shader that computes the desired value, occlusion in this case:

air -surf occlusionpass myscene.rib

However, if we’re trying to record all output values in a single rendering, we need to preserve the existing shader assignments.  There are at least two ways to add additional passes to the output mix without clobbering the existing shaders:

Method 1:

Add an additional output variable with the desired value to the surface shaders.  For shaders built with the Vshade user interface, the VPlastic surface shader can serve as a model.  It includes extra blocks that compute an occlusion value exported as a __occlusion output variable.  In the Vshade source network, the occlusion code and output variables are just two blocks which can easily be copied to other Vshade surface shaders.

Vshade occlusion blocks

For text-based shaders, we can copy-and-paste the necessary code fragments.  First, add two new arbitrary output variables (AOVs):

surface mysurf(...;
   output varying color __occlusion = 0;
   output varying vector __bent_normal = 0;
)

then include code to compute the occlusion values:

if (raylevel()==0) {
  if ((isshadowray()+isindirectray())==0) {
    float doOcclusion = 0;
    option("display:__occlusion", doOcclusion);

    if (doOcclusion!=0) {
       normal Nf = faceforward(normalize(Normal),I);
       __occlusion = occlusion(Position,Nf,PI*0.5,__bent_normal);
       __bent_normal = vtransform("current","world",__bent_normal);
     }
   }
}

This code only computes the __occlusion value when it is being saved in an output image.

With this method of computing occlusion, the occlusion quality parameters must be set using the corresponding indirect attributes, which are documented in the Air user manual in the Indirect Lighting section of the Lighting chapter.

Method 2:

Use a volume shader that emits the desired value, and assign the volume shader as the Atmosphere shader for the desired objects.  Atmosphere shaders are normally used for volumetric effects.  For scenes that do not require atmospheric effects, we can use a “fake” atmosphere shader (that does not modify the main output color or opacity) as a container for additional output variables.

As an example, I’ve converted to the massive_occlusionpass surface shader included with Air to a volume shader – massive_occlusion_layer:

http://www.sitexgraphics.com/massive_occlusion_layer.zip

The converted shader provides a __occlusion output variable with the occlusion result; the shader does not alter the output color or opacity from the surface shader.

To assign a volume shader as an atmosphere shader, use the Atmosphere RIB statement:

Atmosphere "massive_occlusion_layer"

If you are rendering with Massive, you can assign the above shader to all objects by placing the above text in a small file  and either specifying that file as the rib options file in Massive, or including it on the command line when rendering from a command shell:

air addocc.rib myscene.rib

Although the above discussion focused on occlusion, the same techniques can be used to compute and export any desired value for inclusion in a multi-layer EXR file or other storage format.

Posted in Passes | Tagged , , , | Comments Off on Adding an occlusion pass

Visualizing procedural bounding boxes

Procedural primitives are a powerful mechanism for efficiently rendering complex scenes.  In a scene file a procedural primitive is defined with the Procedural RIB command:

Procedural “type” [arguments] [minx maxx miny maxy minz maxz]

The array of 6 floats at the end defines a bounding box for all objects that might be created by the procedural.  The procedural prim acts a placeholder in the scene.  The procedural e is evaluated only when and if the renderer needs to access the interior of the bounding box.  If the bound is never encountered by the renderer – because say the bounding box is off-screen or occluded by other objects – the procedural primitive is never evaluated.

Because of the on-demand manner in which a procedural primitive is created, it is important that the bounding box be accurate.  If the bound is too large, the renderer may unnecessarily evaluate a procedural prim whose contents are hidden.  If the bound is too small, objects of created by the procedural primitive may be rendered incorrectly (usually appearing to be clipped along bucket boundaries or the boundaries of the bounding box).

Here is a small RIB filter plugin to aid in visualizing the bounding box for a procedural primitive:

http://www.sitexgraphics.com/showprocbd.zip

Unzip the archive to the procedurals directory of your Air installation, and Air will be able to find the showprocbd plugin without a path reference.

You can use the -rif command line switch to apply the showprocbd RIB filter to a scene:

air -rif showprocbd myscene.rib

Here’s an example showing a small group of agents from the Massive crowd simulation program.  Massive uses a procedural primitive to generate agents geometry at render time.

By default the showprocbd filter replaces each procedural primitive with a box representing the procedural bound. This can be help accelerate preview rendering in cases where the full expanded geometry is not needed.

Showprocbd has a number of options for customizing its behavior.  For example, you can set the alpha and color for the box:

air -rif “showprocbd boxalpha 0.5 boxcolor 1 .8 .6” myscene.rib

Including a “replace 0” in the argument list retains the contents of the procedural primitive:

air -rif “showprocbd boxalpha 0.5 replace 0” myscene.rib

In this scene we can see that for some agents the elbows protrude slightly outside the bounding box.

The box can be represented by lines instead of or in addition to polygons:

air -rif “showprocbd boxalpha 0 linewidth 3 linecolor .7 .8 .5” myscene.rib

Box corners can also be rendered:

air -rif “showprocbd boxalpha 0 cornerwidth 20 cornercolor 1 0 0 linewidth 5” myscene.rib

Finally, instead of applying the filter as a command line option, you can define the current filter for an object as a RIB attribute:

Attribute “render” “rifilter” “showprocbd replace 0 boxalpha 0.5”

Posted in RIB Filters | Tagged , , , | Comments Off on Visualizing procedural bounding boxes