From BlenderWiki

Jump to: navigation, search

Adding a Shader Node

There are a few files you need to edit in order to add a shader. We will add a math node in this tutorial.

source/blender/blenkernel/BKE_node.h

In this file you need to add #define for your new node you will see them listed with a line like this

#define SH_NODE_OUTPUT 1

Go to the bottom, add your node using the naming convention

SH_NODE_NAME
and then number it +1 to the last added node. So for our tutorial we will add:
#define SH_NODE_MATH 112


source/blender/blenkernel/intern/node_shaders.c

In this file the main part of the definition for our node layout is done. First we define the input sockets. The define SOCK_VALUE means that it is a value socket. This can be SOCK_VALUE, SOCK_RGBA or SOCK_VECTOR. for each input socket there needs to be an entry. See the other nodes in the file for examples. This structure needs the {-1, 0, ""} as a sentinel.

/* **************** Value Math ******************** */ 
static bNodeSocketType sh_node_math_in[]= { 
	{ SOCK_VALUE, 1, "Value 1", 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f}, 
	{ SOCK_VALUE, 1, "Value 2", 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f}, 
	{ -1, 0, "" } 
};

Not unlike the input sockets are the output sockets:

static bNodeSocketType sh_node_math_out[]= { 
	{ SOCK_VALUE, 0, "Value Out", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, 
	{ -1, 0, "" } 
};

The syntax of bNodeSocketType is documented in the file as:

/* SocketType syntax: 
   socket type, max connections (0 is no limit), name, 4 values for default, 2 values for range */

Next is the function that evaluates the input of the node and provides the output. The values for the sockets are accessed through the in and out arrays. The index of in or out being the socket # and primarily using the vec member to get the values off of it. Please be aware that this example has no protection for divide by zero. The variable node->custom1 will be set in the next file.

static void node_shader_exec_math(void *data, bNode *node, bNodeStack **in, 
bNodeStack **out) 
{ 
	/* stack order in: fac, col1, col2 */ 
	/* stack order out: col */ 
	float val1= in[0]->vec[0]; 
	float val2= in[1]->vec[0]; 
	switch(node->custom1){ 
 
	case 0: // Add 
		out[0]->vec[0] = val1 + val2; 
		break; 
	case 1: // Subtract 
		out[0]->vec[0] = val1 - val2; 
		break; 
	case 2: // Multiply 
		out[0]->vec[0] = val1 * val2; 
		break; 
	case 3: // Divide 
		out[0]->vec[0] = val1 / val2; 
	break; 
	} 
}

and the node definition.

static bNodeType sh_node_math= { 
	/* type code   */ SH_NODE_MATH, 
	/* name        */ "Math", 
	/* width+range */ 80, 40, 120, 
	/* class+opts  */ NODE_CLASS_OPERATOR, NODE_OPTIONS, 
	/* input sock  */ sh_node_math_in, 
	/* output sock */ sh_node_math_out, 
	/* storage     */ "", 
	/* execfunc    */ node_shader_exec_math 
};

You will also need to add this node definition to the node_all_shaders[] array at the bottom of the file before the NULL entry.

&sh_node_math

source/blender/src/drawnode.c

If you node needs nothing other than its inputs to generate its output, you do not need to add anything to this file. Otherwise you will need to add any special controls here. In our case we want to add a pulldown for the math operation to do. If you notice we are using the &node->custom1 variable to store the pulldown option. You will need to return the height that these widgets will take up as well.

static int node_shader_buts_math(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) 
{ 
	if(block) { 
		uiBut *bt; 
		/* blend type */ 
		bt=uiDefButS(block, MENU, B_NODE_EXEC,  "Add %x0|Subtract %x1|Multiply %x2 |Divide %x3", butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, &node->custom1, 0, 0, 0, 0, ""); 
		uiButSetFunc(bt, node_but_title_cb, node, bt); 
	} 
	return 20; 
}

Then in the node_shader_set_butfunc function you need to add a case for your shader type and a call to the function that you just created that will make the menu options.

	case SH_NODE_MATH: 
		ntype->butfunc= node_shader_buts_math; 
		break;

After all this your node *should* work. Although I have probably left something out.