Wednesday, February 29, 2012

Triple Switch!

That's gonna be the title for my new movie. . . Or the managerial move I make that loses my kid the little league championship game. . . Or a utility node in Maya.
The triple switch is such a weird node. . . Not sure I've ever seen anyone use it in production. But in certain circumstances it can be useful and on rare occasions can be very handy indeed.
Basically the idea of the node is that you can create a geometry-specific attribute of a single material. So, fer example, you could put one shader on 100 objects and have, say, the color be different for each object. Still using just one shader, mind you. . . the color is different for each object, but all the other attrs of the shaders behave as normal. Here's the vid about how that works.

Maya: Using the Triple Switch utility node from zeth willie on Vimeo.

It's kind of hard to imagine getting the most out of this node without some coding, since by definition the node becomes more useful the more stuff (and therefore connections) you have in your scene. . . Here's the code I used to set up the basic random color thingy from the video. To use it, hook the triple switch up to the material, apply the material shader to the objects. Select the TS, then the objects and run the code. Obviously, if you want different results (which you should, probably) then adjust whatever parameters and values you'd like:
//triple switch should already be created and connected to shader
//select triple then objects
string $sel[] = `ls -sl`;
int $sizeObj = size($sel);
string $triple = $sel[0];

for ($i=1; $i<$sizeObj; $i++) {
    string $me = $sel[$i];
    select -r $me;

    //these are the per object attrs we're adding
    addAttr -at "float" -k 1 -ln "redMult";
    addAttr -at "float" -k 1 -ln "greenMult";
    addAttr -at "float" -k 1 -ln "blueMult";

    //these are the random values for those attrs
    float $rRand = `rand .75 1.25`;
    float $gRand = `rand .75 1.25`;
    float $bRand = `rand .75 1.25`;

    //assign the values to the attrs
    setAttr ($me + ".redMult") $rRand;
    setAttr ($me + ".greenMult") $gRand;
    setAttr ($me + ".blueMult") $bRand;

    //connect the objects to the TS
    string $child[] = `listRelatives -c $me`;
    string $shape = $child[0];
    string $meShape = ($shape + ".instObjGroups[0]");

    connectAttr ($meShape) ($triple+".input["+($i-1)+"].inShape");

    //connect the attrs to the TS at the same index the obj is connected
    connectAttr ($me + ".redMult") ($triple+".input["+($i-1)+"].inComp1");
    connectAttr ($me + ".greenMult") ($triple+".input["+($i-1)+"].inComp2");
    connectAttr ($me + ".blueMult") ($triple+".input["+($i-1)+"].inComp3");


EDIT: Here's the code I used to create the distance setup. Seems a bit wonky to do things this way, but it more or less works . . . The point here being that since you can use an attr to drive the triple switch, you can control that attr with any of the usual (or unusual means) you control attrs in Maya. For this one you'll need to create a ".tightenFalloff" attr on the measure object first. (BTW, you actually don't need to drive an attr with the distance numbers, you could just plug them into the triple switch directly, but that's a little mysterious for anyone who might use this. The point, again, was simply to illustrate that you don't need colors to drive the triple switch):
//color by distance
//triple switch should already be created and connected to shader
//select triple then measure object, then textured objects
string $sel[] = `ls -sl`;
int $sizeObj = size($sel);
string $triple = $sel[0];
string $mObject = $sel[1];

for ($i=2; $i<$sizeObj; $i++) {
    string $me = $sel[$i];
    string $meDist = $me + "Distance";
    select -r $me;
    addAttr -at "float" -min 0 -max 1 -k 1 -ln "distance";
    //create distance node
    shadingNode -asUtility distanceBetween -n $meDist;
    connectAttr ($me + ".worldMatrix") ($meDist + ".inMatrix1");
    connectAttr ($mObject + ".worldMatrix") ($meDist + ".inMatrix2");
    connectAttr ($me + ".rotatePivotTranslate") ($meDist + ".point1");
    connectAttr ($mObject + ".rotatePivotTranslate") ($meDist + ".point2");
    //connect the distance to a mult node
    shadingNode -asUtility multiplyDivide -n ($me+"mult");
    connectAttr ($mObject+".tightenFalloff") (($me+"mult")+".input1X");  
    connectAttr ($meDist+".distance") (($me+"mult")+".input2X");
    //connect the dist node to the attr on the object
    connectAttr (($me+"mult")+".outputX") ($me+".distance");

    string $child[] = `listRelatives -c $me`;
    string $shape = $child[0];
    string $meShape = ($shape + ".instObjGroups[0]");

    connectAttr ($meShape) ($triple+".input["+($i-2)+"].inShape");

    connectAttr ($me + ".distance") ($triple+".input["+($i-2)+"].inComp1");
    connectAttr ($me + ".distance") ($triple+".input["+($i-2)+"].inComp2");
    connectAttr ($me + ".distance") ($triple+".input["+($i-2)+"].inComp3");



  1. Nice Post! But what would you use it for? Well I can think of a couple of tutorials that have used it.
    I think there is a gnomon grape tutorial for mental ray that uses it to get some organic random different shades of purple for the grapes. Another tutorial where the windows of a city building that use different grime maps to add variation. Also a tutorial for a train destinations board or something of that ilk. where the triple switch is used to control the letters. So it definately has it's uses.

  2. Cheers Mark! The grape tutorial is probably the one I mention in the video. Didn't know it was Gnomon . . . But grime maps and swapping out letters on a texture is pretty much right in line with how I would imagine one would use it, just haven't seen anyone else use it in person.


  3. As always, love your tutorial. Very useful and it gives me a bunch of idea around this Triple Switch node. About the last part of tutorial, can you make more clearly explain about how you connect the distance node to color of the triple switch node?. I really don't get it.
    And can you share us the script you in there as well?

  4. Hello,

    Thanks for the useful tutorial.

    I'm trying to come up with a way to blend between normal maps (and possibly associate them with blendshapes). I mistakenly thought I could use a layered texture, but, so far I have not had any success.

    Do you think the triple switch could be used for this purpose (create a shader with normal maps that could be blended between)? Any ideas how to set such a network up?

  5. @Illunara-
    Thanks! re: the distance stuff . . . The basic idea is that if you can get attrs into the triple switch as color (or whatever shader parameter you want), you can then use any other means in Maya to generate or control THOSE attr. So in this case, on each cube I create a distance node measuring how far the cube is from the sphere. Then I plug that resulting distance into the distance attr on the cube. I use that attr to drive the color (same in all three channels) of the triple switch for that particular piece of geo. So each cube measures and records its own distance and the triple switch uses that to determine each cubes color. I'll edit the post and put that code up there too.
    I've been asked a few times about normal maps and animated textures. Doubt triple switch is the most useful way to do that. If I have any time this week maybe I'll so a tutorial on that stuff. . .

  6. Thanks much... I'll check back to see if you come up with anything.

  7. @Zeth
    thanks for the quick reply. Looking forward to your next tutorial :d

  8. back in the patch modeling days, we used Triple Shading Switch so you could use multi textures over the patches with one shader for ALL.

    we stopped using it when we switched to mental ray, cause it was extremely slow. ( which I think most people did as well)

    also moving from nurbs patch models to poly models made it less needed, since you didn't have multi surface models anymore.


  9. Aha! Figured there were some more technical uses for this guy. And yeah, it does tend to get pretty slow.
    Thanks Steve . . .


  10. Hi first of all great tip and script.
    I have a small problem, when i execute the second part of your script than everything is ok and works. But when i save the scene and reopen the scene again the script dont work anymore. Any tip how make this work ?

    thanks in advance

  11. Hi Willie ,thanks for your great posts, I was wondering if you could explain triple switch connections with a mia_X shader because it does not work the same as a blinn....I need the texture maps into the diffuse and specular maps into refl_color of the mia.

    1. Hey gooseneck-

      Not really too hard (though it does stink that maya doesn't deal w/ mental ray that well). What you have to do is assign a blinn or lambert to your objects and add the triple switch to the color, fer intance. Then add the objects into the triple switch ("add surfaces" or whatever the button is called). Then assign your shaders per object in the triple sw, then you can just assign the triple switch into the diffuse of your mia-x. Then right-click blinn, select objects w/ shader, then right-click the mia, assign shader to selected.
      The triple switch actually works fine with any thing it's just *recognizing* the surfaces from the shading group that it can't do, for some reason. Hope that helps. Thanks for the question, sorry for the delay in answering!