2
$\begingroup$

I am trying to render a scene and its depth map using the Python APIs of Blender 2.8. I created a rendering node and connected its Image and Depth fields to two Output nodes, writing to PNG and EXR, respectively.

I managed to render with Blender 2.8 many scenes created with Blender versions older than 2.8. However, when I try to render the Blender 2.8 classroom or barber shop demos, I get no output. Basically the nodes are ignored.

The classroom file can be found at https://www.blender.org/download/demo-files/ and the script that I am using is the one below.

Thanks in advance for any help :)

import bpy
import os
import numpy as np

# Remove all the cameras in the scene.
bpy.ops.object.select_all(action='DESELECT')
for i, item in enumerate(bpy.data.objects):
    if item.type == 'CAMERA':
        bpy.data.objects[i].select_set(True)
        bpy.ops.object.delete()

# Create a new camera. Like every newly created object, the camera is automatically assigned to `bpy.context.object`.
bpy.ops.object.camera_add()
cam = bpy.context.object

# Rename the new camera (not necessary).
cam.name = 'Camera_360'

# Turn the camera into an omnidirectional one.
cam.data.type = 'PANO'
cam.data.cycles.panorama_type = 'EQUIRECTANGULAR'

# Set the rendering range: every object between the two bounds below will be rendered.
cam.data.clip_start = 0.0
cam.data.clip_end = 1000.0
# The upper bound should be specified for each blender project:
# `1000` may represent a large distance in one project and a small one somewhere else.

# List of camera resolutions.
# resolutions = [(512, 256), (1024, 512)]
resolutions = [(512, 256)]

# List of camera positions in the scene.
camera_coordinates = [(0, 0, 1)]

# Define the camera field of view.
cam.data.cycles.latitude_min = (- np.pi / 2.0)
cam.data.cycles.latitude_max = np.pi / 2.0
cam.data.cycles.longitude_min = (- np.pi)
cam.data.cycles.longitude_max = np.pi

# Define the camera rotation.
# The rotation follows the rule of the right hand.
cam.rotation_euler[0] = np.pi / 2.0     # Along x.
cam.rotation_euler[1] = 0.0             # Along y.
cam.rotation_euler[2] = 0.0             # Along z.

# Specify the device.
computation_type = 'CUDA'
gpu_id = (3,)

# Set the number of rendering samples.
# bpy.context.scene.cycles.samples = 5000
bpy.context.scene.cycles.samples = 50

# Select the computing device.
prefs = bpy.context.preferences.addons['cycles'].preferences
devices = prefs.get_devices()
if computation_type == 'CUDA':
    bpy.context.scene.cycles.device = 'GPU'
    prefs.compute_device_type = 'CUDA'
    for i, gpu in enumerate(devices[0]):
        gpu.use = (i in gpu_id)

# Assign the new camera to the scene.
bpy.context.scene.camera = cam

# Activate the use of nodes.
bpy.context.scene.use_nodes = True

# Render an image for any pair ((width, height), (x, y, z)).
for width, height in resolutions:
    for x, y, z in camera_coordinates:

        # Set the camera parameters.
        bpy.context.scene.render.resolution_percentage = 100
        bpy.context.scene.render.resolution_x = int(width)
        bpy.context.scene.render.resolution_y = int(height)
        bpy.context.scene.camera.location.x = float(x)
        bpy.context.scene.camera.location.y = float(y)
        bpy.context.scene.camera.location.z = float(z)
        tree = bpy.context.scene.node_tree
        links = tree.links
        rl = tree.nodes.new(type="CompositorNodeRLayers")

        # Depth map.
        fileDepthOutput = tree.nodes.new(type="CompositorNodeOutputFile")
        fileDepthOutput.format.file_format = 'OPEN_EXR'
        fileDepthOutput.base_path = 'outputImages/{w}_{h}'.format(w=width, h=height)
        fileDepthId = 'test_{x}_{y}_{z}_{w}_{h}_depth_'.format(x=x, y=y, z=z, w=width, h=height)
        fileDepthOutputSocket = fileDepthOutput.file_slots.new(fileDepthId)
        links.new(rl.outputs['Depth'], fileDepthOutputSocket)

        # Texture.
        fileTextureOutput = tree.nodes.new(type="CompositorNodeOutputFile")
        fileTextureOutput.format.file_format = 'PNG'
        fileTextureOutput.base_path = 'outputImages/{w}_{h}'.format(w=width, h=height)
        fileTextureOutputId = 'test_{x}_{y}_{z}_{w}_{h}_'.format(x=x, y=y, z=z, w=width, h=height)
        fileTextureOutputSocket = fileTextureOutput.file_slots.new(fileTextureOutputId)
        links.new(rl.outputs['Image'], fileTextureOutputSocket)

        # Launch the rendering.
        bpy.ops.render.render(write_still=False)

        # Clean the created nodes.
        bpy.context.scene.node_tree.nodes.remove(fileTextureOutput)
        bpy.context.scene.node_tree.nodes.remove(fileDepthOutput)
$\endgroup$
0
3
$\begingroup$

The reason for that is that the compositor is disabled by default in those scenes. To enable the compositor check "Compositing" under "Post Processing" in the "Output" tab.

Compositing option

$\endgroup$
1
  • $\begingroup$ @Mattia In order to enable this by script set bpy.context.scene.render.use_compositing = True. Note that the project contains multiple scenes which are used in the compositor. If you want to save the image with the compositing effect, you'll have to connect your File Output node to the same image output that is connected to the Composite node (in this case the Switch node). Additionally you would have to enable compositing, adjust the resolution and place the camera for the other scenes as well. $\endgroup$
    – Robert Gützkow
    Dec 12 '19 at 23:06

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.