How can I create my own shader node?

As you could see in the shader workflow description, there are a lot of maya nodes which need a translation. And you will sometimes need to extend the currently existing shaders or add new ones.
At the moment only maya internal shader nodes are supported, no mentalray and no custom ones can be recognized, but they will sometime.
Okay, lets see how you can create an additional maya shading node. To keep it simple we will create a reverse node.

Create a simple nurbs plane in maya, apply a lambert shader and map a file node to the color attribute of the lambert shader. My result looks like this:



The hypershade network is made of three nodes:



Now we want to reverse the colors with the help of a revese node. If we simply put this node between the file node and the lambert shader this way:



the image disappears from our rendering.



The reason is that because the reverse shading node is not yet supported, the hypershade translation stops at this point and gives a default color for the lambert shader, what is gray.

Manipulating the shaderDefinitions.txt file

From the shader workflow text, you know that the shading node consits of two parts, the definition in the shaderDefnitions.txt file and the vex source code.
Lets see how to add the shader to the current shaderDefinitions file. Open the file (from the ressources subdirectory of your plugin installation) in a text editor.

Before we add the new node we need to know some informations:
Normally the nodes are called exactly as the node is called with a small difference. e.g our node is called in the interface reverse. Internally the type is kReverse. With a small 'k' and the first letter as uppercase. This is true for all nodes as much as I know.

The input attribute is an color value, called input, and the output is a color value as well called output.
With these informations we can build our node:

shader_start
 name:kReverse  
 inatt:input:color:0,0,0
 outatt:output:color
shader_end

As you can see, the output has no default value because it is calclulated automatically. Write this into the shaderDefinitions.txt file. Then we try it in maya. What should happen now is that the node is recognized by the translator, but because we dont have an shader node include file for the reverse node, the compiler will fail. Lets test it..... and indeed we get the expected problems.

In the output window you see the compiler errors like:
error cpp error: "....../shaders/lambert2SG_surface.vfl":5 Unable to include "Reverse.h"
and others. The output image looks the same as before, without texture. If you have a look at the created shader source in the current project/mantra/scenename/shaders/lambert1SG_surface.vfl, then you can read something like this:
// code created by reverse1
vector reverse1_input = file1_outColor;
vector reverse1_output;
Reverse(reverse1_input,reverse1_output);
Looks as if the node is recognized correctly, but we dont have the source file yet. Lets create it now.

Createing the shader node source file:
Create a new text file in the shaderIncludes directory called reverse.h.

Now we create a vex function. Have a look at the houdini vex documentation for the structure of a vex function. Important: The arguments in the vex function must have the exact the same order and type as defined in the shaderDefinitons file. And also important: Every shader node gets the current uvs as very first argument as a vector. The uv argument is inserted automatically by the translator so it does not have to appear in the shaderDefinitions file.
void Reverse(vector uv; vector input; vector output)
{
}
The name of the function is the name of the internal maya name without the lowercase 'k'. If we use this for rendering now, the shader should work, but it will produce a black image because the default of output
is black. In vex there is no difference between color and vector so all tree-value variables are vectors.

The good thing here is that you dont need to restart maya now, because the include file is read every time from disk. This way you can simply modify your source code, rerender and see the result. Here our result is black or undefined what is not what we want.

The reverse node in maya simply takes the input and substracts it from 1.0. Thats all. Lets modify our source code this way:
void Reverse(vector uv; vector input; vector output)
{
 vector one = {1.0, 1.0, 1.0};
 output = one - input;
}
And do a new rendering. And voilá, this is our result:



Thats all. Its quite easy and you dont need any compilation or other fancy things. Try it.