3. PhotoRealistic RenderMan and the RenderMan Interface

PhotoRealistic RenderMan is intended to be compatible with the RenderMan Interface Version 3.2. As new capabilities are added to PRMan, improvements to a draft version of the RI Spec may be made and this draft is linked into this document.  The draft version of the RI Spec should be considered a work-in-progress and must not be construed as an official document.  Specifically, the draft should be expected to undergo numerous and frequent revisions prior to final adoption.  For the definitive, official version of the RenderMan Specification, please refer to Pixar's web site.

3.1. Optional Capabilities

Optional capabilities are those features specified in the document that are not required to be supported in all implementations of compatible renderers. The subroutines which would normally implement the interface to these capabilities must exist, but need not do anything. The level of support of an optional capability by a specific renderer implementation can be divided into three categories: fully implemented, in which the renderer supplies the features in all of their generality; incompletely implemented, in which the renderer supports a subset of the feature, but has certain restrictions on the parameter values which can be handled correctly; and unimplemented, in which the renderer has no support for the feature. The RenderMan Interface Version 3.2 document specifies what the default action of a renderer should be if unimplemented capabilities are requested.

The following capabilities correspond to those discussed in Section 1.1.2 of the RenderMan Interface Version 3.2 specification:

Solid Modeling
The Solid Modeling optional capability is fully implemented.
Level of Detail
The Level of Detail optional capability is fully implemented.
Motion Blur
The Motion Blur optional capability is completely implemented beginning in version 3.8. PRMan 3.8 permits a piecewise linear interpolation of positions within a single frame. The RIB file syntax is exactly as described in the RenderMan Specification. Each motion-block specifies a sequence of times, and there is one version of the transformation (or object specification) that corresponds to each time value. The shutter specifies the range of these times will appear in the frame, and the motion is piecewise linearly interpolated between the knots at the given times.

For example:

Shutter [0.0 1.0]
MotionBegin [0.0 0.25 0.75 1.0]
    Translate  0.0 10.0  0.0
    Translate 10.0  0.0  0.0
    Translate  0.0  0.0 20.0
    Translate  0.0  0.0  0.0
Sphere 1 -1 1 360

describes a ball that is moving around violently in 3-D.

As with previous versions of motion-blur, transformations and object deformations are both legal inside the motion block. There is an arbitrary limit of no more that 6 unique time values specified throughout in the RIB file as a whole. That is, you can use up to 6 time values in any motion-block, as long as it's always the same 6 times. Also, currently multisegment motion blur is not supported for camera transformations; that is, you may use only two time values in a motion block which occurs before RiWorldBegin.

The shutter open and close times are not required to match any of the specified time values, and if they do not, the objects and transformations will be correctly clipped to the shutter's range. For example, the shutter in the above example could run from 0.1 to 0.9, and the "right thing" would happen. If the shutter extends outside the range specified in the motion block, two things happen. Transformations are clamped to their endpoints. In the example above, the ball is considered stationary at (0,10,0) prior to time 0.0, and stationary again at (0,0,0) after time 1.0. Geometry, on the other hand, is non-existent outside of the motion-block's time range. Therefore, one may have a geometry appear in the middle of a frame, or similarly vanish intraframe.

Rotations are not divided into segments automatically. Rotations that need more temporal resolution must be specified by the model (or the RIB generation program) as follows:

Shutter [0.0 1.0]
MotionBegin [0.0 0.25 0.50 0.75 1.0]
    Rotate   0.0  0.0 1.0 0.0
    Rotate  10.0  0.0 1.0 0.0
    Rotate  20.0  0.0 1.0 0.0
    Rotate  30.0  0.0 1.0 0.0
    Rotate  40.0  0.0 1.0 0.0

In the current implementation, shading of each segment of the object's motion is calculated independently, at the time value that represents the beginning of that segment. However, shading parameters can not yet be interpolated through time. Therefore, any shading differences that are due only to position will be visible on the various segments of the motion path (for example, specular highlight location). Note that shadows are evaluated only at shutter open time. Users should be aware that large amounts of blur can significantly increase both rendering time and memory usage, and should refer to Section 8.5 for usage notes.

Depth of Field
The Depth of Field optional capability is fully implemented.
Special Camera Projections
The Special Camera Projections optional capability is not implemented. Only the standard orthographic and perspective projections are available.
The Displacements optional capability is fully implemented. Users should refer to the description of the displacementbound attribute (see Section 5.2) for notes on using displacement shaders correctly.
Spectral Colors
The Spectral Colors optional capability is not implemented. The implementation converts all input colors to RGB before they are used internally.
Volume Shading
The Volume Shading optional capability is incompletely implemented. Atmosphere, Interior, and Exterior shaders work, however the incident and opposite Shading Language functions always return 0.0.
Ray Tracing, Global Illumination
The Radiosity optional capabilities are not supported by PhotoRealistic RenderMan. The Ray Tracing optional capabilities are fully implemented.
Area Light Sources
The Area Light Sources optional capability is not implemented. Calls to RiAreaLightSource cause a point light source to be created, just as though RiLightSource had been called.

3.2. Shading Language Limitations

The Shading Language compiler and interpreter in PhotoRealistic RenderMan has certain limitations which must be taken into consideration when shaders are written for PhotoRealistic RenderMan. If these are not understood, shaders which seem to compile correctly will produce incorrect results.

3.2.1. Area Functions Inside Conditionals

One shouldn't use any area or neighborhood-sensitive functions inside conditional blocks whose conditional test depends upon varying expressions. The sensitive Shading Language functions are: texture(), environment(), shadow(), Deriv(), Du(), Dv(), area(), calculatenormal(). These functions depend on comparing various values at more than one point on the surface. The conditional partitions the object being shaded into two sets, those that passed the conditional and those that did not. Values are undefined in places where the conditional failed, but they are still referenced by their neighbors who did pass the conditional. This causes the comparisons to be undefined, and leads to visible artifacts. As a result, the following:

if (u < 0.5) {
        s0 = u * 2;
        Ci = texture("foo", s0, t);
} else {
        s0 = (u - 0.5) * 2;
        s0 = s0 * s0;
        Ci = texture("foo", s0, t);

should be coded as:

if (u < 0.5) {
        s0 = u * 2;
} else {
        s0 = (u - 0.5) * 2;
        s0 = s0 * s0;
Ci = texture("foo", s0, t);

This evaluates the texture access outside the conditional, allowing it to filter correctly.

Note that this is not a problem for conditional blocks whose conditional test depends upon a uniform expression, since the object cannot be partitioned into two sets by a uniform expression, by definition.

3.2.2. Broad Solar Lights

The solar block is used by distantlight to specify a light which is emitted from infinity along a particular axis direction. In this use, the solar block takes two arguments, the axis vector A, and 0.0, which is the angular width of the emission cone. The RenderMan specification refers to the fact that this cone can have non-zero width, and specifically mentions the use of solar with no arguments to write an environment mapping light source using a 360 degree cone.

PhotoRealistic RenderMan does support solar cones of any angular width, including the zero-argument omnidirectional case. The meaning of a non-zero width solar cone is extremely confusing to explain. Nonetheless, imagine a distant light source which is willing to emit light in any of a range of directions (not just down its axis vector), and merely needs the renderer to tell it which direction is pointed most favorably toward the specular highlight of surface. Another way of thinking of it is a large area light source, located at infinity, where each point on the area light is emitting a little spotlight.

The most obvious example is an environment-mapping light. The light wants to cast the environment texture map like a slide projector from infinity, and just needs to know which pixel on the map will reflect back into the camera. The pixel to choose is based entirely on the reflection direction R of the surface; the light itself is willing to send light in any direction as needed.

The second example is a diffuse skylight, where light is arriving on the surface from everywhere above it, and would like to be colored by all of it (radiosity-style). In this case, the solar light cone would be a hemisphere pointed down.

At this time, PhotoRealistic RenderMan will not point-sample the area light source, but it will attempt to find the most favorable direction by considering the size of the solar cone and the surface's reflection direction. The light direction vector L inside the solar block will be this direction. In the specific case of an omnidirectional light, this L will be exactly equal to -R. For narrower solar cones, it will be some vector between -R and A, such that it falls within both cones and is somewhat central to the intersection of the cones.

Here is a light source which casts an environment map onto a surface. Notice the use of the __nondiffuse flag to put the environment only in the specular component (since environment maps are really specular reflections of the worldsphere).

light envir ( string mapname = ""; float __nondiffuse = 1; ) {
    solar() {
	Cl = environment(mapname, vtransform("world", -L));

Note: Some surface shaders use non-standard reflection directions for their specular highlights. For example, some anisotropic shaders (such as brushedmetal) have multiple specular highlights, none of them in the "normal" place. solar's guess about which direction is the most favorable direction will be wrong in these cases.


Pixar Animation Studios
(510) 752-3000 (voice)   (510) 752-3151 (fax)
Copyright © 1996- Pixar. All rights reserved.
RenderMan® is a registered trademark of Pixar.