Distributed rendering of single images #104327

Merged
David Zhang merged 22 commits from David-Zhang-10/flamenco:single-image-render into main 2024-09-03 06:47:49 +02:00
Showing only changes of commit 6fca87e42f - Show all commits

View File

@ -193,56 +193,94 @@ overscan = 16
feed_in_input = None feed_in_input = None
render_layers_node = None render_layers_node = None
for node in node_tree.nodes: for node in node_tree.nodes:
if node.type == 'R_LAYERS': if node.type == 'R_LAYERS':
feed_in_input = node.outputs[0] feed_in_input = node.outputs[0]
render_layers_node = node render_layers_node = node
break break
for link in node_tree.links: for link in node_tree.links:
if link.from_socket == feed_in_input: if link.from_socket == feed_in_input:
feed_in_output = link.to_socket feed_in_output = link.to_socket
from os import listdir from os import listdir
from os.path import isfile, join from os.path import isfile, join
root = "${path.join(renderDir, path.basename(renderOutput))}/######" root = "${path.join(renderDir, path.basename(renderOutput))}/######"
image_files = [f for f in listdir(root) if isfile(join(root, f))] image_files = [f for f in listdir(root) if isfile(join(root, f))]
image_nodes = [] separate_nodes = []
first_crop_node = None
translate_nodes = [] translate_nodes = []
for image_file in image_files: for i, image_file in enumerate(image_files):
image_node = node_tree.nodes.new('CompositorNodeImage') image_node = node_tree.nodes.new('CompositorNodeImage')
image_node.image = bpy.data.images.load(root + '/' + image_file) image_node.image = bpy.data.images.load(root + '/' + image_file)
crop_node = node_tree.nodes.new('CompositorNodeCrop') crop_node = node_tree.nodes.new('CompositorNodeCrop')
left, top, right, bottom = image_file.split('-') crop_node.use_crop_size = True
if left == '0': left, top, right, bottom = image_file.split('-')
crop_node.min_x = 0 if left == '0':
crop_node.max_x = ${settings.tile_size_x} crop_node.min_x = 0
else: crop_node.max_x = ${settings.tile_size_x}
crop_node.min_x = overscan else:
crop_node.max_x = ${settings.tile_size_x} + overscan crop_node.min_x = overscan
if top == '0': crop_node.max_x = ${settings.tile_size_x} + overscan
crop_node.max_y = 0 if top == '0':
crop_node.min_y = ${settings.tile_size_y} crop_node.max_y = 0
else: crop_node.min_y = ${settings.tile_size_y}
crop_node.max_y = overscan else:
crop_node.min_y = ${settings.tile_size_y} + overscan crop_node.max_y = overscan
crop_node.min_y = ${settings.tile_size_y} + overscan
if i == 0:
first_crop_node = crop_node
translate_node = node_tree.nodes.new('CompositorNodeTranslate') translate_node = node_tree.nodes.new('CompositorNodeTranslate')
translate_node.inputs[1].default_value = (int(left), int(top)) # translate_node.use_relative = True
node_tree.links.new(image_node.outputs[0], crop_node.inputs[0]) translate_node.inputs[1].default_value = float(left) + (${settings.tile_size_x} - ${settings.resolution_x}) / 2
node_tree.links.new(crop_node.outputs[0], translate_node.inputs[0]) translate_node.inputs[2].default_value = float(top) + (${settings.tile_size_y} - ${settings.resolution_y}) / 2
translate_nodes.append(translate_node) translate_nodes.append(translate_node)
separate_node = node_tree.nodes.new('CompositorNodeSeparateColor')
separate_nodes.append(separate_node)
node_tree.links.new(image_node.outputs[0], crop_node.inputs[0])
node_tree.links.new(crop_node.outputs[0], translate_node.inputs[0])
node_tree.links.new(translate_node.outputs[0], separate_node.inputs[0])
scale_node = node_tree.nodes.new('CompositorNodeScale')
scale_node.space = 'RELATIVE'
scale_node.inputs[1].default_value = ${settings.resolution_x} / ${settings.tile_size_x}
scale_node.inputs[2].default_value = ${settings.resolution_y} / ${settings.tile_size_y}
node_tree.links.new(first_crop_node.outputs[0], scale_node.inputs[0])
mix_node = node_tree.nodes.new('CompositorNodeMixRGB')
mix_node.blend_type = 'MIX'
mix_node.inputs[0].default_value = 0.0
mix_node.inputs[1].default_value = (0, 0, 0, 1)
node_tree.links.new(scale_node.outputs[0], mix_node.inputs[2])
mix_adds = [node_tree.nodes.new('CompositorNodeMixRGB') for _ in range(len(separate_nodes))]
math_adds = [node_tree.nodes.new('CompositorNodeMath') for _ in range(len(separate_nodes))]
for i, mix_add in enumerate(mix_adds):
mix_add.blend_type = 'ADD'
if i == 0:
node_tree.links.new(mix_node.outputs[0], mix_add.inputs[1])
else:
node_tree.links.new(mix_adds[i - 1].outputs[0], mix_add.inputs[1])
node_tree.links.new(translate_nodes[i].outputs[0], mix_add.inputs[2])
for i, math_add in enumerate(math_adds):
math_add.operation = 'ADD'
if i == 0:
node_tree.links.new(mix_node.outputs[0], math_add.inputs[0])
else:
node_tree.links.new(math_adds[i - 1].outputs[0], math_add.inputs[0])
node_tree.links.new(separate_nodes[i - 1].outputs[3], math_add.inputs[1])
set_alpha_node = node_tree.nodes.new('CompositorNodeSetAlpha')
set_alpha_node.mode = 'REPLACE_ALPHA'
node_tree.links.new(mix_adds[-1].outputs[0], set_alpha_node.inputs[0])
node_tree.links.new(math_adds[-1].outputs[0], set_alpha_node.inputs[1])
node_tree.links.new(set_alpha_node.outputs[0], feed_in_output)
alpha_overs = [node_tree.nodes.new('CompositorNodeAlphaOver') for _ in range(len(image_nodes) - 1)]
for i in range(len(image_nodes) - 1):
if i == 0:
node_tree.links.new(translate_nodes[i].outputs[0], alpha_overs[i].inputs[1])
else:
node_tree.links.new(alpha_overs[i - 1].outputs[0], alpha_overs[i].inputs[1])
node_tree.links.new(translate_nodes[i + 1].outputs[0], alpha_overs[i].inputs[2])
node_tree.links.new(alpha_overs[-1].outputs[0], feed_in_output)
node_tree.nodes.remove(render_layers_node) node_tree.nodes.remove(render_layers_node)
render.image_settings.file_format = 'PNG'
bpy.ops.render.render(write_still=True)` bpy.ops.render.render(write_still=True)`
const command = author.Command("blender-render", { const command = author.Command("blender-render", {