Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions modules/core/src/lib/deck-picker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1027,7 +1027,10 @@ export default class DeckPicker {

/**
* Determine which layers to use for the depth (pickZ) pass.
* - If a non-draped layer was picked, use just that layer.
* - If a non-terrain-dependent layer was picked, use just that layer.
* - If an offset layer was picked, include terrain layers alongside it so
* TerrainEffect.preRender can bind the heightmap and the layer renders at
* its correct elevation (terrain_z + data_z).
* - If a draped layer was picked (geometry is at z=0) or no layer was picked
* (e.g. no-FBO tiles at extreme zoom), fall back to terrain layers.
*/
Expand All @@ -1036,12 +1039,17 @@ export default class DeckPicker {
return [];
}
const {pickedLayer} = pickInfo;
const isDraped = pickedLayer?.state?.terrainDrawMode === 'drape';
if (pickedLayer && !isDraped) {
const terrainLayers = pickableLayers.filter(l => l.props.operation.includes('terrain'));
const terrainDrawMode = pickedLayer?.state?.terrainDrawMode;
if (pickedLayer && terrainDrawMode === 'offset') {
// For offset layers, include terrain layers alongside
return [pickedLayer, ...terrainLayers];
}
if (pickedLayer && terrainDrawMode !== 'drape') {
return [pickedLayer];
}
// For draped layers or when no layer was picked, use terrain layers for depth
return pickableLayers.filter(l => l.props.operation.includes('terrain'));
return terrainLayers;
}

/**
Expand Down
38 changes: 38 additions & 0 deletions test/modules/core/lib/deck-picker.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,41 @@ test('DeckPicker#pick async empty', async () => {
layerManager.finalize();
deckPicker.finalize();
});

test('DeckPicker#getDepthLayers', () => {
const deckPicker = new DeckPicker(device);
// depthFBO must exist or the method early-returns []
deckPicker.depthFBO = {destroy: () => {}};

const terrainLayer = {props: {operation: 'terrain+draw'}, state: {}};
const offsetLayer = {props: {operation: 'draw'}, state: {terrainDrawMode: 'offset'}};
const drapedLayer = {props: {operation: 'draw'}, state: {terrainDrawMode: 'drape'}};
const regularLayer = {props: {operation: 'draw'}, state: {}};

const pickableLayers = [offsetLayer, terrainLayer, regularLayer, drapedLayer];
const noPick = {pickedColor: null, pickedObjectIndex: -1};

// unproject3D disabled → always []
expect(deckPicker._getDepthLayers(noPick, pickableLayers, false)).toEqual([]);

// nothing picked → terrain layers
expect(deckPicker._getDepthLayers(noPick, pickableLayers, true)).toEqual([terrainLayer]);

// regular layer picked → just that layer
expect(
deckPicker._getDepthLayers({...noPick, pickedLayer: regularLayer}, pickableLayers, true)
).toEqual([regularLayer]);

// drape layer picked → terrain layers (geometry is at z=0, need terrain for depth)
expect(
deckPicker._getDepthLayers({...noPick, pickedLayer: drapedLayer}, pickableLayers, true)
).toEqual([terrainLayer]);

// offset layer picked → [pickedLayer, ...terrainLayers] so TerrainEffect.preRender
// doesn't early-exit and the heightmap is available for the depth pass
expect(
deckPicker._getDepthLayers({...noPick, pickedLayer: offsetLayer}, pickableLayers, true)
).toEqual([offsetLayer, terrainLayer]);

deckPicker.finalize();
});