1
$\begingroup$

I am trying to create a script that would render my scene multiple times (let's say, a hundred times), with only some minor changes after each render. What I am trying to do is to render something, then make a change, and then render again, and repeat this process. Right now, I currently face two problems

  1. How to ensure the rendering is first finished before any other changes are done? That means, render is commenced, finished, and then necessary changes are made to the scene? I already figured out that there exists a method in bpy.app.handlers (bpy.app.handlers.render_complete()) that triggers when rendering is done, but so far I did not figure out how to make it work. I am not even sure this is exactly the function I need and. Either way, I am not really sure about what argument is needed since documentation doesn't mention anything specifically.
  2. How to set a name for a file that is being rendered? Right now I am using OS library to rename a file after it is rendered (since the file is labelled as "" defaultly), but this seems like an extremely unreliable way to do it (also, it raises some other problems that might pop up later.
$\endgroup$
1

1 Answer 1

2
$\begingroup$

Example to do something after render

enter image description here

# make sure your blend file is saved and in object mode
import bpy, bmesh

bpy.context.scene.render.image_settings.file_format = 'PNG'
bpy.context.scene.render.resolution_percentage = 10

def remove_first_vert(object_name):  # object type must: 'MESH'
    oj = bpy.data.objects[object_name]
    bpy.ops.object.mode_set(mode='EDIT')
    me = oj.data
    bm = bmesh.from_edit_mesh(me)
    bm.verts.ensure_lookup_table()
    bmesh.ops.delete(bm, geom=[bm.verts[0]], context='VERTS')
    bmesh.update_edit_mesh(me)
    bpy.ops.object.mode_set(mode='OBJECT')


for r in range(4):
    bpy.context.scene.render.filepath = f"//img_{r}.png"
    bpy.ops.render.render(write_still=True)
    #  Interface locked until render finish

    remove_first_vert('Cube')

Print time when render done use bpy.app.handlers

enter image description here

# make sure your blend file is saved and in object mode
import bpy, bmesh

import time
from bpy.app.handlers import persistent
@persistent
def fn_print_time_when_render_done(dummy):
    print("----- the time is: ", time.time())

bpy.context.scene.render.image_settings.file_format = 'PNG'
bpy.context.scene.render.resolution_percentage = 10

def remove_first_vert(object_name):  # object type must: 'MESH'
    oj = bpy.data.objects[object_name]
    bpy.ops.object.mode_set(mode='EDIT')
    me = oj.data
    bm = bmesh.from_edit_mesh(me)
    bm.verts.ensure_lookup_table()
    bmesh.ops.delete(bm, geom=[bm.verts[0]], context='VERTS')
    bmesh.update_edit_mesh(me)
    bpy.ops.object.mode_set(mode='OBJECT')

bpy.app.handlers.render_complete.append(fn_print_time_when_render_done)

for r in range(4):
    bpy.context.scene.render.filepath = f"//img_{r}.png"
    bpy.ops.render.render(write_still=True)
    #  Interface locked until render finish

    remove_first_vert('Cube')

bpy.app.handlers.render_complete.remove(fn_print_time_when_render_done)
$\endgroup$

Not the answer you're looking for? Browse other questions tagged .