05: Assigning hold out material on $sel
Often we want to have certain objects act as a hold out object (for matting purposes). Basicly, what it means is assigning a shader that is black in both rgb and alpha. However, when you do this on several objects it can become a bit of a hassle, because just can't just assign, say, a black surface shader. Well, you can, but it probably means that it wont line up with the beauty pass, since the hold out shader doesn't have the corresponding displacement shader and as such, you'll end up with mismatching edges.
So what we'll do here is take the "holdOut_mat" (a black surface shader with matte opacity 0), or create it if it doesn't allready exist, find the existing displacement shader on the selected objedt, and for each selected object create and assign a shading group with the "holdOut_mat" as a surface material and connect the original displacement shader to the shading group's displacement mat attribute:
Here's what the scene looks like:
We'll assign a hold out material on the 3 balls on the back row:
// --------------- assign holdout material --------------------- global proc assignHOMat(){ string $sel[] = `ls -sl`; if (!`size($sel)`){ print "nothing is selected!\n"; }else{ string $shader = "holdOut_mat"; if (!`objExists $shader`){ $shader = `shadingNode -asShader surfaceShader -n "holdOut_mat"`; setAttr ($shader + ".outMatteOpacity") -type double3 0 0 0 ; } for ( $i=0; $i < size($sel) ; $i++ ){ string $shape[] = `listRelatives -s $sel[$i]`; string $exSG[] = `listConnections -type shadingEngine $shape[0]`; for ( $sg=0; $sg<size($exSG); $sg++){ string $exDispShader[] = `listConnections -type displacementShader $exSG[$sg]`; if (`size($exDispShader)` > 0){ string $newSG = `sets -renderable true -noSurfaceShader true -empty -name ($sel[$i] + "_holdOut_SG")`; connectAttr -f ($shader + ".outColor") ($newSG + ".surfaceShader"); connectAttr -f ($exDispShader[0] + ".displacement") ($newSG + ".displacementShader"); select -r $sel[$i]; sets -e -forceElement $newSG; print ($sel[$i] + " was assigned the holdOut material\n"); }else{ string $newSG = "holdOut_SG"; if (!`objExists $newSG`){ $newSG = `sets -r 1 -nss 1 -em -n ( "holdOut_SG")`; connectAttr -f ($shader + ".outColor") ($newSG + ".surfaceShader"); } select -r $sel[$i]; sets -e -forceElement $newSG; print ($sel[$i] + " was assigned the holdOut material\n"); } } } } select -r $sel; // reselect the original selection. } assignHOMat();
We now end up with this:
Note the preserved displacement on the middle ball. The alpha channel looks like this:
The holdOut shading network now looks like this:
The two non-displaced spheres are connected to the general "holdOut_SG" while the displaced one (sphere2) has its own shading group called "sphere2_holdOut_SG". They all share the same hold out surface shader.
This is a nice way of applying other shaders that require per object displacement textures as well, like other "utility" shaders (if you can't use passes) i.e. depth, lighting passes shaders, shadow catchers' shaders, ambient occlusion, etc.
.













