next up previous contents
Next: Miscellaneous Tools Up: Blue Moon Rendering Tools Previous: Photo-realistic rendering with rendrib   Contents


Shaders and Textures

You've probably already used some of the ``standard'' shaders such as "matte", "metal", "plastic", and so on. Part of the real power of BMRT is the ability to write your own shaders to control the appearance of your objects. There are several types of shaders:

Surface shaders
describe the appearance of surfaces and how they react to the lights that shine on them.
Displacement shaders
describe how surfaces wrinkle or bump.
Light shaders
describe the directions, amounts, and colors of illumination distributed by a light source in the scene.
Volume shaders
describe how light is affected as it passes through a participating medium such as smoke or haze.
Imager shaders
describe color transformations made to final pixel values before they are output.

There are several standard shaders available. Standard surface shaders include "constant", "matte", "metal", "plastic", "shiny", and "paintedplastic". Standard light source shaders are "ambientlight", "distantlight", "pointlight", and "spotlight". Standard volume shaders are "depthcue" and "fog". The only standard displacement shader is "bumpy".

Compiling interpreted shaders with slc

Once you have written a shader, save it in a file whose name ends with the extension .sl. To compile it, do the following:


This will result either in a compiled shading language object file called myshader.slc, or you will get error messages. Hopefully, the error message will direct you to the line in your file on which the error occurred, and some clue as to the type of error. slc only can compile one .sl file at a time.

The slc program takes the following command line arguments:


Just like a C compiler, the -I switch, followed immediately by a directory name (without a space between -I and the path), will add that path to the list of directories which will be searched for any files that are requested by any #include directives inside your shader source. Multiple directories may be specified by using multiple -I switches.


Just like a C compiler, the -D switch, followed immediately by a symbol name (and possibly with an initial value), will define a proprocessor macro symbol. This allows you to have conditional compilation based on defined symbols using the #if and #ifdef statements in your shader source code files. The slc program automatically defines the symbol BMRT.

-o name

Specifies an alternate filename for the resulting .slc file. Without this switch, the output file is derived from the name of your shader.


Quiet mode, only reports errors without any chit-chat.


Verbose mode, lots of extra chit-chat.


Encrypts the resulting .slc file.


Just print out the architecture name (e.g., sgi_m3, linux, etc.).


On some platforms, this will compile your shader to a machine-code DSO file. See the following section for details.

IMPORTANT NOTE: slc uses the C preprocessor (cpp). On Unix-like operating systems, this executable is usually kept in the /lib directory, so that's where slc looks for it. If it can't find it there (or, like on Windows, it doesn't normally exist at all), slc will look for it in $BMRTHOME/bin. So you will need to set the environment variable BMRTHOME to point to the directory in which you have installed BMRT.

Since .sl files are passed through the C preprocessor, you can use the #include directive, just as you would for C language source code. You can also give an explicit path for include files using the -I command line option to slc (just like you would for the C compiler). You can also use #ifdef and other C preprocessor directives in a shader. A variable named BMRT is defined, so you can do something like #ifdef BMRT.

The output of slc is an ASCII file for a sort of ``assembly language'' for a virtual machine. When rendrib renders your frame and needs a particular shader, this assembly code is read, converted to bytecodes, and interpreted to execute your shader. Because the slc's output is ASCII and is for a virtual machine, it is completely machine-independent. In other words, you can compile your shader on one platform, and use that .slc file on any other platform. But, like any other interpreted bytecode, even though BMRT's interpreter is fairly efficient, it is not as efficient as compiled machine code.

Compiling .sl files to DSO's/DLL's

slc is also capable of compiling programs to native machine code (by first translating into C++ and then invoking the system's C++ compiler), and dynamically loading the code and executing it directly when the shader is needed by rendrib. Some complex shaders can run significantly faster (translating into overall rendering speedups of between 10-50%) if you compile your shaders into DSO's.

You can do this with the -dso flag (or -dll on Windows):

	slc -dso

This will create a file called myshader.ARCH.slc, where ARCH is the code name of the platform (such as linux, intelnt, sgi_m3, etc.).

There are several very important limitations and caveats to remember when using DSO's:

  • The resulting DSO file (the ARCH.slc file) is specific to one platform. If you have a multiplatform environment or wish to distribute the DSO shader to users with different platforms, you will have to recompile the source on that platform.

  • Not all shaders will have speed benefits by being compiled into DSO's. Generally, the biggest benefit will be from shaders that have lots of instructions. Short, inexpensive shaders like plastic will render no faster as a DSO than when interpreted. Shaders which are expensive specifically because they have many noise or texture calls will not speed up much as DSO's, because the time is already being spent within those expensive operations, which are already compiled in the renderer. But some shaders do speed up quite a bit - for example, the shader that comes with BMRT runs about twice as fast when compiled into a DSO as when interpreted. If your scene rendering time is dominated by executing complex shaders, you can probably speed up rendering by around 25% by selectively compiling your most expensive shaders as DSO's.

  • This feature is relatively new and untested, having first been documented and enabled with BMRT 2.5 (and only enabled for Windows with BMRT 2.6). Therefore, it's likely that some people will try to compile shaders that slc cannot figure out how to translate into C++. In such a case, you will receive error messages that appear to eminate from the C compiler. If this happens, it will be very helpful if you could send the original shader source to so that we can fix the compiler.

  • It's also possible that the translation to C++ is buggy. If you experience any quirky behavior, you should first delete the compiled .slc file and compile using ordinary slc, without using the -dso flag. If the shader behavior differs depending on whether or not you use the -dso flag, please report the problem (with an example) to

Using slctell to list shader arguments

The slctell program reports the type of a shader and its parameter names and default values. Usage is simple: just give the shader name on the command line. For example,

	slctell plastic


	surface "shaders/plastic.slc"
	    "Ka" "uniform float"
	                Default value: 1
	    "Kd" "uniform float"
	                Default value: 0.5
	    "Ks" "uniform float"
	                Default value: 0.5
	    "roughness" "uniform float"
	                Default value: 0.1
	    "specularcolor" "uniform color"
	                Default value: "rgb" [1 1 1]

The slctell program should correctly report shader information for both interpreted and compiled DSO shaders. Note, however, that in either case, slctell can only report the default values for parameters that are given defaults by simple assignment. In other words, if a constant (or a named space point) is used as the default value, slctell will report it correctly, but if the default is the result of a function, complex computation, or involves a graphics state variable, there is no way that slctell will correctly report the default value.

Making tiled TIFF files with mkmip

BMRT has always used TIFF files for stored image textures (as opposed to PRMan, which requires you to convert to a proprietary texture format). Though BMRT accepts regular scanline (or strip) oriented TIFF files, it is able to perform certain optimizations if the TIFF files you supply happen to be tile-oriented. In particular, BMRT is able to significantly reduce the memory needed for texture mapping with tiled TIFF files.

The mkmip program converts scanline TIFF files into multiresolution, tiled TIFF files. The mkmip program will also convert zfiles into shadow maps (tiled float TIFFs) and will combine six views into a cube face environment map. Command line usage is:

  • For textures:
        mkmip [options] tifffile texturefile
  • For shadows:
        mkmip -shadow [options] zfile shadowfile
  • For cube-face environment maps:
        mkmip -envcube [options] px nx py ny pz nz envfile
  • For latitude-longitude environment maps:
        mkmip -envlatl [options] tifffile envfile

where options include:

-smode wrapmode
-tmode wrapmode
-mode wrapmode

where wrapmode is one of: periodic, black, or clamp. This specifies the behavior of the texture when outside the [0,1] lookup range. Note that -smode and -tmode specify wrapping behavior separately for the s and t directions, while -mode specifies both at the same time. The default behavior is black.

-resize option

Controls the resizing of non-square and non-power-of-two textures when being converted to MIP-maps. The option may be any of: up, down, round, up-, down-, round-. The up, down, and round indicates that the texture should be resized to the next highest power of two, the next lowest power of two, of the ``nearest'' power of two, respectively. For each option, the trailing dash indicates that the texture coordinates should always range from 0 to 1, regardless of the aspect ratio of the original texture. Absence of the dash indicates that the texture should encode its original aspect ratio and adjust the texture coordinates appropriately at texture lookup time. The option that probably gives the most intuitive use is up-. The default is up.

-fov fovangle

for envcube only, specifies the field of view of the faces.

Note: rendrib specifically wants TIFF files as texture and environment maps. The files can be 8, 16, or 32 bits per channel, but cannot be palette color files. Single channel greyscale is okay, as are 3 channel RGB or 4 channel RGBA files. Ordinary scanline TIFF is fine, but if you use the mkmip program to pre-process the textures into multiresolution tiled TIFF, your rendering will be much more efficient.

next up previous contents
Next: Miscellaneous Tools Up: Blue Moon Rendering Tools Previous: Photo-realistic rendering with rendrib   Contents
Exluna, Inc.