Custom Passes in 3Delight

Quite often in CG when working with multiple passes – you want  to do different things depending on what type of pass your rendering – the two more common ways to do this are to either create two different shaders and change the assignment for each pass or to write a shader which is able to figure out what type of pass it is and act appropriately.

For example in a bake pass you typically want to bake out attributes which aren’t dependant on the position or direction of the camera  – this includes things like diffuse/ambient shading, subsurface scattering and ambient occlusion data  – which can all be baked out and reused on objects. Only when the position and direction of the objects or lights changes does the scene need to be rebaked.

In order to control this in 3Delight you can use the RiMel commands to setup custom RIB commands which can be read by your shaders. The following MEL commands are placed inside a PreWorldMEL attribute on the render pass itself.

RiOption -n "user" -p "pass" "string" "bake";

RiAttribute -n "cull" -p "hidden" "integer" "0";
RiAttribute -n "cull" -p "backfacing" "integer" "0";
RiAttribute -n "dice" -p "rasterorient" "integer" "0";

This will output the following commands into the RIB file.

Option "user" "string pass" [ "bake" ]
Attribute "cull" "integer hidden" [ 0 ]
Attribute "cull" "integer backfacing" [ 0 ]
Attribute "dice" "integer rasterorient" [ 0 ]

Then within the shader I can query what pass I’m currently rendering and do something appropriate for that type of pass.

uniform string passtype = "";
option( "user:pass", passtype );
if (passtype == "bake")
    // Do something here

By default 3Delight also exports out the name of the render pass to an attribute called delight_renderpass_name – this is name of your render pass inside Maya. You can query that name using the following RSL. Obviously using this method highly depends on what you call your passes – the following shading code wouldn’t work if the render pass was called anything other than “bake” – for example if you wanted to do multiple bake passes for within the same scene like separating out animated bakes (which require multiple frames) from static bakes (things which don’t move which can be stored in one frame).

string passtype = "";
option ("user:delight_renderpass_name",passtype);
if (passtype == "bake")
	// Do something here	

HSV Adjustments

The following function can be used to do Hue, Saturation and Value adjustments on a colour input.

color hsvAdjust (color input; float hue, saturation, value;)
    color toHSV = ctransform("RGB", "HSV", input);
    toHSV *= color (hue, saturation, value);
    return ctransform ("HSV", "RGB", toHSV);

For example to de-saturate a colour input, you would use the following…

color myColour = (0.5, 0.2, 0.4);
myColour = hsvAdjust (myColour, 0, 0, 1);

Gamma Correction

The following function shows how to gamma correct a float using RSL. g is the value you wish to correct and f is the gamma value.

float gammacorrect(float g; float f;)
	return pow(g, f);

To use this inside a shader you would use something like this…

float myValue = 0.5;
float gamma = 2.2;
float myFloat = gammacorrect(myValue, gamma);

The result of which would be 0.5^2.2 = 0.217637641. To correct a colour input, you would need a function like so. c is our colour input and f is the gamma value to use. The major difference here is the use of setcomp in order to operate on each colour channel individually.

color gammacorrect(color c; float f;)
	color d;
	setcomp(d, 0, pow(comp(c,0), f));
	setcomp(d, 1, pow(comp(c,1), f));
	setcomp(d, 2, pow(comp(c,2), f));
	return d;

Note that Renderman is smart enough to recognise that although we have two functions with the same name called “gammacorrect” – they are returning two different types of data – one being a floating point number the other being a colour. As long as the variable you are passing the data into – in this case “myColour” – is of the correct type, it’ll know what to do with it.

color myValue = 0.5;
float gamma = 2.2;
color myColour = gammacorrect(myValue, gamma);