HelloworldΒΆ

The typical Kubric workflow involves a worker file, that describes the scene and how to render it. Let us go through examples/helloworld.py line by line (full source at the bottom of this page).

First, we need to create a (default) scene and attach the renderer (Blender) to it.

scene = kb.Scene(resolution=(256, 256))
renderer = KubricRenderer(scene)

Next we will create a floor (i.e. cube), and add a sphere on top of it (with default materials).

scene += kb.Cube(scale=(10, 10, 0.1), position=(0, 0, -0.1))
scene += kb.Sphere(scale=1, position=(0, 0, 1.))

We also add a directional light to illuminate the scene, and a camera for rendering:

scene += kb.DirectionalLight(position=(-1, -0.5, 3), look_at=(0, 0, 0), intensity=1.5)
scene += kb.PerspectiveCamera(position=(2, -0.5, 4), look_at=(0, 0, 1))

We can export this scene as a Blender file to see what is happening (you will be able to open the blend file in Blender and inspect it as visualized in the screenshot below):

renderer.save_state("helloworld.blend")
Blender scene generated by Kubric

Or ask Blender to render an image (from the given camera):

layers = renderer.render_still()

The result is a dictionary of numpy arrays, each containing one layer of information exported by kubric. The relevant layers for now are:

  • the image (layers["rgba"])

  • the corresponding depth map (layers["depth"])

  • the (instance) segmentation map (layers["segmentation"])

We can save these array as PNG images using:

kb.write_png(frame["rgba"], "output/helloworld.png")
kb.write_palette_png(frame["segmentation"], "output/helloworld_segmentation.png")
scale = kb.write_scaled_png(frame["depth"], "output/helloworld_depth.png")
logging.info("Depth scale: %s", scale)

where the first line saves the RGBA image as a regular PNG, the second one saves the segmentation as a grayscale PNG but with an associated palette that makes it easier to visually see the segments, and the third line stores the depth map as a 16bit PNG after rescaling the values. This is necessary to accommodate the float32 depth values.

Image rendered by Kubric (via Blender) Depth image rendered by Kubric (via Blender) Segmentation image rendered by Kubric (via Blender)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import logging
import kubric as kb
from kubric.renderer.blender import Blender as KubricRenderer

logging.basicConfig(level="INFO")

# --- create scene and attach a renderer to it
scene = kb.Scene(resolution=(256, 256))
renderer = KubricRenderer(scene, scratch_dir="output_tmp")

# --- populate the scene with objects, lights, cameras
scene += kb.Cube(name="floor", scale=(10, 10, 0.1), position=(0, 0, -0.1))
scene += kb.Sphere(name="ball", scale=1, position=(0, 0, 1.))
scene += kb.DirectionalLight(name="sun", position=(-1, -0.5, 3), look_at=(0, 0, 0), intensity=1.5)
scene += kb.PerspectiveCamera(name="camera", position=(3, -1, 4), look_at=(0, 0, 1))

# --- render (and save the blender file)
renderer.save_state("output/helloworld.blend")
frame = renderer.render_still()

# --- save the output as pngs
kb.write_png(frame["rgba"], "output/helloworld.png")
kb.write_palette_png(frame["segmentation"], "output/helloworld_segmentation.png")
scale = kb.write_scaled_png(frame["depth"], "output/helloworld_depth.png")
logging.info("Depth scale: %s", scale)