final render image

VSFX 755 - Procedural 3D Shader Programming

Renderman RSL Conditional Shader


Project Summary:
Write an RSL shader that uses conditional statements to alter a surface's attributes based upon some varying input.

Results:
Click on the image to the right to see a final render.

The Brief

A simple application of this shader would utilize the trailing number on the name of each object in a Maya scene. I generated a simple arrangement using several hundred poly planes, keeping the default name of each since they end in varying numbers. The shader is written such that if a plane's name ends in 1 it is assigned a set color and opacity, if it ends in 2 it receives a different color and opacity, and so on for all ten digits (0-9).

Sample Images

Click on the images below to see simple demos of variations of the shader described below.

Example render 1 Example render 2 Example render 3 Example render 4 Example render 5 Example render 6

Building the Arrangement

I created a basic poly plane, used duplicate special to arrange it in a ring, duplicated the ring and turned it 90 degrees to the first to make a spherical group. I then made a volume emitter to produce a random arrangement of particles. I wrote the code at right to create duplicates of the poly groups and move them to each particle's position, giving me a sufficiently random arrangement.
$pCount = `getAttr particle1.count`;
print $pCount;

for($i=0; $i<=$pCount; $i++){
   $position = `getParticleAttr -at position particle1.pt[$i]`;
   $posX = $position[0];
   $posY = $position[1];
   $posZ = $position[2];
   select -r shardGrp1;
   duplicate -rr;
   move -a $posX $posY $posZ;
   rotate -r -os 0 `rand(360)` 0;
}

The Shader

At right you see the simple shader written to demonstrate the conditional capabilities of the RSL language. First a variable called 'str' is used to store the name of the current object, in this case the poly plane from Maya. The 'opacMod' variable is used as a modifier to the opacity calulations at the end of the shader. The conditonal part of the shader is simply a chain of 'if-else' statements that evaluate 'str' for a match. '1$' tells the match function to look for a 1 at the end of the string, i.e. the name of the object. The shader continues thru the chain until it finds a match and applies the color and opacity modification value found within. In this way, one shader can be applied wholesale to the group of poly planes and the shader will do all the heavy lifting randomizing and applying the attributes; much easier than creating 10 different shaders and applying them by hand to each poly plane. Variations to the color and opacity commands easily create the different versions you see above.
surface conditionalColor(float Kd = 1)
{
color surfcolor = 1;

string str;

float success = attribute("identifier:name", str);
float opacMod = 1.0;

if( match( "1$", str) ){
   surfcolor = color(1.0,0.6,0.0);
   opacMod = .1;
}else if( match( "2$", str) ){
   surfcolor = color(0.8,0.4,0.0);
   opacMod = .2;
}else if( match( "3$", str) ){
   surfcolor = color(0.6,1.0,0.4);
   opacMod = .3;
}else if( match( "4$", str) ){
   surfcolor = color(0.8,1.0,0.0);
   opacMod = .4;
}else if( match( "5$", str) ){
   surfcolor = color(0.6,0.6,0.0);
   opacMod = .5;
}else if( match( "6$", str) ){
   surfcolor = color(1.0,0.6,0.0);
   opacMod = .6;
}else if( match( "7$", str) ){
   surfcolor = color(0.4,0.6,0.0);
   opacMod = .7;
}else if( match( "8$", str) ){
   surfcolor = color(0.8,0.4,0.0);
   opacMod = .8;
}else if( match( "9$", str) ){
   surfcolor = color(0.4,0.6,0.0);
   opacMod = .9;
}else if( match( "0$", str) ){
   surfcolor = color(0.4,0.4,0.0);
   opacMod = 1.0;
}

normal n = normalize(N);
normal nf = faceforward(n, I);

Oi = Os * opacMod;

color diffusecolor = Kd * diffuse(nf);
Ci = Oi * Cs * surfcolor * diffusecolor;
}

Conclusions

That's about all it takes. This version is a very simple application of the conditional statements but the power it offers is obvious. Another version might use the position of the object, say it's Y-value, to determine how much of a specific color or opacity it receives. So long as an attribute could be passed in string form thru to the shader, it can be evaluated and used to alter the results.