Abstract
- This project is a study in C++ programming techniques to develop an custom pattern node called “SideMask“.
- In addition, it covers creating a Maya interface for the shader using a template Python script from Arnold.
- The current implementation of the SideMask node allows an artist to:
- Apply two colors to a surface – one color for the front side and a second color for the back side.
- Swap the front/back side colors
- Perform a cross-dissolve of the two colors
Algorithm
/*
maya/projects/arnold/src_c++/dd_SideMask.cpp
*/
#include
#include
#include "utilities.h"
AI_SHADER_NODE_EXPORT_METHODS(SampleMethods);
namespace {
enum paramIndex { k_front_color, k_rear_color, k_swap, k_cross_dissolve};
};
node_parameters {
AiParameterRGB("frontColor", 0.7f, 0.7f, 0);
AiParameterRGB("rearColor", 0.7f, 0, 0);
AiParameterBool("swap", 0);
AiParameterFlt("cross_dissolve", 0);
}
shader_evaluate {
AtRGB front = AiShaderEvalParamRGB(k_front_color);
AtRGB rear = AiShaderEvalParamRGB(k_rear_color);
bool swap = AiShaderEvalParamBool(k_swap);
float dissolve = AiShaderEvalParamFlt(k_cross_dissolve);
// incoming direction of the "camera ray", already
// normalized, but it must be reversed so that it is
// tail-to-tail with the surface normal.
// Geometric surface normal, but we have to normalize
// the vector otherwise we get the wrong angle (as the
// cosine) when we use the dot product.
float dot = AiV3Dot(-(sg->Rd), AiV3Normalize(sg->Ng));
AtRGB a, b;
if(dot < 0) {
a = (swap) ? front : rear;
b = (swap) ? rear : front;
}
else
{
a = (swap) ? rear : front;
b = (swap) ? front : rear;
}
sg->out.RGB() = mix(a, b, dissolve);
}
node_loader {
if (i > 0)
return false;
node->methods = SampleMethods;
node->output_type = AI_TYPE_RGB;
node->name = "ddFrontRear";
node->node_type = AI_NODE_SHADER;
strcpy(node->version, AI_VERSION);
return true;
}
// The remaining macros can be left "empty"
node_initialize { }
node_update { }
node_finish { }
Instead of having to write a Mix function in each coding project, a utility header file “utilities.h” was created. This allows us to define the functions and declarations which can be reused for multiple coding project, thus minimizing the potential for errors.
To use make use of that header file, we need to: write in a #include directive in every .cpp file or other header file that requires that declaration. The #include directive inserts a copy of the header file directly into the .cpp file prior to compilation.
Notice in line 6 of the above C++ code that we do so via ‘#include “utilities.h” ‘. To learn more, visit docs.microsoft.com.
/*
maya/projects/arnold/src_c++/utilties.h
*/
AtRGB mix(AtRGB a, AtRGB b, float alpha){
return a*(1-alpha) +b *alpha;
}
# This .mtd file is intended for use with Maya. If your shader will be used by
# Houdini the "style" of the .mtd can be set in Preferences->Languages-Arnold SDK.
#
# This file is automatically updated by Cutter when its corresponding shader
# is compiled.
[node ddFrontRear]
maya.id INT 15
maya.name STRING "ddFrontRear"
maya.classification STRING "Utility"
[attr frontColor]
maya.name STRING "frontColor"
# desc STRING ""
[attr rearColor]
maya.name STRING "rearColor"
# desc STRING ""
[attr swap]
maya.name STRING "swap"
# desc STRING ""
[attr cross_dissolve]
maya.name STRING "cross_dissolve"
# desc STRING ""
min FLOAT 0
max FLOAT 1
# softmin FLOAT 0
# softmax FLOAT 10
Template Python File
# maya/projects/arnold/ddFrontRearTemplate.py
import pymel.core as pm
import mtoa.utils as utils
import mtoa.ui.ae.utils as aeUtils
from mtoa.ui.ae.shaderTemplate import ShaderAETemplate
# notice the name of the class must be AEtemplate
class AEddFrontRearTemplate(ShaderAETemplate):
def setup(self):
# Add the shader swatch to the AE
self.addSwatch()
self.beginScrollLayout()
# Add a list that allows to replace the shader for other one
self.addCustom('message', 'AEshaderTypeNew', 'AEshaderTypeReplace')
# Begins a "Color Section"
self.beginLayout("Color Section", collapse=True)
self.addControl("frontColor", label="Front Color", annotation="Front Color")
self.addControl("rearColor", label="Rear Color", annotation="Rear Color")
# Begins a "Swap Dissolve"
self.beginLayout("Swap Dissolve", collapse=True)
self.addControl("swap", label="swap", annotation="swap")
self.addControl("cross_dissolve", label="Cross Dissolve",
annotation="Dissolves between front and rear colors")
self.endLayout()
# include/call base class/node attributes
pm.mel.AEdependNodeTemplate(self.nodeName)
# Add Section for the extra controls not displayed before
self.addExtraControls()
self.endScrollLayout()
How to Install
Referencing the python file
- Open your Maya Environment file located in: ~/Library/Preferences/Autodesk/maya/2020/
- Add this line at the end: MTOA_TEMPLATES_PATH = $HOME/Documents/maya/projects/arnold
- Save the file
Conclusion
As interesting as Shader Development is, I find that it is a shame that I will not being using this skill set in my future employment or Motion Design career. One of thing I asked myself when selecting courses to take at SCAD is: “Can I learn this outside of school after I graduate?” Technically yes, but it would be immensely difficult due to lack of allocation of resources, time, and effort as this is quite niche and advanced topic. Taking a ten-week course allows one to focus and deeper on an expertise or subject matter, and come out with a substantial research or portfolio piece.
That said, this course and study will serve as a testimony to how different disciplines can inform a creative practice. Only time will tell how “useful” this study was in hindsight, or maybe not at all which is just as perfectly fine.