Professional Documents
Culture Documents
2012/11/16
Contents
1 Creating your first Arnold shader 1
1.1 Pre-requisites . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1.1 Installing a C++ Compiler . . . . . . . . . . . . . . . . 1
1.1.2 Installing Arnold SDK . . . . . . . . . . . . . . . . . . 1
1.1.3 Installing MtoA . . . . . . . . . . . . . . . . . . . . . . 1
1.1.4 Installing MtoA Troubleshooting . . . . . . . . . . . 2
1.1.5 Installing MtoA and Arnold in separate folders (Ad-
vanced) . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Creating a shader . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3 Using the shader in Maya . . . . . . . . . . . . . . . . . . . . 7
1.3.1 Adding Maya Metadata to your shader with a meta-
data file . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.3.2 Choosing a Maya ID for the shader . . . . . . . . . . . 8
1.3.3 Creating the Maya interface for your shader . . . . . . 8
1.3.4 Where to place your files . . . . . . . . . . . . . . . . . 9
1.3.5 Adding Maya Metadata to your shader in its source
code (Advanced) . . . . . . . . . . . . . . . . . . . . . 10
i
1 Creating your first Arnold shader
1.1 Pre-requisites
To be able to create Arnold shaders, you need these three components in-
stalled: a C++ compiler, the Arnold SDK and the MtoA plugin.
Windows
In order to install MtoA in windows, you will have to download the
required version package, for example: MtoA-0.20.0-win64-2012.exe,
and you will have two options:
1. You can use the installer with the two component MtoA for
Maya 20XX and MtoA for Maya 20XX Env Variables se-
lected.
2. You can use the installer with only the component MtoA for
Maya 20XX selected. In this case you will need to add these
definitions to your Maya.env file
Edit this file:
C:\Users\<User_Name>\Documents\maya\20XX-x64\Maya.env
and add these definitions:
1
MAYA_RENDER_DESC_PATH = C:\solidangle\mtoadeploy\20XX
PATH = %PATH%;C:\solidangle\mtoadeploy\20XX\bin
Now, when you start Maya, you will be able to load MtoA in the Plug-in
Manager.
Of course you can select another folder that suits you better, so for the rest
of the tutorial, we will assume that you have set the environment variable
MTOA PATH to the path where the MtoA plugin is located. In this case, you
should have to execute this command:
set MTOA_PATH="C:\solidangle\mtoadeploy\20XX"
If MtoA plugin does not appear atumatically in the Maya Plug-in Man-
ager, try these steps:
If you can see the MtoA plugin, but it does not load
If you can see the MtoA plugin but it does not load or it crashes when
trying to load, try these steps:
2
3. Remove (and backup) your Maya preferences folder:
C:\Users\<User_Name>\Documents\maya\20XX-x64\prefs
4. Try MtoA using a clean Maya installation
5. Try MtoA using a clean configured computer
Windows
2. Add the Arnold bin folder (%ARNOLD PATH\bin) you want to use to the
PATH environment variable.
Linux
1. Follow the same steps as in Windows, but the Arnold libs to remove in
the first step would be: libai.so.
2. Add the Arnold bin folder (%ARNOLD PATH\bin) you want to use to the
LD LIBRARY PATH environment variable.
Mac
1. Follow the same steps as in Windows, but the Arnold libs to remove in
the first step would be: libai.dylib and libOpenImageIO.dylib.
2. Add the Arnold bin folder (%ARNOLD PATH\bin) you want to use to the
DYLD LIBRARY PATH environment variable.
3
1.2 Creating a shader
To create your first Arnold shader, write the following code in a file called
simpleShader.cpp.
simpleShader.cpp
1 #include <ai.h>
2 #include <cstring>
3 // A Simple Shader
4 AI_SHADER_NODE_EXPORT_METHODS(SimpleMethods);
5
6 namespace
7 {
8
9 enum SimpleParams { p_color };
10
11 };
12
13 node_parameters
14 {
15 AiParameterRGB("constantColor", 0.7f, 0.7f, 0.7f);
16 }
17
18 node_initialize
19 {
20 }
21
22 node_update
23 {
24 }
25
26 node_finish
27 {
28 }
29
30 shader_evaluate
31 {
32 AtColor color = AiShaderEvalParamRGB(p_color);
33 sg->out.RGB = color;
34 }
35
36 node_loader
37 {
38 if (i > 0)
39 return false;
40
41 node->methods = SimpleMethods;
42 node->output_type = AI_TYPE_RGB;
43 node->name = "simple";
4
44 node->node_type = AI_NODE_SHADER;
45 strcpy(node->version, AI_VERSION);
46 return true;
47 }
Windows
Open a Visual Studio command prompt and execute the following com-
mand:
cl /LD /I %ARNOLD_PATH%\include /EHsc simpleShader.cpp
/link /LIBPATH:%ARNOLD_PATH%\lib ai.lib
Of course you can also create a Visual Studio project and adjust the
settings to specify the include folder, the lib folder, add the ai.lib, and
set it to create a .dll file
Linux
Execute the following commands in a console:
g++ -o simpleShader.os -c -fPIC -D_LINUX
-I$ARNOLD_PATH/include simpleShader.cpp
g++ -o simpleShader.so -shared simpleShader.os
-L$ARNOLD_PATH/bin -lai
Congratulations! You have created your first shader. Now, to check if Arnold
can recognize it, execute the following command:
%ARNOLD_PATH%\bin\kick -l <path_to_shader> -info simple
If you execute this command in the same folder where your shader is located,
the -l <path_to_shader> is not required.
To test how the shader is working, you can use the following simple scene:
5
simpleScene.ass
1 ### Scene using "simple" shader
2
3 options
4 {
5 name options
6 camera "camera"
7 }
8
9 persp_camera
10 {
11 name camera
12 matrix
13 1 0 0 0
14 0 1 0 0
15 0 0 1 0
16 0 0 30 1
17 }
18
19 sphere
20 {
21 name pSphereShape2
22 center 0 0 0
23 radius 10
24 shader "simpleShader"
25 }
26
27 simple
28 {
29 name simpleShader
30 constantColor 1 0 0
31 }
Figure 1: simpleScene
6
If the shader cannot be loaded, you will get this warning:
00:00:00 10MB WARNING | [ass] line 28: node "simple" is not installed
And this image:
simpleShader.mtd
1 # simple 0x00070000
2
3 [node simple]
4 maya.name STRING "mySimple"
5 maya.id INT 0x00070000
6 maya.classification STRING "shader/surface"
7 maya.output_name STRING "outColor"
8 maya.output_shortname STRING "out"
9
10 [attr constantColor]
11 maya.name STRING "color"
7
1.3.2 Choosing a Maya ID for the shader
From Autodesk help:
For plug-ins that will forever be internal to your site use the
constructor that takes a single unsigned int parameter. The nu-
meric range 0 - 0x7ffff (524288 ids) has been reserved for such
plug-ins.
The example plug-ins provided with Maya in the plug-in de-
velopment kit will use ids in the range 0x80000 - 0xfffff (524288
ids). If you customize one of these example plug-ins, you should
change the id to avoid future conflicts.
Plug-ins that are intended to be shared between sites will need
to have a globally unique id. The Autodesk Developer Network
(ADN) will provide such ids in blocks of 256. You will be assigned
one or more 24-bit prefixes. Once this has been obtained, use the
MTypeId constructor that takes 2 unsigned int parameters. The
prefix goes in the first parameter, and you are responsible for
managing the allocation of the 256 ids that go into the second
parameter.
For the purposes of this text, we will use IDs begining from 0x70000, but feel
free to use the IDs that could suit you better. Also, if you are developing
a quality shader that you would like to share with the MtoA comunity, feel
free to ask us for an ID granted by Autodesk to MtoA.
mySimpleTemplate.py
1 import pymel.core as pm
2 import mtoa.utils as utils
3 import mtoa.ui.ae.utils as aeUtils
4 from mtoa.ui.ae.shaderTemplate import ShaderAETemplate
5
6
7 class AEmySimpleTemplate(ShaderAETemplate):
8
9 def setup(self):
10 # Add the shader swatch to the AE
11 self.addSwatch()
8
12
13 self.beginScrollLayout()
14
15 # Add a list that allows to replace the shader for other one
16 self.addCustom(message, AEshaderTypeNew,
17 AEshaderTypeReplace)
18
19 # Begins a "Color Section"
20 self.beginLayout("Color Section", collapse=False)
21 # Add a control for the "constatColor" shader attribute
22 self.addControl("constantColor", label="Color",
23 annotation="Constant Color")
24
25 self.endLayout()
26
27 # include/call base class/node attributes
28 pm.mel.AEdependNodeTemplate(self.nodeName)
29
30 # Add Section for the extra controls not displayed before
31 self.addExtraControls()
32 self.endScrollLayout()
In the addControl method, the first argument is the shader attribute name
or the maya.name metadata of that attribute. So in this case the parameter
could be: constantColor or color.
Note that the name of the defined class should be: AE<shader_name>Template
and the file name <shader_name>Template.py where <shader_name> is the
value of the maya.name metadata of the shader.
Compiled Shader
This is the shader you compiled, and it will be responsible for the shader
behaviour. In this example, it is simpleShader.dll in Windows. You
can copy it to: %MTOA PATH%\shaders\ or to any other folder that is
included in the environment variable %ARNOLD PLUGIN PATH%
Metadata File
This is the file where all the metadata information is located. This will
9
add information that Maya needs about the shader. The name of this
file must be thes same as the shader, but with a .mtd extension. In
this example its name will be simpleShader.mtd . This file will have
to be copied to the same folder where the Compiled Shader is located.
Template File
This is the file where the Maya Template for this shader is defined. The
name of this file and the class name inside it has to follow the rules from
previous section. In this example it is mySimpleTemplate.py . This
file can be copied to this folder: %MTOA PATH%\scripts\mtoa\ui\ae\
or to any other folder that is included in the environment variable
%MTOA TEMPLATE PATH%
Now, with everything in its correct place, when you use the aiSimple shader
in Maya, you will be able to see this Attribute Editor for it.
10
mayaShader.cpp
node_parameters
{
// Node metadata
AiMetaDataSetStr(mds, NULL, "maya.name", "aiSimple");
AiMetaDataSetInt(mds, NULL, "maya.id", 0x00070000);
AiMetaDataSetStr(mds, NULL, "maya.classification", "shader/surface");
AiMetaDataSetStr(mds, NULL, "maya.output_name", "outColor");
AiMetaDataSetStr(mds, NULL, "maya.output_shortname", "out");
11
2 Creating a Shader Loader
If you write several shaders, it could be useful to create a loader that will
load all of them from the same library file. It is also possible to create a
metadata file with all the metadata information from all the shaders.
myShader1.cpp
1 #include <ai.h>
2
3 AI_SHADER_NODE_EXPORT_METHODS(MyShader1Mtd);
4
5 namespace
6 {
7
8 enum MyShader1Params { p_color };
9
10 };
11
12 node_parameters
13 {
14 AiParameterRGB("color1", 0.0f, 0.0f, 0.0f);
15 }
16
17 node_initialize
18 {
19 }
20
21 node_update
22 {
23 }
24
25 node_finish
26 {
27 }
28
29 shader_evaluate
30 {
31 AtColor color = AiShaderEvalParamRGB(p_color);
32 sg->out.RGB = color;
33 }
12
myShader2.cpp
1 #include <ai.h>
2
3 AI_SHADER_NODE_EXPORT_METHODS(MyShader2Mtd);
4
5 namespace
6 {
7
8 enum MyShader2Params { p_color };
9
10 };
11
12 node_parameters
13 {
14 AiParameterRGB("color2", 1.0f, 1.0f, 1.0f);
15 }
16
17 node_initialize
18 {
19 }
20
21 node_update
22 {
23 }
24
25 node_finish
26 {
27 }
28
29 shader_evaluate
30 {
31 AtColor color = AiShaderEvalParamRGB(p_color);
32 sg->out.RGB = color;
33 }
13
6
7 enum{
8 MY_SHADER_1 = 0,
9 MY_SHADER_2
10 };
11
12 node_loader
13 {
14 switch (i)
15 {
16 case MY_SHADER_1:
17 node->methods = MyShader1Mtd;
18 node->output_type = AI_TYPE_RGB;
19 node->name = "myShader1";
20 node->node_type = AI_NODE_SHADER;
21 break;
22
23 case MY_SHADER_2:
24 node->methods = MyShader2Mtd;
25 node->output_type = AI_TYPE_RGB;
26 node->name = "myShader2";
27 node->node_type = AI_NODE_SHADER;
28 break;
29
30 default:
31 return false;
32 }
33
34 strcpy(node->version, AI_VERSION);
35
36 return true;
37 }
When you have these files, you can compile them in a similar way to a single
shader:
In Windows
Open a Visual Studio command prompt and execute the following:
cl /LD /I %ARNOLD_PATH%\include /EHsc
loader.cpp myShader1.cpp myShader2.cpp
/link /LIBPATH:%ARNOLD_PATH%\lib ai.lib
Or you can compile each shader separately and then link them to the
loader:
cl /c /I %ARNOLD_PATH%\include /EHsc myShader1.cpp
cl /c /I %ARNOLD_PATH%\include /EHsc myShader2.cpp
cl /LD /I %ARNOLD_PATH%\include /EHsc loader.cpp
14
myShader1.obj myShader2.obj
/link /LIBPATH:%ARNOLD_PATH%\lib ai.lib
Now you can, as with your first shader, use kick with the -info option to
check if they have been correctly created and loaded by Arnold.
node: myShader1
type: shader
output: RGB
parameters: 2
filename: <path_to_shader>/loader.dll
version: X.X.X.X
node: myShader2
type: shader
output: RGB
parameters: 2
filename: <path_to_shader>/loader.dll
version: X.X.X.X
Finally, to make these shaders availables to MtoA, you should copy the com-
piled file to this location:
%MTOA_PATH%\shaders\
15
loader.mtd
1 # myShader1 0x00070001
2 # myShader2 0x00070002
3
4 [node myShader1]
5 maya.name STRING "aiMyShader1"
6 maya.id INT 0x00070001
7 maya.classification STRING "shader/surface"
8 maya.output_name STRING "outColor"
9 maya.output_shortname STRING "out"
10
11 [attr color1]
12 maya.name STRING "color"
13
14 [node myShader2]
15 maya.name STRING "aiMyShader2"
16 maya.id INT 0x00070002
17 maya.classification STRING "shader/surface"
18 maya.output_name STRING "outColor"
19 maya.output_shortname STRING "out"
20
21 [attr color2]
22 maya.name STRING "color"
Then copy this file to the same folder where the compiled shaders are:
%MTOA PATH%\shaders\
Remember that the metafile name should be the same as the compiled shader;
if for example, your loader is called loader.dll, the metadata file must be
loader.mtd.
16
3 Adding parameters to your shader
Here we will add more different parameters to our shader and they will be
integrated to the Maya interface. This will allow us to have an easy way to
modify our shader in Maya.
parametersShader.cpp
1 #include <ai.h>
2
3 AI_SHADER_NODE_EXPORT_METHODS(ParametersShaderMtd);
4
5 namespace
6 {
7
8 enum ParametersShaderParams { p_int, p_uint, p_bool, p_float,
9 p_RGB, p_vector, p_point, p_point2,
10 p_string, p_matrix, p_enum };
11
12 const char* enum_list[] =
13 {
14 "First value",
15 "Second value",
16 "Third value",
17 NULL
18 };
19
20 };
21
22 node_parameters
23 {
24 AtMatrix id;
25 AiM4Identity(id);
26
27 AiParameterInt("IntParam", 0);
28 AiParameterUInt("UIntParam", 0);
29 AiParameterBool("BoolParam", 0);
30 AiParameterFlt("FltParam", 0.0f);
31 AiParameterRGB("RGBParam", 1.0f, 0.0f, 0.0f);
32 AiParameterVec("VecParam", 1.0f, 1.0f, 1.0f);
33 AiParameterPnt("PntParam", 0.5f, 0.5f, 0.5f);
34 AiParameterPnt2("Pnt2Param", 0.7f, 0.7f);
17
35 AiParameterStr("StrParam", "");
36 AiParameterMtx("MtxParam", id);
37 AiParameterEnum("EnumParam", 0, enum_list);
38 AiParameterArray("ArrayParam", AiArray(0, 0, AI_TYPE_RGB));
39 }
40
41 node_initialize
42 {
43 }
44
45 node_update
46 {
47 }
48
49 node_finish
50 {
51 }
52
53 shader_evaluate
54 {
55 AtColor color = AiShaderEvalParamRGB(p_RGB);
56 sg->out.RGB = color;
57 }
You can see that node parameters of different types are defined, but only the
RGBParam is used.
Now, to add the shader to the loader, you only need to add this code to the
previous Loader.cpp file from the previous section:
loader.cpp
extern AtNodeMethods* ParametersShaderMtd;
enum{
MY_SHADER_1 = 0,
MY_SHADER_2,
PARAMETERS_SHADER
};
...
case PARAMETERS_SHADER:
node->methods = ParametersShaderMtd;
node->output_type = AI_TYPE_RGB;
node->name = "parametersShader";
node->node_type = AI_NODE_SHADER;
break;
You will be able to compile the loader again as described in the previous sec-
tion, check that Arnold can load the shader correctly, and copy the compiled
18
shader to the correct folder so that Maya can use it. If you do so, you will
discover that it is usable but not well integrated in Maya.
loader.mtd
25 [node parametersShader]
26 desc STRING "Arnold shader to test parameters."
27 maya.name STRING "aiParametersShader"
28 maya.id INT 0x00070003
29 maya.classification STRING "shader/surface"
30 maya.output_name STRING "outColor"
31 maya.output_shortname STRING "out"
32
33 [attr IntParam]
34 desc STRING "Integer parameter."
35 min INT -100
36 max INT 100
37 softmin INT -10
38 softmax INT 10
39 default INT -10
40 maya.shortname STRING "int"
41 maya.name STRING "integer"
42 [attr UIntParam]
43 desc STRING "UInteger parameter."
44 min INT 0
45 max INT 100
46 softmin INT 0
47 softmax INT 10
48 default INT 0
49 maya.shortname STRING "uint"
50 maya.name STRING "uinteger"
51 [attr BoolParam]
52 desc STRING "Bool parameter."
53 default BOOL True
54 maya.shortname STRING "bl"
55 maya.name STRING "bool"
19
56 [attr FltParam]
57 desc STRING "Float parameter."
58 min FLOAT 0
59 max FLOAT 10
60 softmin FLOAT 0
61 softmax FLOAT 1
62 default FLOAT 0.5
63 maya.shortname STRING "flt"
64 maya.name STRING "float"
65 [attr RGBParam]
66 desc STRING "RGB parameter."
67 maya.name STRING "color"
68 maya.shortname STRING "cl"
69 [attr VecParam]
70 desc STRING "Vector parameter."
71 maya.name STRING "vector"
72 maya.shortname STRING "vec"
73 [attr PntParam]
74 desc STRING "Point parameter."
75 maya.name STRING "point"
76 maya.shortname STRING "pnt"
77 [attr Pnt2Param]
78 desc STRING "2D Point parameter."
79 maya.name STRING "point2"
80 maya.shortname STRING "pnt2"
81 [attr StrParam]
82 desc STRING "String parameter."
83 maya.name STRING "string"
84 maya.shortname STRING "str"
85 default STRING "empty"
86 [attr MtxParam]
87 desc STRING "Matrix parameter."
88 maya.name STRING "matrix"
89 maya.shortname STRING "mtx"
90 [attr EnumParam]
91 desc STRING "Enumeration parameter."
92 default INT 1
93 maya.name STRING "enumeration"
94 maya.shortname STRING "enum"
95 [attr ArrayParam]
96 desc STRING "Color Array parameter."
97 maya.name STRING "colorarray"
98 maya.shortname STRING "carray"
This describes attributes that will be used for the Maya representation of
the parameters as name, shortname, slider limits, descriptions and default
values.
20
3.2.2 Adding a Maya template
The last task to do is to create a Maya template for this shader. This is similar
to the one created in the first section: self.addControl(parameterName,
label="Parameter Label"). But adding the rest of the controls. The cor-
rect control for each attribute will be created automatically.
Create an aiParametersShaderTemplate.py file in
%MTOA_PATH%\scripts\mtoa\ui\ae\ or in any folder that is definded in
%MTOA_TEMPLATE_PATH%
aiParametersShaderTemplate.py
1 import pymel.core as pm
2 from mtoa.ui.ae.shaderTemplate import ShaderAETemplate
3
4 class AEaiParametersShaderTemplate(ShaderAETemplate):
5 def setup(self):
6 self.addSwatch()
7 self.beginScrollLayout()
8 self.addCustom(message, AEshaderTypeNew,
9 AEshaderTypeReplace)
10
11 self.beginLayout("Parameters list", collapse=False)
12 self.addControl("integer", label="Integer Param")
13 self.addControl("uinteger", label="Unsigned Int Param")
14 self.addControl("bool", label="Bool param")
15 self.addControl("float", label="Float param")
16 self.addControl("color", label="Color param")
17 self.addControl("vector", label="Vector param")
18 self.addControl("point", label="Point param")
19 self.addControl("point2", label="2D Point param")
20 self.addControl("string", label="String param")
21 self.addControl("matrix", label="Matrix param")
22 self.addControl("enumeration", label="Enumeration param")
23 self.addControl("colorarray", label="Color Array param")
24 self.endLayout()
25
26 pm.mel.AEdependNodeTemplate(self.nodeName)
27
28 self.addExtraControls()
29 self.endScrollLayout()
When you use the ParametersShader in Maya, you will be able to see this
Attribute Editor for it.
21
Figure 4: ParametersShader Template
Now you will be able to configure your shaders input parameters from Maya.
22
self.addControl("float", label="Float param")
...
To this:
aiParametersShaderTemplate.py
...
self.addControl("uinteger", label="Unsigned Int Param")
self.addControl("bool", label="Bool param 1")
self.addControl("bool", label="Bool param 2")
self.addControl("float", label="Float param")
...
aiParametersShaderTemplate.py
...
self.addControl("uinteger", label="Unsigned Int Param")
self.beginNoOptimize()
self.addControl("bool", label="Bool param 1")
self.addControl("bool", label="Bool param 2")
self.endNoOptimize()
self.addControl("float", label="Float param")
...
23
3.2.4 Method called when an attribute is changed
Sometimes we may need a certain action to be performed everytime an at-
tribute is changed. For example to evaluate that the introduced value is
correct.
Lets imagine we require that the value of the uinteger attribute is always
greater or equal to the integer attribute. We can try to achieve thit with
the following code.
aiParametersShaderTemplate.py
import pymel.core as pm
import maya.cmds as cmds
from mtoa.ui.ae.shaderTemplate import ShaderAETemplate
class AEaiParametersShaderTemplate(ShaderAETemplate):
def checkInteger(self, nodeName):
intAttr = self.nodeAttr(integer)
uintAttr = self.nodeAttr(uinteger)
intValue = cmds.getAttr(intAttr)
uintValue = cmds.getAttr(uintAttr)
if intValue > uintValue:
cmds.setAttr(uintAttr,intValue)
def setup(self):
self.addSwatch()
self.beginScrollLayout()
self.addCustom(message, AEshaderTypeNew,
AEshaderTypeReplace)
Now everytime that that the integer attribute is updated, if it has a value
greater that the uinteger value, this will be increased to be equals to that
value. But, of course, if you decrease the uinteger parameter, this could be
lower than the integer one. To deal also with this case we can easily write
this code:
aiParametersShaderTemplate.py
import pymel.core as pm
import maya.cmds as cmds
from mtoa.ui.ae.shaderTemplate import ShaderAETemplate
class AEaiParametersShaderTemplate(ShaderAETemplate):
def checkInteger(self, nodeName):
24
intAttr = self.nodeAttr(integer)
uintAttr = self.nodeAttr(uinteger)
intValue = cmds.getAttr(intAttr)
uintValue = cmds.getAttr(uintAttr)
if intValue > uintValue:
cmds.setAttr(uintAttr,intValue)
def checkUinteger(self, nodeName):
intAttr = self.nodeAttr(integer)
uintAttr = self.nodeAttr(uinteger)
intValue = cmds.getAttr(intAttr)
uintValue = cmds.getAttr(uintAttr)
if intValue > uintValue:
cmds.setAttr(intAttr,uintValue)
def setup(self):
self.addSwatch()
self.beginScrollLayout()
self.addCustom(message, AEshaderTypeNew,
AEshaderTypeReplace)
aiParametersShaderTemplate.py
import pymel.core as pm
import maya.cmds as cmds
import mtoa.ui.ae.utils as aeUtils
from mtoa.ui.ae.shaderTemplate import ShaderAETemplate
class AEaiParametersShaderTemplate(ShaderAETemplate):
def changeBool(self, nodeName):
aeUtils.arnoldDimControlIfFalse(nodeName, "float", "bool")
def setup(self):
25
self.addSwatch()
self.beginScrollLayout()
self.addCustom(message, AEshaderTypeNew,
AEshaderTypeReplace)
aiParametersShaderTemplate.py
import pymel.core as pm
import maya.cmds as cmds
import mtoa.ui.ae.utils as aeUtils
from mtoa.ui.ae.shaderTemplate import ShaderAETemplate
class AEaiParametersShaderTemplate(ShaderAETemplate):
def changeColor(self, nodeName):
redAttr = self.nodeAttr(colorR)
redValue = pm.getAttr(redAttr)
dim = not (redValue > 0)
pm.editorTemplate(dimControl=(nodeName, "float", dim))
def setup(self):
self.addSwatch()
self.beginScrollLayout()
self.addCustom(message, AEshaderTypeNew,
AEshaderTypeReplace)
26
3.2.6 Creating a custom control
MtoA will automatically create a control for the attributes based on its type,
but sometimes you may need more flexibility and create a custom control for
a certain attribute. For example, lets imagine that the string attribute in
the previous example is used to point to a file. Then you may want a control
with a button that shows a file explorer so you can enter the file name in a
more intuitive way. Here is an example to get that behavior:
aiParametersShaderTemplate.py
import pymel.core as pm
import maya.cmds as cmds
from mtoa.ui.ae.shaderTemplate import ShaderAETemplate
class AEaiParametersShaderTemplate(ShaderAETemplate):
def filenameEdit(self, mData) :
attr = self.nodeAttr(string)
cmds.setAttr(attr,mData,type="string")
def setup(self):
self.addSwatch()
self.beginScrollLayout()
self.addCustom(message, AEshaderTypeNew,
AEshaderTypeReplace)
27
3.2.7 Summary of Template Commands
Here we will summarize all the previously used template methods and add
some new ones:
addSwatch
As previously seen, this command creates a Swatch in the Attribute
Editor that shows a preview of the Shader.
beginScrollLayout endScrollLayout
Begins and ends a Vertical Scroll Layout where you can place sections
and attributes.
beginLayout endLayout
Begins and ends a Layout. You can give it a name and define if it will
be collapsed or not by default.
self.beginLayout("Section Name", collapse=False)
addControl
Creates a control for a shader attribute. It automatically creates the
correct control depending on the type of attribute. You can define a
label and a changeCommand.
self.addControl("attrname", label="My Attr",
changeCommand=self.changeAttr])
addCustom
Creates a custom control for a shader attribute.
self.addCustom(attrName, newMethod, replaceMethod)
addSeparator
Adds a separator in the layout.
beginNoOptimize endNoOptimize
Stops and starts again the layout space optimization.
addBumpLayout
Creates a section that will allow you to connect a bump normal map-
ping to the shader.
addExtraControls
All extra attributes will be grouped in an Extra Controls section
28
addCustom(message,AEshaderTypeNew,AEshaderTypeReplace)
Creates a Type scroll list where you can change the shader type
of the node.
pm.mel.AEdependNodeTemplate(self.nodeName)
Creates the Node Behavior section in the shader template.
29
4 Creating a Light Filter Shader
To create this shader you will need, as previously, a source code file, a loader,
a metadata and a template. We will take a look at them here.
simpleLightFilter.cpp
1 #include <ai.h>
2
3
4 AI_SHADER_NODE_EXPORT_METHODS(SimpleLightFilterMtd);
5
6 enum simpleLightFilterParams {
7 p_intensity
8 };
9
10 node_parameters
11 {
12 AiParameterFlt("Intensity", 0.0f);
13 }
14
15 node_initialize
16 {
17 }
18
19 node_update
20 {
21 }
22
23 node_finish
24 {
25 }
26
27 shader_evaluate
28 {
29 float intensity = AiShaderEvalParamFlt(p_intensity);
30 sg->Liu = sg->Liu*intensity;
31 }
Now, to add the shader to the loader, you only need to add this code to the
previous Loader.cpp file from the previous sections:
30
loader.cpp
...
extern AtNodeMethods* SimpleLightFilterMtd;
enum{
MY_SHADER_1 = 0,
MY_SHADER_2,
PARAMETERS_SHADER,
SIMPLE_LIGHT_FILTER
};
...
case SIMPLE_LIGHT_FILTER:
node->methods = SimpleLightFilterMtd;
node->output_type = AI_TYPE_RGB;
node->name = "simpleLightFilter";
node->node_type = AI_NODE_SHADER;
break;
...
You will be able to compile the light filter and the loader again as described
in the previous sections, check that Arnold can load the shader correctly, and
copy the compiled shader to the correct folder (as if it was a normal shader)
so that Maya can use it.
loader.mtd
101
102 [node simplyLightFilter]
103 maya.name STRING "aiSimplyLightFilter"
104 maya.id INT 0x00070004
105 maya.classification STRING "light/filter"
106 maya.lights STRING "pointLight spotLight"
107
108 [attr Intensity]
109 maya.name STRING "lightIntensity"
31
110 softmin FLOAT 0
111 softmax FLOAT 10
112 default FLOAT 1
aiSimpleLightFilterTemplate.py
1 import pymel.core as pm
2 from mtoa.ui.ae.shaderTemplate import ShaderAETemplate
3
4 class AEaiSimpleLightFilterTemplate(ShaderAETemplate):
5 def setup(self):
6 self.beginScrollLayout()
7
8 self.beginLayout("Parameters", collapse=False)
9 self.addControl(lightIntensity, label="Light Intensity")
10
11 self.endLayout()
12
13 pm.mel.AEdependNodeTemplate(self.nodeName)
14 self.addExtraControls()
15 self.endScrollLayout()
Now, when you create a type of light that is accepted by this light filter,
you will be able to add this light filter in the Light Filters section in the
Arnold section of the light:
32
Figure 7: Light Filters Menu
33