WIP: Single-frame job compiler #104194
@ -6,7 +6,7 @@ const JOB_TYPE = {
|
|||||||
// Settings for artists to determine:
|
// Settings for artists to determine:
|
||||||
{ key: "frame", type: "int32", required: true, eval: "C.scene.frame_current",
|
{ key: "frame", type: "int32", required: true, eval: "C.scene.frame_current",
|
||||||
description: "Frame to render"},
|
description: "Frame to render"},
|
||||||
{ key: "chunk_size", type: "int32", default: 128, propargs: {min: 1}, description: "Number of samples to render in one Blender render task",
|
{ key: "tile_size", type: "int32", default: 5, propargs: {min: 1, max: 100}, description: "Tile size for each Task (sizes are in % of the full image)",
|
||||||
visible: "submission" },
|
visible: "submission" },
|
||||||
|
|
||||||
|
|
||||||
@ -86,39 +86,42 @@ function renderOutputPath(job) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function tileChunker(tile_size) {
|
||||||
|
let tiles = [];
|
||||||
|
const rows = Math.floor(100 / tile_size);
|
||||||
|
const columns = Math.floor(100 / tile_size);
|
||||||
|
for (let row = 1; row <= rows; row++) {
|
||||||
|
for (let column = 1; column <= columns; column++) {
|
||||||
|
tiles.push({"row": row, "column": column});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tiles;
|
||||||
|
}
|
||||||
|
|
||||||
function authorRenderTasks(settings, renderDir, renderOutput) {
|
function authorRenderTasks(settings, renderDir, renderOutput) {
|
||||||
print("authorRenderTasks(", renderDir, renderOutput, ")");
|
print("authorRenderTasks(", renderDir, renderOutput, ")");
|
||||||
let renderTasks = [];
|
let renderTasks = [];
|
||||||
let chunks = frameChunker(settings.samples, settings.chunk_size);
|
let tiles = tileChunker(settings.tile_size);
|
||||||
for (let chunk of chunks) {
|
print(tiles);
|
||||||
const task = author.Task(`render-${chunk}`, "blender");
|
for (let tile of tiles) {
|
||||||
let chunk_arr = chunk.split("-", 2);
|
const task = author.Task(`render-r${tile.row}c${tile.column}`, "blender");
|
||||||
let chunk_end;
|
|
||||||
let chunk_start;
|
|
||||||
if (chunk_arr.length < 2) {
|
|
||||||
chunk_end = chunk_arr[0];
|
|
||||||
chunk_start = chunk_arr[0] - 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
chunk_end = chunk_arr[1];
|
|
||||||
chunk_start = chunk_arr[0] - 1;
|
|
||||||
}
|
|
||||||
let chunk_size = chunk_end - chunk_start;
|
|
||||||
let pythonExpression = `
|
let pythonExpression = `
|
||||||
import bpy
|
import bpy
|
||||||
bpy.context.scene.render.engine = 'CYCLES'
|
bpy.context.scene.render.engine = 'CYCLES'
|
||||||
bpy.context.scene.render.use_compositing = False
|
bpy.context.scene.render.use_compositing = False
|
||||||
bpy.context.scene.cycles.use_denoising = False
|
bpy.context.scene.cycles.use_denoising = False
|
||||||
bpy.context.scene.render.image_settings.file_format = 'OPEN_EXR_MULTILAYER'
|
bpy.context.scene.render.image_settings.file_format = 'OPEN_EXR_MULTILAYER'
|
||||||
bpy.context.scene.cycles.samples = ${chunk_size}
|
bpy.context.scene.render.use_crop_to_border = False
|
||||||
bpy.context.scene.cycles.sample_offset = ${chunk_start}`;
|
bpy.context.scene.render.border_min_x = ${tile.column} * ${settings.tile_size} / 100
|
||||||
|
bpy.context.scene.render.border_max_x = ${settings.tile_size} / 100 + ${tile.column} * ${settings.tile_size} / 100
|
||||||
|
bpy.context.scene.render.border_min_y = ${tile.row} * ${settings.tile_size} / 100
|
||||||
|
bpy.context.scene.render.border_max_y = ${settings.tile_size} / 100 + ${tile.row} * ${settings.tile_size} / 100`;
|
||||||
if (settings.use_denoising) {
|
if (settings.use_denoising) {
|
||||||
pythonExpression += `
|
pythonExpression += `
|
||||||
for layer in bpy.context.scene.view_layers:
|
for layer in bpy.context.scene.view_layers:
|
||||||
layer['cycles']['denoising_store_passes'] = 1
|
layer['cycles']['denoising_store_passes'] = 1
|
||||||
layer.use_pass_vector = True`;
|
layer.use_pass_vector = True`;
|
||||||
}
|
}
|
||||||
print(pythonExpression);
|
|
||||||
const command = author.Command("blender-render", {
|
const command = author.Command("blender-render", {
|
||||||
exe: "{blender}",
|
exe: "{blender}",
|
||||||
exeArgs: "{blenderArgs}",
|
exeArgs: "{blenderArgs}",
|
||||||
@ -127,7 +130,7 @@ for layer in bpy.context.scene.view_layers:
|
|||||||
args: [
|
args: [
|
||||||
"--python-exit-code", 1,
|
"--python-exit-code", 1,
|
||||||
"--python-expr", pythonExpression,
|
"--python-expr", pythonExpression,
|
||||||
"--render-output", path.join(renderDir, path.basename(renderOutput), "samples", chunk),
|
"--render-output", path.join(renderDir, path.basename(renderOutput), "tiles", "r" + tile.row + "c" + tile.column),
|
||||||
"--render-frame", settings.frame
|
"--render-frame", settings.frame
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
@ -145,7 +148,7 @@ import pathlib
|
|||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
basepath = "${renderOutput}/"
|
basepath = "${renderOutput}/"
|
||||||
renders = basepath + "samples/"
|
renders = basepath + "tiles/"
|
||||||
tmp = basepath + 'merge_tmp/'
|
tmp = basepath + 'merge_tmp/'
|
||||||
filenames = [f for f in os.listdir(renders) if os.path.isfile(renders + f)]
|
filenames = [f for f in os.listdir(renders) if os.path.isfile(renders + f)]
|
||||||
filenames.sort()
|
filenames.sort()
|
||||||
|
Loading…
Reference in New Issue
Block a user