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
															

