This is a beauty passes rebuilder for Arnold that separates the different passes that make the beauty and then merge them again, so compositors can tweak specific passes as they please.
It has 5 kinds of rebuilds:
- Basic Light Rebuild: Separates direct and indirect light
- Basic Albedo Rebuild: Separates the albedo and the light influence
- Simple Beauty Rebuild: Separates the most used basic beauty passes (diffuse, emission, specular, sss, transmission)
- Advance Beauty Rebuild: Separates the most used basic beauty passes and at the same time separates the direct and indirect light influence of them
- Complex Beauty Rebuild: Separates the most used basic beauty passes, separating the direct and indirect light influence and also the albedo influence
If you want to take into consideration coat and volume passes too, you can edit the AOV lists in the script.
It also checks if the read file contains all the passes that are needed for the selected rebuild type. If not, it tells which are the missing ones, before generating the rebuild.
class arnold_beauty_rebuilder(): def __init__(self): self.readN = nuke.selectedNode() self.readNXpos = int(self.readN['xpos'].value()) self.readNYpos = int(self.readN['ypos'].value()) self.readNChannels = self.readN.channels() self.readNLayers = list(set([c.split('.')[0] for c in self.readNChannels])) self.basicLightAOVList = ['indirect', 'direct'] self.basicAlbedoAOVList = ['diffuse_albedo', ['diffuse_indirect', 'diffuse_direct']] self.simpleBeautyAOVList = ['diffuse', 'emission', 'specular', 'sss', 'transmission'] self.advanceBeautyAOVList = [['diffuse_indirect', 'diffuse_direct'], 'emission', ['specular_indirect', 'specular_direct'], ['sss_indirect', 'sss_direct'], ['transmission_indirect', 'transmission_direct']] self.complexBeautyAOVList = [['diffuse_albedo', ['diffuse_indirect', 'diffuse_direct']], 'emission', ['specular_albedo', ['specular_indirect', 'specular_direct']], ['sss_albedo', ['sss_indirect', 'sss_direct']], ['transmission_albedo', ['transmission_indirect', 'transmission_direct']]] def checkLayers(self, aovList): self.finalAOVList = [] self.missingAOV = [] for aov in aovList: if type(aov) is str: self.finalAOVList.append(aov) else: for subAOV in aov: if type(subAOV) is str: self.finalAOVList.append(subAOV) else: for subSubAOV in subAOV: self.finalAOVList.append(subSubAOV) for aov in self.finalAOVList: if aov not in self.readNLayers: self.missingAOV.append(aov) if len(self.missingAOV) != 0: strMissingAOV = '' for i in self.missingAOV: strMissingAOV = strMissingAOV + '\n' + '-' + i nuke.message('Warning! The following AOVs are missing:' + '\n' + strMissingAOV) def set_unpremult(self): self.unpremult = nuke.nodes.Unpremult(channels='all') self.unpremult.setXpos(self.readNXpos) self.unpremult.setYpos(self.readNYpos + 150) self.unpremult.setInput(0, self.readN) def set_oDot(self): self.oDot = nuke.nodes.Dot() self.oDot.setXpos(self.readNXpos + 34) self.oDot.setYpos(self.readNYpos + 250) self.oDot.setInput(0, nuke.toNode(self.unpremult.name())) def set_auxDot(self, tDot): self.auxDot = nuke.nodes.Dot() self.auxDot.setXpos(int(nuke.toNode(tDot)['xpos'].getValue())+200) self.auxDot.setYpos(int(nuke.toNode(tDot)['ypos'].getValue())) self.auxDot.setInput(0, nuke.toNode(tDot)) self.lastAuxDot = self.auxDot.name() def set_shuffle(self, channelS): self.shuffleID = channelS self.shuffleID = nuke.nodes.Shuffle(label=channelS.upper()) self.shuffleID.knob('in').setValue(channelS) self.shuffleID.setXpos(int(self.auxDot['xpos'].getValue())-34) self.shuffleID.setYpos(int(self.auxDot['ypos'].getValue())+50) self.shuffleID.setInput(0, nuke.toNode(self.auxDot.name())) def set_remove(self, channelK): self.remove = nuke.nodes.Remove(operation='keep', channels=channelK) self.remove.setXpos(int(nuke.toNode(self.shuffleID.name())['xpos'].getValue())) self.remove.setYpos(int(nuke.toNode(self.shuffleID.name())['ypos'].getValue())+50) self.remove.setInput(0, nuke.toNode(self.shuffleID.name())) def set_merge(self, mergeType, aLine='NOTHING', bLine='NOTHING'): self.mergeID = nuke.nodes.Merge(operation=mergeType) self.mergeID.setXpos(int(nuke.toNode(bLine)['xpos'].getValue())) self.mergeID.setYpos(int(nuke.toNode(bLine)['ypos'].getValue())+200) if bLine != 0: self.mergeID.setInput(0, nuke.toNode(bLine)) elif aLine != 0: self.mergeID.setInput(1, nuke.toNode(aLine)) def set_merge_dot(self, target, y): self.mergeDot = nuke.nodes.Dot() self.mergeDot.setXpos(int(nuke.toNode(target)['xpos'].getValue())+34) self.mergeDot.setYpos(int(nuke.toNode(target)['ypos'].getValue())+y+3) self.mergeDot.setInput(0, nuke.toNode(target)) def set_alpha(self, target): self.set_shuffle('alpha') self.set_remove('alpha') self.copy = nuke.nodes.Copy(from0='rgba.alpha', to0='rgba.alpha') self.copy.setXpos(int(nuke.toNode(target)['xpos'].getValue())) self.copy.setYpos(int(nuke.toNode(target)['ypos'].getValue())+200) self.copy.setInput(0, nuke.toNode(target)) self.copyDot = nuke.nodes.Dot() self.copyDot.setXpos(int(nuke.toNode(self.shuffleID.name())['xpos'].getValue())+34) self.copyDot.setYpos(int(nuke.toNode(self.copy.name())['ypos'].getValue())+11) self.copyDot.setInput(0, nuke.toNode(self.remove.name())) self.copy.setInput(1, self.copyDot) def set_premult(self, target, x='NOTHING', y='NOTHING'): self.premult = nuke.nodes.Premult() self.premult.setXpos(int(nuke.toNode(target)['xpos'].getValue())+x) self.premult.setYpos(int(nuke.toNode(self.copy.name())['ypos'].getValue())+y) self.premult.setInput(0, nuke.toNode(target)) def basicLight_rebuild(self): self.set_unpremult() self.set_oDot() self.set_auxDot(self.oDot.name()) self.set_shuffle('indirect') self.set_remove('rgb') self.set_merge('plus', 0, self.remove.name()) self.set_auxDot(self.lastAuxDot) self.set_shuffle('direct') self.set_remove('rgb') self.set_merge_dot(self.remove.name(), 200) self.mergeID.setInput(1, nuke.toNode(self.mergeDot.name())) self.set_auxDot(self.lastAuxDot) self.set_alpha(self.mergeID.name()) self.set_premult(self.copy.name(), 0, 75) self.set_premult(self.oDot.name(), -34, 75) def basicAlbedo_rebuild(self): self.set_unpremult() self.set_oDot() for subAOV in self.basicAlbedoAOVList: if type(subAOV) is str: self.set_auxDot(self.oDot.name()) self.set_shuffle(subAOV) self.set_remove('rgb') self.set_merge_dot(self.remove.name(), 200) self.set_merge('multiply', 0, self.mergeDot.name()) lastMerge = self.mergeID.name() multiplyMerge = self.mergeID.name() nuke.toNode(self.mergeID.name()).setYpos(int(nuke.toNode(self.mergeID.name())['ypos'].getValue())+200) nuke.toNode(self.mergeID.name()).setXpos(int(nuke.toNode(self.mergeID.name())['xpos'].getValue())-34) self.set_merge_dot(self.mergeDot.name(), -3) nuke.toNode(self.mergeDot.name()).setXpos(int(nuke.toNode(self.mergeDot.name())['xpos'].getValue())+134) self.set_merge('divide', 0, self.mergeDot.name()) divideMerge = self.mergeID.name() nuke.toNode(divideMerge).setXpos(int(nuke.toNode(divideMerge)['xpos'].getValue())-34) self.set_merge_dot(self.mergeID.name(), 200+1) nuke.toNode(multiplyMerge).setInput(1, nuke.toNode(self.mergeDot.name())) else: for subSubAOV in subAOV: self.set_auxDot(self.lastAuxDot) if subAOV.index(subSubAOV) == 0: nuke.toNode(self.lastAuxDot).setXpos(int(nuke.toNode(self.lastAuxDot)['xpos'].getValue())+150) self.set_shuffle(subSubAOV) self.set_remove('rgb') if subAOV.index(subSubAOV) == 0: self.set_merge('plus', 0, self.remove.name()) self.set_merge_dot(self.mergeID.name(), 200+3) divideDot = self.mergeDot.name() else: self.set_merge_dot(self.remove.name(), 200) self.mergeID.setInput(1, nuke.toNode(self.mergeDot.name())) nuke.toNode(divideMerge).setInput(1, nuke.toNode(divideDot)) self.set_auxDot(self.lastAuxDot) self.set_alpha(lastMerge) self.set_premult(self.copy.name(), 0, 75) self.set_premult(self.oDot.name(), -34, 75) def simpleBeauty_rebuild(self): self.set_unpremult() self.set_oDot() mergeList = [] dotList = [] for aov in self.simpleBeautyAOVList: if self.simpleBeautyAOVList.index(aov) == 0: self.set_auxDot(self.oDot.name()) self.set_shuffle(aov) self.set_remove('rgb') for i in range(len(self.simpleBeautyAOVList)-1): if range(len(self.simpleBeautyAOVList)-1).index(i) == 0: self.set_merge('plus', 0, self.remove.name()) else: self.set_merge('plus', 0, self.mergeID.name()) mergeList.append(self.mergeID.name()) else: self.set_auxDot(self.lastAuxDot) self.set_shuffle(aov) self.set_remove('rgb') self.set_merge_dot(self.remove.name(), 200 * self.simpleBeautyAOVList.index(aov)) dotList.append(self.mergeDot.name()) for merge in mergeList: nuke.toNode(merge).setInput(1, nuke.toNode(dotList[mergeList.index(merge)])) self.set_auxDot(self.lastAuxDot) self.set_alpha(self.mergeID.name()) self.set_premult(self.copy.name(), 0, 75) self.set_premult(self.oDot.name(), -34, 75) def advanceBeauty_rebuild(self): self.set_unpremult() self.set_oDot() mergeList = [] dotList = [] for aov in self.advanceBeautyAOVList: if type(aov) is str: self.set_auxDot(self.lastAuxDot) self.set_shuffle(aov) self.set_remove('rgb') self.set_merge_dot(self.remove.name(), 200 * (self.advanceBeautyAOVList.index(aov)+1)) dotList.append(self.mergeDot.name()) elif self.advanceBeautyAOVList.index(aov) == 0: for subAOV in aov: if aov.index(subAOV) == 0: self.set_auxDot(self.oDot.name()) self.set_shuffle(subAOV) self.set_remove('rgb') for i in range(len(self.advanceBeautyAOVList)): if range(len(self.advanceBeautyAOVList)).index(i) == 0: self.set_merge('plus', 0, self.remove.name()) else: self.set_merge('plus', 0, self.mergeID.name()) mergeList.append(self.mergeID.name()) lastMerge = self.mergeID.name() else: self.set_auxDot(self.lastAuxDot) self.set_shuffle(subAOV) self.set_remove('rgb') self.set_merge_dot(self.remove.name(), 200) dotList.append(self.mergeDot.name()) else: for subAOV in aov: self.set_auxDot(self.lastAuxDot) self.set_shuffle(subAOV) self.set_remove('rgb') if aov.index(subAOV) == 0: self.set_merge('plus', 0, self.remove.name()) self.set_merge_dot(self.mergeID.name(), 200 * self.advanceBeautyAOVList.index(aov)) dotList.append(self.mergeDot.name()) else: self.set_merge_dot(self.remove.name(), 200) self.mergeID.setInput(1, nuke.toNode(self.mergeDot.name())) for merge in mergeList: nuke.toNode(merge).setYpos(int(nuke.toNode(dotList[mergeList.index(merge)])['ypos'].getValue())) nuke.toNode(merge).setInput(1, nuke.toNode(dotList[mergeList.index(merge)])) self.set_auxDot(self.lastAuxDot) self.set_alpha(lastMerge) self.set_premult(self.copy.name(), 0, 75) self.set_premult(self.oDot.name(), -34, 75) def complexBeauty_rebuild(self): self.set_unpremult() self.set_oDot() mergeList = [] dotList = [] for aov in self.complexBeautyAOVList: if type(aov) is str: self.set_auxDot(self.lastAuxDot) self.set_shuffle(aov) self.set_remove('rgb') self.set_merge_dot(self.remove.name(), 200 * (self.complexBeautyAOVList.index(aov)+3)) dotList.append(self.mergeDot.name()) elif self.complexBeautyAOVList.index(aov) == 0: for subAOV in aov: if type(subAOV) is str: self.set_auxDot(self.oDot.name()) self.set_shuffle(subAOV) self.set_remove('rgb') self.set_merge_dot(self.remove.name(), 200) self.set_merge('multiply', 0, self.mergeDot.name()) multiplyMerge = self.mergeID.name() nuke.toNode(self.mergeID.name()).setYpos(int(nuke.toNode(self.mergeID.name())['ypos'].getValue())+200) nuke.toNode(self.mergeID.name()).setXpos(int(nuke.toNode(self.mergeID.name())['xpos'].getValue())-34) for i in range(len(self.complexBeautyAOVList)-1): self.set_merge('plus', 0, self.mergeID.name()) mergeList.append(self.mergeID.name()) lastMerge = self.mergeID.name() self.set_merge_dot(self.mergeDot.name(), -3) nuke.toNode(self.mergeDot.name()).setXpos(int(nuke.toNode(self.mergeDot.name())['xpos'].getValue())+134) self.set_merge('divide', 0, self.mergeDot.name()) divideMerge = self.mergeID.name() nuke.toNode(divideMerge).setXpos(int(nuke.toNode(divideMerge)['xpos'].getValue())-34) self.set_merge_dot(self.mergeID.name(), 200) nuke.toNode(multiplyMerge).setInput(1, nuke.toNode(self.mergeDot.name())) else: for subSubAOV in subAOV: self.set_auxDot(self.lastAuxDot) if subAOV.index(subSubAOV) == 0: nuke.toNode(self.lastAuxDot).setXpos(int(nuke.toNode(self.lastAuxDot)['xpos'].getValue())+150) self.set_shuffle(subSubAOV) self.set_remove('rgb') if subAOV.index(subSubAOV) == 0: self.set_merge('plus', 0, self.remove.name()) self.set_merge_dot(self.mergeID.name(), 200+3) divideDot = self.mergeDot.name() else: self.set_merge_dot(self.remove.name(), 200) self.mergeID.setInput(1, nuke.toNode(self.mergeDot.name())) nuke.toNode(divideMerge).setInput(1, nuke.toNode(divideDot)) else: for subAOV in aov: if type(subAOV) is str: self.set_auxDot(self.lastAuxDot) self.set_shuffle(subAOV) self.set_remove('rgb') self.set_merge_dot(self.remove.name(), 200) self.set_merge('multiply', 0, self.mergeDot.name()) nuke.toNode(self.mergeID.name()).setYpos(int(nuke.toNode(self.mergeID.name())['ypos'].getValue())+200) nuke.toNode(self.mergeID.name()).setXpos(int(nuke.toNode(self.mergeID.name())['xpos'].getValue())-34) multiplyMerge = self.mergeID.name() self.set_merge_dot(self.mergeDot.name(), -3) nuke.toNode(self.mergeDot.name()).setXpos(int(nuke.toNode(self.mergeDot.name())['xpos'].getValue())+134) divideDot = self.mergeDot.name() self.set_merge_dot(self.mergeID.name(), 200 * (self.complexBeautyAOVList.index(aov))) dotList.append(self.mergeDot.name()) self.set_merge('divide', 0, divideDot) divideMerge = self.mergeID.name() nuke.toNode(self.mergeID.name()).setXpos(int(nuke.toNode(self.mergeID.name())['xpos'].getValue())-34) self.set_merge_dot(self.mergeID.name(), 200) nuke.toNode(multiplyMerge).setInput(1, nuke.toNode(self.mergeDot.name())) else: for subSubAOV in subAOV: self.set_auxDot(self.lastAuxDot) if subAOV.index(subSubAOV) == 0: nuke.toNode(self.lastAuxDot).setXpos(int(nuke.toNode(self.lastAuxDot)['xpos'].getValue())+150) self.set_shuffle(subSubAOV) self.set_remove('rgb') if subAOV.index(subSubAOV) == 0: self.set_merge('plus', 0, self.remove.name()) self.set_merge_dot(self.mergeID.name(), 200+3) nuke.toNode(divideMerge).setInput(1, nuke.toNode(self.mergeDot.name())) else: self.set_merge_dot(self.remove.name(), 200) self.mergeID.setInput(1, nuke.toNode(self.mergeDot.name())) for merge in mergeList: nuke.toNode(merge).setInput(1, nuke.toNode(dotList[mergeList.index(merge)])) self.set_auxDot(self.lastAuxDot) self.set_alpha(lastMerge) self.set_premult(self.copy.name(), 0, 75) self.set_premult(self.oDot.name(), -34, 75) def arnold_beauty_rebuild(): if nuke.selectedNode().Class() != 'Read': nuke.message('Please, select a Read node') else: abr = arnold_beauty_rebuilder() abrCL = getattr(abr, 'checkLayers') p = nuke.Panel('Arnold Beauty Rebuild') rebuilds = ['Basic\ light\ rebuild', ' Basic\ albedo\ rebuild', ' Basic\ beauty\ rebuild', ' Advance\ beauty\ rebuild', ' Complex\ beauty\ rebuild'] p.addEnumerationPulldown('Rebuild type', (','.join(rebuilds)).replace(',', '')) if not p.show(): return rebuildType = p.value('Rebuild type') if rebuildType == rebuilds[0].replace('\\', ''): abrCL(getattr(abr, 'basicLightAOVList')) abrBL = getattr(abr, 'basicLight_rebuild') abrBL() elif rebuildType == rebuilds[1][1:].replace('\\', ''): abrCL(getattr(abr, 'basicAlbedoAOVList')) abrBA = getattr(abr, 'basicAlbedo_rebuild') abrBA() elif rebuildType == rebuilds[2][1:].replace('\\', ''): abrCL(getattr(abr, 'simpleBeautyAOVList')) abrSB = getattr(abr, 'simpleBeauty_rebuild') abrSB() elif rebuildType == rebuilds[3][1:].replace('\\', ''): abrCL(getattr(abr, 'advanceBeautyAOVList')) abrAB = getattr(abr, 'advanceBeauty_rebuild') abrAB() else: abrCL(getattr(abr, 'complexBeautyAOVList')) abrCB = getattr(abr, 'complexBeauty_rebuild') abrCB()