feat(extensions): TerrainExtension GlobeView support#10248
Closed
charlieforward9 wants to merge 2 commits intomasterfrom
Closed
feat(extensions): TerrainExtension GlobeView support#10248charlieforward9 wants to merge 2 commits intomasterfrom
charlieforward9 wants to merge 2 commits intomasterfrom
Conversation
Make TerrainExtension's draped rendering (height-map and terrain-cover FBOs) work on GlobeView as well as MapView. The existing implementation packed layer bounds into the live viewport's common space, which on GlobeView is sphere cartesian — incomparable with screen-space bounds, and invalid as a UV basis for the draped sampler. All bounds are now expressed in ABSOLUTE Web Mercator common space, regardless of the active projection. The FBO is rendered via a WebMercatorViewport in both cases, so the cover/height-map texture is projection-invariant and a projection toggle no longer requires re-rendering. Changes: - projection-utils: new `MERCATOR_REFERENCE_VIEWPORT` plus helpers `lngLatToMercatorCommon` and `getMercatorReferenceViewport` so other modules can compute bounds in the shared absolute-Mercator basis. - terrain-cover, height-map-builder: project layer bounds through the Mercator reference viewport; on globe, skip the viewport-bounds intersection in `getRenderBounds` (which would yield sphere cartesian coords) and use full layer bounds. - shader-module: compute `terrainMercPos` per-fragment by unprojecting globe cartesian back to lng/lat and forward-projecting through project_mercator_, so USE_HEIGHT_MAP / USE_COVER samples against the absolute-Mercator bounds uniform on any projection. The project module's helpers are VS-only, so the value is passed via varying; terrain meshes are fine enough that interpolation error is negligible. Bounds uniform is packed as absolute Mercator (no commonOrigin subtract), since the shader computes absolute xy itself. Example updated with a GlobeView toggle so the terrain-extension demo exercises both projections (requires TerrainLayer's grid tesselator from the companion geo-layers PR. EOF )
This was referenced Apr 19, 2026
Collaborator
Author
|
Superseded by #10251 (rebranched under |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes
TerrainExtension(draped rendering of layers onto a terrain surface) work onGlobeViewas well asMapView.The existing implementation packed layer bounds into the live viewport's common space, which on
GlobeViewis sphere cartesian — incomparable with screen-space bounds, and invalid as a UV basis for the draped sampler. Cover/height-map FBOs therefore rendered with corrupted UV math on globe.All bounds are now expressed in absolute Web Mercator common space, regardless of the active projection. The FBO itself is rendered via a
WebMercatorViewportin both cases, so the cover/height-map texture becomes projection-invariant — the same draw target can be sampled fromMapViewandGlobeViewwithout re-rendering, and a projection toggle does not invalidate it.Changes:
projection-utils— newMERCATOR_REFERENCE_VIEWPORTplus helperslngLatToMercatorCommonandgetMercatorReferenceViewportso other modules can compute bounds in the shared absolute-Mercator basis.terrain-cover,height-map-builder— project layer bounds through the Mercator reference viewport. On globe, skip the viewport-bounds intersection ingetRenderBounds(which would yield sphere cartesian coords) and use full layer bounds.makeViewportunprojects bounds through the Mercator reference instead of the live viewport for geospatial inputs.shader-module— computeterrainMercPosper-fragment by unprojecting globe cartesian back to lng/lat and forward-projecting throughproject_mercator_, soUSE_HEIGHT_MAP/USE_COVERsample against the absolute-Mercator bounds uniform on any projection. Theprojectmodule's mercator helpers are VS-only, so the value is passed via varying; terrain meshes are fine enough that interpolation error is negligible. Theboundsuniform is packed as absolute Mercator (nocommonOriginsubtract) since the shader computes absolute xy itself.Example app (
examples/website/terrain-extension) updated with aMapView/GlobeViewtoggle so the demo exercises both projections. (RequiresTerrainLayer'stesselator: 'grid'from the companion geo-layers PR.)Why
The docs list
_TerrainExtensionas experimental, but it's already widely used for draping icons/labels/polygons onto terrain. Extending it toGlobeViewlets apps keep the same draped layers across projection toggles without needing a separate code path.Test plan
MapViewwithTerrainExtensionandTerrainLayersource — unchanged behaviorGlobeViewwithTerrainExtensionandTerrainLayer(tesselator: 'grid')source — layers drape correctly on sphereUSE_HEIGHT_MAP(elevation offsets for icons/text) correct on both projectionsUSE_COVER(draped overlays on terrain surface) correct on both projectionsCompanion PRs