Skip to content

fix(core): Tile3DLayer renders correctly on GlobeView#10252

Merged
felixpalmer merged 10 commits into
visgl:masterfrom
NEW-HEAT:cr/feat/tile-3d-layer-globe
May 14, 2026
Merged

fix(core): Tile3DLayer renders correctly on GlobeView#10252
felixpalmer merged 10 commits into
visgl:masterfrom
NEW-HEAT:cr/feat/tile-3d-layer-globe

Conversation

@charlieforward9
Copy link
Copy Markdown
Collaborator

@charlieforward9 charlieforward9 commented Apr 20, 2026

Summary

GlobeView.fixes.mov

Fixes two bugs that prevent Tile3DLayer (and any other COORDINATE_SYSTEM.METER_OFFSETS layer) from rendering correctly on GlobeView.

1. METER_OFFSETS on GlobeView — tiles render as flat "flaps"

project_position in project.glsl only handled COORDINATE_SYSTEM_LNGLAT inside the PROJECTION_MODE_GLOBE branch. METER_OFFSETS positions (what loaders.gl 3D Tiles feed us via cartographicModelMatrix + cartographicOrigin) fell through to the linear project_offset_ path, which treats the meter offsets as raw common-space units rather than as vectors in the ENU tangent frame anchored at the coordinate origin. Result: each tile rendered as a flat patch in globe common space, producing the characteristic "folded flaps sticking out of the sphere" look.

Fix: in the GLOBE projection branch, build the east/north/up basis at coordinateOrigin in globe common space, scale the meter offsets by GLOBE_RADIUS / EARTH_RADIUS, and add them to the origin position. Each tile now lands at its geographic location oriented with the surface. One shader-level change covers all three Tile3DLayer sub-paths (PointCloudLayer, MeshLayer, ScenegraphLayer) plus any other METER_OFFSETS layer.

2. GlobeView far plane wrecks depth precision at close zoom

GlobeView.farZ was (altitude + GLOBE_RADIUS*2*scale/height) * farZMultiplier, which pushes far past the horizon — earth's curvature occludes everything beyond the tangent horizon anyway. At zoom 16 this gives a far/near ratio around 40,000:1, which destroys depth-buffer precision and produces visible z-fighting on 3D features (dark bands cutting across Tile3DLayer meshes).

Fix: use the horizon-distance formula sqrt(h^2 + 2*R*h) for the far plane, keep a 2x multiplier for headroom so tall features (mountains, buildings) peeking above the horizon stay visible. Drops far/near from ~40,000 to ~500 at zoom 16 (~80x depth precision boost). At zoom 0 the new bound is marginally tighter than before (1.79 vs 2.14) — the back half of the globe is occluded anyway.

Example

Updated examples/website/google-3d-tiles/app.jsx with a Map/Globe toggle so the fix can be exercised end-to-end against the Google Photorealistic 3D Tiles dataset. Initial view state adjusted (minZoom: 0, maxZoom: 24, pitch: 0) so users can zoom all the way out to see the globe and all the way in to see street-level 3D detail.

Test plan

  • yarn build passes
  • Local node tests pass (pre-commit hooks)
  • Manually verified: Google 3D Tiles render correctly on globe at all zooms (no flaps)
  • Manually verified: no z-fighting on Tile3DLayer meshes at close zoom on GlobeView
  • Manually verified: MapView rendering unchanged
  • Reviewer: run examples/website/google-3d-tiles and toggle between Map/Globe

@coveralls
Copy link
Copy Markdown

coveralls commented Apr 20, 2026

Coverage Status

coverage: 83.494% (-0.03%) from 83.519% — NEW-HEAT:cr/feat/tile-3d-layer-globe into visgl:master

@charlieforward9 charlieforward9 linked an issue Apr 20, 2026 that may be closed by this pull request
7 tasks
Copy link
Copy Markdown
Collaborator

@felixpalmer felixpalmer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing work!

Comment thread modules/core/src/shaderlib/project/project.glsl.ts Outdated
Comment thread modules/core/src/shaderlib/project/project.glsl.ts
@felixpalmer

This comment was marked as resolved.

Tile3DLayer (and any other layer using COORDINATE_SYSTEM.METER_OFFSETS)
rendered as flat "flaps" sticking out of the sphere on GlobeView because
project_position only handled COORDINATE_SYSTEM_LNGLAT in the
PROJECTION_MODE_GLOBE branch. METER_OFFSETS positions fell through to
the linear project_offset_ path, which treats the meter offsets as raw
common-space units rather than as vectors in the ENU tangent frame
anchored at the coordinate origin.

Attach the tangent plane to the sphere: build the east/north/up basis
at the origin in globe common space, scale the meter offsets by
GLOBE_RADIUS / EARTH_RADIUS, and add them to the origin position on the
globe surface. Each tile now lands at its correct geographic location
oriented with the surface.

Also update the google-3d-tiles example with a Map/Globe toggle so the
fix can be exercised end-to-end against the Google Photorealistic 3D
Tiles dataset.
GlobeView.farZ was computed as (altitude + GLOBE_RADIUS*2*scale/height),
which pushes the far plane roughly a full globe-diameter beyond the
camera. At close zoom this produces a far/near ratio on the order of
40,000:1, which destroys depth-buffer precision and causes z-fighting
on 3D features like Tile3DLayer meshes (buildings, terrain surfaces).

Replace with the horizon-distance formula sqrt(h^2 + 2*R*h) - the
distance from the camera at altitude h to the tangent horizon on a
sphere of radius R. Earth's curvature occludes everything beyond that
anyway. Keep a 2x multiplier so tall features (mountains, buildings)
peeking above the horizon stay in view.

At zoom=16 this drops far/near from ~40,000 to ~500, an ~80x boost in
depth precision that eliminates visible z-fighting on 3D tile meshes.
At zoom=0 the new bound is slightly tighter than before (1.79 vs
2.14), which is fine - the back half of the globe is occluded anyway.
@charlieforward9 charlieforward9 force-pushed the cr/feat/tile-3d-layer-globe branch from c8125d5 to c57abbd Compare April 22, 2026 14:11
@charlieforward9 charlieforward9 changed the base branch from 9.3-release to master April 22, 2026 14:16
Comment thread modules/core/src/shaderlib/project/project.glsl.ts Outdated
Comment thread modules/core/src/views/globe-view.ts
@charlieforward9
Copy link
Copy Markdown
Collaborator Author

Let's goooooo! 🏦🏦🏦🏦🏦🏦🏦🏦

@andreasplesch
Copy link
Copy Markdown

That looks great. Would a GlobeViewport start to support pitch and bearing, for cases where you want to preserve a perspective from say the LEO or the ISS which shows the curvature of the earth (so no map projection) looking obliquely (not straight down) at a point or the horizon ?

image

@charlieforward9
Copy link
Copy Markdown
Collaborator Author

@andreasplesch yes,

#10249 got it started, #10298 will land it

@felixpalmer felixpalmer merged commit 626010b into visgl:master May 14, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Tiles Disappear in Google 3D Tiles Map

4 participants