# keeping render layers at their original resolution when composed

I wrote a script to generate a multiview render of an animation. You can see the result 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
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)

for j in range(N_PERSP_x):
bpy.context.screen.scene=basescene
# print('A bpy.context.screen.scene',bpy.context.screen.scene)
#

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)
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')

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')
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?

• '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... Dec 13, 2018 at 13:51
• @MartinZ hope it is clearer now Dec 13, 2018 at 15:37
• 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? Dec 13, 2018 at 15:45
• it is for an animation.. I was also hoping that rendering the same perspective from different perspective could save some computations... Dec 13, 2018 at 16:24

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.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
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
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))