Hello,
I am building an addon that can export passes to a numpy array. Unfortunately, it doesn’t seem like it is something one can do easily.
My current (and not working) solution is to get the pixel values from a viewer node bpy.data.images["Viewer Node"].pixels
. While this work for one pass, when I try to change the input of the viewer node via a script, the pixel values does not update to the ones of the new pass (but the link is correctly created because when I switch back to the compositing tab, it is there).
My piece of code to change the viewer node’s input:
def pass_to_viewernode(pass_name: str):
tree = bpy.context.scene.node_tree
rl_node = tree.nodes.get("Render Layers")
composite_node = tree.nodes.get("Viewer")
render_pass = rl_node.outputs[pass_name]
tree.links.new(render_pass, composite_node.inputs[0], True)
I found out that by manually moving the link back into the viewer node input will trigger an update of the pixel values, but it is not a behaviour I succeeded to reproduce via a script.
The other piece of code I am using to save the array. It will only save the same array n times, with n being the number of passes to save.
def get_pass_img(passname: str, n_channels: int, dtype: str):
pass_to_viewernode(passname)
bpy.data.images["Viewer Node"].reload()
pixels = deepcopy(bpy.data.images["Viewer Node"].pixels)
viewer = np.array(pixels)
viewer = viewer.reshape((1024, 2048, -1))[:, :, :n_channels]
viewer = viewer.astype(dtype)
return viewer
bpy.ops.render.render(write_still=True)
rendered_passes = {}
for passname, pass_data in render_passes.items():
pass_img = get_pass_img(passname, **pass_data)
rendered_passes[passname] = pass_img
np.savez_compressed(savedir / str(image_id), **rendered_passes)
Do you have any workaround to trigger the update of the node via a script (I know that bpy.ops.render.render will do, but it will also rerender the entire frame which takes time considering the large number of assets) ?
Thank you for your time.