Blue Moon Rendering Tools 2.4

Part 5: Photorealistic Rendering with rendrib


revised 26 Jan 1999


Larry I. Gritz
lg@bmrt.org



The rendrib program is a high-quality renderer incorporating the techniques of ray tracing and radiosity to make (potentially) very realistic images. This renderer supports not only the required features of the RenderMan Interface, but also many of the more advanced Optional Capabilities, such as: ray tracing, radiosity, solid modeling, depth of field, motion blur, area light sources, texture mapping, environment mapping, displacements, volume and imager shading, and support of the RenderMan Shading Language.

The format for invoking rendrib is as follows:

	rendrib [options] myfile.rib

Usually, this will result in one or more TIFF image files to be written to disk. If the RIB file specified framebuffer display (as opposed to file), or you override with the -d flag, the resulting image will be displayed as a window on your screen. When the rendering is complete, rendrib will pause. Hitting the ESC key will terminate. Alternately, if you hit the 'w' key, the image in the window will be written to a file (using the filename specified in the RIB file's Display command).

5.1 Command Line Switches

5.1.1 Setting image resolution, sampling rate, crop window

If your RIB file contains Format or PixelSamples statements, then the values specified by these statements will be used to determine the image resolution and sampling rate for your image. If these statements are not in the RIB files, the default values will be used (640x480 pixels and 2x2 sampling, respectively). You can change the defaults by using the -res and -samples command line arguments. Each take two arguments giving the x and y resolution or sampling rates. For example, if you want your image to be rendered at 320x240 resolution with only 1 sample per pixel, you can invoke rendrib in the following way:
	rendrib -res 320 240 -samples 1 1 myfile.rib

Note that if the RIB file contains a Format or PixelSamples statement which explicitly specifies the image resolution, then the -res or -samples options will be ignored and the image will be rendered using the values in the RIB file.

An alternative to setting a fixed number of samples per pixel is to use variance-based sampling. This method samples highly only in regions with high variance. To invoke this option, you can either put the PixelVariance directive in your RIB file, or use the -var command line option. This option takes three arguments: the desired maximum variance, the minimum number of samples per pixel, and the maximum number of samples per pixel. Here is an example:

	rendrib -res 320 240 -var 0.01 4 32 myfile.rib
Note that this example set the maximum variance in a pixel to 0.01, which totally overrides the PixelSamples directive or -samples option. In this example, all pixels will have at least 4, and at most 32 samples. For most effective variance-based sampling, you need to properly set the minimum and maximum numbers of samples per pixel. This is explained in the "implementation-specific Options" section of this chapter.

You can specify only a crop window to be rendered using the -crop option. It takes four arguments which are the same as the arguments to the CropWindow RIB directive. This can be used to render only a portion of an image. The default is to render the entire image. Here is an example:

	rendrib -res 320 240 -crop 0.25 0.6 0.5 1 myfile.rib

5.1.2 Verbose output

By default, rendrib creates image files, and the only text output that rendrib creates is a periodic update of the current scanline which is being rendered and a notice when the rendering is complete. Errors are of course output if there are problems with the RIB file. There are two command line switches which can increase the amount of feedback which rendrib provides.

The -v option (which stands for verbose) takes no arguments. Its result is to inform you of all RIB files which are read and all shaders which are loaded. For example:

		rendrib -v myfile.rib

The -stats option will print rendering statistics after the image is completed. Statistics include data such as total number of rays cast, percentage of shadow rays which were occluded, memory usage, and so on. For example:

	rendrib -stats myfile.rib

You can combine the -v and -stats options if you want.

5.1.3 Selecting Particular Frames

Sometimes you may only want to render a subset of frames from a multi-frame RIB file. You can do this by using the -frames command line option. This option takes two integer arguments: the first and last frame numbers to display. For example,

	rendrib -frames 10 10 myfile.rib

This example will render only frame number 10 from this RIB file. If you are going to use this option, it is recommended that your frames be numbered sequentially starting with 0 or 1.

5.1.4 Radiosity

By default, rendrib calculates images using the rendering technique of ray tracing. Ray tracing alone does no energy balancing of the scene. In other words, it does not account for interreflected light. However, rendrib supports radiosity, which is a method for performing these calculations. You can instruct rendrib to perform a radiosity pass prior to the ray tracing by using the -radio command line switch. This command is followed by a single numerical argument, which is the number of radiosity steps to perform. For example, the following command causes rendrib to perform 50 radiosity steps prior to forming its image:

	rendrib -radio 50 myfile.rib
If the energy is balanced in fewer steps than you specify, rendrib will skip the remaining steps (saving time). Depending on your scene, the radiosity calculations can take a long time, but they are independent of the final resolution of your image.

By default, rendrib calculates the visibility between geometric elements by casting a minimum of one ray between the two elements. You can increase this number to get better accuracy (but at a big decrease in speed) by using the -rsamples option. This option takes a single integer argument. The minimum number of rays used to determine visibility will be the square of this argument. For example, the following command will perform a radiosity pass of 100 steps, using a minimum of 4 sample rays per visibility calculation:

	rendrib -radio 100 -rsamples 2 myfile.rib

Several implementation-specific options and attributes alter the way in which radiosity is calculated. These are discussed in the following sections.

5.1.5 Rendering directly to the display

By default, any fully rendered frames are sent to a TIFF image file. However, you can override this and render directly to the display using the -d command line option. This option only works some platforms. Here is an example:

	rendrib -d -res 256 256 -samples 1 1 myfile.rib
You can specify an optional integer argument to the -d switch, which causes the scanlines to be interleaved, giving you a kind of progressive refinement display. For example,
	rendrib -d 8 -res 256 256 -samples 1 1 myfile.rib

will display every 8th scanline first (making a very quick, but blocky image), then compute every 4th scanline, then every 2nd, and so on, until you get the final image. This is extremely useful if you want to quickly see a rough version of the scene.

You can also specify the position of the window on your display using the -pos option. For example, to ensure that your window's upper left corner falls on pixel (300, 200), try:

	rendrib -d 8 -pos 300 200 myfile.rib

5.1.6 Safeguarding existing files

When you submit a RIB file for rendering, the image files will have filenames as specified in the RIB file with the Display directive. If a file already exists with the same name, the original file will be overwritten with the new image. Sometimes you may want to avoid this. Using the -safe command line option will abort rendering of any frame which would overwrite an existing disk file. This is mostly useful if you are rendering many frames in a sequence, and do not want to overwrite any frames already rendered. Here is an example:

	rendrib -safe -frames 100 200 myfile.rib
This example will render a block of 100 frames from the RIB file, but will skip over any frames which happen to already have been rendered.

5.1.7 Quick ASCII preview

Try this out for amusement:

        rendrib -ascii myfile.rib

This will produce an ASCII (yes, exactly what you think) representation of your scene to the terminal window!

5.2 Nonstandard Options

Several of the features of this renderer can be controlled as nonstandard options. The mechanism for this is to use the Option RIB directive. The syntax for this is:
	Option name  params
Where name is the option name, and params is a list of token/value pairs which correspond to this option. Remember that options apply to an entire rendered frame, while attributes apply to specific pieces of geometry. Implementation-specific attributes are discussed in the following subsection. The various nonstandard options are listed below.

Remember that both of BMRT's renderers (rendrib and rgl) read from a file called .rendribrc both in the local directory where it is run, and also in your home directory. This file can be plain RIB, which means that if you want to set any defaults of the options discussed below, you can just put the Option or Attribute lines in this file in your home directory.

5.2.1 Rendering Options

Option "render" "minsamples" [8] "maxsamples" [64]
This sets the minimum and maximum number of samples per pixel, for scenes when the pixel variance metric is used. This only works if the RIB file contains a PixelVariance statement, but not a PixelSamples statement. These numbers are both integers.
Option "render" "max_raylevel" [4]
This sets the maximum number of recursive rays that will be cast between reflectors and refractors. This has no effect if there are no truly reflective or refractive objects in the scene (in other words, shaders which use the trace() function). This number is an integer.
Option "render" "minshadowbias" [0.01]
The "minshadowbias" option is the minimum distance that one object has to be in order to shadow another object. This keeps objects from self-shadowing themselves. If there are serious problems with self-shadowing, this number can be increased. You may need to decrease this number if the scale of your objects is such that 0.01 is on the order of the size of your objects. In general, however, you will probably never need to use this option if you don't notice self-shadowing artifacts in your images.
Option "render" "prmanspecular" [1]
Pixar's PRMan does not use the SL specular() function as listed in the RI standard. BMRT uses the standard function, which results in specular highlights looking very different in the two renderers. This option, which takes an integer, causes BMRT's specular function to behave much more like PRMan's with a value of 1, and uses the specular function from the standard when given a value of 0. The default used to be zero (standard), but starting with BMRT 2.3.4, the default is 1 (PRMan). Use this option with a value of 0 in order to revert to the old (RI standard) behavior.

5.2.2 Radiosity Options

Option "radiosity" "steps" 
In addition to using the -radio command line option to rendrib, you can specify the number of radiosity steps with this option. Setting steps to 0 indicates that radiosity should not be used. Nonzero indicates that radiosity should be used (with the given number of steps) even if the -radio command line switch is not given to rendrib.
Option "radiosity" "minpatchsamples" 
Just like the -rsamples command line option to rendrib, this option lets you set the minimum number of samples per patch to determine radiosity form factors. Actually, the minimum total number of samples per patch is this number squared (since it is this number in each direction). In some cases, the render will decide to use more samples, but this is the minimum.

5.2.3 Search Path Options

There are times that the renderer needs auxiliary files, such as texture map files, shader descriptions, or other RIB files (when you use ReadArchive). Generally, rendrib only searches the current directory for any files, unless you give a complete path name. However, you can instruct rendrib to search a list of directories for these files (just like how your execution PATH variable works for the shell).
	Option "searchpath" "texture" "/usr/local/textures" 
	Option "searchpath" "shader" "/u0/lg/shaders"
	Option "searchpath" "archive" "path1:path2:path3" 

5.2.4 Runtime Options

Option "runtime" "verbosity" verb
This option controls the same output as the -v and -stats command line options. The verb parameter is a string which controls the level of verbosity. Possible values, in order of increasing output detail, are: "silent", "normal", "stats", "debug".

5.2.5 Other Options

Option "limits" "texturememory" [k]
This option controls sets a texture cache size to k, which is an integer, measured in Kbytes. The renderer will try to keep no more than this amount of memory tied up with textures. Setting it low keeps memory consumption down if you use many textures. But setting it too low may cause thrashing if it just can't keep enough in cache. The default is 1000 (i.e. 1 Mbytes). The texture cache is only used for tiled textures, i.e. those made with the mkmip program. For regular scanline TIFF files, texture memory can grow very large.
Option "limits" "geommemory" [k]
Analogous to the texturememory option, this sets a limit to the amount of memory used to hold the diced pieces of NURBS, bicubics, and displaced geometry. It is an integer, giving a measurement in Kbytes. The default is 40000 (i.e. 40 Mbytes). This can keep your memory consumption down for large scenes, but setting it too low may cause you to continually be throwing out and regenerating your NURBS or displaced surfaces.
Option "limits" "derivmemory" [k]
A certain amount of memory is needed to allow rendrib's Shading Language interpreter to correctly compute derivatives. Very occasionally, you may need to increase this number (generally only if you have absolutely humongous shaders with many texture or other derivative calls). The argument is an integer, giving a measurement in Kbytes. The default is 2 (i.e. 2048 bytes). If your frames are not crashing mysteriously in the shaders, don't screw with this number!

5.3 Nonstandard Attributes

Several of the features of this renderer can be controlled as nonstandard attributes. The mechanism for this is to use the Attribute RIB directive. The syntax for this is:
	Attribute name  params
Where name is the attribute name, and params is a list of token/value pairs which correspond to this attribute. Remember that options apply to an entire rendered frame, while attributes apply to specific pieces of geometry. The various nonstandard attributes are listed below.

5.3.1 Radiosity Attributes

The following attributes control specific features of the radiosity computations. These attributes have absolutely no effect if you are not performing radiosity calculations.
Attribute "radiosity" "averagecolor" [color]
By default, the radiosity renderer assumes that the diffuse reflectivity of a surface is the default color value (set by Color) times the Kd value sent to the shader for that surface. For the lighting calculations to be accurate, the reflective color should be the average color of the patch. For surfaces with a solid color, this is fine. However, some surface shaders create surfaces whose average colors have nothing to do with the color set by the Color directive. In this case, you should explicitly set the average color using the attribute above. You may have to guess what the average color is for a particular surface.
Attribute "radiosity" "emissioncolor" [color]
All surfaces which are not light sources (Lightsource or AreaLightsource) are assumed to be reflectors only (i.e. they do not glow). If you want a piece of geometry to actually emit radiative energy into the environment, you can either declare it as an AreaLightSource, or you could declare it as regular geometry but give it an emission color (see above). The tradeoffs are discussed further in the radiosity section of this chapter.
Attribute "radiosity" "patchsize" ps "elemsize" es "minsize" ms 
This attribute tells rendrib how finely to mesh the environment for radiosity calculations. The statement above instructs to chop all geometry into patches no larger than ps units on a side. Each patch is then diced into elements no larger than es units on a side. As a result of analyzing the radiosity gradients, elements may be diced even finer, but a particular element will not be diced if its longest edge is shorter than ms units. The smaller these numbers, the longer the radiosity calculation will take (but it will be more accurate). This attribute can be used to set these numbers on a surface-by-surface basis (i.e. different surfaces in the scene may have different dicing rates). The units ps, es, and ms represent are measured in the current (i.e. local) coordinate system in effect at the time of this Attribute statement.
Attribute "radiosity" "zonal" zonalval
This attribute controls which radiosity calculations are performed on surfaces. This can be set on a surface-by-surface basis. Possible values for zonalval are shown below, in order of increasing computational cost:
"none"
The surface will neither shoot or receive energy, i.e. it will be ignored by the radiosity calculation.
"zonal_receives"
The surface receives radiant energy, but does not shoot it back into the environment.
"zonal_shoots"
The surface reflects (or emits) energy, but does not receive energy from other patches.
"fully_zonal"
The surfaces both receives and shoots energy. This is the default zonal property of materials.

5.3.2 General Rendering Attributes

Attribute "render" "visibility" bitmask
This attribute controls which rays may "see" an object. The bitmask parameter is an integer, which is the sum of:
1 - The object is visibile from primary (camera) rays.
2 - The object is visibile from reflection rays.
4 - The object is visibile from shadow rays.
This attribute is useful for certain special effects, such as having an object which appears only in the reflections of other objects, but is not visible when the camera looks at it. Or an object which only casts shadows, but is not in reflections or is not seen from the camera. The default, obviously, is 7.
Attribute "render" "casts_shadows" shadowval
This attribute controls how surfaces shadow other surfaces. Possible values for shadowval are shown below, in order of increasing computational cost:
"none"
The surface will not cast shadows on any other surface, therefore it may be ignored completely for shadow computations.
"opaque"
The surface will completely shadow any object which it occludes. In other words, this tells the renderer to treat this object as completely opaque.
"Os"
The surface may partially shadow, depending on the value set by the Opacity directive. In other words, it has a constant opacity across the surface. (This is the default.)
"shade"
The surface may have a complex opacity pattern, therefore its surface shader should be called on a point-by-point basis to determine its opacity for shadow computations.
The default value is "Os". You can optimize rendering time by making surfaces known to be opaque "opaque", and surfaces known not to shadow other surfaces "none." It is important, however, to use "shade" for any surfaces whose shaders modify the opacity of the surface in any patterned way.

5.3.3 Displacement and Subdivision Attributes

Attribute "render" "truedisplacement" [onoff]
Takes an integer argument, which if nonzero will make this primitive be diced and displaced using its displacement shader (if any). Only a displacement shader can move the diced geometry -- altering "P" in a surface shader will not move the surface, only the normals. Using a displacement shader without this attribute also only results in the normals being modified, but not the surface. Be sure to set displacement bounds if you displace! Please see the section on "limitations of rendrib" for details on the limitations placed on true displacements.
Attribute "displacementbound" "coordinatesystem" [space] "sphere" [rad]
For truly displaced surfaces, specifies the amount that its bounding box should grow to account for the displacement. The box is grown rad (a float) units in all directions, expressed in the coordinate system space (a string). This works just like the nonstandard option of the same name in PRMan.
Attribute "render" "patch_maxlevel" [maxlevel] "patch_minlevel" [minlevel]
Takes an integer argument giving the maximum (or minimum) subdivision level for bicubic and NURBS patches. These patches are subdivided based on the screen size of the patch and their curvature. This attribute will split the patches into at least (minlevel x minlevel) and at most (maxlevel x maxlevel) subpatches. The default is min=1, max=256. In general, you shouldn't ever need to change this, but occasionally you may need to set a specific subdivision rate for some reason.
Attribute "render" "patch_multiplier" [float]
Takes an float argument giving a multiplier for the dicing rate that BMRT computes for displaced surfaces and for certain curved surfaces which are subdivided. The default is 1.0. Smaller values will make the scene render faster and using less memory, but may produce a more faceted appearance to certain curved surfaces. Larger values will make more accurate surfaces, but will take longer and more memory to render. The default is probably just right for 99% of scenes, but occasionally you may need to tweak this.

5.3.4 Light Source Attributes

Attribute "light" "shadows" "on"
Attribute "light" "shadows" "off"
Turns the automatic ray cast shadow calculations on or off on a light-by-light basis. This attribute can be used for any LightSource or AreaLightSource which is declared. For example, the following RIB fragment declares a point light source which casts shadows:
	Attribute "light" "shadows" "on"
	LightSource "pointlight" 1 "from" [ 0 10 0 ]
Attribute "light" "nsamples" [n]
Sets the number of times to sample a particular light source to n, an integer (default = 1). This is only useful for an area light which is being undersampled -- i.e. its soft shadows are too noisy. By increasing the number of samples, you can reduce the noise by increasing sampling of this one light, independently of overall PixelSamples.

5.4 Nonstandard Shading Language Features

In order to more fully support the ray tracing features of BMRT, a few nonstandard functions have been added to BMRT's Shading Language. The next chapter describes how to use the Shading Language Compiler.

Note that these functions are not supported by PRMan's SL compiler. However, using the "ray server", PRMan's functionality can be extended to support these functions by using BMRT to compute them.

color trace (point from, vector dir)
Traces a ray from position from in the direction of vector dir. The return value is the incoming light from that direction.
color visibility (point p1, p2)
Forces a visibility (shadow) check between two arbitrary points, retuning the spectral visibility between them. If there is no geometry between the two points, the return value will be (1,1,1). If fully opaque geometry is between the two points, the return value will be (0,0,0). Partially opaque occluders will result in the return of a partial transmission value.

An example use of this function would be to make an explicit shadow check in a light source shader, rather than to mark lights as casting shadows in the RIB stream (as described in the previous section on nonstandard attributes). For example:

    light
    shadowpointlight (float intensity = 1;
    	              color lightcolor = 1;
	              point from = point "shader" (0,0,0);
                      float raytraceshadow = 1;)
    {
        illuminate (from) {
            Cl = intensity * lightcolor / (L . L);
            if (raytraceshadow != 0)
                Cl *= visibility (Ps, from);
        }
    }
float rayhittest (point from, vector dir, 
                  output point Ph, output vector Nh) 
Probes geometry from point from looking in direction dir. If no geometry is hit by the ray probe, the return value will be very large (1e38). If geometry is encountered, the position and normal of the geometry hit will be stored in Ph and Nh, respectively, and the return value will be the distance to the geometry.
float fulltrace (point pos, vector dir,
                 output color hitcolor, output float hitdist,
                 output point Phit, output vector Nhit,
                 output point Pmiss, output point Rmiss)
Traces a ray from pos in the direction dir.

If any object is hit by the ray, then hitdist will be set to the distance of the nearest object hit by the ray, Phit and Nhit will be set to the position and surface normal of that nearest object at the intersection point, and hitcolor will be set to the light color arriving from the ray (just like the return value of trace).

If no object is hit by the ray, then hitdist will be set to 1.0e30, hitcolor will bet set to (0,0,0).

In either case, in the course of tracing, if any ray (including subsequent rays traced through glass, for example) ever misses all objects entirely, then Pmiss and Rmiss will be set to the position and direction of the deepest ray that failed to hit any objects, and the return value of this function will be the depth of the ray which missed. If no ray misses (i.e. some ray eventually hits a nonreflective, nonrefractive object), then the return value of this function will be zero. An example use of this functionality would be to combine ray tracing of near objects with an environment map of far objects: missdepth = fulltrace (P, R, C, d, Phit, Nhit, Pmiss, Rmiss); if (missdepth > 0) C += environment ("foo.env", Rmiss) / missdepth;

The code fragment above traces a ray (for example, through glass). If the ray emerging from the far side of the glass misses all objects, it adds in a contribution from an environment map, scaled such that the more layers of glass it went through, the dimmer it will be.

float isshadowray ()
Returns 1 if this shader is being executed in order to evaluate the transparency of a surface for the purpose of a shadow ray. If the shader is instead being evaluated for visible appearance, this function will return 0. This function can be used to alter the behavior of a shader so that it does one thing in the case of visibility rays, something else in the case of shadow rays.
float raylevel ()
Returns the level of the ray which caused this shader to be executed. A return value of 0 indicates that this shader is being executed on a camera (eye) ray, 1 that it is the result of a single reflection or refraction, etc. This allows one to customize the behavior of a shader based on how "deep" in the reflection/refraction "tree.

5.5 Global Illumination

The purpose of the RenderMan standard is to allow one to specify the description of a scene without having to worry about how to render it. Thus, no mention is made in the standard of any particular rendering method. A particular implementation of the standard may support any one (or many) of the following: wireframe; flat shaded, Gouraud shaded, or Phong shaded z-buffered polygons; A-buffer; REYES; ray tracing; radiosity; or any other rendering method. Since this renderer stems largely from my own research in the area of illumination, it incorporates many of the latest advances in global illumination and rendering technology.

The default rendering method used by this renderer is ray tracing. Of course, if you only use standard surfaces and light sources, the results will not be very dramatic. But the shaders which use the trace() function can cast reflection and refraction rays. Light sources which cast ray-traced shadows can be added automatically, even from area light sources. However, ray tracing will still determine illumination only via direct paths from light sources to surfaces being shaded. No knowledge of interreflection between objects is available to the ray tracer.

That's where radiosity come into the picture. Radiosity will help to capture effects such as indirect illumination, soft shadows, and color bleeding. To render the scene using radiosity, just type:

	rendrib -radio n myfile.rib
The parameter n is a number giving the maximum number of radiosity steps to perform. A typical number might be 50. Higher values of n will yield more accurate illumination solutions, but will also take much longer to compute. If the solution to the illumination equations converges in fewer steps, the program will simply terminate early, and not perform the additional steps. After the radiosity calculation ends, ray tracing will be used to form an image. This method of using radiosity followed by ray tracing is known as "two-pass" rendering. There are several advantages to the two-pass method:

If you want to use these features, you will need to make a few slight modifications to your RIB files, outlined below:

  1. You should set the meshing rates for the patches and elements. See "patchsize," "elemsize," and "minsize" in the "nonstandard attributes" section of this document.
  2. For any nonobvious surfaces, you need to give the average diffuse reflectivity. (Obvious means that the average diffuse reflectivity is the same as the color set by the Color directive.) See the "nonstandard attributes" section of this document for details on setting the average and emissive colors for surfaces. The renderer is smart enough to query shaders for their "Kd" values, so there is no need to premultiply the average color by Kd. However, that's about as smart as it gets, so don't expect any tricks done by the surface shader to be somehow divined by the radiosity engine. Any texture mapped objects must also have their average color declared in order to specify the average color of the texture map.
  3. Specular highlights will be included in the final image, but will not be taken into consideration in the first pass. That's okay, they provide very little global illumination anyway, with the following exception...
  4. Mirrors may reflect light directly from a light source to another object in a specular manner. Curved reflectors will tend to either spread the light out or to focus the light to form caustics. These features are supported, provided that you put the following additional light source declaration in your file:
    	LightSource "bouncer"
    

    The "bouncer" light source is actually a program which calculates these additional light paths for specular-to-diffuse illumination. In addition, any objects which you wish to act as specular reflectors, regardless of their shader type need to have the following additional attribute declared before the geometry is instanced:

    	Attribute "radiosity" "specularcolor" [ color ]
    

When rendering with radiosity, there are two ways to make area light sources. One way is to use the AreaLightSource directive, explicitly making area light sources. The second way is to declare regular geometry, but setting an emission color:

	Attribute "radiosity" "emissioncolor" [color],
The difference is subtle. Both ways will make these patches shoot light into their environment. However, only the geometry declared with AreaLightSource will be resampled again on the second pass. This results in more accurate shadows and nicer illumination, but at the expense of much longer rendering time on the second pass.

5.6 Optimizing Rendering Time

Please note that rendering full color frames can take a really long time! High quality rendering, especially ray tracing, is notoriously slow. Try a couple test frames first, to make sure you have everything right before you compute many frames. Multiply the time it takes for each frame by the total number of frames you need. If your total rendering time is prohibitive (say, 5 months), you'd better change something!

A good rule of thumb is that each frame in a 1 minute animation should take between 15 and 45 minutes to render on a typical machine in your computation arsenal. If your frames take less than 15 minutes each to render, you can probably afford to go ahead and use more features, more complex textures, higher sampling, or whatever. If your frames take much more than 45 minutes (and certainly if they take longer than an hour), you should really try to use some of the optimization methods outlined below. If you are computing only a single image, of course you can allow as much time as you want.

Don't bother praying or panicking: I have it on good authority that neither does much to increase rendering throughput. Some optimization hints are listed below. Obvious, effective, easy optimizations are listed first. Trickier or subtler optimizations are listed last.

5.6.1 Image Resolution

Use low resolution when you can. You may want to do test frames at 320 x 240 resolution or lower. Remember that video resolution is only about 640 x 480 pixels. It's pointless to render at higher resolution if you intend to record onto videotape, since any higher resolution will be lost in the scan conversion.

5.6.2 Pixel Sampling Rate and Antialiasing

Try to specify only 1 sample per pixel for test frames. You can sometimes get away with one sample per pixel for final video frames, too. However, to get really good looking frames you probably need to do higher sampling for antialiasing. There are several sources of aliasing: geometric edges, motion blur, area light shadows, depth of field effects, reflections/refractions, and texture patterns.

Usually, 2x2 sampling is perfectly adequate to antialias geometric edges for video images. Higher than 3x3 does not usually give noticeable improvements for geometric edges. Motion blur, depth of field, and area light shadow penumbra tend to take lots of samples to antialias. There's not much you can do about that if you insist on using these effects.

If the source of your aliasing is blurry reflections or refractions from shaders which use the trace() function, you should consult the documentation for those shaders. There may be ways to increase the sampling rate for that surface only without increasing the sampling rate for the entire image (you can do this for my "shiny" and "glass" shaders).

Higher sampling rates should never be used to eliminate aliasing in shaders. Well written shaders should be smart enough to analytically antialias themselves by frequency clamping or other trickery. It's considered bad style to write shaders which alias badly enough to require high sampling at the image level.

5.6.3 Geometric Representation

Keep your geometry simple, and use curved surface primitives instead of lots of polygons whenever possible. Try writing surface or displacement shaders to add detail to surfaces. It's generally faster to fake the appearance of complexity than it is to create objects with real geometric complexity. Try to make your images interesting through the use of complex textures used on relatively simple geometry.

5.6.4 Lights and Shadows

Shadows are important visual cues, but you must use them wisely. Shadowed light sources can really increase rendering time. Only cast shadows from light sources that really need them. If you have several light sources in a scene, you may be able to get away with having only the brightest one cast shadows. Nobody may know the difference!

Similarly, most objects can be treated as completely opaque (this assumption speeds rendering time). Some objects do not need to cast shadows at all (for example, floors or walls in a room). See the "nonstandard attributes" section of this chapter for information on giving the renderer shadowing hints.

5.6.5 Shading Models

Keep your shading models simple. Complex procedural textures (such as wood or marble) take much more time to compute than plastic. On the other hand, it is much cheaper to use custom surface or displacement shaders to make surfaces look complex than it is to actually use complex geometry.

Distribution of rays results in noise. The fewer samples per pixel, the higher the noise. So if you want to keep sampling rates low and reduce noise in the image, you should: avoid using the "blur'' parameter in the "shiny'' and "glass'' surfaces; do not use depth of field; use nonphysical lights ("pointlight'', "distantlight'', etc.) instead of physical and area lights.

5.7 Limitations of rendrib

The following list should delineate any implementation-specific limitations and incompatibilities with the published RenderMan standard.

  1. True displacement of surface points is only partially supported. If you displace in a surface shader, or even in a displacement shader without using the "truedisplacement" attribute, only the surface normals will be purturbed, the points will not move. This usually looks fine as long as the bumps are small. However, if you use the "truedisplacement" attribute, a displacement shader will actually do what you expect and move the surface points.

    True displacements are somewhat limited: (1) it only works for displacement shaders, not surface shaders; (2) it uses lots of memory, and also takes more time to render; (3) you cannot use "message passing" between the displacement and surface shaders; (4) you must remember to set displacement bounds; (5) you may get odd self-shadowing of surfaces during radiosity calculations if you use too small a shadow bias.

  2. Motion Blur is supported, but all motion must be linear (i.e. transformations are specified only at the beginning and ending of the motion). Transformations motion blur correctly, but geometry and shading commands simply use the first of the two specifications, and don't blur.
  3. The following optional capabilities are not supported: Level of Detail, Special Camera Projections, Nonlinear Deformations, Spectral Colors.
  4. The optional Shadow Depth Mapping capability is not supported, but you shouldn't need it anyway, since ray tracing can be used for shadows.
  5. Visible surfaces are always resolved, even if the argument to Hider is "paint".
  6. rendrib specifically wants TIFF files as texture and environment maps. The files can be 8 or 16 bits per channel, but cannot be palette color files. Single channel greyscale is okay, as are 3 channel RGB or 4 channel RGBA files.

5.8 Incompatibilities with PRMan

As I write this, the BMRT and Pixar's PhotoRealistic RenderMan ((R) Pixar) (sometimes called PRMan) are the only two widely available implementations of RenderMan. While rendrib uses ray tracing and radiosity, PRMan uses a scanline method called REYES. Though both renderers should take nearly the same input, the difference in their underlying methods necessarily results in different subsets of the RenderMan standard supported by the two programs. This section lists some of the incompatibilities of the two programs. These differences should not be construed as bugs in either program, but are mostly natural limitations of the two rendering methods. This list is for the user who uses both programs, or wishes to use one program to render output meant for the other.

  1. slc outputs compiled Shading Language as ".slc" files , which are not compatible with Pixar's ".slo" files. The shading language source files (".sl") are compatible. (Previous versions of BMRT used the extension ".so" for compiled shaders. These were not dynamic shared object files, so to avoid confusion they are now named ".slc" files.)
  2. The texture mapping and environment mapping routines in rendrib take TIFF files directly, and do not read PRMan's proprietary texture format.
  3. rendrib does not support shadow depth mapping, and cannot read or write PRMan's depth files.
  4. PRMan doesn't support true area light sources (but instead places a point light at the current origin), but rendrib supports area light sources correctly.
  5. Rendrib's support of true displacement of surface points is limited in the following ways: (1) it only works for displacement shaders, not surface shaders; (2) it uses lots of memory, and also takes more time to render; (3) you cannot use "message passing" between the displacement and surface shaders; (4) you must remember to set displacement bounds; (5) you may get odd self-shadowing of surfaces during radiosity calculations if you use too small a shadow bias.
  6. PRMan's trace() function always returns 0, but rendrib actually traces rays properly.
  7. PRMan does not support Imager, Interior, or Exterior shaders. rendrib fully supports these kinds of shaders.
  8. PRMan supports several nonstandard primitives which are not currently supported by rendrib, including: Curves, Points, SubdivisionMesh.

This document last updated 26 Jan 1999 by lg@bmrt.org

All BMRT components are Copyright 1990-1998 by Larry I. Gritz. All rights reserved.

The RenderMan Interface Procedures and RIB Protocol are: Copyright 1988, 1989, Pixar. All rights reserved. RenderMan is a registered trademark of Pixar.