Pixar
April 2001
These release notes describe significant changes and enhancements to the RenderMan Toolkit for the 3.9 release over the 3.8 release. In successive sections, we cover
The new Blobby surface type implements free-form self-blending implicit-function surfaces in the style of Jim Blinn's blobby molecules, Nishimura et al.'s Metaballs and Wyvill, McPheeters and Wyvill's soft objects. Blobby surfaces may be composed of spherical and sausage-like line-segment primitives with extremely flexible control over blending. The surface type also provides for repulsion to avoid intersection with irregular ground planes, represented by prman-produced Z-files.
Blobbies may be shaded much like ordinary parametric primitives, with the caveat that they have no u and v parameters. Nevertheless, they may be given vertex values, by attaching scalar values or reference coordinate fields to primitive sub-objects that will be blended appropriately by prman. Motion-blur, depth-of-field and all of prman's other advanced sampling features also work as expected.
In the Renderman C binding, blobby implicits are specified by:
void RiBlobby( RtInt nleaf, RtInt ncode, RtInt code[], RtInt nflt, RtFloat flt[], RtInt nstr, RtString str[], ...);
In a RIB stream, the syntax is:
Blobby nleaf [ code ] [ floats ] [ strings ] parameterlist
The code array is a sequence of machine language-like instructions describing the object's primitive blob fields and the operations that combine them. Floating point parameters of the primitive fields are stored in the floats array. File names of the z-files of repellers are in the strings array. The integer nleaf is the number of primitive blobs in object, also the number of items in each varying or vertex parameter.
Each instruction has a numeric opcode followed by a number of operands. Instructions specifying primitive fields start at 1000. They are:
Opcode | Operands | Operation |
---|---|---|
1000 | float | constant |
1001 | float | ellipsoid |
1002 | float | segment blob |
1003 | string, float | repelling ground plane |
For all four of these operators, the operands are indices into the appropriate arrays.
There are several more opcodes that compute composite fields by combining the results of previous instructions in various ways. Every instruction in the code array has a number, starting with zero for the first instruction, that when used as an operand refers to its result. The combining opcodes are:
Opcode | Operands | Operation |
---|---|---|
0 | count, ... | add |
1 | count, ... | multiply |
2 | count, ... | maximum |
3 | count, ... | minimum |
4 | subtrahend, minuend | subtract |
5 | dividend, divisor | divide |
6 | negand | negate |
7 | idempotentate | identity |
Add, multiply, maximum and minimum all take variable numbers of arguments. The first argument is the number of operands, and the rest are indices of results computed by previous instructions. The identity operator does nothing useful, and is only included for the convenience of programs that automatically generate Renderman input.
More details on usage can be found in AppNote #31.
The texture system has been optimized and is more than twice as fast as PRMan 3.8. Shadow maps, noise, arrays, and parsing are also substantially faster. In combination with other speedups mentioned below, these changes have reduced the overall rendering time by approximately 30-40% for the very large scenes rendered here at Pixar. In addition, for some large scenes memory usage has been reduced by over 50%.
The usage of soft shadows is now two to three times faster than PRMan 3.8. There have also been minor changes in the format of minmax soft shadow texture files. Texture files generated from previous versions of the renderer may not work, and will need to be regenerated from the z files via txmake or RiMakeShadow.
The NURBS primitive has been almost entirely rewritten, resulting in better accuracy and significant speedups on scenes with NURBS geometry modelled with a large number of control points. In addition, shading rates are now guaranteed more stringently than before. Various bugs related to vertex variables have also been fixed.
Curves now have improved dicing behaviour and tighter bounding boxes, resulting in a significant reduction in overall shading time. As a result, and as a means of making RiCurves parameters more generally useful, uniform RiCurves parameters are now bound per curve rather than per segment.
The renderer currently attempts to be backward-compatible with regards to curve uniforms. Per-segment uniform curve parameters are accepted, and forced to to be compatible with the uniform semantics by using the data associated with first segment on each curve. A warning message will be issued if the conversion results in a loss of data (i.e., if the per-segment data varies along a curve).
Added new tag "smoothtriangles" for subdivision meshes. This tag takes one integer value that should be set to either 1 (on) or 0 (off), the default being on. When on, the tag specifies that a special subdivision rule be applied to all triangular faces; this rule was empirically determined to make triangles subdivide more smoothly. However, it was recently shown that this rule breaks the nice property that two separate meshes can be joined seamlessly by overlapping their boundaries; i.e. when there are triangles at either boundary, it is impossible to join the meshes seamlessly. The tag introduced is meant to overstep the problem by allowing the user to turn off the offending subdivision rule. The syntax is:
SubdivisionMesh "catmull-clark" ... ["smoothtriangles"] [1 0] [0] []
Derivatives and normals are calculated using a new technique, which will eliminate or reduce several shading artifacts.
The new technique will change surface normals slightly, and may give bumpy surfaces a softer appearance.
Note: These changes only take effect when smooth shading is enabled (via ShadingInterpolation "smooth"). When constant shading is used (the default setting), derivatives and normals are unchanged from previous releases. Smooth shading and centered derivatives are highly recommended in order to minimize rendering artifacts.
If desired, centered derivatives can be turned off as follows:
Attribute "derivatives" "centered" [0]
PRMan now eliminates all cracks within single primitives, even when large displacements are used. This has been implemented for all surface types except polygons and implicits. It is controlled by the following attribute (turned on by default):
Attribute "stitch" "enable" [1]
Cracks may still occur between separate primitives (for example, between two adjacent bicubic patches). As in previous releases, such cracks may be reduced by turning on binary dicing:
Attribute "dice" "binary" [1]
Binary dicing has been optimized, reducing overall rendering times by 25-40% on scenes that use this feature. It is no longer a significant performance penalty and can be turned on by default.
There is a new hider option to extend occlusion culling to account for layers of transparent visible points. This "opacity culling" can result in a significant time and memory savings in scenes with a large number of semi-transparent, layered objects (e.g., hair).
The essential idea is to consider a stack of sampled geometries as being fully opaque if its accumulated opacity is large enough. To specify just how small "large enough" is, there is a new "limits" option:
Option "limits" "othreshold" [rthresh gthresh bthresh]
A stack of visible points whose accumulated opacity is greater (in each channel) than the specified limit will be considered fully opaque by the hider, and objects behind the stack will be culled.
By default, opacity culling is enabled, with the default opacity threshold being [0.996 0.996 0.996].
The zfile display driver now supports gzip compression. This can be enabled by adding the parameter "zcompression" with value "zip" to the RiDisplay parameter list:
Display "ri.zfile" "zfile" "z" "zcompression" ["zip"]
Because the tiff display driver also interprets the "compression" parameter, you can separately enable compression for the zfile when rendering with the "rgbaz" mode:
Display "ri.tif" "tiff" "rgbaz" "compression" ["lzw"] "zcompression" ["zip"]
Statistics output now includes a table summarizing memory use. Current memory use, percentage of current memory, and peak memory use are reported for each of a number of categories; the current memory statistics are primarily useful when generated mid-frame (e.g. by killing prman with a SIGHUP).
More information on using statistics can be found in AppNote #30.
Changes have been made to jittering which eliminate the artifacts occuring when using PixelSamples which were powers of two (ie: "PixelSamples 4 4"). In addition, the "stamping" artifacts which resulted from using both motion blur and depth of field (at all PixelSamples settings) have been reduced.
In addition, when using multi-segment motion blur, coordinate system transformations which take place inside shaders are now correctly updated over each segment of time.
Just like the built-in noise() function invokes a different variety depending on how you cast or assign it, you may now have the same flexibility with your DSO shadeops. Previously, you could have several variants of a shadeop distinguished by the types of the arguments passed to the function, but not by the return type.
Previously, all variants of a function, say sqr(), had to be stored in a file sqr.so. You couldn't combine shadeops of other names in the same .so file, which is handy if you want them to share common data.
In PRMan 3.9, rather than looking specifically at the <name>.so file, the shader compiler will search all .so files in your include path until it finds one (of any name) with the shadeop table for your function. Because the name of the .so file no longer matters, you can create .so file libraries containing an arbitrary collection of DSO shadeops.
If multiple DSO shadeops in the same .so file all use the same named initializer routine, then the initializer will be called only the first time that any of those shadeops is invoked. Upon further calls to any of the shadeops which share an initializer, they will all be passed pointers to the data block returned by the first initializer. In other words, all of the shadeops which share the same initializer will also share the same per-thread data store.
Previously, DSO shadeop initializer routines were passed no arguments. Now they are passed two: an integer signifying a unique integer ID for the thread, and a void* which is a blind handle to a texturing context for the thread. If your shadeop method routines will need this data, you should stash it somewhere in the data that you allocate and return from the initializer routine.
Previously compiled routines should continue to operate with no problems. New routines should use the new shadeop.h and declare these two parameters. They are not required to use the parameters in any way.
The intended use of the texture context pointer is that it will be required to pass in to a future API entry point which will allow your DSO shadeops to request filtered texture lookups. (This may be introduced in future releases of PRMan.)
The error reporting for DSO function matching has been significantly beefed up. You can now expect to see error messages from DSO mismatches carefully explaining which argument choices were available and which you apparently were asking for. For example:
>nshader testsqr.sl "testsqr.sl", line 12: ERROR: DSO "s.so" had several ambiguous versions of sqr() matching your arguments. Choices were: vector sqr (vector) float sqr (vector) Your call was:sqr (vector) "testsqr.sl", line 15: ERROR: DSO "s.so" had no version of sqr() matching your arguments. Choices were: float sqr (float) point sqr (point) vector sqr (vector) float sqr (vector) normal sqr (normal) color sqr (color) Your call was: matrix sqr (matrix) testsqr: ERRORS -- NOT COMPILED.
PRMan now allows DSOs access to the internal implementation of noise, including the nonperiodic, periodic, and cellular varieties. These are accessed via Rx functions, prototyped in the "rx.h" header file:
extern RtStatus RxNoise(int inDimension, float *in, int outDimension, float *out); extern RtStatus RxPNoise(int inDimension, float *in, float *period, int outDimension, float *out); extern RtStatus RxCellNoise(int inDimension, float *in, int outDimension, float *out);
These functions take as input an array of floats in with dimensionality specified in inDimension (which can be 1 to 4). The output noise values is placed in out, which has dimensionality specified in outDimension. The period parameter for RxPNoise should be nonzero for periodic noise.
The renderer now supports "uniform texture lookups". In the past, the texture shadeops (texture, shadow, environment) didn't allow uniform arguments, and the return type was always varying. Now, the compiler allows a uniform return type from a texture shadeop if and only if all the arguments are uniform. In this case, only one texture lookup is done per grid.
Like built-in functions (such as noise) and DSO functions, users are now allowed to write SL functions which are polymorphic. In other words, you may write multiple functions with the same name, but which take different arguments, and the compiler will correctly use the right function under the right circumstances.
The comp and setcomp functions have been extended to access and set individual floating point components of matrices:
float comp (matrix m; float row, column) void setcomp (matrix m; float row, column; float newvalue)
In 3.9.2, a new Option was added which allows the renderer to apply translations to the absolute paths used to look up resources such as shaders and texture maps. More information can be found in section 4.16 of the User Manual.
There is now a searchpath mechanism for procedural primitive DSOs, specified via:
Option "searchpath" "procedural" [ pathstring ]
As usual, the default searchpath is "."
The sloargs library now allows you to query whether a shader parameter has output storage class.
The renderer now provides the standard parameter "PixelAspectRatio" to display drivers.
Some parts of the renderer now use double-precision floating point arithmetic, to avoid round-off error.
The 4096-character restriction on token length in RIB files has been removed. This allows for very long resource searchpaths.
Starting with the 3.9.1 release, the official location for the prman executable is now $RMANTREE/bin/prman. The old paths $RMANTREE/prman/bin/prman and $RMANTREE/etc/prman are now deprecated, and are now symbolic links to the new location; if you rely on this path in your scripts, please update them to use the new location.
Similarly, in 3.9.1 the confidence test $RMANTREE/prman/etc/setup has been moved to $RMANTREE/etc/setup, and the library $RMANTREE/prman/lib/libprman.a has been moved to $RMANTREE/lib; $RMANTREE/prman/lib/libprman.a is now a symbolic link to $RMANTREE/lib/libprman.a.
Pixar Animation Studios
|