0
$\begingroup$

I wrote a script to generate a multiview render of an animation. You can see the result here enter image description here Still everything is rendered at the resolution of the final image and then scaled down. This wastes a lot of time. I want to render the input render layers at their original resolution and then compose them in the larger image that is the composite layer output. But it appears that the resolution of the final channel large image defines the resolution of all the renderings. Setting the original render layers resolution does not seem to change anything.

So the composite node has a resolution Nbase_x X Mbase_y and the NXM components have resolution base_x X base_y. All these quantities are fixed for the all animation. When rendering I see that also the original images are scaled and fit to Nbase_x X Mbase_y.

Does anybody have any suggestion?

It would save a lot of time to render the component at the actual resolution.

Here is the code

bpy.ops.scene.new(type='NEW')
sizescene=bpy.context.screen.scene
sizescene.render.resolution_y = len(anglelist_y)*resy
sizescene.render.resolution_x = N_PERSP_x*resx
sizescene.render.resolution_percentage=100

bpy.context.scene.use_nodes = True
tree = bpy.context.scene.node_tree
# clear default nodes
for node in tree.nodes:
    print(node,node.name)
    tree.nodes.remove(node)

new_render_layer_node = tree.nodes.new(type = 'CompositorNodeRLayers')
new_render_layer_node.location.x=-200
new_render_layer_node.scene=sizescene
new_render_layer_node.layer=sizescene.render.layers.active.name
bpy.ops.object.camera_add(view_align=False,
                           location=[0, 0, 0],
                           rotation=[(pi/2), 0, (2*pi)])



last_node=new_render_layer_node
for i in range(len(anglelist_y)):

   blender_angle_y = -anglelist_y[i] + (pi/2)

   z = RADIUS*math.cos(blender_angle_y)
   zz= RADIUS*math.sin(blender_angle_y)
   for j in range(N_PERSP_x):
       bpy.context.screen.scene=basescene
       # print('A bpy.context.screen.scene',bpy.context.screen.scene)
       bpy.ops.scene.new(type='LINK_OBJECTS')
       # 

       newscene=bpy.context.screen.scene
       bpy.context.screen.scene.name='scene_h_'+ str(i)+'_w_'+str(j)
       new_render_layer =  newscene.render.layers.new('rl_h_'+ str(i)+'_w_'+str(j)) 
       newscene.render.layers.active = new_render_layer
       bpy.context.screen.scene.render.layers.active=new_render_layer
       new_render_layer_node = tree.nodes.new(type = 'CompositorNodeRLayers')
       new_render_layer_node.scene=newscene
       new_render_layer_node.layer=new_render_layer.name
       new_render_layer_node.location.x = 200*i
       new_render_layer_node.location.y = 400*j
       new_render_layer_node.name='rl_h_'+ str(i)+'_w_'+str(j)

       new_scale_node = tree.nodes.new(type = 'CompositorNodeScale')
       new_scale_node.inputs[1].default_value=1.0/N_PERSP_x
       new_scale_node.inputs[2].default_value=1.0/len(anglelist_y)
       links = tree.links
       link = links.new(new_render_layer_node.outputs[0], new_scale_node.inputs[0])
       new_scale_node.hide=True
       new_scale_node.location.x = 1000+200*i
       new_scale_node.location.y = 400*j

       new_transf_node = tree.nodes.new(type = 'CompositorNodeTranslate')

       link = links.new(new_scale_node.outputs[0], new_transf_node.inputs[0])
       new_transf_node.inputs[1].default_value=resx*(j-(N_PERSP_x-1)/2.0)#/N_PERSP_x
       new_transf_node.inputs[2].default_value=resy*(i-(len(anglelist_y)-1)/2.0)#/(len(anglelist_y))
       new_transf_node.hide=True
       new_transf_node.location.x = 1000+200*i+100
       new_transf_node.location.y = 400*j

       if last_node is None:
          last_node=new_transf_node
       else:
          alphanode=tree.nodes.new(type = 'CompositorNodeAlphaOver')
          link = links.new(new_transf_node.outputs[0], alphanode.inputs[2])
          link = links.new(last_node.outputs[0], alphanode.inputs[1])
          alphanode.location.x = 2000+200*i
          alphanode.location.y = 200*j
          last_node=alphanode

ps: Would baking be of any help with an high number of cameras?

$\endgroup$
  • 1
    $\begingroup$ 'Does anybody have any suggestion?' - What kind of suggestions are you after? You described what you are doing, however you have not stated what you are trying to achieve anywhere. How are we supposed to know? It's a question and answer site - I think it might be a good idea to start with an actual question... $\endgroup$ – Martin Z Dec 13 '18 at 13:51
  • $\begingroup$ @MartinZ hope it is clearer now $\endgroup$ – Dimitri Ognibene Dec 13 '18 at 15:37
  • 1
    $\begingroup$ What if you render them at a small resolution, then save them to disk with the file output node and then combine the images later? $\endgroup$ – Leander Dec 13 '18 at 15:45
  • $\begingroup$ it is for an animation.. I was also hoping that rendering the same perspective from different perspective could save some computations... $\endgroup$ – Dimitri Ognibene Dec 13 '18 at 16:24
1
$\begingroup$

At this time it is not possible to practically change the output resolution during the render process of an animation in between rendering frames. If Python is used and rendering is done with a custom animation render operator that would change resolution in between frames it does not allow to preview the rendered images in the UI because of the way scripting and multi-threaded rendering works in Blender(long story...) and that may be a problem, because you cannot see if the render does not contain any mistakes until it's complete.

It seems the best thing to do would be to render the images at needed resolution and then combine them into higher resolution result after the rendering is done. This can be done automatically using Python. I would have attempted to provide more detailed help with that if more information was provided. I can still share a script I use to combine renders split into separate tile grid(3x3,4x4 and so on) for rendering on a render farm. I use it for combining stills so it's for one image at a time, however this can be done with image sequences instead of images. Have a look at the code, maybe it will help you come up with something:

import bpy, os
from mathutils import Vector

folder = 'C:\\SplitRender\\'
n = 3 

def path_iterator(some_folder):
    for fp in os.listdir(some_folder):
        if fp.endswith( tuple( bpy.path.extensions_image ) ):
            yield fp

images = [] 
for imgPath in path_iterator( folder ):
    if 'Combined' not in imgPath:
        if imgPath not in bpy.data.images: 
            fullPath = os.path.join( folder, imgPath )
            a = bpy.data.images.load(fullPath)
        a = bpy.data.images.get(imgPath)
        images.append(a)
bpy.context.scene.render.resolution_x = a.size[0]*n
bpy.context.scene.render.resolution_y = a.size[1]*n

bpy.context.scene.use_nodes = True
tree = bpy.context.scene.node_tree
links = tree.links     
for every_node in tree.nodes:
    tree.nodes.remove(every_node)   

image_location = Vector((0,0))
offset = Vector((0,-35))    

comp_node = tree.nodes.new('CompositorNodeComposite')   
comp_node.location = 600,0  
count = 0      
for im in images:
    image_node = tree.nodes.new(type='CompositorNodeImage')
    image_node.image = im
    image_location += offset
    image_node.location = image_location 
    image_node.hide = True
    image_node.width_hidden = 60
    translate_node = tree.nodes.new(type='CompositorNodeTranslate')
    translate_node.location = image_location + Vector((170,0))
    translate_node.hide = True
    translate_node.width_hidden = 60
    translate_node.use_relative = False
    step_x = a.size[0]
    step_y = a.size[1]
    steps_side = count%n
    steps_up = count//n 
    reverse = (steps_up%2*-2)+1
    translate_node.inputs[1].default_value = -reverse*(step_x+(step_x/2)*((n+1)%2)) + step_x*steps_side*reverse
    translate_node.inputs[2].default_value = -step_y -(step_y/2)*((n+1)%2) + step_y*steps_up
    links.new(image_node.outputs[0], translate_node.inputs[0])
    if count == 0:
        last_node = translate_node
    else:
        mix_node = tree.nodes.new(type='CompositorNodeAlphaOver')
        mix_node.hide = True
        mix_node.width_hidden = 40
        mix_node.location = image_location + Vector((360,0))
        links.new(last_node.outputs[0], mix_node.inputs[1])
        links.new(translate_node.outputs[0], mix_node.inputs[2])
        last_node = mix_node

    count+=1
    #print(im.name + '_____' + str(reverse))
links.new(last_node.outputs[0], comp_node.inputs[0])

bpy.context.scene.render.filepath = folder + 'Combined'

bpy.ops.render.render(write_still=True)
$\endgroup$
  • $\begingroup$ actually I don't change size of the animation during rendering. It is only that the composite node has a resolultion Nbase_x X Mbase_y and the NXM components have resolution base_x X base_y. all these quantities are fixed for the all animation. I can also render without preview in headless mode if this helps.. I don't have a render farm $\endgroup$ – Dimitri Ognibene Dec 13 '18 at 18:11
  • 1
    $\begingroup$ In order to composite and output bigger resolution result you would need to change render dimensions after all the smaller render layers are rendered. So you would need to change resolution multiple times in between rendering frames consisting of multiple render layers. I do not recommend this solution. It will be easier to render everything out and then combine everything after that. You do not need a render farm, you can just have a look at how the script works it is similar to what you need. $\endgroup$ – Martin Z Dec 13 '18 at 20:12
  • $\begingroup$ thanks a lot. At the moment I'm not costumizing the rendering phases. I just create the scene and render it from the guy but I'll move to purely batch rendering soon. So for what I understand there is no way to keep rendering at low resolution and then integrating in the compositor? Otherwise, could you share the code you use to create the components? Any idea about baking... I'm not interested in too realistic output.. just in speed and multiple views $\endgroup$ – Dimitri Ognibene Dec 13 '18 at 23:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.