Abstract
- This project is a study in C++ programming techniques to develop an Arnold Shader node for rendering in Autodesk Maya.
- The shader is written and compiled in Professor Malcolm Kesson’s custom written script editor called “Cutter“.
The following implementation of the pattern node allows an artist
to apply two colors to a surface based on a cutoff value in the ‘u’ texture direction.
use a menu to choose the ‘u’ or ‘v’ or radial transition of the colors,
use a slider to perform a color blending of the two colors.
Algorithm
/*
dd_redleft_pattern.cpp
5 April 2021
Based on the shader code given in the Arnold doc "Creating a Shader".
https://docs.arnoldrenderer.com/display/AFMUG/Creating+a+shader#CreatingaShader-1.1.1InstallingaC++Compiler
*/
#include
#include
#include
AI_SHADER_NODE_EXPORT_METHODS(SampleMethods);
AtRGB mix(AtRGB a, AtRGB b, float alpha){
return a*(1-alpha) +b *alpha;
}
namespace {
enum paramIndex { k_pat_color, k_base_color, k_offset, k_direction, k_blur, k_urepeats, k_vrepeats, k_ushift, k_vshift};
};
static const char* menu_items[] = { "U", "V","Radial", NULL };
node_parameters {
AiParameterRGB("patternColor", 0.7f, 0, 0);
AiParameterRGB("baseColor", 0.7f, 0.7f, 0);
AiParameterFlt("offset", 0.5);
AiParameterEnum("direction", 1, menu_items);
AiParameterFlt("blur", 0);
AiParameterFlt("u_repeats", 1); // u_repeats becomes "U Repeats"
AiParameterFlt("v_repeats", 1);
AiParameterFlt("u_shift", 0);
AiParameterFlt("v_shift", 0);
}
shader_evaluate {
AtRGB base = AiShaderEvalParamRGB(k_pat_color);
AtRGB pat = AiShaderEvalParamRGB(k_base_color);
float offset = AiShaderEvalParamFlt(k_offset);
int dir = AiShaderEvalParamEnum(k_direction);
float blur = AiShaderEvalParamFlt(k_blur);
float u_reps = AiShaderEvalParamFlt(k_urepeats);
float v_reps = AiShaderEvalParamFlt(k_vrepeats);
float u_shift = AiShaderEvalParamFlt(k_ushift);
float v_shift = AiShaderEvalParamFlt(k_vshift);
float blend;
// how all repeating patterns work...
float u_copy = fmod(sg->u * u_reps,1);
float v_copy = fmod(sg->v * v_reps,1);
//row
int row = floor(sg->v * v_reps);
bool rowIsEven = (row%2 ? 1:0);
if(rowIsEven)
u_copy = fmod((sg->u+u_shift) * u_reps,1);
//column
int col = floor(sg->u * u_reps);
bool colIsEven = (col%2? 1:0);
if(colIsEven)
v_copy = fmod((sg->v + v_shift) * v_reps,1);
//main
if(dir == 0)
//sg->out.RGB() = (sg->u >= offset) ? pat : base;
blend = AiSmoothStep(offset - blur, offset, u_copy);//sg->u);
else if(dir==1)
//sg->out.RGB() = (sg->v >= offset) ? pat : base;
blend = AiSmoothStep(offset - blur, offset, v_copy);//sg->v);
else
{
// find the distance of the current shading point(u,v)
// to the center of the uv space(0.5,0.5) and then
// test to the offset value.
float a = v_copy - 0.5;//sg->v -0.5;
float b = 0.5- u_copy;// 0.5- sg->u;
float hyp = sqrt(a*a+b*b);
blend = AiSmoothStep(offset - blur, offset, hyp);
}
sg->out.RGB() = mix(base,pat,blend);
}
node_loader {
if (i > 0)
return false;
node->methods = SampleMethods;
node->output_type = AI_TYPE_RGB;
node->name = "dd_redleft_pattern";
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 { }
# 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. Only edit the file immediately before publishing the shader. Make
# a backup of your edited .mtd file before recompiling the shader otherwise your
# edits will be over-written by Cutter.
[node dd_redleft_pattern]
maya.id INT 13
maya.name STRING "dd_redleft_pattern"
maya.classification STRING "Utility"
[attr patternColor]
maya.name STRING "patternColor"
# desc STRING ""
[attr baseColor]
maya.name STRING "baseColor"
# desc STRING ""
[attr offset]
maya.name STRING "offset"
# desc STRING ""
# min FLOAT 0
# max FLOAT 10
# softmin FLOAT 0
# softmax FLOAT 10
[attr direction]
maya.name STRING "direction"
# desc STRING ""
[attr blur]
maya.name STRING "blur"
# desc STRING ""
# min FLOAT 0
# max FLOAT 10
# softmin FLOAT 0
# softmax FLOAT 10
[attr u_repeats]
maya.name STRING "u_repeats"
# desc STRING ""
# min FLOAT 0
# max FLOAT 10
# softmin FLOAT 0
# softmax FLOAT 10
[attr v_repeats]
maya.name STRING "v_repeats"
# desc STRING ""
# min FLOAT 0
# max FLOAT 10
# softmin FLOAT 0
# softmax FLOAT 10
[attr u_shift]
maya.name STRING "u_shift"
# desc STRING ""
# min FLOAT 0
# max FLOAT 10
# softmin FLOAT 0
# softmax FLOAT 10
[attr v_shift]
maya.name STRING "v_shift"
# desc STRING ""
# min FLOAT 0
# max FLOAT 10
# softmin FLOAT 0
# softmax FLOAT 10
How to Install
- Download this zip file.
Unzip and put the files under your Maya script folder: Users/username/Documents/Maya/projects/arnold
- In Maya > Hypershade > Arnold Utility, the node will be present.
Conclusion
Shader development and C++ has always been a giant mystery to me despite having Javascript coding experience. In this project, I was able to learn that C++ is not very different from other coding languages; though there are the exceptions of Dynamic Memory and Pointers which I have yet to understand completely. I do believe that in the weeks to come, I will develop a solid proficiency with C++ much like what I did with my Python programming studies. — 6 April 2021