visgl / deck.gl

WebGL2 powered visualization framework
https://deck.gl
MIT License
12.3k stars 2.09k forks source link

[Bug] TerrainLayer Missing tiles, poor performances, slow re-load. #8976

Open ImanEmadi opened 5 months ago

ImanEmadi commented 5 months ago

Description

Hello,

I am using the TerrainLayer with mapbox service APIs to render a 3D map:

const ELEVATION_DECODER = {
    rScaler: 6553.6,
    gScaler: 25.6,
    bScaler: 0.1,
    offset: -10000
};
const terrain_l_props = {
    id: 'terrain',
    minZoom: 0,
    maxZoom: 23,
    elevationDecoder: ELEVATION_DECODER,
    elevationData: TERRAIN_IMAGE,
    texture: SURFACE_IMAGE,
    wireframe: false,
    color: [255, 255, 255],
    opacity: 1,
};

 return   <DeckGL
            key={"DeckGL"}
            parameters={{
                depthTest: true,
            }}
            initialViewState={viewState}
            controller={true}
            views={new MapView({ repeat: true, orthographic: false })}
            {...props}
        >
            <TerrainLayer
                {...terrain_l_props}
            />
            {children}
        </DeckGL>

When i zoom in and then out, many tiles of the map disappear and leave white squares behinds, sometimes they take long to re-render again. this also happens sometimes when i rotate the camera. to me, it seems like that the TerrainLayer is clearing some tiles off the map, that it assumes are out of the viewPort, for some reasons.

also i should note that, if i replace this TerrainLayer with react-map-gl's Map component, the 3D map is rendered smoothly, with no problem and missing tiles and loads much faster.

since this significant amount of performance change is obtained just by replacing the TerrainLayer, while not changing anything else, i believe this is a problem with the TerrainLayer that needs to be addressed.

again, the slow performance of the map can not be due to my internet or system, as everything goes very smoothly if i render it with react-map-gl

Screenshot from 2024-06-25 09-11-37

Flavors

Expected Behavior

I expect the 3D map not to remove the tiles that are still visible to the user, additionally, i expect them to load faster.

Steps to Reproduce

Install deck.gl deps, copy paste the code from me, additionally, make some small visualizations over the map like PathLayers and etc... that's it for me.

Environment

Logs

No response

Pessimistress commented 5 months ago

Do you see the same issue when you visit https://deck.gl/examples/terrain-layer ?

ImanEmadi commented 5 months ago

Yes, the only difference is they load faster in deck.gl's example. but when i zoom out for example, the surrounding tiles have to load again. image

Pessimistress commented 5 months ago

The tiles are not being "loaded again". If you are viewing the map at that zoom level for the first time, then the tiles at that zoom level have never been loaded, and it takes time to load them.

I cannot tell why your own app loads slower since your code snippet is incomplete. However, you should make sure that ELEVATION_DECODER is defined as a constant outside of the render function, otherwise the whole tile cache will clear due to elevationEncoder prop change.

ImanEmadi commented 5 months ago

thanks for the reply, The thing is, it's not the first time, i start at zoom e.g. 2, then i zoom it, e.g. 18, and once i zoom out, the surrounding tiles are not there anymore, they load again, and before they are loaded, they are just some white tiles. this behavior doesn't happen when using mapbox Map component, after a zoom in-zoom out, the tiles around are still there.

also , the ELEVATION_DECODER is outside of the function, but i still feel like this problem has something to do with caching, like tiles are cleared when they shouldn't, my code pretty much describes how i am using it, the two consts are outside of the component and are constant.

Pessimistress commented 5 months ago

The size of the cache and request limits can be configured by layer props: https://deck.gl/docs/api-reference/geo-layers/tile-layer#maxcachesize

ImanEmadi commented 5 months ago

So i am setting a very big value for cacheSize, and also setting tileSize to 256, i can see the performance is slightly better now. but still, some specific parts of the map, do not load, (using mapbox url as per deck.gl example)

const ELEVATION_DECODER = {
    rScaler: 6553.6,
    gScaler: 25.6,
    bScaler: 0.1,
    offset: -10000
};
const ambientLight = new AmbientLight({ color: [255, 255, 255], intensity: 2.5 })
const lightingEffect = new LightingEffect({ ambientLight });

function Map3D({ layers = [], ...props }) {
    const TL = new TerrainLayer({
        id: 'terrain',
        minZoom: 2,
        maxZoom: 14,
        elevationDecoder: ELEVATION_DECODER,
        elevationData: TERRAIN_IMAGE,
        texture: SURFACE_IMAGE,
        wireframe: false,
        color: [255, 255, 255],
        opacity: 1,
        loadOptions: { maxConcurrency: 16 },
        getPolygonOffset: false,
        maxCacheSize: 1500,
        tileSize: 256
    });

    return <DeckGL
        key={'deck'}
        id="deck"
        parameters={{ depthTest: true }}
        controller
        layers={[TL, ...layers]}
        views={new MapView({ repeat: true, orthographic: false })}
        initialViewState={{
            zoom: 5,
            pitch: 50,
            longitude: 10.5,
            latitude: 51.0,
            maxPitch: 85,
            minPitch: 5,
            minZoom: 2,
            maxZoom: 14
        }}
        effects={[lightingEffect]}
        {...props}
    />
}

the following screenshot is taken after waiting for ~10seconds, also i definitely know my internet connection is stable.

Screenshot from 2024-07-05 10-02-07

ImanEmadi commented 5 months ago

when i zoom into the white area:

Screenshot from 2024-07-05 10-10-45