Skip to content

Adding a CesiumWebMapTileServiceRasterOverlay or CesiumGeoJsonDocumentRasterOverlay at runtime reloads every loaded tile (flicker) #712

Description

@baruchInsert-tech

Summary

Adding a CesiumRasterOverlay to a Cesium3DTileset that has already loaded causes every loaded tile to be destroyed and rebuilt. The tileset visibly blinks. The same happens on remove and re-add, and it recurs on every add rather than being a one-time cost.

We reproduce this with both overlay types we use:

  • CesiumGeoJsonDocumentRasterOverlay
  • CesiumWebMapTileServiceRasterOverlay

The underlying mechanism lives in cesium-native and, having read through it, appears to be a sound
tradeoff rather than a defect (details below). We are raising it here because from the Unity side it
is neither discoverable nor, for GeoJSON overlays, avoidable:

  1. Nothing in CesiumRasterOverlay, CesiumGeoJsonDocumentRasterOverlay or
    CesiumWebMapTileServiceRasterOverlay suggests that adding an overlay can destroy tile content,
    or that projection compatibility between overlays on the same tileset matters at all.
  2. CesiumGeoJsonDocumentRasterOverlay exposes no projection setting, so even once you understand
    the cause there is no way to avoid it from Unity.

So this is a documentation request plus a small API request, not a bug report.

Our use cases: hovering an item in a UI list draws that item's footprint as a GeoJSON overlay on the
base map, and users toggle WMTS imagery layers on and off. Both make the base map flicker, which
makes them unusable as interactive affordances.

It is not RecreateTileset

Worth stating up front, since it is the natural first guess: nothing calls
Cesium3DTileset.RecreateTileset() on this path. We checked every caller.

  • The CesiumRasterOverlay base class only ever calls Refresh() (RemoveFromTileset() +
    AddToTileset()), never RecreateTileset -- see Source/Runtime/CesiumRasterOverlay.cs.
  • The per-overlay AddToTileset / RemoveFromTileset implementations operate on the live
    Tileset's overlay collection only.
  • RecreateTileset is called only from Cesium3DTileset property setters, the "Refresh Tileset"
    inspector button, CesiumGeoreference.ReloadEllipsoid, and some editor-window paths
    (CesiumEditorWindowImpl.cpp, IonAssetsTreeViewImpl.cpp, SelectIonTokenWindowImpl.cpp). None
    are in play here, and our project never calls it.

What actually happens is per-tile content reload in
Cesium3DTilesSelection/src/TilesetContentManager.cpp (~line 2126):

if (status.firstIndexWithMissingProjection) {
  // The mesh doesn't have the right texture coordinates for this
  // overlay's projection, so we need to kick it back to the unloaded
  // state to fix that.
  // In the future, we could add the ability to add the required
  // texture coordinates without starting over from scratch.
  unloadTileContent(tile);
  return;
}

Adding an overlay whose projection is not among those a loaded tile generated texture coordinates
for forces that tile to reload. This looks justified: overlay texture coordinates are per-vertex
glTF attributes (_CESIUMOVERLAY_n) generated during load, and Cesium for Unity discards the glTF
once conversion is done -- CesiumGltfGameObject
(native~/src/Runtime/UnityPrepareRendererResources.h) retains only the GameObject and
primitiveInfos. Retrofitting a UV set onto an already-uploaded Unity mesh would mean
reconstructing that data and re-uploading to the GPU.

Filed against cesium-native:

Why each overlay type hits it

GeoJSON overlays always hit it. GeoJsonDocumentRasterOverlay hardcodes GeographicProjection
with no override, while CesiumWebMapTileServiceRasterOverlay.projection defaults to WebMercator
(Source/Runtime/CesiumWebMapTileServiceRasterOverlay.cs). On a Web Mercator tileset the mismatch
is guaranteed.

WMTS overlays hit it when projections are mixed. They do expose projection, so an application
that keeps every overlay on one projection is fine. Ours mixes them -- our configuration sets
Geographic for some layers and leaves others at the WebMercator default -- and adding a
mismatched one produces the same flicker.

We have not isolated a case where an overlay is added with a projection that is already in use by
the tileset and the reload still happens. Our reading of the code says that case should leave loaded
tiles untouched, and confirmation of that would be valuable, since it is the property applications
would need to rely on to work around this.

Steps to reproduce

With a GeoJSON overlay:

  1. Create a Cesium3DTileset with a CesiumWebMapTileServiceRasterOverlay left at its default
    WebMercator projection.
  2. Enter play mode and let the tileset load.
  3. At runtime, AddComponent<CesiumGeoJsonDocumentRasterOverlay>() on the same GameObject and
    assign a valid document.
  4. Observe the tileset's tiles disappear and reload.

With a WMTS overlay:

  1. Same tileset and WebMercator base overlay as above, fully loaded.
  2. At runtime, AddComponent<CesiumWebMapTileServiceRasterOverlay>() on the same GameObject,
    configure it, set projection = Geographic, and enable it.
  3. Observe the same reload.

Expected: the new overlay is draped over the existing tiles.
Actual: all loaded tile GameObjects are destroyed and rebuilt; the tileset flickers.

Workarounds we tried

  • Reusing a single overlay component and swapping only document does not help. The document setter
    calls Refresh(), which removes and re-adds the overlay, so the projection is reintroduced as
    "missing" for any tile that loaded in the meantime.
  • Keeping an overlay permanently attached so its projection is always registered does avoid the
    reload, but for GeoJSON overlays only if it always holds a non-empty document -- an empty
    FeatureCollection crashes the process (filed separately against cesium-native: ).
  • Matching the projections (setting the WMTS overlay to Geographic where the service supports
    EPSG:4326) removes the flicker completely, which confirms the diagnosis. This is only possible
    when the imagery service actually serves that projection.

What would help

  • Documentation. A note on CesiumRasterOverlay -- the base class, since this affects every
    subclass -- that adding an overlay whose projection is not already in use by the tileset will
    force loaded tiles to reload, and that this makes such overlays unsuitable for frequently toggled
    visuals. This alone would have saved us a lot of investigation. Ideally it would also state the
    positive guarantee: that matching projections avoids the reload.
  • A projection setting on CesiumGeoJsonDocumentRasterOverlay, once the corresponding option
    exists in GeoJsonDocumentRasterOverlayOptions in cesium-native (see linked issue). WMTS
    overlays already expose projection, so applications can avoid the mismatch there; GeoJSON
    overlays are currently the only ones with no way out.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions