Mental Ray Shaders in 3ds Max

Introduction

This topic describes how a developer can use a mental ray shader to work with 3ds Max. Part of this document also applies to integrating custom phenomena. This document does not describe the details of shader writing and will mainly focus on how the shader's code (or executables) can be used to work within 3ds Max. For information on writing mental ray shader see the mental ray documentation.

The mental ray Connection

The mental ray Connection is a component of 3ds Max that acts as a bridge between the mental ray shaders and 3ds Max, providing UI support for these shaders in 3ds Max. The mental ray Connection supports shaders written in the mental ray Scene Description Language (.mi files).

At startup time, the mental ray Connection looks for shaders installed in a number of locations for 3ds Max, loads them into memory and makes the necessary connections between the shader (specifically its parameters) and the UI of 3ds Max. There are three default install locations:

Shader Declarations

For a mental ray shader to work in 3ds Max (during mental ray renders) a scene description language declaration (a .mi file) is required and possibly the location of its implementation. 3ds Max will generate a basic UI for the shader's parameters.

Phenomena

A phenomenon works as a wrapper for one or more mental ray shaders, to combine their effects or make their user interface simpler for the user. Mental ray phenomena do not require a DLL, so the developer is only required to describe them in .mi files. The following is an example phenomenon named MyBlueDGS that includes a shader named dsg_material:

declare phenomenon
    color "MyBlueDGS" ()

    shader "dgs_material" "myDgs" (	"diffuse " 0 0 1, )
   	root = " myDgs "
   	apply texture
end declare

Shader with Embedded C/C++ Code

Writing an embedded shader can sometimes be useful for the user who has to deal with cross platform development issues like having shaders compiled to .so files instead of .dll. Here is an example file (stark.mi):

$code
#include "shader.h"
DLLEXPORT int stark_version(void) {return (1);}
DLLEXPORT miBoolean stark(miColor*result, miState *state, miTag *light)
{
    miScalar dot_nl;
    mi_trace_light(result, 0, &dot_nl, state, *mi_eval_tag(light));
    result->r = dot_nl > 0.4 ? 1 : .2;
    result->g = dot_nl > 0.7 ? 1 : .2;
    result->b = dot_nl > 0.0 ? 1 : .2;
    result->a =1;
    return (miTRUE);
}
$end code

declare shader "stark" (light "light") 
version 1 
apply texture
end declare

This is relatively easy to use, but has a negative impact on the start-up of 3ds Max, because the mental ray Connection has to compile every embedded shader in the .mi file on start-up.

This approach is not recommended for production shaders, except when doing rapid prototyping or debugging.

Creating a shader with its matching DLL

This is an alternative to embedding C/C++ code in a shader. The developer needs to create separate .mi and .C/.CPP files compiled to a .DLL. The following is an example of this case:

(Stark.mi)
declare shader "stark" (light "light") 
version 1 
apply texture
end declare
(Stark.c)
#include "shader.h"
DLLEXPORT int stark_version(void) {return (1);}
DLLEXPORT miBoolean stark(miColor*result, miState *state, miTag *light)
{
    miScalar dot_nl;
    mi_trace_light(result, 0, &dot_nl, state, *mi_eval_tag(light));
    result->r = dot_nl > 0.4 ? 1 : .2;
    result->g = dot_nl > 0.7 ? 1 : .2;
    result->b = dot_nl > 0.0 ? 1 : .2;
    result->a =1;
    return (miTRUE);
}

In this example the file "shader.h" is found at: [3ds max install]\ mentalimages\dev\include \shader.h

The 32-bit DLL will need to be compiled against the library: [3ds max install]\ mentalimages\dev\lib32 \shader.lib

The 64-bit DLL will need to be compiled against the library: [3ds max install]\ mentalimages\dev\lib64\shader.lib

It is recommended to use MS Visual Studio .NET to compile the DLLs, but unless the shader has some interaction with 3ds Max SDK, other compilers might be used as well.

Shader with Linked C/C++ Code

It is possible for a user to write a shader with embedded C/C++ code, but to have the source code in a separate C/CPP file. This makes it possible to test compilation of a shader without starting the main application.

As with the embedded C/C++ code, since this technique does not involve a separate DLL, the product will need to compile the shader on startup. Here is an example:

(stark.mi)

(stark.mi)
registry "{stark}"
    code "[source location]\stark.c"
end registry
$lookup "{stark}"

declare shader "stark" (light "light") 
version 1 
apply texture
end declare

Compilation Process

When the mental ray connection compiles a shader compilation errors are sent to the message log. To open the message log, go to the Rendering menu and select "Render Message Window…". The message dialog can be set up to automatically open when errors are triggered.

Configuring Shader Installation via 3rdparty.mi

The file 3rdparty.mi allows the developers to install shaders that do not use the automatic load location of the mental ray Connection, or do not have a matching .dll and .mi file names. The file is stored in: [3ds Max install]\mentalimages\shaders_3rdparty\mentalray\3rdparty.mi

As an example, consider the case that the developer creates three .mi files to contain the shader declarations.

If a developer wishes to store the implementation for these shaders in a single file called "MyBigLib.dll" the Connection cannot automatically load this file because it does not have the same name as the .mi files. The solution is to use the 3rd party install location to specify link and mi statements to the file 3rdparty.mi file such as:
registry "{_AUTODESK_REG_3DSMAX_LOAD_3RDPARTY_SHADERS}"

# Note: this is a comment. 

link "mentalimages\shaders_3rdparty\mentalray\shaders\MybigLib.dll"
mi mylibpart1.mi
mi mylibpart2.mi
mi mylibpart3.mi
 
end registry

For more information please refer to the mental ray documentation.

Apply Statements

The apply statements are used by 3ds Max to restrict the listing of a shader in various locations of the 3ds Max UI. For example, the statement apply lens in a .mi file indicates that the declared shader is a lens shader for cameras and will not show up in the UI when browsing for other kinds of shaders. Shaders that have multiple uses may declare multiple apply types.. While the mental ray shader is not strict about using the apply statements, the Connect will force the developer to use apply statements to clear out the application of the current shader for the user. For more information about apply statements and supported apply types see the "Shader Apply Flags" topic in the mental ray documentation.

GUI Attributes

GUI attributes are extensions to the .mi syntax that allow authors to further refine the declaration of a shader for use in 3ds Max. Some examples of the shader aspects that can be controlled via GUI attributes are:

The use of GUI attributes for UI generation is not strictly required, as 3ds Max will, by default, generate generic UI elements for any parameters defined as part of the shader declaration in a .mi file. GUI attributes are used to modify how the UI elements are displayed in 3ds Max.

GUI attributes are also used for specifying shader types that are supported by 3ds Max but are not natively present in the mental ray syntax for apply statements.

The syntax for declaring GUI attributes in a shader is described in the mental ray programming book. The following example demonstrates adding contour as a new shader apply type using GUI attributes:

declare shader
    "max_BlendMaterial" (
        struct "Parameters" {
            scalar MixAmount
        }
    )
    version 1
    apply material
	
    gui "gui_max_BlendMaterial"
    {
        control "Global" "Global"
        (
            "addApply" "contour"
        )
        control "Parameters" "struct"
        {
            control "MixAmount" "scalar"
            ( 
                "value" 1.0, 
                "range" 0.0 100.0, 
                "hardrange" -10.0 110.0,
                "step" 0.1,
                "helptext" "Determines amount of Material2 in percent",
                "position" 40 30 20 100

            )
        }
    }
enddeclare

By convention, the name of the GUI is the name of the shader with the prefix "gui_" at the beginning. Each control must correspond to a single parameter by name. The control type must also match. "struct" parameters imply a "struct" control type which starts and ends with curly braces '{}' which define a control group. A control that is not a "struct" starts and ends with parentheses '()' and defines a group of attributes. A parameter that has no corresponding control attributes will use default, automatically generated values.

Every attributes may either define one to four scalars (floats), a single character string, or no parameter at all.

It is important to note that the mental ray syntax is very relaxed for GUI attributes. Thus, a developer will have to implement strict consistency checks themselves, and report warnings/errors when inconsistencies are found.

Note that all the strings (attribute & control names) are CASE SENSITIVE.

Shader Attributes

addApply

Additional apply type information. Used to specify the following apply types which cannot be specified with the normal .mi syntax:

  • bump
  • contour_shader
  • contour_store
  • contour_contrast
  • contour_output
  • illum
  • pass_merge

Several apply types may be given, in which case they must be separated by commas and/or blank spaces.

hidden

Hides the shader from the user interface. No argument is needed with this attribute.

nonConnectable

Equivalent to specifying the "nonConnectable" attribute on all the parameters of the shader.

uiName

This attribute specifies a shader name that is used strictly in the UI - the uiName is not used to reference this shader in phenomena or by 3ds Max. The UI name can change at any time without affecting the compatibility of .max files that use this shader. Changing the base name of the shader will affect .max file compatibility. This name may also be used to localize names into different languages without affecting phenomena or .max file compatibility.

outputTypes

Used to specify the buffers that an output shader needs. The parameter is a string that contains a comma-separated list of buffers with optional + or - symbols that indicate interpolation. For a full list of frame buffers, refer to the "Output Statements" section of the mental ray manual.

Parameter Attributes

applyTypes

Associated with a shader parameter, this tells 3ds Max what types of shaders can be assigned to the parameter. When this attribute is not present, all types of shaders are accepted. The value for this attribute is a string of comma-delimited "apply types". Valid apply types are:

lens, material, light, shadow, environment, volume, texture, photon, geometry, displace, emitter, output, lightmap, photonvol, other, bump, contour_shader, contour_store, contour_contrast, contour_output, illum, pass_merge

fileopenButton and filesaveButton

These attributes are associated with a string parameter and will tell 3ds Max to create a "File Open" or "File Save" button instead of the normal edit box associated with string parameters. The user will be able to use this button to browse for a file to open or save.

These attributes can optionally be followed by a string value. The string value is used as a list of file types in the file open/save dialog. The format of the string is as follows:

<description1>|<pattern1>|<description2>|<pattern2>|...|

In other words, it is a sequence of file type descriptions and file type patterns each separated by a '|' vertical bar and terminated by a '|' vertical bar. For example:

Data(*.dat)|*.dat|Excel(*.csv)|*.csv|All|*.*|

specifies 3 types in the file type dropdown, the first reading "Data(*.dat)" and matching *.dat and the second reading "Excel(*.csv)" and matching *.csv and the third reading "All" and matching any file.

helptext

This attribute is followed by a string that will be displayed as the tooltip of the control.

hidden

This attribute hides the parameter from the UI. No value is needed with this parameter. A good default value should be supplied for the parameter if it is to be hidden, as the default value will automatically be used.

min and max

An alternative to "range" - "min" and "max" are two attributes that can be used to specify a range. These are only valid for scalar parameters. They have the same syntax as the "value" attribute for a scalar parameter (i.e. they accept a scalar or a string, which specifies a value with units). Note 1: Both attributes must be specified - if only one of them is specified, then it is ignored. Note 2: If the attribute "range" is also specified, then "min" and "max" are ignored.

noAlpha

Associated to a color parameter, this attribute tells the translator to create a UI color swatch that does not have an alpha component.

nonConnectable

Flags this parameter as not connectable. i.e., it will not have a "connection" button created for it in the "connections" rollup, so its value may not be connectable to the output of another shader.

range

Range of values for scalar and integer parameters. Two scalar values are specified, the first one being the minimum value and the second one being the maximum value.

textureInfo

Provides additional information on texture parameters. Valid values are:

  • "max_bitmap": default, see below.
  • "max_texmap": results in the creation of a parameter block parameter of type TYPE_TEXMAP.

By default, a parameter of type TYPE_FILENAME is created, and a file open button is created in the UI. The associated shader connection button can be used to assign a shader instead of a file.

typeOverride

Used to override the type of a parameter. Currently only used with parameters of type "scalar texture". Mental ray does not distinguish between scalar textures and shaders, so this attribute is necessary for the translator.

uiName

This attribute specifies a parameter name that is used strictly in the UI - the uiName is not used to reference this parameter in phenomena or by 3ds Max. The UI name can change at any time without affecting the compatibility of .max files that use this shader. Changing the base name of the parameter will affect .max file compatibility. This name may also be used to localize names into different languages without affecting phenomena or .max file compatibility.

units

Possible value: "world".

The attribute is used to specify that a scalar parameter should be displayed in the UI as a world unit value. The correct unit conversions will be performed on the value, and the abbreviation of the current units (i.e. "cm") will be displayed with the value. This affects only the UI, and does not affect the internal representation of the value (i.e. the shader is never aware of this).

value

Default value for a parameter. Supported parameters are:

Parameter type Value type
Boolean, integer 1 scalar
Float 1 scalar, or a string. A string may be used to specify a value with units, e.g. “17m” for 17 meters”. All unit types supported by 3ds Max are accepted. There must NOT be a space between the value and the unit.
Color, vector 3 scalars
String string
Shader, data string (name of default shader)

writableTexture

Associated with a texture parameter (color, scalar, or vector texture), this tells the translator that the shader expects a writable texture. The translator will create a UI to handle the writable texture, and will pass all the necessary information to mental ray.