RSL2GSL version 1.0.3

Translator from the RenderMan® Shading Language to the Gelato® Shading Language


RenderMan is a registered trademark of Pixar, Inc.
Gelato is a registered trademark of NVIDIA Corporation

Introduction


RSL2GSL can parse RSL (Renderman shading language) source and output either RSL or GSL (Gelato shading language). One feature this provides is the ability to have both GSL and RSl coexist in the same shader source.

The product is released with a Modified BSD License.

The source is available.

The source was developed under Linux (Red Hat 9 & Fedora Core 2). It also seems to work just fine under Windows (at least it has been built and run under using Cygwin).


Options

Usage:

multShader.pl [options] shaderFile *

options

  -h|-help       Print this message
   -dt|dumpTree   Dump parse tree to stdout
   -ds|dsdout     Dump shader to stdout
   -gsl           Translate to Gelato shading language.
                    Otherwise the default is to leave the code in RSL.
                    (No translation)
   -kt|keepTemp   Do not delete the temporary file, that is created during
                    the translation process.  The default is to remove it
                    after the shader compiler is called.
   -noshad        Stop after the file process is done.  Do not call the
                    shader compiler.
   -output FILE   Write output to FILE.
   -xtrapp SCRIPT After the standard pre-processor is called. The file
                    will be processed again using the specified SCRIPT.
   -v|verbose     Dump out extra debugging information out to stderr.

This will (attempt to) translate shaderFile from RSL to GSL. More information can be found in the ReadMe.html file included with this distribution.

If neither the -dt or -ds options are given, the program will attempt to call a shader compiler. In this situation if the -gsl option is given the shader compiler will be gelato otherwise it will be a RSL compiler. The actual compiler chosen is determined by the multShader.ini file.

* As this is a perl script, Windows users may need to preface the command with perl:
perl multShader.pl [options] shaderFile


//RSL source : tests/f.h
float func (float f1, f2, f3) { }


> multShader.pl -ds -gsl tests/f.h

// GSL source 
#include <_rsl2gsl.h>
 
 float func (
     float f1,
     float f2,
     float f3)
{
}


multShader.ini

The translator looks for an initialization file, multShader.ini, to override its default settings. This file is searched for in the following locations (in this order):
  1. Installation directory where multShader.pl and related files are located.
  2. User's home directory
  3. Current location where the translator is being run from
The following is what the standard multShader.ini looks like:

###progs
cpp	cpp 	#location of C pre-processor
rsl	shader  #RenderMan shader compiler
gsl	gslc    #Gelato shader compiler

##gelato
##rayTrace defaults
Indirect	defaultIndirect
Occlusion	defaultOcclusion
The C-PreProcessor is called on the shader source code.
The RSL compiler is called if the parsetree completes and the -gsl and -ds options aren't used.
The GSL_COMPILER is called if the parsetree completes and the -gsl option is given but the -ds isn't.

Indirect token name is used for indirect trace sets.
Occlusion token name is used for Occlusion trace sets.


Things to know


What doesn't work

There will be features that the translator doesn't handle or there will be constructs that will be more efficient to do in GSL natively. The parser provides for this need by a feature called RAWBLOCK. The syntax for this is double curly braces (or double square brackets). Like the name infers, a RAWBLOCK must be an entire block (statement). It can not be only part of a statement (expression).

#if GELATO
{{
   displace ("shader", .2);
}}
#else // RSL
point sP = transform ("shader", P);
sN = normalize (ntransform ("shader", N);
sP += .2 * sN;
P = transform ("shader", "current", sP);
N = calculatenormal (P);
#endif
environment
The optional 4 point texture coordinate variant isn't (currently) supported. The following parameters are: firstchannel.

indirectdiffuse
The translator will give the trace set name as "defaultIndirect". (Unless a different name is provided in the multShader.ini.) A trace set attribute of this name will need to be attached to the desired geometry before this call will be applied.
The only optional parameters that will be accepted are: bias, maxdist, subset, and environmentdir. Any other RSL options will be ignored and a warning given.

occlusion
The translator will give the trace set name as "defaultOcculusion". (Unless a different name is provided in the multShader.ini.) A trace set attribute of this name will need to be attached to the desired geometry before this call will be applied.
The only optional parameters that will be accepted are: bias, maxdist, subset, environmentdir, and coneangle. Any other RSL options will be ignored and a warning given.

rayinfo
The translator only supports the request for depth and some portions of type.

shadow
Doesn't support the channel, 4 point texture coordinates (currently), s/t blur, or s/t width options.

The following builtin calls are not supported at all and will require hand editing to have a shader that will successfully compile:

transmission, photonmap, irradiancecache, incident, opposite, shadername, renderinfo, option, Deriv, depth, gather.


PRMan ?: TRIOP

Be a little wary of the ?: operator. It may not be doing what you expect or at best beware that PRMan's behavior doesn't jive with shading language precedence.

Under PRMan the ?: operator precedence appears to be change depending on the context of its use.

For example:

float a = 1, b = 2;
float c = a + b > 2 ? 1 : -1;

This results in c = 1

float a = 1, b = 2;
float c = 5 * (b > 2)? 1: -1;

Results in c = -5

In the first example the triop has the expected precedence (which is the lowest). However, when the parentheses are around the conditional portion, the triop now has higher precedence than the mult!

This kind of grammar is very difficult to do within a YACC/Bison parser (which is what this parser uses). So the parser allows the first case. However, the second case will cause a syntax error.

To make the parser behave (and to give the proper syntax for the second example to produce the result of -5, the second line would need to be:

float c = 5 * ((b > 2)? 1: -1);
I suppose the argument could be made that as it is a "triop" there are three components: boolean_conditional, ? success, : failure. So by putting the parentheses around the conditional section, this should imply that the entire "operator" should take precedence.

Regardless, it is really difficult to devise a clean YACC/Bison grammar in the attempt to deal with this kind of "contextual" knowledge.

So the take home messages are these:

  1. Take a close look at your usages of the triop to make sure that it is indeed providing the results that you intend.
  2. This translator may give you syntax errors for code that went through just fine with PRMan. The above were my excuses for failing address this.

Watch Your Lights

There are some things to be aware of with lights between RenderMan and Gelato. (Especially as the translator won't deal with this for you.)

Within RenderMan, the L for non light shaders points from the surface towards the light shader. For light shaders, L is pointing in the opposite direction (from the light to the surface. All of your RenderMan light shaders have been built with this in mind (whether you were paying attention or not).

With Gelato L is pointing in the same direction for light shaders and non-light shaders. According to Table 5.5 from the Gelato techref.pdf: "vector L Direction of incoming light (points from Ps to Pl)."

What does all this mean?

For one, care should be given with the variable that is used as the "axis" vector (This is the second illuminance parameter, not counting the optional category parameter) when used outside of the illumince block.

Compare the uberlight.sl, from the Advanced RenderMan book, with the uberlight that comes with Gelato.

/* RenderMan snippet */
vector axis = normalize(vector "shader" (0,0,1));
illuminate (from, axis, angle) {

  L = axis * length(Ps-from);

/* Gelato snippet */
vector axis = vector ("shader", 0, 0, 1);
emit (from, axis, angle) {

  L = -axis * length(Ps-from);  
The translator will not handle doing the -axis for you. One tell tale sign that something like this might be going on with your translated light shaders is if the surface looks like it is being backlit when the light is really front lighting (or vise-versa). One other thing that I have noticed is sometimes a light shader might refer to N. To make the light shader work under Gelato, I have had to change the N to Ns.


Windows OS support

This release has been designed under and tested under Linux (specifically RH 9 and Fedora Core2). The Windows support was added as an after thought, as to not get inundated with request for Windows builds.

The following are some things to keep in mind which may help you duplicate the environment that I used when building the system. But first keep in mind that I don't use Windows much so I won't be able to answer too many questions on "if this will work?" or "why didn't you use that instead?".


Source & Development

The source has been made available so you have the power to fix bugs or extend the system as needed.

Running 'make' should be all that is needed to get building going.

Please send these back to the RMR so these can be shared with others.

Also please check with me before embarking on any radial changes to the code.

Check out the Wishlist to get some hints on what would be some good things to fix.


Future wishlist

The following are some things, I would like to see improved on.

Authors

Brent Burley
Tal Lancaster

Contact: rsl2gsl AT renderman DOT org

Tal Lancaster
Last modified: Sun Dec 11 16:08:10 PST 2005