Shader Versioning

The parameter set of a shader must always be correctly described by its declaration in the .mi scene file. It is a common source of errors to have a mismatch between the .mi and the .c shader parameters. This can lead to incorrect rendering results but can also cause shader crashes, for example if the shader mistakes a floating-point number for an array length.

For this reason it is highly recommended to attach version numbers to both the .mi declaration and the shader itself. Version numbers are positive integers, and should begin with 1 (0 is the default if the version number is missing). For example, the .mi declaration of a shader myshader might be defined as:

declare shader  
    color "myshader" ( parameters )  
    version 42  
end declare  

There are two ways to ensure that the version number is correct. The recommended method is writing a pseudo-shader that provides the version number:

DLLEXPORT int myshader_version(void) {return(42);}

DLLEXPORT miBoolean myshader(
    miColor         *result,
    miState         *state,
    struct myshader *paras)
{
...
}

Before mental ray calls a shader for the first time, just before looking for its initialization shader (whose name would be myshader_init), mental ray checks whether a function exists whose name is the shader name followed by _version. If it does, it is called and the version number is compared with the version number in the .mi declaration. If there is a mismatch, an error message is printed. If the version shader does not exist, a warning message is printed.

The second method for shader version comparison is an explicit comparison in the shader using mi_query:

#define MYSHADER_VERSION 42

DLLEXPORT miBoolean myshader(
    miColor         *result,
    miState         *state,
    struct myshader *paras)
{
    int             version;

    mi_query(miQ_DECL_VERSION, state, 0, &version);
    if (version != MYSHADER_VERSION)
        mi_error("myshader: wrong declaration");
    ...
}

This method can be used to support several versions in a single shader implementation, but this is rarely necessary. Note that mental ray does not abort on a shader mismatch, which can lead to trouble later.

It is very important to always increment the version number every time the shader parameters change. Problems introduced by mismatches are hard to find, especially if the shader versions on master and slave hosts do not agree. (Slaves always use the master's declaration but their local libraries.)

The following sections discuss the various types of shaders, and how to write custom shaders of those types. Basic concepts are introduced step by step, including supporting functions and state variables supplied by mental ray. All support functions are summarized at the end of this chapter.

Most shader sources shown in this chapter were taken from the standard shader libraries, base.so, physics.so, and contour.so ( .dll on NT). Shader source code is available on ftp://ftp.mentalimages.com/pub/.

Copyright © 1986, 2013 NVIDIA Corporation