What happened?
Summary
CesiumJS renders Google Photorealistic 3D Tiles with severe corruption on a specific
browser+GPU combination: sharp, full-height vertical coloured stripes covering part of
the canvas, with a clean diagonal boundary against the correctly rendered region. It is
present in the first frame and never clears.
Crucially: Mapbox GL JS renders perfectly on the exact same device, same browser, same
page (satellite raster + raster-dem terrain + 3D pitch + animated camera). So WebGL on
this device is not broken in general — something specific to CesiumJS's rendering is
incompatible here.
Environment
- Device: Samsung Galaxy S25 FE (SM-S731B), Android 16 (BP4A.251205.006)
- GPU/driver: ANGLE ((Samsung Xclipse 940) on Vulkan 1.3.279), OpenGL ES 3.2,
DRIVER_VERSION 24.1.307 — the device's own GLES driver is itself an ANGLE-on-Vulkan layer
- Browser: Chrome 151.0.7922.83 (Android) — BROKEN
- CesiumJS: 1.122 (also reproduced on 1.144)
- Data: Cesium.createGooglePhotorealistic3DTileset()
Control experiments
- Microsoft Edge 149 (Chromium) on the SAME device renders CesiumJS CLEAN.
chrome://gpu vs edge://gpu difference:
- Chrome: GL implementation parts = (gl=egl-angle, angle=opengles),
Display type = ANGLE_OPENGLES, Passthrough Command Decoder = true
- Edge: GL implementation parts = (gl=egl-gles2, angle=none),
Display type = DEFAULT, Passthrough Command Decoder = false
i.e. Chrome stacks its own ANGLE on top of the device's ANGLE-on-Vulkan driver.
- Mapbox GL JS on the same device/browser/page: CLEAN.
Configurations tested — all still corrupted (19 total)
- Bare Viewer with NO options at all (default globe, AA, MSAA, SSE=16, resolutionScale)
- contextOptions.requestWebgl1 = true (WebGL 1 instead of WebGL 2)
- scene.logarithmicDepthBuffer = false
- tileset.skipLevelOfDetail = false
- scene.postProcessStages.fxaa.enabled = false AND postProcessStages.removeAll()
- contextOptions.webgl: antialias false, alpha false, stencil false,
powerPreference 'high-performance', preserveDrawingBuffer true and false
- scene3DOnly true, shadows false, terrainShadows DISABLED, scene.fog.enabled false
- msaaSamples 0, 1, 4
- maximumScreenSpaceError 4 / 8 / 16, dynamicScreenSpaceError on/off
- resolutionScale / useBrowserRecommendedResolution: drawing buffer from 245x378 to
1561x2409 — canvas size always equals drawingBuffer size, never clamped
- globe enabled and disabled
- CesiumJS 1.122 and 1.144
- Copying scene.canvas into a 2D canvas inside scene.postRender and displaying the copy:
the copy is corrupted too, so the corruption is inside the WebGL drawing buffer,
not in page compositing
- chrome://flags: #enable-vulkan Disabled, #vulkan-from-angle Disabled,
#use-angle = OpenGL ES (verified applied via chrome://gpu command line) — still corrupted
Ask
What does CesiumJS do in its render pipeline that Mapbox GL JS does not, which could
break under a stacked ANGLE configuration? Is there any Scene/Viewer/Cesium3DTileset
option that avoids it? I am happy to run any instrumented build or test page on this
device — I have it in hand and can reproduce reliably.
Impact
This is a production app for real-estate professionals in Türkiye. Samsung Exynos
devices (Xclipse GPUs) are common here, so this affects a meaningful share of users. We
have had to detect the corruption at runtime and route affected users to a different
renderer.
Reproduction steps
...
Sandcastle example
No response
Environment
Browser:
CesiumJS Version:
Operating System:
AI acknowledgment
What happened?
Summary
CesiumJS renders Google Photorealistic 3D Tiles with severe corruption on a specific
browser+GPU combination: sharp, full-height vertical coloured stripes covering part of
the canvas, with a clean diagonal boundary against the correctly rendered region. It is
present in the first frame and never clears.
Crucially: Mapbox GL JS renders perfectly on the exact same device, same browser, same
page (satellite raster + raster-dem terrain + 3D pitch + animated camera). So WebGL on
this device is not broken in general — something specific to CesiumJS's rendering is
incompatible here.
Environment
DRIVER_VERSION 24.1.307 — the device's own GLES driver is itself an ANGLE-on-Vulkan layer
Control experiments
chrome://gpu vs edge://gpu difference:
Display type = ANGLE_OPENGLES, Passthrough Command Decoder = true
Display type = DEFAULT, Passthrough Command Decoder = false
i.e. Chrome stacks its own ANGLE on top of the device's ANGLE-on-Vulkan driver.
Configurations tested — all still corrupted (19 total)
powerPreference 'high-performance', preserveDrawingBuffer true and false
1561x2409 — canvas size always equals drawingBuffer size, never clamped
the copy is corrupted too, so the corruption is inside the WebGL drawing buffer,
not in page compositing
#use-angle = OpenGL ES (verified applied via chrome://gpu command line) — still corrupted
Ask
What does CesiumJS do in its render pipeline that Mapbox GL JS does not, which could
break under a stacked ANGLE configuration? Is there any Scene/Viewer/Cesium3DTileset
option that avoids it? I am happy to run any instrumented build or test page on this
device — I have it in hand and can reproduce reliably.
Impact
This is a production app for real-estate professionals in Türkiye. Samsung Exynos
devices (Xclipse GPUs) are common here, so this affects a meaningful share of users. We
have had to detect the corruption at runtime and route affected users to a different
renderer.
Reproduction steps
...
Sandcastle example
No response
Environment
Browser:
CesiumJS Version:
Operating System:
AI acknowledgment