Transparent backgrounds in Blender Python scripts

Creating 3D models in Blender 3 is a lot of fun, and being able to render them into high-quality images takes that to a whole new level. And, in the movies, computer generated imagery is often composited over other images and video using chroma-keying (e.g. green-screening). So it’s really amazing that Blender lets us create images with just our models and no background, so we can add a chroma-keyed background or simply add a background image as a layer under the render in our favourite image editor. So obviously I wanted to find out how to set that up in a Blender Python script.

Obviously we could just set the world background colour, say to green. But that has the disadvantage that we’re limited to chroma-keying and that could mean lower quality outputs than properly-transparent backgrounds. Plus, a coloured world background reflects light, causing ugly colour-casts over our models that can be hard to mitigate. It could also seem a good idea to use a black world background with zero alpha, but it turns out that doesn’t work either. In fact, the way to do it is quite simple: we just use Blender’s ‘film_transparent’ render setting!

So, as a simple example, we can just open Blender and use the default cube, camera and light. Then switch to the scripting layout so we can edit our Python code. If you don’t fancy copying and pasting you can head to the Parth3D Github repo and download it to open in the scripting section. You should then end up with a Blender window that looks like the screenshot below (albeit without any code if you’re going to copy and paste as we go along). Any time you want to save your code just head to the ‘Text’ menu above the code, and select ‘Save’. And note that the cube is in object mode, although it should work fine in edit mode too.

Code in the Blender scripting layout.

The first thing we need to do is import the bpy library, which is a library Blender provides that helps us interact with it from Python scripts. Then we use it to set our renderer to Eevee, simply to make rendering quicker: you can change ‘BLENDER_EEVEE’ to ‘CYCLES’ if you want, but with only a single cube in the scene it won’t give amazing improvements.

import bpy

# Set the renderer to Eevee
bpy.context.scene.render.engine = 'BLENDER_EEVEE'

Now comes the exciting part: we’re going to set up the renderer’s output image settings so that it has an alpha channel. That means we can save the renders to an 8-bits-per-channel PNG image that will preserve transparency. The code is below, which uses the bpy library to access the render image settings.

# Set the image format to an 8-bit PNG with alpha channel
bpy.context.scene.render.image_settings.file_format = 'PNG'
bpy.context.scene.render.image_settings.color_mode = 'RGBA'
bpy.context.scene.render.image_settings.color_depth = '8'

Now, let’s also set the size of the render image in a similar way, again using bpy. I decided to render to a VGA image (640×480 pixels) simply to keep the render time down. However, for a simple test, there’s no need to use a high-resolution image. But for your own scenes you can set it to whatever resolution you need.

# Set the size of the image to render
bpy.context.scene.render.resolution_x = 640
bpy.context.scene.render.resolution_y = 480

The code below is the ‘magic potion’ that’s going to make our renders have a transparent background. This is where we use bpy to set the ‘film_transparent’ mode: True will make our backgrounds transparent, and False will make them opaque.

# Tell Blender to render the background transparent
bpy.context.scene.render.film_transparent = True

The last thing we need to do is tell Blender to output our render to an image file, which is quite easy, as you can see below, using bpy. However, if we just give the code a filename (e.g. ‘test.png’) Blender can try to save the image to a file in the folder it lives in. And that can even mean it fails with an error that it doesn’t have permission to save the file there. So we’re using another feature of bpy that tells us the absolute path for the scene file. We then simply append the filename to that path. For that reason, don’t forget to save the Blender scene now, before running the code.

# We save the file in the same place as the blender file
fname = bpy.path.abspath("//") + "backgroundtest.png"

# Render our image of the scene through the default camera
bpy.context.scene.render.filepath = fname
bpy.ops.render.render(write_still=True)

Now all you need to do is run the script. If you haven’t done any scripting in Blender you can do that by clicking the little white triangle button at the top right of the code area. Of course, you could also just run the script from a commandline terminal (using Cycles), and it will work the same. But that’s a bit more advanced for this example. When the script runs you won’t see anything exciting happen, but you should find a file called ‘backgroundtest.png’ in your scene-file folder. If you open it you should see something like the image below.

The saved render image, the checkerboard pattern representing transparency.

And that’s all there is to it! You should now be able to open the image in your favourite image editor (e.g. GIMP, Photoshop or Paint Shop Pro) and simply insert a layer below it. When you paste another image into that new under-layer, or fill it with green, you should see that the cube stays and the background changes. And if you’re doing a movie (e.g. by animating the scene in the Python code and saving multiple render-frames) you can automate the compositing, such as with Python scripts or some Processing code. You can even use Processing to add a dynamic background that changes with time, save the compositied frames, and then use their movie-maker to create your own CGI video clip. Basically, with some simple code, we can create some quite exciting results 🙂