TV21: Terrain Scatter Blend and Contact Shading
TV21 extends the terrain scatter workflow with terrain-aware mesh grounding controls. The goal is to reduce the hard “floating prop” seam where instanced meshes meet the terrain and to add localized darkening where the terrain should visually press into the mesh base.
What shipped
New per-batch Python settings on
forge3d.terrain_scatter.TerrainScatterBatch:terrain_blend=TerrainMeshBlendSettings(...)terrain_contact=TerrainContactSettings(...)
Shared offscreen and viewer support through the existing terrain scatter contract.
Terrain-aware shader logic in the instanced mesh path:
seam alpha fade based on sampled terrain height under each fragment
localized contact darkening near the terrain intersection band
Backward-compatible disabled path:
leaving both settings at defaults preserves the pre-TV21 image
explicit disabled settings are pixel-identical to the baseline path
Regression coverage for three representative cases:
rock cluster
road edge
building foundation
Public API
import forge3d as f3d
from forge3d import terrain_scatter as ts
batch = ts.TerrainScatterBatch(
name="foundation",
color=(0.70, 0.71, 0.69, 1.0),
transforms=transforms,
terrain_blend=ts.TerrainMeshBlendSettings(
enabled=True,
bury_depth=1.4,
fade_distance=3.4,
),
terrain_contact=ts.TerrainContactSettings(
enabled=True,
distance=3.0,
strength=0.28,
vertical_weight=0.85,
),
levels=[ts.TerrainScatterLevel(mesh=f3d.geometry.primitive_mesh("box"))],
)
ts.apply_to_renderer(renderer, [batch])
Parameter semantics
terrain_blend.enabledEnables seam fading against the terrain heightfield.
terrain_blend.bury_depthHow far the mesh can sink into the terrain before the blend is fully opaque again.
Use this to hide harsh mesh-ground cut lines on buried bases.
terrain_blend.fade_distanceHow far above the terrain the fade continues before the mesh returns to full opacity.
Larger values soften transitions over sloped terrain.
terrain_contact.enabledEnables terrain-proximity darkening near the mesh base.
terrain_contact.distanceWorld-space distance band used for the contact effect.
terrain_contact.strengthDarkening strength in
[0, 1].
terrain_contact.vertical_weightBias toward flatter upward-facing surfaces.
Higher values keep the contact effect concentrated near horizontal bases instead of climbing steep side walls.
Workflow notes
Both settings serialize through:
TerrainScatterBatch.to_native_dict()TerrainScatterBatch.to_viewer_payload()
The viewer IPC payload carries the same
terrain_blendandterrain_contactdictionaries as the offscreen renderer path.Validation is enforced in Python and Rust:
bury_depth >= 0fade_distance > 0distance > 0strength in [0, 1]vertical_weight in [0, 1]
Example and tests
Real-DEM example:
python examples/terrain_tv21_blending_demo.pyExample notes:
docs/examples/blending_demo.mdFeature regression tests:
tests/test_terrain_tv21_blending.pyReal-DEM example smoke test:
tests/test_terrain_tv21_demo.py
The real-DEM example writes per-case baseline, TV21, and diff images plus a contact sheet and JSON summary so the visual change is inspectable without opening the viewer. Each crop preserves the DEM shape but normalizes local relief into a close-up-friendly range so the grounding controls remain legible at example scale.