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):
- Installation directory where multShader.pl and related files are located.
- User's home directory
- 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
- In Gelato C and opacity are similar to Cs, Ci and Os, Oi combined. So where ever C or opacity are seen in the shader source they are renamed to __rslgsl_C and __rslgsl_opacity respectfully.
- The translator predefines Cs and Os and sets them to the gelato C and opacity. It also will replace Ci and Oi with C and opacity.
- deltau and deltav are reserved in gelato, so the translator will rename this instances to __rslgsl_deltau and __rslgsl_deltav.
- In Gelato, ray tracing calls need to have a trace set. The translator gives a name specific to the raytace call. For the shader to work, an trace set attribute with the same name will need to be attached the all of the geometry that this call is to be applied to. The actual name used is determined by the setting in the multShader.ini file. More specific information can be found in the "What doesn't work" section.
- Gelato doesn't define s and t texture coordinates in shaders. So the translator will define them in the shader parameter list and initializes them to u and v respectfully. However, the translator can't do this if the shader already has s or t defined in its parameter list.
If you have functions that are relying on the RSL global s, t, you will have to have these functions declared as internal functions and declare them as externs:
extern float s, t;
- The translator embeds an include file called _rsl2gsl.h. This file contains various helper functions to aid in the translation process.
- Gelato uses a different interface for DSO shadeOps than RenderMan. In other words shadeOps written for RenderMan are not binary compatible with Gelato. The translator can't do anything about this. So shadeOps will need to be modified by hand and recompiled for them to work. Obviously, if some renderer specific feature, was being used (ie. RxNoise, RxTexture) some substitute behavior will need to be used in place.
- If you intend to share RenderMan and Gelto code in the same files, keep in mind that __PRMAN__ and GELATO are the pre-defined values to test against when the code is run through cpp. Also RAWBLOCKS allows embedding language specific features into the source, which bypasses the translator section.
- "lerp" is an unkown texture access specifier.
- ? : tri-operator operator, under PRMan's shader compiler, seems to not obey the RenderMan language syntax.
- lights/emit some care needs to be given when trying to translate RMan lights to Gelato lights. For one in gelato the direction of L is opposite of RMan. For more details see the Lights section.
- gtrace has been added to the translator to have your code refer to Gelato's trace call. Use trace when referring to RMan. Use gtrace to when you want to refer to the gelato trace call. This allows you to avoid the code duplication that would occur otherwise when trying to use RAWBLOCKS to handle the RMan gather block.
- Watch out for RSL functions that declare local variables called du or dv. The translator assumes that when it sees du or dv, that they are RSL built-in variables and replace them with the gelato equivalent. Which will result in a compiler error.
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:
- Take a close look at your usages of the triop to make sure that it is indeed providing the results that you intend.
- 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?".
- The Windows binaries were built under the Cygwin system. You may need to have it installed and to run under that environment for things to work. Also everything runs only under the command line. Cygwin provides one.
- perl -- (Cygwin provides) The main wrapper program is a perl script. You will need perl to be able to run the script: multShader.pl. Also under Windows you will need to preface the script with , perl: perl multShader.pl . . .
- cpp -- (Cygwin provides) the translator depends on running the C Pre-processor. This allows for including any specified include files and performing macro substitution.
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.
- Loose the symtable.* code and write a more modern setup in C++.
- It wouldn't be that difficult to be able to directly translate from RMan gather blocks to Gelato's trace call.
- Keep the parser and translator current with RMan and gelato feature sets.
- Make the parser smarter so RAWBLOCKS could occur anywhere in a statement. -- This might not be practical while still relying on the YACC/Bison grammar.
Authors
Brent Burley
Tal Lancaster
Contact: rsl2gsl AT renderman DOT org
Tal Lancaster
Last modified: Sun Dec 11 16:08:10 PST 2005