I'm quite fluent with programming in general, and scripting in 3D (particularly with Houdini, python+vex), but I'm new to scripting in Blender.
What I'd like to do is render each frame of an animation multiple times with different textures (and eventually, more different parameters, but I'll get to that once this is done).
texture_paths = [...] # list of paths to textures
for frame in range(1, num_frames):
for texture_path in texture_paths:
set_texture(texture_path)
texture_name = os.path.splitext(os.path.basename(texture_path))[0]
output_path = os.path.join(output_root, texture_name, f'{texture_name}.{frame}.exr'
set_render_path(output_path)
render_frame(frame)
Looking around, I think set_render_path
and render_frame
could be defined as follows (pls correct if wrong or if there are gotchas I'm missing)
def set_render_path(output_path):
bpy.context.scene.render.filepath = output_path
def render_frame(frame):
bpy.context.scene.frame_set(frame)
bpy.ops.render.render(animation=False, write_still=True)
but I can't for the life of me figure out how to programmatically change the texture (i.e. image in an image node in a shader graph). When I look at the log when I manually load an image via the GUI, it just says bpy.ops.image.open
. So it seems this is dependent on which node and context is active. When I select the node on which I'd like to change the texture, the log says bpy.ops.node.select(deselect_all=True, select_passthrough=True, location=(248, 328))
! Which seems like it's selecting based on where my mouse clicked, which seems insane! I.e. if I organize my node graph, will my script stop working? (in Houdini, I would simply access any node - even parameter - directly via a hierarchy of unique IDs. E.g. "/context/parent/child/node/parameter").
How can I programmatically change the image of a specific image node in a shader graph in Blender?
(I did see this post, but they solved it by duplicating objects and materials, and hiding objects before render. This is not feasible for me as I have dozens of textures. Changing texture on the fly would be much more preferable if possible.)