- New variable types
- Arrays
- New texture mapping tokens
- New built-in functions
- Message passing
- Scoping changes
The 3.1 specification of the RenderMan Interface defined only one type of geometric triple: point. In affine geometry, points and vectors behave differently. For example, points may be translated but vectors are immune to translation.
In addition to point, RenderDotC defines vector and normal types. All three have x, y, and z components. They only behave differently when being automatically transformed from one coordinate system to another. Vectors transform the same was as points except translation is ignored. Normals are transformed such that they remain perpendicular to a plane undergoing the same transformation. More specifically, normals are mutiplied by the inverse transpose of the transformation matrix.
Shader parameters may be declared point, vector or normal using RiDeclare. When triples are passed to the shader, they are automatically transformed to the current space. The details of this transformation depend upon the type.
In addition, triples may be implicitly transformed from within the shader. For example:
vector up = vector "shader" (0, 1, 0);This projects the vector (0, 1, 0) from "shader" space to "current" space.
To explicitly transform a point, vector, or normal from one space to another, use the transform, vtransform, or ntransform function, respectively. The vtransform and ntransform functions are shading language extensions documented below.
Matrices
The matrix data type represents a 4x4 array of floating point numbers. Such matrices are often called "homogeneous" or "affine" transformations because multiplying a 3D point or vector by a 4x4 matrix performs an affine transformation (the fourth row is necessary for translating points). This is the same type of matrix that RenderDotC uses internally to implement coordinate systems, transform(), etc.
In RIB, a matrix is declared like this:
Declare "mshader" "uniform matrix"Varying and vertex matrices are also allowed. Matrices may be passed from RIB to shaders in the token-value lists of shaders or primitives:
Surface "printall" "mshader" [1 0 0 0 0 1 0 0 0 0 1 0 10 20 30 1]Matrices passed to shaders are automatically projected from "shader" to "current" space, while matrices passed to primitives undergo the "object" to "current" transformation.
Points "P" [0 0 0] "mobject" [1 0 0 0 0 1 0 0 0 0 1 0 10 20 30 1]
Within the shading language, matrices may be explicitly initialized with a list of 16 values:
uniform matrix mscalexy = (2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);This syntax is similar to the way points are initialized. Like points, matrix initializers take an optional coordinate system:
uniform matrix mscalexy = matrix "shader" (2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);The latter syntax prepends the "current" to "space" transformation (where "space" is "shader" in the example).
Casting from a float to a matrix results in a matrix with all zeros except on the diagonal, where all four values equal the original float. This is often used to create the identity matrix. The following two lines are equivalent:
uniform matrix identity = 1;The equality and inequality operators are defined on matrices:
uniform matrix identity = (1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
if (m1 == m2) ...These operators compare the matrices component-by-component.
if (m1 != m2) ...
Matrices may be multiplied or divided:
m3 = m1 * m2;Dividing by a matrix is equivalent to multiplying the left hand matrix by the inverse of the right hand matrix. If the right hand matrix is uninvertible, and error message will be printed and the result of the division expression will be the left hand matrix.
m3 = m1 / m2;
The following builtin functions take matrix arguments:
float determinant(matrix m)They are described in detail below.
matrix inverse(matrix m)
point transform(matrix m, point p)
vector vtransform(matrix m, vector v)
normal ntransform(matrix m, normal n)
point transform(string space, matrix m, point p)
vector vtransform(string space, matrix m, vector n)
normal ntransform(string space, matrix m, normal n)
matrix translate(matrix m, point t)
matrix rotate(matrix m, float angle, vector axis)
matrix scale(matrix m, point s)
float comp(matrix m; float row, column)
void setcomp(matrix m; float row, column; float newvalue)
printf("%m", m1)
uniform string months[12] = {"january", "february", "march", ...};
An array element may be used in any exression where a single variable of the same base type is allowed. If an element of an array is used as an actual parameter to a function which returns a value in that parameter, this sets that element to the return value. In other words, array elements are call-by-reference, just like other function arguments in RenderMan shading language.
If an array of strings is used as the first argument to texture(), then it's ambiguous whether square brackets indicate an array subscript or a channel number. If two sets of square brackets are present, the first is the array subscript and the second is the channel number. If only one set of square brackets appear, then they are interpreted as an array subscript. The channel number will default to 0 in this case.
The spline function has been extended to allow
control vertices to be passed as arrays.
SL: | Defaults |
texture(mapname, "width", x) | 1.0 |
texture(mapname, "fill", x) | 0.0 |
texture(mapname, "lerp", b) | 1.0 |
texture(mapname, "filter", "s") | "box" |
texture(mapname, "blur", x) | 0.0 |
texture(mapname, "sblur", x) | 0.0 |
texture(mapname, "tblur", x) | 0.0 |
shadow(mapname, "bias", x) | (bias0 + bias1) / 2 |
shadow(map1,map2,map3) | - none - |
shadow(mapname, "source", p1, p2, p3, p4) | P |
shadow(mapname, "gapbias", x) | (bias0 + bias1) * 5 |
C = texture("map.tex"[0], "fill", 0);
A = texture("map.tex"[3], "fill", 1);
If the texture map has an alpha channel it will be used. Otherwise, it will default to opaque (1).
The "fill" token is not recognized by the shadow() function.
Note that this flag may be overridden by the enable lerp option.
The "lerp" token is not recognized by the shadow() function.
Note that this flag may be overridden by the enable gaussian option.
The shadow() function honors only the "box" and "gaussian" filters.
totalds = swidth * ds + sblur
totaldt = twidth * dt + tblur
where ds and dt are the actual dimensions of the area being textured in texture coordinates. Values for sblur and tblur are usually small, such as 0.001, because 1.0 covers the entire width of the texture.
The "blur" token may be used to conveniently set "sblur" and "tblur" to the same value.
The "bias" token is only honored by the shadow() function.
Consecutive pixels in a shadow map whose values differ by gapbias or less are inferred to be generated by the same object. For more information, see the tutorial on creating soft shadows.
vector vtransform(string tospace; vector v)These are corrolaries to the original transform() functions. Where transform() works correctly on points, vtransform is for vectors and ntransform is for normals. Vectors and normals transform differently than points. Care should be taken to choose the form that is correct for the application.
vector vtransform(string fromspace, tospace; vector v)
normal ntransform(string tospace; normal n)
normal ntransform(string fromspace, tospace; normal n)
If fromspace is not specified, "current" is the default.
point transform(matrix m, point p)These explicitly multiply a point, vector or normal by a matrix. Again, vectors and normals transform differently than points.
vector vtransform(matrix m, vector v)
normal ntransform(matrix m, normal n)
point transform(string space, matrix m, point p)This form first transforms the point, vector, or normal from "space" to "current" and then multiply by the matrix.
vector vtransform(string space, matrix m, vector v)
normal ntransform(string space, matrix m, normal n)
float ptlined(point P0, point P1, point Q)Returns the euclidean distance from point Q to the nearest point on the line segment from P0 to P1. Note that if the point nearest Q on the infinite line through P0 and P1 does not lie between P0 and P1, it will be clamped to that range before the distance is taken. In other words, ptlined() does not return the distance between Q and an infinite line.
float cellnoise(float x)Returns a pseudorandom value that depends upon the floor of all its arguments. The random values are uniformly distributed over the range from 0 to 1. The results are repeatable: given the same input (or input similar enough that the floor of all arguments is identical) cellnoise will return the same value.
float cellnoise(float s, float t)
float cellnoise(point pt)
float cellnoise(point pt, float t)
point cellnoise(float x)
point cellnoise(float s, float t)
point cellnoise(point pt)
point cellnoise(point pt, float t)
color cellnoise(float x)
color cellnoise(float s, float t)
color cellnoise(point pt)
color cellnoise(point pt, float t)
float min(float a, b, ...)The min and max functions can now take two or more arguments. The min/max of all arguments is returned.
point min(point a, b, ...)
point min(vector a, b, ...)
point min(normal a, b, ...)
color min(color a, b, ...)
float max(float a, b, ...)
point max(point a, b, ...)
point max(vector a, b, ...)
point max(normal a, b, ...)
color max(color a, b, ...)
float clamp(float a, min, max)The clamp and mix functions now operate on all of the scalar data types. Those with more than one component are computed separately on each component.
point clamp(point a, min, max)
point clamp(vector a, min, max)
point clamp(normal a, min, max)
color clamp(color a, min, max)
float mix(float fg, bg; float value)
point mix(point fg, bg; float value)
point mix(vector fg, bg; float value)
point mix(normal fg, bg; float value)
color mix(color fg, bg; float value)
float noise(point pt, float t)Four dimensional noise is now supported. The return value is repeatable and depends on all four input values. A common application is to use time as the fourth dimension.
color noise(point pt, float t)
point noise(point pt, float t)
float pnoise(float v, uniform float period)Periodic noise behaves the same as regular noise but with the additional property that the return value repeats itself with the frequency given by the period argument. In other words, pnoise(v, period) == pnoise(v + period, period) For best results, all periods should be specified with integers.
float pnoise(float u, float v, uniform float uperiod, uniform float vperiod)
float pnoise(point pt, uniform point period)
float pnoise(point pt, float t, uniform point pperiod, uniform float tperiod)
point pnoise(float v, uniform float period)
point pnoise(float u, float v, uniform float uperiod, uniform float vperiod)
point pnoise(point pt, uniform point period)
point pnoise(point pt, float t, uniform point pperiod, uniform float tperiod)
color pnoise(float v, uniform float period)
color pnoise(float u, float v, uniform float uperiod, uniform float vperiod)
color pnoise(point pt, uniform point period)
color pnoise(point pt, float t, uniform point pperiod, uniform float tperiod)
float determinant(matrix m)Returns the determinant of matrix m.
matrix inverse(matrix m)Inverts a matrix. This is equivalent to (1 / m). If the matrix is singular (i.e. uninvertible), an error message will be printed and the function will return the identity matrix.
matrix translate(matrix m, point t)These functions post-multiply m by a translation, rotation, or scale matrix, respectively. Note that the rotation angle is in radians.
matrix rotate(matrix m, float angle, vector axis)
matrix scale(matrix m, point s)
float comp(matrix m; float row, column)These functions get and set individual components of matrices.
void setcomp(matrix m; float row, column; float newvalue)
printf("%m", m1)The printf function has been augmented to handle matrices. Use the "%m" conversion specifier.
In the first form, the range is automatically computed as abs(Du(s1)*du) + abs(Dv(s1)*dv), resulting in a smooth step over the size of one surface element. The usual warning about not using "area operators" inside of varying conditionals apply to the first form of filterstep. In the second form, the range equals abs(s2 - s1). This form may be used inside varying conditionals.
The parameter list may contain token-value pairs. To specify which filter kernel to use, include the token "filter" followed by "box", "triangle", "catmull-rom", or "gaussian". For example, to select the Gaussian filter kernel:
filterstep(edge, s1, "filter", "gaussian");The default filter is "catmull-rom".
To adjust the amount of overfilter, use the token "width" (or "swidth" synonymously) followed by a floating point number indicating a factor to multiply the filter width by. For example, to double the filter size:
filterstep(edge, s1, "width", 2.0);Each filter kernel has an inherent width of support. Outside of that area of support, filterstep returns either 0 or 1. For reference:
filterstep(x, 0, 1, "filter", "box") is defined over the range x = -0.5 to 0.5 (width 1).Increasing the difference between s0 and s1 or increasing the amout of overfilter with the "width" token will increase the area of support for all of the filter kernels. In other words, the total support width of a filter is the product of its inherent width, the overfilter factor, and the range (either abs(Du(s1)*du) + abs(Dv(s1)*dv) or abs(s2 - s1)).
filterstep(x, 0, 1, "filter", "triangle") is defined over the range x = -1 to 1 (width 2).
filterstep(x, 0, 1, "filter", "catmull-rom") is defined over the range x = -2 to 2 (width 4).
filterstep(x, 0, 1, "filter", "gaussian") is defined over the range x =-1.5 to 1.5 (width 3).
All of the filters used by filterstep() change their shape to match the width. Contrast that with the pixel filters RiCatmullRomFilter() and RiSincFilter() which retain their shape but are merely windowed by xwidth and ywidth.
The difference between this form and the standard one from the RenderMan spec is that the basis of the spline may be specified. The old form is still supported with the implied basis "catmull-rom". With the new form, the basis may be "catmull-rom", "bezier", "hermite", "linear", or "bspline" (note: not "b-spline"). The "linear" basis needs some further explanation. The first and last control vertices are completely ignored. Points on the spline are linearly interpolated between the nearest two control vertices.
float spline([string basis;] float v; float f[])The control vertices may optionally be passed to spline() in a shading language array of four or more values. If the basis is omitted, it defaults to "catmull-rom".
color spline([string basis;] float v, color c[])
point spline([string basis;] float v, point p[])
float attribute(string, variable)RenderMan attributes can vary from one primitive to the next. The data returned by attribute() is within the context of the primitive being shaded. Note that "displacementbound:coordinatesystem" always returns "camera", and that "displacementbound:sphere" returns the bound in camera coordinates.
value of string variable type RenderMan Interface call "ShadingRate" uniform float ShadingRate "Matte" uniform float Matte "GeometricApproximation:motionfactor" uniform float GeometricApproximation "motionfactor" "Sides" uniform float Sides "displacementbound:sphere" uniform float Attribute "displacementbound" "sphere" "displacementbound:coordinatesystem" uniform string Attribute "displacementbound" "coordinatesystem" "identifier:name" uniform string Attribute "identifier" "name"
float option(string, variable)
value of string variable type RenderMan Interface call "Format" uniform float[3] RiFormat "DepthOfField" uniform float[3] RiDepthOfField "Shutter" uniform float[2] RiShutter "Clipping" uniform float[2] RiClipping float textureinfo(filename, string, variable)
value of string variable type description of data returned "resolution" uniform float[2] x and y dimensions of highest resolution subimage in texture map "type" uniform string "texture", "shadow" or "environment" "channels" uniform float number of channels in texture map (e.g. "rgb" is 3 channels) "viewingmatrix" uniform matrix world-to-light transformation matrix in a shadow map "projectionmatrix" uniform matrix world-to-NDC transformation matrix in a shadow map float rendererinfo(string, variable)
value of string variable type description of data returned "renderer" uniform string name of renderer "version" uniform float [4] the renderer version as four separate numbers "versionstring" uniform string version of the renderer as a string
float displacement(string varname; {float|point|color|string}
value)
float lightsource(string varname; {float|point|color|string}
value)
float surface(string varname; {float|point|color|string}
value)
float atmosphere(string varname; {float|point|color|string}
value)
The name of the function matches the type of shader from which you wish to receive a message. The first argument is a string containing the name of a variable that may be exported from the sending shader. If the sending shader exists, and it has an output parameter varname, and it's the same type as value, then the value of the output parameter is stored in value and the function returns 1. Otherwise, the function returns 0 and value is left unchanged. If the parameter is uniform and value is varying, then it is promoted. The lightsource() function may only be called within an illuminance loop.
It makes more sense to pass messages "downstream" to shaders that have not yet been evaluated. For a given piece of geometry, the order of evaluation of shaders in RenderDotC is displacement, all of the lights, surface, and atmosphere. Attempting to pass messages "upstream" will yield the default value from the parameter initializer.
displacement waves(float ampl = 1;
output varying vector displaced = 0;)
As a convenience, all parameters whose names begin with a double underscore are automatically flagged as output.
lightsource blacklight(uniform string __category = "uv,black")
This string variable may contain one or more group names, separated by commas, indicating that this light is a member of each of these groups. These names are defined by the user. The renderer does not predefine any category names.
The benefit of declaring a light to be a member of a category is that other shaders may selectively ignore whole categories of lights. The illuminance() function now takes an optional first argument which is a string:
illuminance("black", P)
In the example above, the illuminance loop will only be executed for lights that belong to the category "black". Note that the category argument to illuminance() may not be a comma-delimited list but rather a single category.
The category string may optionally be prefixed with a minus sign:
illuminance("-black", P)
This causes illuminance() to explicitly exclude a category and accept
all others.
The output keyword may be used in shader parameter lists for the purpose of sending messages.
Variable declarations beginning with extern are completely ignored.
This keyword exists only for compatibility with other renderers.
In RenderDotC, globals and variables declared in outer scopes are always
available to user-defined functions, provided that they are not hidden
by local variables of the same name.