I wanted to render using the maya hardware renderer (very quick). For this to work colors need to be visible in the viewer. Triple Shading Switch in Maya is equivalent to Renderman per object primitive variable shading that I’ve used on other projects. Scroll down for alternative 3delight/Renderman version with pros and cons.
Some Notes.
1 – select objects and run ADD_PRIMITIVE_VAR() and then randomColors() or rampColors().
2 – attach shader with tripleShadingSwitch utility connected to color input
3 – in tripleShadingSwitch attributes “add surfaces”. objects will fill in the “InShape” column. Note the order is important as the “In Triple” column runs from 0 > from top. if wanting to match up in relation to ramp. This will be the case if you have picked the geo objects in the order you want when attaching the shader.
If you have a lot of objects you could use something like this
to ensure they are selected in numeric order. In this example “box21”, “box22” etc. Also useful for the rampColors() function.
def pickinorder(): for x in range(21,110): pm.select("box" + str(x),tgl=True)
4 – create ramp texture and adjust colors. Need to break UV coordinate in ramp to set/read as 0-1 value.
5 – Run tripleShader() to connect up the InShape to the InTriple.
If colors not showing in viewport?
make sure shading > use default shader is switched off, hardware rendering is on. if these are greyed out – it maybe a maya bug – change name of shader.
ADD PRIMITIVES FOR COLOR
import pymel.core as pm def ADD_PRIMITIVE_VAR(): selection = pm.ls(sl = True) for object in selection: objectShape = object.getShape() pm.select(objectShape); delightSurfaceColor = "delightSurfaceColor"; delightSurfaceColorR = "delightSurfaceColorR"; delightSurfaceColorG = "delightSurfaceColorG"; delightSurfaceColorB = "delightSurfaceColorB"; pm.addAttr(longName=delightSurfaceColor, at='double3'); pm.addAttr(longName=delightSurfaceColorR, parent=delightSurfaceColor,attributeType='double'); pm.addAttr(longName=delightSurfaceColorG, parent=delightSurfaceColor, attributeType='double'); pm.addAttr(longName=delightSurfaceColorB, parent=delightSurfaceColor, attributeType='double'); pm.setAttr (objectShape + ".delightSurfaceColor",keyable=True); pm.setAttr (objectShape + ".delightSurfaceColorR",keyable=True); pm.setAttr (objectShape + ".delightSurfaceColorG",keyable=True); pm.setAttr (objectShape + ".delightSurfaceColorB",keyable=True);
RANDOM COLORS FROM RAMP
right click over Uv Coord under UV Coordinates under ramp1 texture and “Break Connection”
def randomColors(): import random as rand import pymel.core as pm selection = pm.ls(sl = True) for object in selection: objectShape = object.getShape() whichColor = rand.uniform (0,1); pm.setAttr( "ramp1.uvCoord.vCoord",whichColor); vCoordColor = pm.getAttr( 'ramp1.outColor'); pm.setAttr (objectShape + ".delightSurfaceColor",vCoordColor);
COLOR FROM RAMP NORMALISED
In this technique the color for each object is picked from equal spaces through the 0-1 range of the ramp.
def rampColors(): selection = pm.ls(sl = True) # set objectMAX to number of objects objectMIN = 1 objectMAX = 9 objectNumber = 1 for object in selection: objectShape = object.getShape() pm.select(objectShape); normalized_Color = (float(objectNumber) - objectMIN) / (objectMAX - objectMIN)/1) colorNumber = normalized_Color; pm.setAttr( "ramp1.uvCoord.vCoord",colorNumber); vCoordColor = pm.getAttr( 'ramp1.outColor'); pm.setAttr (objectShape + ".delightSurfaceColor",vCoordColor) objectNumber += 1
Connect up triple Shading Switch to each object shape
def tripleShader(): selection = pm.ls(sl = True) objectCounter = 0 for object in selection: shape = object.getShape() mysource = (shape + ".instObjGroups[0]") pm.connectAttr (shape + '.delightSurfaceColorR', 'tripleShadingSwitch1.input' + "[" + str(objectCounter)+ "]" + ".inComp1") pm.connectAttr (shape + '.delightSurfaceColorG', 'tripleShadingSwitch1.input' + "[" + str(objectCounter) + "]" + ".inComp2") pm.connectAttr (shape + '.delightSurfaceColorB', 'tripleShadingSwitch1.input' + "[" + str(objectCounter) + "]" + ".inComp3") objectCounter = objectCounter + 1
If maya complains “Warning: line 1: Cannot add the following items to the set since the set has restrictions on membership:” then just force it
# FORCE SHADER ONTO OBJECTS change 'blinn5SG' to whatever shading group. selection = pm.ls(sl = True) for object in selection: pm.sets ('blinn5SG',forceElement=True,e=True);
Doing it in 3delight / Renderman with Primitive Variables
The same process with running the functions ADD_PRIMITIVE_VAR() and then randomColors() or rampColors() but in this case a RSL node is linked up to the shader. In Maya under Hypershade > utilities > Renderman Code
then under Shading pararmeters add in
“shader_input color SurfaceColor
output color o_outColor”
and under Shading Code
“o_outColor = SurfaceColor;”
then connect up color out of Renderman Code Utility to color input of shader
Example for Textures
import pymel.core as pm import random as rand def ADD_PRIMITIVE_TEX(): selection = pm.ls(sl = True) for object in selection: rNum = rand.randrange(1,8,1) objectShape = object.getShape() pm.select(objectShape); delightTex = "delightTex"; pm.addAttr(longName=delightTex, dataType='string'); # random texture between 1 and 8 pm.setAttr (objectShape + ".delightTex","sourceimages/stone" + str(rNum)+".tdl");
Pros and Cons
An immediate advantage of the this over the triple shading switch is you can instance the original geometry and the color will be inherited. Its just less finickity as well. Disadvantage is you don’t get color feedback in the viewport.
PRMAN
import pymel.core as pm def ADD_COLOR_PRIM(): selection = pm.ls(sl = True) for object in selection: objectShape = object.getShape() pm.select(objectShape); rmanCsurfcolor = "rmanCsurfcolor" rmanCsurfcolorR = "rmanCsurfcolorR"; rmanCsurfcolorG = "rmanCsurfcolorG" rmanCsurfcolorB = "rmanCsurfcolorB" pm.addAttr(longName=rmanCsurfcolor, at='double3'); pm.addAttr(longName=rmanCsurfcolorR, parent=rmanCsurfcolor,attributeType='double'); pm.addAttr(longName=rmanCsurfcolorG, parent=rmanCsurfcolor, attributeType='double'); pm.addAttr(longName=rmanCsurfcolorB, parent=rmanCsurfcolor, attributeType='double'); pm.setAttr (objectShape + ".rmanCsurfcolor",keyable=True); pm.setAttr (objectShape + ".rmanCsurfcolorR",keyable=True); pm.setAttr (objectShape + ".rmanCsurfcolorG",keyable=True); pm.setAttr (objectShape + ".rmanCsurfcolorB",keyable=True); ADD_COLOR_PRIM()
import pymel.core as pm def ADD_TEXTURE_PRIM(): selection = pm.ls(sl = True) for object in selection: objectShape = object.getShape() pm.select(objectShape); rmanFtexture = "rmanFtexture" pm.addAttr(longName=rmanFtexture, at='float'); pm.setAttr (objectShape + ".rmanFtexture",keyable=True); ADD_TEXTURE_PRIM()