I've read quite a few posts about this issue but couldn't find out why it's not working in my case. I'm generating a large amount of images and want to add random hdr background images. I'm using the following code

scene = bpy.context.scene
scene.render.use_compositing = True
scene.use_nodes = True
nodes = bpy.context.scene.node_tree.nodes.values() # from last iteration, remove
for node in nodes:
renderNode = scene.node_tree.nodes.new('CompositorNodeRLayers')
compositeNode = scene.node_tree.nodes.new('CompositorNodeComposite')
AlphaNode = scene.node_tree.nodes.new('CompositorNodeAlphaOver')
BackgroundNode = scene.node_tree.nodes.new('CompositorNodeImage')
bg_path = random.choice(self.background_files)
if bg_path == None:
    bg_img = self.__load_or_reuse(bg_path)
    BackgroundNode.image = bg_img.copy()
    #BackgroundNode.image = self.load_background()
    print("background", BackgroundNode.image)
    scene.node_tree.links.new(compositeNode.inputs['Image'], AlphaNode.outputs['Image'])
    scene.node_tree.links.new(AlphaNode.inputs[1], BackgroundNode.outputs['Image'])
    scene.node_tree.links.new(AlphaNode.inputs[2], renderNode.outputs['Image'])
    scene.node_tree.links.new(compositeNode.inputs['Z'], renderNode.outputs['Depth'])
    scene.node_tree.links.new(compositeNode.inputs['Alpha'], renderNode.outputs['Alpha'])

which prints: background <bpy_struct, Image("large_corridor_2k.hdr.002") at 0x7fd7c11d5a08> and the following code to store images as PNG's:

        bpy.context.scene.render.image_settings.file_format = 'PNG'
        bpy.context.scene.render.image_settings.use_zbuffer = False
        bpy.context.scene.render.filepath = os.path.join(self.render_path, "render_full" + ".png")
        bpy.ops.render.render(write_still = True)

It doesn't matter whether I use Cycles or Eevee:

    #bpy.context.scene.render.engine = 'CYCLES' #later
    #bpy.context.scene.cycles.device = "GPU"
    #bpy.context.scene.cycles.feature_set = "SUPPORTED"
    bpy.context.scene.render.film_transparent = True
    bpy.context.scene.render.engine = 'BLENDER_EEVEE'
    bpy.context.scene.render.image_settings.file_format = 'OPEN_EXR'
    bpy.context.scene.render.image_settings.use_zbuffer = True

I can see the image in the viewer, but the stored images just have the objects and the grey-grey squares as background. I would prefer to skip some addons for this task as the script will run on servers and there it's beneficial to use the vanilla blender.

What else could I try?

  • $\begingroup$ Don't get your issue. You'd like to render random background layers (by flattening a few hdris) and then put another transparent image on top of them using the compositor? $\endgroup$
    – brockmann
    Aug 24 '21 at 8:38
  • $\begingroup$ I am generating a large amount (N) scenes. For each single scene I want exactly one HDRi image as background image. I have a large set of HDRi images from which I pick randomly and the scenes are generated randomly. The scene is showing up on the rendered image, the HDRi image was not. A common recommendation here on SE to fix this was using an AlphaOver node to get the HDRi Background into the rendered image. That was not working in my case and I wonder why. $\endgroup$
    – ZuseZ3
    Aug 24 '21 at 23:13
  • $\begingroup$ You can get the hdri rendered by default without any compositing, the reason why I was asking what you are trying to do. How you can load the hdris from a folder called 'hdrs' in the same folder as the blend file: pasteall.org/4XLV/raw When running the script, the output of the default scene is: i.stack.imgur.com/LKhYQ.jpg, related: blender.stackexchange.com/questions/209584/… $\endgroup$
    – brockmann
    Aug 25 '21 at 6:54

As already explained in Using Python to add an HDRI to world node, you can use BlendDataImages.load() to load and assign the image to the Environment Texture node. How you can get a reference to any shader node is nicely explained in Control Cycles/Eevee material nodes and material properties using python? (same principle for world shader nodes).

Demo on how to iterate through a list of images (by using the default hdris that comes with blender), assign each to the world background of the default scene, set the render path based on the hdris and render in one go:

enter image description here

import bpy
import os

C = bpy.context
scn = C.scene

folder = bpy.path.abspath("//hdrs")
hdris = [os.path.join(folder, f) for f in os.listdir(folder) if f.endswith(".exr")] 

# Get the environment node tree of the current scene
node_tree = scn.world.node_tree
tree_nodes = node_tree.nodes

# Get the environment texture node
node_environment = tree_nodes.get("__PLACEHOLDER__")

if node_environment:
    # Iterate through the hdri list
    for hdri in hdris:
        # Load and assign the image to the node property
        node_environment.image = bpy.data.images.load(hdri)
        # Set the output path and render (jpg is a placeholder)
        hdr_folder, hdr_file = os.path.split(hdri)
        hdr_name, hdr_ext = os.path.splitext(hdr_file)
        scn.render.filepath = bpy.path.abspath("//rndr_{}.jpg".format(hdr_name))


Make sure to disable Film > Transparent property otherwise the rendering will be transparent.

>>> C.scene.render.film_transparent = False

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.