rambobambo
(rambobambo)
January 27, 2023, 5:43pm
1
Is it even possible to automate any of the stages in my workflow with a script? I have about 20 View Layers on one scene in my projects. I need to render each View Layer separately and save it to an EXR file (I need it on separate layers for photoshop).
My Steps:
I create a “File Output” node with input with the same amount and names as the layer view.
Plug all nodes from “Render Layers” into the appropriate place in the “File Output” node.
Any chance to do this with scripts? I thought maybe there was an add-on for this, but unfortunately I couldn’t find anything.
rambobambo
(rambobambo)
January 27, 2023, 9:42pm
2
I’m posting the finished script here, maybe someone will find it useful
import bpy
C = bpy.context
D = bpy.data
# print('-'*40)
# ensure compositor is using nodes
if not C.scene.use_nodes:
C.scene.use_nodes = True
# get the names of all view layers in current scene
#v_layers = [v_layer.name for v_layer in C.scene.view_layers]
# or get the names of view layers that are not excluded from render
v_layers = [v_layer.name for v_layer in C.scene.view_layers if v_layer.use]
# ensure denoising data available in render pass
# requires cycles render engine
if not C.scene.render.engine == 'CYCLES':
C.scene.render.engine = 'CYCLES'
x_spacing = 300
y_spacing = -500
for i, vl_name in enumerate(v_layers):
# print('-'*40)
# print(f'idx:{i} name:{vl_name}')
if not D.scenes[C.scene.name].cycles.use_denoising:
D.scenes[C.scene.name].cycles.use_denoising = True
if not C.scene.view_layers[vl_name].cycles.use_denoising:
C.scene.view_layers[vl_name].cycles.use_denoising = True
if not C.scene.view_layers[vl_name].cycles.denoising_store_passes:
C.scene.view_layers[vl_name].cycles.denoising_store_passes = True
# add render layer node
rl_node = C.scene.node_tree.nodes.get("rl_"+vl_name)
if not rl_node:
rl_node = C.scene.node_tree.nodes.new('CompositorNodeRLayers')
rl_node.name = "rl_"+vl_name
rl_node.label = "rl_"+vl_name
rl_node.layer = vl_name
rl_node.location[0] = 0 * x_spacing
rl_node.location[1] = (i) * y_spacing
# add de-noise node
dn_node = C.scene.node_tree.nodes.get("dn_"+vl_name)
if not dn_node:
dn_node = C.scene.node_tree.nodes.new('CompositorNodeDenoise')
dn_node.name = "dn_"+vl_name
dn_node.label = "dn_"+vl_name
dn_node.prefilter = 'FAST'
dn_node.location[0] = 1 * x_spacing
dn_node.location[1] = (i) * y_spacing
# add mixrgb node
mix_node = C.scene.node_tree.nodes.get("mix_"+vl_name)
if not mix_node:
mix_node = C.scene.node_tree.nodes.new('CompositorNodeMixRGB')
mix_node.name = "mix_"+vl_name
mix_node.label = "mix_"+vl_name
mix_node.inputs['Fac'].default_value = 0.75
mix_node.location[0] = 1.75 * x_spacing
mix_node.location[1] = (i) * y_spacing
# add file output node and slots
op_node = C.scene.node_tree.nodes.get("File Output")
if not op_node:
op_node = C.scene.node_tree.nodes.new('CompositorNodeOutputFile')
op_node.file_slots.clear()
op_node.name = "File Output"
op_node.label = "File Output"
op_node.location[0] = 2.5 * x_spacing
if len(op_node.file_slots) < i+1:
op_node.file_slots.new(vl_name)
op_node.file_slots[i].path = vl_name
op_node.format.file_format = 'OPEN_EXR_MULTILAYER'
op_node.format.color_depth = '16'
C.scene.node_tree.links.new(op_node.inputs[i], mix_node.outputs[0])
C.scene.node_tree.links.new(mix_node.inputs[1], rl_node.outputs['Image'])
C.scene.node_tree.links.new(mix_node.inputs[2], dn_node.outputs[0])
C.scene.node_tree.links.new(dn_node.inputs['Image'], rl_node.outputs['Image'])
C.scene.node_tree.links.new(dn_node.inputs['Normal'], rl_node.outputs['Denoising Normal'])
C.scene.node_tree.links.new(dn_node.inputs['Albedo'], rl_node.outputs['Denoising Albedo'])