Python: Gaussian Splats#

Render 73 procedural Gaussian splats: three colored rings and a soft white splat, above the existing documentation ground with studio lighting. The scene uses local documentation assets and needs no captured Gaussian dataset.

The scene defines a ParticleField3DGaussianSplat prim. The following USDA declaration and equivalent Python code show one orange splat. The supplied scene uses the same array layout for all 73 splats. See Gaussian Splats for the attribute meanings.

def ParticleField3DGaussianSplat "Splat" {
    point3f[] positions = [(0, 0, 0)]
    quatf[] orientations = [(1, 0, 0, 0)]
    float3[] scales = [(1, 0.5, 0.25)]
    float[] opacities = [0.9]
    uniform int radiance:sphericalHarmonicsDegree = 0
    # SH0 = (linear RGB - 0.5) / 0.2820947918; this is orange RGB (1, .3, 0).
    float3[] radiance:sphericalHarmonicsCoefficients = [(1.772454, -0.708982, -1.772454)]
}
splat = stage.DefinePrim("/Splat", "ParticleField3DGaussianSplat")
splat.CreateAttribute("positions", Sdf.ValueTypeNames.Point3fArray, custom=False).Set([(0, 0, 0)])
splat.CreateAttribute("orientations", Sdf.ValueTypeNames.QuatfArray, custom=False).Set([Gf.Quatf(1)])
splat.CreateAttribute("scales", Sdf.ValueTypeNames.Float3Array, custom=False).Set([(1, 0.5, 0.25)])
splat.CreateAttribute("opacities", Sdf.ValueTypeNames.FloatArray, custom=False).Set([0.9])
splat.CreateAttribute("radiance:sphericalHarmonicsDegree", Sdf.ValueTypeNames.Int,
                      custom=False, variability=Sdf.VariabilityUniform).Set(0)
splat.CreateAttribute("radiance:sphericalHarmonicsCoefficients", Sdf.ValueTypeNames.Float3Array,
                      custom=False).Set([(1.772454, -0.708982, -1.772454)])

Before running, follow the Python setup and check the GPU and driver requirements. The first render may take longer while shaders compile and cache.

Start in the public ovrtx repository root, rendering/ovrtx/public in a Kit checkout. The commands below work in Windows PowerShell and Linux shells. Run one mode per process to compare the same scene:

# Enter the Gaussian example project.
cd examples/python/gaussian-splats
# Render Real-Time Path Tracing to a PNG.
uv run main.py --mode rtpt --png _output/rtpt.png
# Render Path Tracing to a PNG.
uv run main.py --mode pt --png _output/pt.png
# Render Minimal with Full MDL and Ray Reconstruction to a PNG.
uv run main.py --mode minimal --png _output/minimal.png
# Save the default RTPT render as a Rerun recording.
uv run main.py --rrd _output/gaussians.rrd

The example saves the first frame by default, with no preceding warmup frames. Use --steps to request later frames. With neither --png nor --rrd, the example opens Rerun.

--scene accepts a USD scene containing a RenderProduct at /Render/Camera and an LdrColor RenderVar at /Render/Camera/LdrColor. The product’s camera relationship must target your Camera prim, and orderedVars must include that RenderVar. These paths are required by this example script.

See Sensor Configuration for this setup. If adapting the USDA example in the Inline Composition section of Loading USD, rename its RenderProduct from DocsCamera to Camera beneath /Render. The Camera prim itself can retain its name.

The following code loads the scene, overrides one mode, renders the requested frames, and copies LdrColor before releasing its mapping.

renderer = ovrtx.Renderer()
stage = ovstage.Stage("ovrtx.example.gaussian-splats")
try:
    renderer.attach_ovstage(stage)
    # Layer a mode override over the same scene; render one mode per run.
    layer = ('#usda 1.0\n(subLayers = [@' + args.scene.resolve().as_posix() + '@])\n'
             'over "Render" {\n over "Camera" {\n token omni:rtx:rendermode = "' + mode + '"\n }\n }\n')
    ovstage.population.open_usd_from_string(stage, layer, ordinal=1)
    stage.advance_write_floor(1, ovstage.Scope.ALL).wait()
    # Render one frame by default; --steps can request later frames.
    for _ in range(args.steps):
        products = renderer.step(render_products={"/Render/Camera"}, delta_time=1/60, ordinal=1)
    output = products["/Render/Camera"].frames[0].render_vars["/Render/Camera/LdrColor"]
    mapped = output.map(device=ovrtx.Device.CPU)
    view = np.from_dlpack(mapped)
    pixels = view.copy()
    del view
    mapped.unmap()
    del mapped, output, products
finally:
    renderer.detach_ovstage()
    renderer.destroy()
    stage.destroy()

See Gaussian Splats for the authoring contract and C: Gaussian Splats for the equivalent C runtime workflow.