Python: Light Path Expressions#

This example sublayers the robot-lineup scene, adds diffuse-reflection, glossy-reflection, glossy-transmission, and caustics LPE RenderVars alongside HdrColor, renders them in Path Tracing mode, and converts the results to sRGB uint8 images for Rerun or PNG output.

Beauty, diffuse reflection, glossy reflection, glossy transmission, and caustics outputs from the robot-lineup scene

The beauty image and four LPE outputs rendered from the same camera.#

“Create a compact ovrtx example that composes an existing scene with reflection, transmission, and caustics LPE RenderVars, renders them with HdrColor, and records sRGB ``uint8`` images.”

See Light Path Expressions for LPE syntax, authoring, labels, and limitations.

Authoring#

The example layer applies the PathTracing settings schema, disables radiance caching, and requests beauty plus four LPE outputs. The USDA and usd-core snippets below author equivalent RenderProducts.

def "Render"
{
    def RenderProduct "Camera" (
        prepend apiSchemas = ["OmniRtxSettingsPtAdvancedAPI_1"]
    )
    {
        bool omni:rtx:pt:radianceCache:enabled = false
        bool omni:rtx:pt:denoising:enabled = true
        bool omni:rtx:pt:denoising:optix:denoiseAOVs = true
        uint omni:rtx:pt:samplesPerPixel = 128
        rel camera = </World/Camera>
        int2 resolution = (1920, 1080)
        token omni:rtx:rendermode = "PathTracing"
        rel orderedVars = [<HdrColor>, <DiffuseReflection>, <GlossyReflection>, <GlossyTransmission>, <Caustics>]

        def RenderVar "HdrColor"
        {
            string sourceName = "HdrColor"
        }

        def RenderVar "DiffuseReflection"
        {
            string sourceName = "E<RD>.*L"
            token sourceType = "lpe"
        }

        def RenderVar "GlossyReflection"
        {
            string sourceName = "E<RG>.*L"
            token sourceType = "lpe"
        }

        def RenderVar "GlossyTransmission"
        {
            string sourceName = "E<TG>.*L"
            token sourceType = "lpe"
        }

        def RenderVar "Caustics"
        {
            string sourceName = "EDG.*L"
            token sourceType = "lpe"
        }
    }
}
render_product = UsdRender.Product.Define(stage, "/Render/Camera")
render_product.GetPrim().ApplyAPI("OmniRtxSettingsPtAdvancedAPI_1")
render_product.GetCameraRel().SetTargets(["/World/Camera"])
render_product.GetResolutionAttr().Set(Gf.Vec2i(1920, 1080))
render_product.GetPrim().CreateAttribute(
    "omni:rtx:rendermode", Sdf.ValueTypeNames.Token
).Set("PathTracing")
render_product.GetPrim().GetAttribute("omni:rtx:pt:radianceCache:enabled").Set(False)
render_product.GetPrim().GetAttribute("omni:rtx:pt:denoising:enabled").Set(True)
render_product.GetPrim().GetAttribute("omni:rtx:pt:denoising:optix:denoiseAOVs").Set(True)
render_product.GetPrim().GetAttribute("omni:rtx:pt:samplesPerPixel").Set(128)

expressions = {
    "DiffuseReflection": "E<RD>.*L",
    "GlossyReflection": "E<RG>.*L",
    "GlossyTransmission": "E<TG>.*L",
    "Caustics": "EDG.*L",
}
render_vars = []
hdr_var = UsdRender.Var.Define(stage, "/Render/Camera/HdrColor")
hdr_var.GetSourceNameAttr().Set("HdrColor")
render_vars.append(hdr_var.GetPath())
for name, expression in expressions.items():
    render_var = UsdRender.Var.Define(stage, f"/Render/Camera/{name}")
    render_var.GetSourceNameAttr().Set(expression)
    render_var.GetSourceTypeAttr().Set(UsdRender.Tokens.lpe)
    render_vars.append(render_var.GetPath())
render_product.GetOrderedVarsRel().SetTargets(render_vars)

Reading The Outputs#

The example maps every returned RenderVar, copies it before unmapping, and converts linear floating-point outputs to display-ready sRGB images.

def read_lpe_outputs(frame) -> dict[str, np.ndarray]:
    images = {}
    for render_var_path, render_var in frame.render_vars.items():
        # Copy before unmapping so each image remains valid after this iteration.
        pixels = _map_render_var(render_var)
        if pixels.dtype == np.uint8:
            image = np.ascontiguousarray(pixels[..., :3])
        elif np.issubdtype(pixels.dtype, np.floating):
            # HdrColor and LPE outputs are linear Rec.709 floating-point images.
            image = _linear_rec709_to_srgb_uint8(pixels)
        else:
            raise TypeError(
                f"Unsupported image dtype for {render_var_path}: {pixels.dtype}"
            )

        print(
            f"  {render_var_path}: shape={pixels.shape}, dtype={pixels.dtype}",
            file=sys.stderr,
        )
        images[render_var_path] = image
    return images


Running#

uv run main.py
uv run main.py --rrd _output/lpes.rrd
uv run main.py --no-rr --png _output/light-path-expressions.png

The first run may take several minutes while shaders compile and cache.