WIP: Single-frame job compiler #104194
@ -46,7 +46,6 @@ function compileJob(job) {
|
||||
const renderDir = path.dirname(renderOutput);
|
||||
const renderTasks = authorRenderTasks(settings, renderDir, renderOutput);
|
||||
const mergeTask = authorCreateMergeTask(settings, renderOutput);
|
||||
const denoiseTask = authorCreateDenoiseTask(settings, renderOutput);
|
||||
const compositeTask = authorCreateCompositeTask(settings, renderOutput);
|
||||
|
||||
for (const rt of renderTasks) {
|
||||
@ -57,17 +56,8 @@ function compileJob(job) {
|
||||
mergeTask.addDependency(rt);
|
||||
}
|
||||
job.addTask(mergeTask);
|
||||
// Add a denoise task if denoising is enabled and
|
||||
// set the merge task as its dependency
|
||||
if (denoiseTask) {
|
||||
denoiseTask.addDependency(mergeTask);
|
||||
job.addTask(denoiseTask);
|
||||
compositeTask.addDependency(denoiseTask);
|
||||
}
|
||||
else {
|
||||
compositeTask.addDependency(mergeTask);
|
||||
}
|
||||
job.addTask(compositeTask);
|
||||
compositeTask.addDependency(mergeTask);
|
||||
job.addTask(compositeTask);
|
||||
}
|
||||
|
||||
// Do field replacement on the render output path.
|
||||
@ -164,6 +154,7 @@ bpy.context.scene.render.use_compositing = True
|
||||
bpy.context.scene.use_nodes = True
|
||||
bpy.context.scene.node_tree.nodes.clear()
|
||||
bpy.context.scene.render.image_settings.file_format = 'OPEN_EXR_MULTILAYER'
|
||||
bpy.context.scene.render.filepath = basepath + "MERGED"
|
||||
|
||||
image_nodes = []
|
||||
for index, image in enumerate(filenames):
|
||||
@ -172,25 +163,53 @@ for index, image in enumerate(filenames):
|
||||
image_nodes.append(bpy.context.scene.node_tree.nodes.new(type='CompositorNodeImage'))
|
||||
image_nodes[index].image = image
|
||||
|
||||
output_node = bpy.context.scene.node_tree.nodes.new(type='CompositorNodeComposite')
|
||||
denoising = "${settings.use_denoising}" == "true"
|
||||
alpha_over_nodes = []
|
||||
albedo_mix_nodes = []
|
||||
normal_mix_nodes = []
|
||||
|
||||
for index, node in enumerate(image_nodes):
|
||||
if index == 0:
|
||||
# Take the first two image nodes and combine them
|
||||
alpha_over_nodes.append(bpy.context.scene.node_tree.nodes.new(type='CompositorNodeAlphaOver'))
|
||||
bpy.context.scene.node_tree.links.new(image_nodes[0].outputs['Combined'], alpha_over_nodes[0].inputs[1])
|
||||
bpy.context.scene.node_tree.links.new(image_nodes[1].outputs['Combined'], alpha_over_nodes[0].inputs[2])
|
||||
bpy.context.scene.node_tree.links.new(image_nodes[0].outputs['Combined'], alpha_over_nodes[index].inputs[1])
|
||||
bpy.context.scene.node_tree.links.new(image_nodes[1].outputs['Combined'], alpha_over_nodes[index].inputs[2])
|
||||
if denoising:
|
||||
albedo_mix_nodes.append(bpy.context.scene.node_tree.nodes.new(type='CompositorNodeMixRGB'))
|
||||
albedo_mix_nodes[index].blend_type = 'ADD'
|
||||
bpy.context.scene.node_tree.links.new(image_nodes[0].outputs['Denoising Albedo'], albedo_mix_nodes[index].inputs[1])
|
||||
bpy.context.scene.node_tree.links.new(image_nodes[1].outputs['Denoising Albedo'], albedo_mix_nodes[index].inputs[2])
|
||||
normal_mix_nodes.append(bpy.context.scene.node_tree.nodes.new(type='CompositorNodeMixRGB'))
|
||||
normal_mix_nodes[index].blend_type = 'ADD'
|
||||
bpy.context.scene.node_tree.links.new(image_nodes[0].outputs['Denoising Normal'], normal_mix_nodes[index].inputs[1])
|
||||
bpy.context.scene.node_tree.links.new(image_nodes[1].outputs['Denoising Normal'], normal_mix_nodes[index].inputs[2])
|
||||
else:
|
||||
# Take one image node and the previous alpha over node
|
||||
alpha_over_nodes.append(bpy.context.scene.node_tree.nodes.new(type='CompositorNodeAlphaOver'))
|
||||
bpy.context.scene.node_tree.links.new(alpha_over_nodes[index-1].outputs['Image'], alpha_over_nodes[index].inputs[1])
|
||||
bpy.context.scene.node_tree.links.new(image_nodes[index+1].outputs['Combined'], alpha_over_nodes[index].inputs[2])
|
||||
if denoising:
|
||||
albedo_mix_nodes.append(bpy.context.scene.node_tree.nodes.new(type='CompositorNodeMixRGB'))
|
||||
albedo_mix_nodes[index].blend_type = 'ADD'
|
||||
bpy.context.scene.node_tree.links.new(albedo_mix_nodes[index-1].outputs['Image'], albedo_mix_nodes[index].inputs[1])
|
||||
bpy.context.scene.node_tree.links.new(image_nodes[index+1].outputs['Denoising Albedo'], albedo_mix_nodes[index].inputs[2])
|
||||
normal_mix_nodes.append(bpy.context.scene.node_tree.nodes.new(type='CompositorNodeMixRGB'))
|
||||
normal_mix_nodes[index].blend_type = 'ADD'
|
||||
bpy.context.scene.node_tree.links.new(normal_mix_nodes[index-1].outputs['Image'], normal_mix_nodes[index].inputs[1])
|
||||
bpy.context.scene.node_tree.links.new(image_nodes[index+1].outputs['Denoising Normal'], normal_mix_nodes[index].inputs[2])
|
||||
if index + 1 == len(image_nodes) - 1:
|
||||
# Link the last image node and feed the output into the composite node
|
||||
output_node = bpy.context.scene.node_tree.nodes.new(type='CompositorNodeOutputFile')
|
||||
output_node.base_path = basepath + "MERGED"
|
||||
bpy.context.scene.node_tree.links.new(alpha_over_nodes[index].outputs['Image'], output_node.inputs['Image'])
|
||||
if denoising:
|
||||
denoise_node = bpy.context.scene.node_tree.nodes.new(type='CompositorNodeDenoise')
|
||||
bpy.context.scene.node_tree.links.new(alpha_over_nodes[index].outputs['Image'], denoise_node.inputs['Image'])
|
||||
bpy.context.scene.node_tree.links.new(albedo_mix_nodes[index].outputs['Image'], denoise_node.inputs['Albedo'])
|
||||
bpy.context.scene.node_tree.links.new(normal_mix_nodes[index].outputs['Image'], denoise_node.inputs['Normal'])
|
||||
bpy.context.scene.node_tree.links.new(denoise_node.outputs['Image'], output_node.inputs['Image'])
|
||||
else:
|
||||
# Link the last image node and feed the output into the composite node
|
||||
bpy.context.scene.node_tree.links.new(alpha_over_nodes[index].outputs['Image'], output_node.inputs['Image'])
|
||||
break
|
||||
bpy.ops.render.render()`;
|
||||
bpy.ops.render.render(write_still=True)`;
|
||||
const command = author.Command("blender-render", {
|
||||
exe: "{blender}",
|
||||
exeArgs: "{blenderArgs}",
|
||||
@ -205,42 +224,14 @@ bpy.ops.render.render()`;
|
||||
return task;
|
||||
}
|
||||
|
||||
function authorCreateDenoiseTask(settings, renderOutput) {
|
||||
if (! settings.use_denoising) {
|
||||
return;
|
||||
}
|
||||
const task = author.Task(`denoise`, "blender");
|
||||
let pythonExpression = `
|
||||
import bpy
|
||||
print("Running the denoiser")
|
||||
bpy.ops.cycles.denoise_animation(input_filepath="${renderOutput}/MERGED.exr", output_filepath="${renderOutput}/DENOISED.exr")`;
|
||||
const command = author.Command("blender-render", {
|
||||
exe: "{blender}",
|
||||
exeArgs: "{blenderArgs}",
|
||||
argsBefore: [],
|
||||
blendfile: settings.blendfile,
|
||||
args: [
|
||||
"--python-exit-code", 1,
|
||||
"--python-expr", pythonExpression
|
||||
]
|
||||
});
|
||||
task.addCommand(command);
|
||||
return task;
|
||||
}
|
||||
|
||||
function authorCreateCompositeTask(settings, renderOutput) {
|
||||
let filename;
|
||||
let pythonExpression = `
|
||||
import pathlib
|
||||
import os
|
||||
import bpy
|
||||
C = bpy.context
|
||||
basepath = "${renderOutput}/"
|
||||
filenames = [f for f in os.listdir(basepath) if os.path.isfile(basepath + f)]
|
||||
if "DENOISED.exr" in filenames:
|
||||
filename = "DENOISED.exr"
|
||||
else:
|
||||
filename = next((s for s in filenames if "MERGED" in s), None)
|
||||
filename = "MERGED.exr"
|
||||
`;
|
||||
if (settings.use_compositing) {
|
||||
// Do the full composite+export pipeline
|
||||
|
Loading…
Reference in New Issue
Block a user