RMS
Using PrimVars with HyperShade


return to main index

topics
    adding a float primvar
    adding a color primvar
    adding a string primvar



Introduction

This tutorial provides three examples of how primvars can be setup and used with RMS and HyperShade. The reader should refer to the tutorial RIB/RSL: Using PrimVars for basic information about primvars.

To use a primvar with a HyperShade material, such as Blinn, requires both the material (aka shader) and the geometry to which it is assigned to be setup correctly. The first example shows how a single instance of Blinn and a float primvar can be used to control the diffuse brightness of a grid of polygons. The second example demonstrates how a color primvar can be to used the control the coloration of a grid of polygons. The third example shows how a random selection of texture maps can be applied to a grid of polygons.



Example 1 - using a "float" primvar

Setting Up the Material

1    In HyperShade create an instance of Blinn and assign it to several surfaces.
2    In the Blinn attribute editor go to the "Attribute->RenderMan" menu and choose,
       "Manage TCL Expressions..."
3    Add the item named "Dc" as shown in figure 1 and "Close" the window.



Figure 1


4    Add the following TCL expression (figure 2)
        [mel "getAttr $OBJNAME.Dc"]
      The square brackets tell TCL to evaluate the getAttr MEL command.
      $OBJNAME will be substituted by TCL by the name of the current instance of Blinn.



Figure 2


      Alternatively, enter the name of the material directly without using TCL, for example,
        blinn2.Dc

5    Scroll to the "Common Material Attributes" tab,
      - connect the "Diffuse" parameter to a "Rman Prim Var Float" node.



Figure 3


6    Rename the "Rman Prim Var Float Attibute" to "Dc" as shown in figure 4.



Figure 4


The name "Dc" is arbitary but it is less confusing if it matches the name chosen from the "RenderMan TCL Expression Manager" window. The name of the node, currently "rmanPrimVarFloat1", need not be changed.


Setting Up the Surfaces

7    Copy and paste the MEL proc, shown in listing 1, into Maya's script window.
      Execute the script in order to load it into memory.

Listing 1


global proc addFloatPrimVar(string $shortname)
{
string $sel[] = `ls -sl`;
string $fullname = "rmanF" + $shortname;
for($current in $sel) {
    string $shapes[] = `listRelatives -s $current`;
    string $shape = $shapes[0];
    if(attributeExists($fullname, $shape) == 0) {
        addAttr -ln $fullname -nn $shortname -at double -k 1 $shape;
        }
    float $val = rand(0.35, 1.0);
    setAttr ($shape + ("." + $fullname)) $val;
    }
}


8    Select the surfaces to which Blinn was assigned,
      - execute the following script,
          addFloatPrimVar("Dc");
The Mel proc will add an attribute named "rmanFDc" to each of the selected surfaces and will then assign it a random value between 0.0 and 1.0. The name of the attribute consists of the prefix "rmanF" and the name given to the primvar in step 6.

When RfM outputs the rib data to the internal or the external version of prman it will "look" for custom attributes beginning with "rmanF". The prefix tells RfM to add a primvar, declared as a "constant float", to each surface. For example,

PointsGeneralPolygons [1] [4] [0 1 3 2] "P" [xyz data...] 
                    "constant float Dc" [0.5523]

Note the prefix acts only as a "hint" to RfM - it is not included in the name of the primvar.

9    Finally, render the scene.



Figure 5



Naming Conventions

Any name can be chosen in step 6, however, it must match the name of the attribute assigned to surfaces in step 8. For example, if "foo" was used in step 6 then "foo" must be used in step 8.



"Dc" & Blinn's Diffuse Parameter?

But how does the random value of the "Dc" primvar control the brightness of Blinn? To discover the answer use the MEL command "rman genrib". This will generate the rib files and shader(s) that would normally be used by the external version of prman. Go to the "renderman/PROJECT/shaders" directory and look for the compiled blinn material, for example, "blinn2_rfm.slo". Open a cmd (Windows) or shell (Linus/OSX) and cd to the "shaders" directory. Enter this command,
      sloinfo blinn2_rfm
Ensure the name of your instance of blinn matches the text shown above in red. The utility program "sloinfo" will list the parameters of the Blinn shader, one of which will be,
      "Dc" "parameter varying float" default value 0.00000
The "rmanPrimVarFloat1" node, added to the Diffuse parameter in step 6, has caused RfM to generate an instance of the Blinn shader with an external parameter, that "feeds" values to the Diffuse brightness and that matches the name of the primvar "bound" to each polyplane. Consequently, what ever value the primvar is given by the MEL script in step 7 will be the value that controls the brightness of the Diffuse color.



Example 2 - using a "color" primvar

Setting Up the Material

1    In HyperShade create an instance of Blinn and assign it to several surfaces.
2    In the Blinn attribute editor go to the "Attribute->RenderMan" menu and choose,
       "Manage TCL Expressions..."
3    Same as step 3 in the previous example, but select the item named "C".
4    Add the following TCL expression - the square brackets must be included.
        [mel "getAttr $OBJNAME.C"]
      Alternatively, directly enter the name of the instance of blinn, for example,
        blinn2.C
5    Scroll to the "Common Material Attributes" tab,
      - connect the "Color" parameter to a "Rman Prim Var Color" node.
6    Rename the "Rman Prim Var Color Attibute" to "C".


Setting Up the Surfaces

7    Copy and paste the MEL proc, shown in listing 2, into Maya's script window.
      Execute the script in order to load it into memory.

Listing 2


global proc addColorPrimVar(string $shortname)
{
string $sel[] = `ls -sl`;
string $fullname = "rmanC" + $shortname;
for($current in $sel) {
    string $shapes[] = `listRelatives -s $current`;
    string $shape = $shapes[0];
    if(attributeExists($fullname, $shape) == 0) {
        addAttr -ln $fullname -nn $shortname -at float3 -usedAsColor -k 1 $shape;
        addAttr -ln  "r" -at "float" -k 1 -p $fullname $shape;
        addAttr -ln  "g" -at "float" -k 1 -p $fullname $shape;
        addAttr -ln  "b" -at "float" -k 1 -p $fullname $shape;
        }
    float $r = rand(0.0, 1.0);
    float $g = rand(0.0, 1.0);
    float $b = rand(0.0, 1.0);
    setAttr ($shape + ("." + $fullname)) -type "double3" $r $g $b;
    }
}


8    Select the surfaces to which Blinn was assigned,
      - execute the following command,
          addColorPrimVar("C");
The procedure will add an attribute named "rmanCC" to each of the selected surfaces and will then assign it random rgb component values between 0.0 and 1.0. The name of the attribute consists of the prefix "rmanC" and the name given to the primvar in step 6.

When RfM outputs the rib data to the internal or the external version of prman it will "look" for custom attributes beginning with "rmanC". The prefix tells RfM to add a primvar, declared as a "constant color", to each surface. For example,

PointsGeneralPolygons [1] [4] [0 1 3 2] "P" [xyz data...] 
                    "constant color C" [0.520171 0.486881 0.625127]

Note the prefix acts only as a "hint" to RfM - it is not included in the name of the primvar.

9    Finally, render the scene.



Figure 6




Example 3 - using a "string" primvar

The workflow for strings is slightly different to floats and colors. Unlike the previous examples there is no need to use a "Rman Prim Var String" node because the shader parameter, "fileTextureName", is automatically "exposed" as a result of connecting a File node to Blinn's "Color" control. This example demonstrates how an arbitary number of images can be used as texture maps.

Setting Up the Material

1    In HyperShade create an instance of Blinn and assign it to several surfaces.
2    Connect a File node to the "Color" parameter.
3    Change the name from "file1" to "MAP".


Setting Up the Surfaces

4    Copy, paste and execute the MEL procs, shown in listing 3, in Maya's script window.
The proc named getTexnames() will read a text file containing the names of image files to be used for texturing. For example, suppose the Maya project directory has a file named "textureDB.txt" containing the following text.

    images/map1.tif
    images/map2.tif
    images/map3.tif
    images/map4.tif

Executing the following in the script window will echo the full paths to the images.

    getTexnames("textureDB.txt");

For example.

    /Users/mkesson/Documents/maya/projects/PrimVar/images/map1.tif
    /Users/mkesson/Documents/maya/projects/PrimVar/images/map2.tif
    /Users/mkesson/Documents/maya/projects/PrimVar/images/map3.tif
    /Users/mkesson/Documents/maya/projects/PrimVar/images/map4.tif

The proc named makeTextures(), when passed an array of image paths, will attempt to convert them to texures suitable for use with Pixar's prman. For example.

    string $paths[] = getTexnames("texturesDB.txt");
    makeTextures($paths);

After executing the code the images directory would contain the following textures.

    /Users/mkesson/Documents/maya/projects/PrimVar/images/map1.tif.tex
    /Users/mkesson/Documents/maya/projects/PrimVar/images/map2.tif.tex
    /Users/mkesson/Documents/maya/projects/PrimVar/images/map3.tif.tex
    /Users/mkesson/Documents/maya/projects/PrimVar/images/map4.tif.tex

However, if "textureDB.txt" had contained a list of prman textures the proc will not use txmake ie. it will not take any action.

5    Running the final proc addStringPrimVar() will randomly assign the textures to a primvar associated with each surface in the scene. For example.

    string $paths[] = getTexnames("texturesDB.txt");
    if(size($paths) > 0) { 
        makeTextures($paths);
        addStringPrimVar("MAP_fileTextureName", $paths);
        }

The text shown in red ("fileTextureName") is the name of the shader parameter that would normally be assigned the path to a texture. However, because primvars are being used its value remains an empty string.



Listing 3


global proc string[] getTexnames(string $database)
{
int     $n = 0;
string  $result[];
string  $projPath = `workspace -q -rootDirectory`;
string  $dbpath = $projPath + $database;
int     $fileid = fopen($dbpath, "r");
string  $line = fgetline($fileid);
  
while(size($line) > 0) {
    $result[$n++] = $projPath + $line;
    $line = fgetline($fileid);
    }
fclose($fileid);
return $result;
}
//------------------------------------------------------------
global proc string[] makeTextures(string $paths[])
{
string   $srcpath, $texpath, $cmd;
string   $result[];
int      $n = 0;
for($srcpath in $paths) {
    $srcpath = strip($srcpath);
    if(!`filetest -r $srcpath`) {
        print("Error: \"" + $srcpath + "\" does not exist.\n");
        continue;
        }
    if(!endsWith($srcpath, ".tex")) {
        $texpath = $srcpath + ".tex";
        $cmd = "txmake " + $srcpath + " " + $texpath;
        system($cmd);
        if(!`filetest -r $texpath`) {
            print("Unable to run \"txmake\" - check your \"PATH\" environment " +
                  "points to RMS/rmantree/bin.\n");
            }
        else
            print("Info: " + $cmd + "\n"); 
        $result[$n++] = $texpath;
        }
    }
return $result;
}
//------------------------------------------------------------
global proc addStringPrimVar(string $shortname, string $items[])
{
string  $sel[] = `ls -sl`;
string  $fullname = "rmanS" + $shortname;
for($item in $sel) {
    string $shapes[] = `listRelatives -s $item`;
    string $shape = $shapes[0];
    if(attributeExists($fullname, $shape) == 0) {
        addAttr -ln $fullname -nn $fullname -dt "string" $shape;
        }
    int     $index = rand(0.0, size($items));
    string     $value = $items[$index];
    setAttr ($shape + ("." + $fullname)) -type "string" $value;
    }
}




Figure 7







© 2002- Malcolm Kesson. All rights reserved.