Types

Floats
Colors
Points, Vectors and Normals 
Transformation Matrices
Arrays
Strings 
Uniform and Varying Variables


The Shading Language is strongly typed and supports the following basic types:

Floats

Floats are used for all scalar calculations. They are also used for integer calculations.

Floating-point variables are defined as follows:

     float a, b=1;

The initialization value may be any scalar expression that contains only uniform operands.

Colors

The Shading Language implements color as an abstract data type independent of the number of samples and the color space. The major operations involving color are color addition (`+' operator) corresponding to the mixing of two light sources, and color filtering (`*' operator) corresponding to the absorption of light by a material. In each case these color operations proceed on a component by component basis.

The number of color samples used in the rendering program is set through the RenderMan Interface. Once the number of color samples has been specified, colors with the appropriate number of samples must be passed to a shader. When setting the number of samples, the user can also specify a transformation from RGB space to this n sample color space. This allows a shader to convert color constants to the specified color space.

Color component values of 0 correspond to minimum intensity, while values of 1 correspond to maximum intensity. A color constant of 0 is equivalent to black, and of 1 is equivalent to white. However, values outside that range are allowed (values less than zero decrement intensity from other sources).

Color variables may be declared with:

      color c, d=1, e=color(1,0,0);

The initialization value may be any scalar or color expression that contains only uniform operands. If a scalar expression is used, its value is promoted to a color by duplicating its value into each component.

Color constants are specified by:

      color [space] (u,v,w)

The optional specifier space indicates the color coordinate system of the 3-tuple. The default color coordinate system is "rgb." Table 11.1, Color Coordinate Systems, lists the color coordinate systems that are supported in the Shading Language.

Table 11.1 Color Coordinate Systems

Coordinate System Description
"rgb" Red, green, and blue
"hsv" Hue, saturation, value
"hsl" Hue, saturation, lightness
"xyz", "XYZ"CIE XYZ coordinates
"YIQ"NTSC coordinates

Points, Vectors, and Normals

Point-like variables are (x,y,z) triples of floats that are used to store locations,direction vectors and surface normals.

A point is a position in 3D space.  A vector has a length and direction, but does not exist in a particular location.  A normal is a special type of vector that is perpendicular to a surface and thus describes the surface's orientation.

All calculations involving points. vectors and normals are assumed to take place in an implementation-dependent coordinate system, usually either the camera or world coordinate system. Procedures exists to transform points, vectors and normals from the shading coordinate system to various named coordinate systems, or to define a point, vector or normal in one of several coordinate systems and transform it to the shading coordinate system. It should be noted that point locations, direction vectors and normals do not transform in the same way as, and therefore it is important to use the correct transformation routine for each type.

A number of standard coordinate systems are known to a shader. These include: "raster", "NDC", "screen", "camera", "world", and "object". These are discussed in the section on Camera in Part I. In addition, a shader knows the coordinate systems shown in Table 11.2, Point Coordinate Systems.

Table 11.2 Point Coordinate Systems

Coordinate System Description
"shader" The coordinate system in which the shader was defined. This is the "object" coordinate system when the shader is defined.
"current"The coordinate system in which the shading calculations are being performed. This is normally the "camera" or "world" coordinate system.
"string"A named coordinate system established using RiCoordinateSystem.

Point variables are declared:

     point u, v=1, w=point(1,1,1);
     vector R;
     normal Nf;

The initialization value may be any scalar or point-like expression. If a scalar expression is used, the value is promoted to a point (or vecdtor or normal) by duplicating its value into each component.

Point, vector and normal constants default to be in the "current" coordinate system. Points, vectors and normals can be specified in any known coordinate system with:

     point [space] (x,y,z)
     vector [space] (x,y,z)
     point [space] (x,y,z)

where the space is a string literal containing the name of the coordinate system.  For example,

     point "world" (0,0,0)

defines a point at the position (0,0,0) in world coordinates. This point is implicitly transformed to the "current" coordinate system. Similarly, 

     vector "object" (0,0,1)

defines a vector pointing toward the +z axis in "object" space, which is implicitly transformed into the equivalent vector expressed in the "current" coordinate system.  Points, vectors and normals passed through the RenderMan Interface are interpreted to be in "shader" or "object" space, depending on whether the point variable was set using a shader command or a geometric primitive command, respectively.

Transformation Matrices

The Shading Language has a matrix type that represents the transformation matrix require to transform points and vectors from one coordinate system to another.  Matrices are represented internally by 16 floats (a 4 x 4 homogeneous transformation matrix).

A matrix can be declared:

   matrix zero = 0;
   matrix ident = 1;
   matrix m = matrix(m00, m01, m02, m03, m10, m11, m12, m13,
                     m20, m21, m22, m23, m30, m31, m32, m33);

Assigning a single floating-point number c to a matrix will result in a matrix with diagonal components all being c and other components being zero (i.e., c times the identity matrix).  Constructing a matrix with 16 floats will create the matrix whose components are those floats, in row-major order.

Similar to point-like types, a matrix may be constructed in reference to a named space.

   matrix q = matrix "shader" 1;
   matrix m = matrix "world" (m00, m01, m02, m03, m10, m11, m12, m13,
                              m20, m21, m22, m23, m30, m31, m32, m33);

The first form creates the matrix that transforms points from "current" space to "shader" space.  Transforming points by this matrix is identical to calling transform("shader", ...).  The second form prepends the current-to-world transformation matrix onto the 4 x 4 matrix with components m00 - m33.  Note that although we have used "shader" and "world" space in our examples, any named space is acceptable.

Strings

Strings are used to name external objects (texture maps, for example). String literals (or constants) are enclosed in double quotes, as in the C language, and may contain any of the shadard C "escape sequences" (such as \n for newline or \" for a quote).

Arrays

The Shading Language supports one-dimensional arrays of all the basic data types. Zero and negative-length arrays are not permitted.

As in C, the syntax for declaring a fixed size array of any data type uses square brackets, i.e. datatype[length]. length is a float constant, which is rounded down to generate an integer length. The syntax for specifying the data of a constant array uses curly braces: {value1, value2, ...}. For example:

  float a[10];
  uniform color C[4], float b[4] = {3.14, 2.17, 0, -1.0};

As in C, individual array elements may be referenced using the familiar square bracket notation. An array element index is a float expression, which is rounded down to generate an integer index. Shading Language arrays perform over/underrun checking at run-time. Unlike C, arrays can be assigned to each other as long as they are of the same type and length. Entire arrays can also be compared for equality.

Shader input parameters and formal parameters of functions may be declared with an unspecified length (i.e. empty square brackets); the length of such arrays is determined by the actual parameter value. The default value of a shader parameter whose length is unspecified must be an empty array.

The length of an array can be determined using the arraylength shadeop.

Resizable Arrays

A resizable array can be obtained by declaring a local array variable with an unspecified or non-constant length. Initialization is optional. For example:

   float A[];                  // initially empty
   float B[] = {1,2};          // initial length is 2
   float C[1+arraylength(B)];  // initial length is 3

Only arrays declared with an unspecified or non-constant length are resizable. Only arrays in local variables are resizable. Note that the length of a shader parameter can also be unspecified, but its length is fixed when the shader parameter is bound, and it cannot be resized.

All built-in functions that operate on fixed-length arrays can also operate on resizable arrays. For example, arraylength returns the length of a fixed or resizable array. An array can be resized using the resize function:

Array assignment resizes the destination array as necessary:

   float A[];          // initially empty.
   A = B;              // resizes A to accommodate B.

Message passing will also resize the result array to match the length of of the source. For example:

   float A[];
   surface("A", A);    // resizes A if necessary.

Arrays are also resized by the push and pop functions:

Length and capacity of resizable arrays

A resizable array has both a length and a capacity (similar to an STL vector). Resizing an array increases its capacity if necessary. However, reducing the length does not decrease the capacity (unless it is set to zero, in which case the storage is reclaimed).

The capacity can be increased without changing the length, thus reserving storage for future operations:

Reserving storage is preferable to incrementally resizing an array, since increasing capacity generally requires copying the array contents. This is especially useful when repeatedly pushing items on an array:

   reserve(A, arraylength(A)+3);       // reallocate A before pushing.
   push(A, 1);
   push(A, 2);
   push(A, 3);

The capacity of an array can be obtained using the following function:

Resizable arrays as parameters


Uniform and Varying Variables

A renderer implementation may choose to shade many points, or even large regions of a surface, at once.  How large such a region may be is implementation-dependent. 

Shaders contain two classes of variables: uniform variables are those whose values are constant over whatever portion of the surface begin shaded, while varying variables are those that may take on different values at different locations on the surface being shaded. For example, shaders inherit a color and a transparency from the graphics state. These values do not change from point to point on the surface and are thus uniform variables. Color and opacity can also be specified at the vertices of geometric primitives (see Section 5, Geometric Primitives). In this case they are bilinearly interpolated across the surface, and therefore are varying variables.

Local variables and arguments to shaders are declared to be either uniform or varying by specifying a storage modifier:

     varying point p;
     uniform point q;

Variables declared in the argument list of a shader are assumed to be uniform variables by default. These are sometimes referred to as instance variables. If a variable is provided only when a shader is instanced, or if it is attached to the geometric primitive as a whole, it should be declared a uniform variable. However, if a variable is to be attached to the vertices of geometric primitive, it should be declared as a varying variable in the shader argument list.

Variables declared locally in the body of a shader, as arguments to a function, or as local variables are assumed to be varying. Declaring a variable to be uniform inside a shader or function definition is never necessary, but may allow the compiler to generate more efficient code.

If a uniform value (or a constant) is assigned to a varying variable or is used in a varying expression, it will be promoted to varying by duplication. It is an error to assign a varying value to a uniform variable or to use a varying value in a uniform expression.


No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior written permission of Pixar. The information in this publication is furnished for informational use only, is subject to change without notice and should not be construed as a commitment by Pixar. Pixar assumes no responsibility or liability for any errors or inaccuracies that may appear in this publication.

 

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