Reference

Home Reference Index Editor Scenery Tab NL2MAT Editor

NL2MAT Programmable Shader Core Language



Introduction

The programmable shader core can be used to customize how the input textures and color from the RGBGen and AlphaGen units will be combined to produce the pixels being rendered. It is a text based language, made up of statements with input and outputs. All statements operate on 4 components (channels) parallely. Those 4 components typically represent the RGBA channels of a color. E.g. The statement "Result = Add ( Tex0, Tex1); " will represent internaly 4 additions for each component (Red, Green, Blue, Alpha). Each component of the first input (Tex0) is added with the corresponding component of the second input (Tex1) and is written to the corresponding component of the Result register. The pseudo code would be similar to " Result[0] = Tex0[0] + Tex1[0]; Result[1] = Tex0[1] + Tex1[1]; Result[2] = Tex0[2] + Tex1[2]; Result[3] = Tex0[3] + Tex1[3]; ".

There are 4 output registers (Result, Specular, Ambient, Emission) that can be used to specify the pixel attributes for furter processing.

When lighting modes for RGB generation are used, the final pixel will be computed using the following pseudo code formula:
Red   = Result[0] * (DiffuseLighting[0] + Ambient[0] * AmbientLighting[0]) + Specular[0] * SpecularLighting[0] + Emission[0]
Green = Result[1] * (DiffuseLighting[1] + Ambient[1] * AmbientLighting[1]) + Specular[1] * SpecularLighting[1] + Emission[1]
Blue  = Result[2] * (DiffuseLighting[2] + Ambient[2] * AmbientLighting[2]) + Specular[2] * SpecularLighting[2] + Emission[2]
Alpha = Result[3]

For all other RGB generation modes, the final pixel will be computed using the following pseudo code:
Red   = Result[0] + Emission[0]
Green = Result[1] + Emission[1]
Blue  = Result[2] + Emission[2]
Alpha = Result[3]


Note that Red, Green, Blue, Alpha are further processed by optional reflection and z-feather effects.


Syntax

The shader program consists of a series of statements, empty lines or comments.

Destination = Parameter;Assignment Statement
Destination = Function ( Parameters... );Statement with built-in function (See below)
// ...Line Comment
/* ... */Multi-Line Comment
Parameter: Either an input register or a constant (See below)
Destination: Output register (See below)
Function: Built-in function (See below)



Registers (4 Component RGBA)

ResultThe main output register for the diffuse (RGB) and alpha values (output only). If not written to, it defaults to the value of the Color input register.
MetallicOptional register for metallic property (output only). It is a one-component register (only the first channel (red) is used). It defaults to zero. When the metallic register is used, the specular register cannot be used..
SmoothnessOptional register for reflection smoothness (output only). It is a one-component register (only the first channel (red) is used. It defaults to the glossiness setting in the basic tab.
RoughnessOptional register for reflection roughness (output only). It is a one-component register (only the first channel (red) is used. It defaults to the 1 - glossiness setting in the basic tab. The roughness is 1-smoothness. When roughness is used, smoothness cannot be used and vice versa.
SpecularOptional register for specular mask (input and output). It is a three-component register. It can be read and written, and it defaults to the specular color from the material or Basic tab. The RGB components of Specular will be multiplied with the specular components of lighting computations to create the final specular color. It will be ignored when RGBGen is not a lighting mode. Assigning a value to the A component will be ignored. Reading from the A component will return an undefined value. When the specular register is used, the metallic register cannot be used at the same time
AmbientOptional register for ambient mask (output only). It is a one-component (only the first channel (red) is used) register. When not used, it defaults to 1. The R component of Ambient will be multiplied with the ambient components of lighting computations to create the final ambient color. It will be ignored when RGBGen is not a lighting mode. The G,B, and A components assigned to Ambient will be ignored.
EmissionOptional register for emission color (output only). When not used, it defaults to {0,0,0,0}. The RGB components of Emission will be added to the color from Result after diffuse and specular lighting was applied. The alpha component of Emission will be ignored.
ColorInput of the RGBGen and AlphaGen Color Units (input only). When RGBGen is one of the lighting modes, the RGB components of Color is identical with the color from the material or Basic tab.
Tmp0Temporary Register 0 (Input/Output)
Tmp1Temporary Register 1 (Input/Output)
Tmp2Temporary Register 2 (Input/Output)
Tmp3Temporary Register 3 (Input/Output)
Tex0Texel of Texture in Unit 0 (Input only)
Tex1Texel of Texture in Unit 1 (Input only)
Tex2Texel of Texture in Unit 2 (Input only)
Tex3Texel of Texture in Unit 3 (Input only)
Entity0Entity Register 0 (Input only), can be set by NL2SCO user colors or scripts.
Entity1Entity Register 1 (Input only), can be set by NL2SCO user colors or scripts.
Entity2Entity Register 2 (Input only), can be set by NL2SCO user colors or scripts.
Entity3Entity Register 3 (Input only), can be set by NL2SCO user colors or scripts.
Entity4Entity Register 4 (Input only), can be set by NL2SCO user colors or scripts.
Entity5Entity Register 5 (Input only), can be set by NL2SCO user colors or scripts.
Entity6Entity Register 6 (Input only), can be set by NL2SCO user colors or scripts.
Entity7Entity Register 7 (Input only), can be set by NL2SCO user colors or scripts.


Constants (Inputs)

Scalars (will be replicated to all channels) e.g. 1.0
Vectors e.g. {1.0, 2.0, 3.0, 4.0}



Functions

Saturate( Val )Clamps values to 0...1
Add (Val1, Val2)Addition. Pseudo Code: Val1 + Val2
Sub (Val1, Val2)Subtraction. Pseudo Code: Val1 - Val2
Mul (Val1, Val2)Multiply. Pseudo Code: Val1 * Val2
Mad (Val1, Val2, Val3)Multiply and Add. Pseudo Code:Val1 * Val2 + Val3
Lerp (Val1, Val2, Val3)Interpolate between Val2 and Val3. Pseudo Code: Val1 * Val2 + (1 - Val1) * Val3
Dp3 (Val1, Val2)Dot Product using the first 3 components (rgb); result will be replicated to all 4 channels. Pseudo Code: Val1[0] * Val2[0] + Val1[1] * Val2[1] + Val1[2] * Val2[2]
Rsqrt( Val )Compute the reciprocal squareroot of Val. Val needs to have a single component swizzle (.r, .g, .b, .a). The result will be replicated to all 4 channels. Pseudo Code: 1/sqrt(Val[n]); where n = 0,1,2,3 depending on swizzle.
Together with the dp3 function, the Rsqrt function can be used for normalizing vectors. See examples below. WARNING: Results for zero and negative input values are undefined and those input values should be avoided. Behaviour for those input values is graphics card and API (DirectX) version dependend.


Write Masks

Output registers can have optional write masks that will prevent channels from being overwritten. If no write mask is specified, all channels will be written to. A write mask is appended to the output register using a dot and then consists of the channels (r, g, b, a) that should be written to. When multiple channels are specified, they need to be in rgba order. All 16 possible write mask combinations are supported (since v2.5.0.6). Examples of most common write masks:
OutputRegisterNo Mask (all channels will be written to)
OutputRegister.rgbaSame as above (all channels will be written to)
OutputRegister.rgbOnly RGB channels will be written to
OutputRegister.rOnly red channel will be written to
OutputRegister.gOnly green channel will be written to
OutputRegister.bOnly blue channel will be written to
OutputRegister.aOnly alpha channel will be written to
OutputRegister.rgOnly red and green channel will be written to
Instead of r, g, b, a, one can also use x, y, z, w.

Swizzle

Input registers can have optional swizzles. Swizzles will control how input channels are re-routed. There are three type of swizzles.

A) No swizzle specified: Channels are directly routed (r' = r; g' = g; b' = b; a' = a).
InputRegisterNo swizzle (input is RGBA)

B) Single swizzle specified: Channels are replicated from a single input channel.
InputRegister.rThe first component (Red channel) will be replicated to all channels, for example say the temporary register tmp0 represents: {0.4, 0.3, 0.7, 2.0}. tmp0.r would then represent: {0.4, 0.4, 0.4, 0.4}
InputRegister.gThe second component (Green channel) will be replicated to all channels, for example say the temporary register tmp0 represents: {0.4, 0.3, 0.7, 2.0}. tmp0.g would then represent: {0.3, 0.3, 0.3, 0.3}
InputRegister.bThe third component (Blue channel) will be replicated to all channels, for example say the temporary register tmp0 represents: {0.4, 0.3, 0.7, 2.0}. tmp0.b would then represent: {0.7, 0.7, 0.7, 0.7}
InputRegister.aThe fourth component (Alpha channel) will be replicated to all channels, for example say the temporary register tmp0 represents: {0.4, 0.3, 0.7, 2.0}. tmp0.a would then represent: {2.0, 2.0, 2.0, 2.0}

C) Full swizzle specified: Four channel identifiers need to be specified. There are many combinations possible, here are a couple of examples:
InputRegister.bgraBlue and Red channels are swapped (r' = b; g' = g; b' = r; a' = a)
InputRegister.rgbaIdentical with no swizzle specified (r' = r; g' = g; b' = b; a' = a)
InputRegister.rrrrIdentical with single swizzle .r (r' = r; g' = r; b' = r; a' = r)
InputRegister.rrraFirst three color channels take color from red channel, while alpha channel is kept (r' = r; g' = r; b' = r; a' = a)
...There are many more possible combinations
Instead of r, g, b, a, one can also use x, y, z, w.

Examples

Example 1

Result.rgb = Tex0;
Result.a = Tex1;
The RGB channels will receive the RGB channels from the texture in Unit 0.
The A channel will receive the A channel from the texture in Unit 1.

Example 2

Tmp0 = Add(Tex0, Tex1);
Result.rgb = Lerp(Tex2.a, Tmp0, Tex2);
Result.a = 1.0;
The texel of the first and second texture will be added, the result will be interpolated between the third texture, using the A channel of the third texture as the interpolation control. The A channel of the result will be set to 1.

Example 3

Result.rgb = Tex0;
Result.a = Dp3(Tex1, 0.33333);
The RGB channels of the result will receive the RGB channels of the first texture. The A channel of the result will receive the average luminosity of the RGB channels of the second texture.

Example 4

Result = Tex0;
Specular = Tex1;
Emission = Mul (Color.a, {0,0,1,0});
The RGBA channels of the result will receive the RGBA channels of the first texture. The second texture is used as a specular mask for the specular lighting. The intensity of the RGBGen alpha mode is used to control a blueish glow effect, using the emission output register.

Example 5

Tmp0 = dp3(Tex0, Tex0);
Tmp0 = add(Tmp0, 0.0001); // avoid zero for rsqrt
Tmp0.r = rsqrt(Tmp0.r);
Result.rgb = Mul(Tex0, Tmp0.r);
Result.a = Tex0.a;
The RGB channels of the first texture are normalized (sqrt(r*r + g*g + b*b) = 1) and set for color channels of the result. The alpha channel of first texture is directly forwarded to the result.