Python: Sliced Rendering#

Renders one 1024×1024 RenderProduct as four successive 512×512 dataWindowNDC crops. The example warms up each crop for 10 frames, captures the next LdrColor output, and stitches the TL, TR, BL, and BR tiles into one RGBA image.

“Render one image as four successive dataWindowNDC crops, warm up each crop, and stitch the captured TL, TR, BL, and BR tiles into a full-resolution image.”

Full image stitched from four rendered crops

The tested crop-update and stitching pattern is:

warmup_frames = 10

def capture(ordinal):
    for _ in range(warmup_frames):
        renderer.step(render_products={"/Render/Camera"}, delta_time=1.0 / 60, ordinal=ordinal)

    products = renderer.step(
        render_products={"/Render/Camera"},
        delta_time=1.0 / 60,
        ordinal=ordinal,
    )
    frame = products["/Render/Camera"].frames[-1]
    var = frame.render_vars[LDR_COLOR_PATH].map(device=ovrtx.Device.CPU)
    view = np.from_dlpack(var)
    pixels = view.copy()
    del view
    var.unmap()
    del var, frame, products
    return pixels

full_frame = capture(ordinal=1)
assert full_frame.shape == (512, 512, 4)
assert full_frame.dtype == np.uint8

slices = (
    # LdrColor rows follow dataWindowNDC's bottom-up Y order.
    ("TL", (0.0, 0.5, 0.5, 1.0), (256, 0)),
    ("TR", (0.5, 0.5, 1.0, 1.0), (256, 256)),
    ("BL", (0.0, 0.0, 0.5, 0.5), (0, 0)),
    ("BR", (0.5, 0.0, 1.0, 0.5), (0, 256)),
)
stitched = np.empty((512, 512, 4), dtype=np.uint8)

with ovstage.PathDictionary(stage) as paths:
    path_list = paths.create_path_list_from_strings(["/Render/Camera"])
    try:
        with stage.query_from_path_list(path_list) as query:
            attribute = paths.intern_token("dataWindowNDC")
            crop_dtype = ovstage.numpy_to_dldatatype(np.dtype(np.float32), lanes=4)

            for ordinal, (label, crop_ndc, (dst_y, dst_x)) in enumerate(slices, start=2):
                crop_values = np.asarray([crop_ndc], dtype=np.float32)
                crop_tensor = ovstage.make_dltensor(
                    crop_values,
                    dtype=crop_dtype,
                    shape=[1],
                    ndim=1,
                )
                stage.write_attribute(
                    query,
                    attribute,
                    ordinal=ordinal,
                    tensors=crop_tensor,
                    is_array=False,
                ).wait()
                stage.advance_write_floor(ordinal, ovstage.Scope.ALL).wait()

                pixels = capture(ordinal)
                assert pixels.shape == (256, 256, 4)
                assert pixels.dtype == np.uint8
                reference_tile = full_frame[dst_y : dst_y + 256, dst_x : dst_x + 256, :3]
                tile_error = np.abs(
                    pixels[:, :, :3].astype(np.int16) - reference_tile.astype(np.int16)
                ).mean()
                assert tile_error < 8.0, f"{label} tile differs from its full-frame region: MAE={tile_error}"
                stitched[dst_y : dst_y + 256, dst_x : dst_x + 256] = pixels
    finally:
        paths.destroy_path_list(path_list)

Image.fromarray(full_frame).save(output_dir / "base.Camera.LdrColor.full.png")
Image.fromarray(stitched).save(output_dir / "base.Camera.LdrColor.sliced.png")

Prerequisites#

  • Python 3.10-3.13

  • uv

  • An NVIDIA RTX-capable GPU and a supported driver

Running#

cd examples/python/sliced-rendering
uv run main.py

Pass --png to save _output/render.png instead of displaying the image.