For this assignment, we were tasked with using RenderMan Shading Language commands to communicate with various RIB options and attributes to generate a more customizable shader.


Basic RSL shaders do not have any knowledge of any object or scene parameters and simply operate by a set of input parameters to determine the output shading. However, RSL also has a number of commands to query more information from the scene. This exercise will discuss attribute() and option().

THE attribute() COMMAND

Recall that the RIB scene description contains all of the objects in the scene, along with more scene and global information and options (see The RenderMan Interface Specification v3.2 for more information):



Option "user" "string user_param" ["UserVal"]
#Other setup information
WorldBegin
	AttributeBegin
		Attribute "visibility" "int camera" [1]
		Attribute "identifier" "string name" ["Object01"]
		Sphere -1 -1 1 360
	AttributeEnd
WorldEnd

The value of these attributes can be accessed by RSL shaders by using the attribute() command. This is a useful way to retrieve object-specific information without having to pass it in as a shader parameter per object. In this exercise, I will retrieve the object name and assume there is a number at the end (as a giant mass of object instances would in Maya). Next, the name strings are queried to generate a number of random cases and perturb the shader color, without having to manually set the random color per object.



colorMod = -1;
//attribute() will return 0 if attribute is not found
if(attribute("identifier:name", attrName) == 1) {
	//do things with the attrName
	//in this case we will test for numbers at the end
	if(match("0$", attrName)) colorMod = 0;
	else if(match("1$", attrName)) colorMod = 1;
	else if(match("2$", attrName)) colorMod = 2;
	else if(match("3$", attrName)) colorMod = 3;
	else if(match("4$", attrName)) colorMod = 4;
	else if(match("5$", attrName)) colorMod = 5;
	else if(match("6$", attrName)) colorMod = 6;
	else if(match("7$", attrName)) colorMod = 7;
	else if(match("8$", attrName)) colorMod = 8;
	else if(match("9$", attrName)) colorMod = 9;
}
//do something with colorMod to generate an output color

The limitations to this approach are obvious - if the object name does not include a number, colorMod will return -1. To use a shader with such hard-coded information requires proper naming conventions be followed between the shader artist and whoever is configuring the Maya scene or RIB file.


Originally, I planned to build some kind of hash for the object string to create a (mostly) unique value for each string based on the ascii values that I could then use to modify the color. Once I discovered the limitations of RSL's built in string operations, I decided against this implementation as I saw no approach but to code a utility function to traverse and test every character of the strings, which would be quite slow. Such a function, if efficient, would remove the requirement that object names end in a number, but would also remove some control from the shader artist.

THE option() COMMAND

Additionally, shader attributes can be controlled in a more global way by the use of the option() command. Global options would tend to control more broad, scene-wide changes.



Option "user" "string season" ["fall"]
#Other setup information
WorldBegin
	#Scene info here
WorldEnd

In this example, a user option is set in the RIB file to determine the season. When dealing with foliage, similar user options can be used to affect large-scale change to all objects through collaborative shading, while user attributes can be used to create variation at the object-to-object level.


seasonMod = 0;
//option() will return 0 if attribute is not found
if(option("user:season", optName) == 1) {
	//do things with the optName
	if(optName == "spring") seasonMod = 0;
	else if(optName == "summer") seasonMod = 1;
	else if(optName == "fall") seasonMod = 2;
	else if(optName == "winter") seasonMod = 3;
}
//use seasonMod to affect the output
//can also check attributes to combine effects

APPLYING COLLABORATIVE SHADING

In this exercise, I used the attribute() command as part of a Slim template for controlling leaf colors on a tree. The template checks the number at the end of the object name and mixes between two user-set colors. I opted for this approach rather than shifting the hue programmatically to provide more user control and to avoid the occasional strange result (blue leaves).


Once the Slim template was created, I built a node network centered around the All-Purpose shader and utilized the ColorByElement template to drive the overall color of the leaves. The shader was then applied to polygonal tree leaf geometry and rendered.