Updated 7/6/2003

Tutorial: RenderMan Render Passes

Render Passes are a crucial aspect of high-end 3D work, but they can be quite a pain to generate if you don't go about it in an efficient way (you can read more about render passes here - including a free Render Passes for Maya plugin).

It is possible to generate your render passes through RenderMan in a particularly elegant manner. This involves two approaches, one where only shader changes are required between passes, and one where changes are required to the scene description.

Arbitrary Output Variables

Most RenderMan renderers nowadays support the generation of multiple output images during a single render. This makes it very easy to render your main image along with render passes such as specular, shadow, depth, colour, etc all at once. This involves generating the RIB file(s) once, loading them from disk once, and processing the scene geometry once and calculating the shading once. This is about as efficient as you can get.

Without using shader output variables, many people generate their render passes by regenerating the whole thing multiple times, each time with minor changes to the shaders applied, or shader parameters.

To generate arbitrary output images (often called extra output channels, or just arb-outs) you need to add output variables to your shader, and assign them values in the body of your shader. Then in your RIB file you need to tell the renderer which shader output variables you want written out as additional images. Each of the additional images will show the scene with the objects shaded purely by the values assigned to the corresponding shader output variable for that pass.

Application note number 24 in the documentation for Pixar's PRMan describe the use of these shader output variables in detail, or see the RenderDotC notes.

Pre-Processing RIB Files

Whilst additional shader outputs are great for generating most render passes, there are situations where you need to change your scene description in order to generate a particular kind of pass.

In this situation most people will revert to the old method of writing out another batch of slightly modified RIB files including these changes. This is very inefficient, as the changes are often miniscule, and the RIB generation time for a complex scene can take hours per frame.

It is possible to have a single RIB file containing conditional sections, by using the C language pre-processor program. This program is included with most Unix installations, and free versions can be downloaded for other platforms. Although this program is normally used during the compilation of C/C++ programs, it is effectively just a filtering program that runs over text files, including or excluding parts of them depending on various conditions.

If you have the following bit of RIB:

   AttributeBegin
     #if defined(SHADOWPASS)
       Surface "null"
     #elif defined(BEAUTYPASS)
       Surface "rmarble"
     #else
       Surface "plastic"
     #endif
     Sphere 1.0 -1.0 1.0 360.0
   AttributeEnd
   AttributeBegin
     #if defined(REFLECTPASS)
     ReadArchive "reflect_environment.rib"
     #endif
   AttributeEnd   

Then in order to get this rendered you would execute one of these:

  cpp -D BEAUTYPASS   my.rib | prman
  cpp -D SHADOWPASS   my.rib | prman
  cpp -D REFLECTPASS  my.rib | prman

...where the sections you wish to include are specified through the '-D NAME' option, which can be used multiple times in one line. Conveniently, the hash symbol is a comment in the RIB format, so even if you directly render this RIB without the pre-processor, it will still be valid RIB and will still render, though it will contain all sections together.

The above example shows a simple way of including or excluding some RIB statements. However, any C/C++ programmer will know how to construct much more complex conditional processing within the RIB files.

Setting up your scene to output these special pre-processor statements should be easy enough. Most applications or plugins that provide RenderMan output also allow you to attach snippets of RIB code to objects, to be output with them in the final RIB file. Failing that, you could always output your objects as RIB archives and manually edit them to insert the additional pre-processor statements.

Conclusion

I've just tried to sketch out the general concepts here, rather than describing it all step-by-step as there are so many different 3D applications and RenderMan translators and renderers around today. If you've got any questions about this approach, feel free to email me.



Return to the Tutorials page