Quickstart
This page gets you onto the main public workflow as fast as possible:
install the package
render a deterministic MapScene
open a terrain scene
add an overlay or notebook widget
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:
Scenefor compact offscreen renderingSession+TerrainRenderer+TerrainRenderParamsfor terrain PBR/POMrender_offline()andoidn_denoise()for offline accumulation and denoise
Next Steps
Read the repo-wide Feature Map.
Browse every runnable script in the Examples Catalog.
Follow the GIS Track or Python Track.
Use the API Reference when you already know the symbol you need.