Quickstart

This page gets you onto the main public workflow as fast as possible:

  1. install the package

  2. render a deterministic MapScene

  3. open a terrain scene

  4. add an overlay or notebook widget

  5. jump to the example or guide that matches your real task

Install

pip install forge3d

Common extras:

pip install "forge3d[jupyter]"
pip install "forge3d[datasets]"
pip install "forge3d[all]"

pip install forge3d installs the native extension and the interactive_viewer launcher used by open_viewer_async(). In source checkouts, the Python wrapper can still pick newer local binaries from target/debug or target/release when they exist.

First MapScene Render

Use MapScene when you want the reproducible offline map-production path:

import forge3d as f3d

scene = f3d.MapScene(
    terrain=f3d.TerrainSource(path=f3d.mini_dem_path(), crs="EPSG:3857"),
    lighting=f3d.LightingPreset(name="rainier_showcase"),
    output=f3d.OutputSpec(
        width=1600,
        height=1000,
        path="mapscene.png",
        samples=4,
        denoiser="atrous",
        aovs=("albedo", "normal", "depth"),
    ),
)

report = scene.validate()
if not report.render_blocked(scene.render_policy):
    scene.render()

manifest = f3d.recipe_manifest(scene)

MapScene.render() uses the GPU-terrain backend for real .npy or GeoTIFF terrain when the native backend is available. When it is not, rendering raises MapSceneNativeUnavailable with structured diagnostic blocks, so unsupported recipes never silently turn into placeholder review images.

First viewer session

Use the bundled mini DEM when you want a zero-download sanity check:

import forge3d as f3d

with f3d.open_viewer_async(
    terrain_path=f3d.mini_dem_path(),
    width=1400,
    height=900,
) as viewer:
    viewer.set_orbit_camera(phi_deg=35, theta_deg=55, radius=1.8, fov_deg=45)
    viewer.set_sun(azimuth_deg=315, elevation_deg=32)
    viewer.snapshot("mini-dem.png", width=1600, height=900)

Use fetch_dem() when you want a larger sample dataset:

import forge3d as f3d

dem_path = f3d.fetch_dem("rainier")

with f3d.open_viewer_async(terrain_path=dem_path, width=1440, height=900) as viewer:
    viewer.set_z_scale(0.1)
    viewer.set_orbit_camera(phi_deg=28, theta_deg=49, radius=5400, fov_deg=42)
    viewer.set_sun(azimuth_deg=302, elevation_deg=24)
    viewer.snapshot("rainier.png", width=1920, height=1080)

First overlay

Raster overlays sit on the same viewer handle:

import forge3d as f3d

dem_path = f3d.fetch_dem("swiss")
overlay_path = f3d.fetch_dataset("swiss-land-cover")

with f3d.open_viewer_async(terrain_path=dem_path, width=1500, height=960) as viewer:
    viewer.load_overlay(
        name="land-cover",
        path=overlay_path,
        opacity=0.82,
        z_order=10,
        preserve_colors=True,
    )
    viewer.set_orbit_camera(phi_deg=90, theta_deg=10, radius=18000, fov_deg=16)
    viewer.set_sun(azimuth_deg=315, elevation_deg=17)
    viewer.snapshot("swiss-land-cover.png")

For custom vector overlays, labels, and other lower-level scene commands, drop to viewer.send_ipc(...) or the helper functions in forge3d.viewer_ipc.

First notebook widget

Use ViewerWidget when you want the same viewer path in Jupyter:

import forge3d as f3d

widget = f3d.ViewerWidget(
    terrain_path=f3d.mini_dem_path(),
    src=f3d.mini_dem(),
    width=960,
    height=600,
)
widget.set_camera(phi_deg=30, theta_deg=58, radius=1.7, fov_deg=42)
widget.set_sun(azimuth_deg=315, elevation_deg=30)
widget

When the full viewer cannot launch, the widget can fall back to an inline preview if you also provided previewable source data through src=.

When To Leave The Viewer Path

Stay with open_viewer_async() and ViewerHandle for most scene work.

Move to the lower-level native surface when you need deterministic offscreen pipelines or explicit renderer control:

  • Scene for compact offscreen rendering

  • Session + TerrainRenderer + TerrainRenderParams for terrain PBR/POM

  • render_offline() and oidn_denoise() for offline accumulation and denoise

Next Steps