Skip to content

Commit

Permalink
fix polygon offset calculation in TileLayer
Browse files Browse the repository at this point in the history
  • Loading branch information
Xiaoji Chen committed Mar 14, 2020
1 parent d74e375 commit c0e1f85
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 7 deletions.
51 changes: 48 additions & 3 deletions modules/core/src/passes/layers-pass.js
Expand Up @@ -48,7 +48,7 @@ export default class LayersPass extends Pass {
// Draws a list of layers in one viewport
// TODO - when picking we could completely skip rendering viewports that dont
// intersect with the picking rect
/* eslint-disable max-depth */
/* eslint-disable max-depth, max-statements */
_drawLayersInViewport(
gl,
{layers, layerFilter, onError, viewport, view, pass = 'unknown', effects, moduleParameters}
Expand Down Expand Up @@ -77,12 +77,18 @@ export default class LayersPass extends Pass {

setParameters(gl, {viewport: glViewport});

const indexResolver = layerIndexResolver();
// render layers in normal colors
for (let layerIndex = 0; layerIndex < layers.length; layerIndex++) {
const layer = layers[layerIndex];
// Check if we should draw layer
const shouldDrawLayer = this._shouldDrawLayer(layer, viewport, pass, layerFilter);

// This is the "logical" index for ordering this layer in the stack
// used to calculate polygon offsets
// It can be the same as another layer
const layerRenderIndex = indexResolver(layer, shouldDrawLayer);

// Calculate stats
if (shouldDrawLayer && layer.props.pickable) {
renderStatus.pickableCount++;
Expand All @@ -103,7 +109,7 @@ export default class LayersPass extends Pass {
try {
layer.drawLayer({
moduleParameters: _moduleParameters,
uniforms: {layerIndex},
uniforms: {layerIndex: layerRenderIndex},
parameters: layerParameters
});
} catch (err) {
Expand All @@ -118,7 +124,7 @@ export default class LayersPass extends Pass {

return renderStatus;
}
/* eslint-enable max-depth */
/* eslint-enable max-depth, max-statements */

/* Methods for subclass overrides */
shouldDrawLayer(layer) {
Expand Down Expand Up @@ -166,6 +172,45 @@ export default class LayersPass extends Pass {
}
}

// If the _index prop is defined, return a layer index that's relative to its parent
// Otherwise return the index of the layer among all rendered layers
// This is done recursively, i.e. if the user overrides a layer's default index,
// all its descendants will be resolved relative to that index.
// This implementation assumes that parent layers always appear before its children
// which is true if the layer array comes from the LayerManager
export function layerIndexResolver(startIndex = 0, layerIndices = {}) {
const resolvers = {};

return (layer, isDrawn) => {
const indexOverride = layer.props._index;
const layerId = layer.id;
const parentId = layer.parent && layer.parent.id;

let index;

if (parentId in resolvers) {
const resolver = (resolvers[parentId] =
resolvers[parentId] || layerIndexResolver(layerIndices[parentId], layerIndices));
index = resolver(layer, isDrawn);
resolvers[layerId] = resolver;
} else if (Number.isFinite(indexOverride)) {
index = indexOverride + (layerIndices[parentId] || 0);
// Mark layer as needing its own resolver
// We don't actually create it until it's used for the first time
resolvers[layerId] = null;
} else {
index = startIndex;
}

if (isDrawn && index >= startIndex) {
startIndex = index + 1;
}

layerIndices[layerId] = index;
return index;
};
}

// Convert viewport top-left CSS coordinates to bottom up WebGL coordinates
function getGLViewport(gl, {viewport}) {
// TODO - dummy default for node
Expand Down
1 change: 0 additions & 1 deletion modules/geo-layers/src/terrain-layer/terrain-layer.js
Expand Up @@ -161,7 +161,6 @@ export default class TerrainLayer extends CompositeLayer {
data: DUMMY_DATA,
mesh,
texture,
getPolygonOffset: null,
coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
getPosition: d => [0, 0, 0],
getColor: color
Expand Down
1 change: 1 addition & 0 deletions modules/geo-layers/src/tile-layer/tile-layer.js
Expand Up @@ -157,6 +157,7 @@ export default class TileLayer extends CompositeLayer {
id: `${this.id}-${tile.x}-${tile.y}-${tile.z}`,
data: tile.data,
visible: isVisible,
_index: 0,
tile
})
);
Expand Down
1 change: 0 additions & 1 deletion test/apps/mapbox-tile/app.js
Expand Up @@ -97,7 +97,6 @@ class Root extends PureComponent {
new TileLayer({
...MAP_LAYER_STYLES,
coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
getPolygonOffset: null,
pickable: true,
getTileData
})
Expand Down
2 changes: 2 additions & 0 deletions test/modules/core/passes/index.js
@@ -1 +1,3 @@
import './layers-pass.spec';
import './pick-layers-pass.spec';
import './shadow-pass.spec';
188 changes: 188 additions & 0 deletions test/modules/core/passes/layers-pass.spec.js
@@ -0,0 +1,188 @@
import test from 'tape-catch';

import {Layer, CompositeLayer, LayerManager} from '@deck.gl/core';
import {layerIndexResolver} from '@deck.gl/core/passes/layers-pass';
import {gl} from '@deck.gl/test-utils';

class TestLayer extends Layer {
initializeState() {}
}

class TestCompositeLayer extends CompositeLayer {
renderLayers() {
const {subLayers} = this.props;

return subLayers.map(
props =>
props.children
? new TestCompositeLayer(
this.getSubLayerProps({id: props.id, subLayers: props.children}),
props
)
: new TestLayer(this.getSubLayerProps({id: props.id}), props)
);
}
}

test('LayersPass#layerIndexResolver', t => {
const TEST_CASES = [
{
title: 'nesting',
layers: [
new TestCompositeLayer({
id: 'layer-1',
subLayers: [
{
id: 'layer-1-1',
children: [
{
id: 'layer-1-1-1',
children: [{id: 'layer-1-1-1-1'}, {id: 'layer-1-1-1-2'}]
},
{
id: 'layer-1-1-2',
children: [{id: 'layer-1-1-2-1'}, {id: 'layer-1-1-2-2'}]
}
]
}
]
})
],
expected: {
'layer-1': 0,
'layer-1-1': 0,
'layer-1-1-1': 0,
'layer-1-1-1-1': 0,
'layer-1-1-1-2': 1,
'layer-1-1-2': 2,
'layer-1-1-2-1': 2,
'layer-1-1-2-2': 3
}
},
{
title: 'visibility',
layers: [
new TestLayer({id: 'layer-1'}),
new TestLayer({id: 'layer-2', visible: false}),
new TestLayer({id: 'layer-3'}),
new TestCompositeLayer({
id: 'layer-4',
visible: false,
subLayers: [{id: 'layer-4-1'}, {id: 'layer-4-2'}]
}),
new TestCompositeLayer({
id: 'layer-5',
subLayers: [
{
id: 'layer-5-1',
children: [
{id: 'layer-5-1-1'},
{id: 'layer-5-1-2'},
{id: 'layer-5-1-3', visible: false}
]
},
{id: 'layer-5-2'},
{
id: 'layer-5-3',
children: [{id: 'layer-5-3-1'}, {id: 'layer-5-3-2'}]
}
]
})
],
expected: {
'layer-1': 0,
'layer-2': 1,
'layer-3': 1,
'layer-4': 2,
'layer-4-1': 2,
'layer-4-2': 2,
'layer-5': 2,
'layer-5-1': 2,
'layer-5-1-1': 2,
'layer-5-1-2': 3,
'layer-5-1-3': 4,
'layer-5-2': 4,
'layer-5-3': 5,
'layer-5-3-1': 5,
'layer-5-3-2': 6
}
},
{
title: 'index override',
layers: [
new TestLayer({id: 'layer-1'}),
new TestCompositeLayer({
id: 'layer-2',
subLayers: [
{
id: 'layer-2-1',
_index: 0,
children: [
{id: 'layer-2-1-1', _index: 2},
{id: 'layer-2-1-2', _index: 1},
{id: 'layer-2-1-3', _index: 0}
]
},
{
id: 'layer-2-2',
_index: 0,
children: [
{id: 'layer-2-2-1'},
{id: 'layer-2-2-2'},
{
id: 'layer-2-2-3',
children: [{id: 'layer-2-2-3-1'}, {id: 'layer-2-2-3-2'}]
},
{id: 'layer-2-2-4'}
]
},
{
id: 'layer-2-3',
children: [{id: 'layer-2-3-1'}, {id: 'layer-2-3-2'}, {id: 'layer-2-3-3'}]
}
]
}),
new TestLayer({id: 'layer-3', _index: 0}),
new TestLayer({id: 'layer-4'})
],
expected: {
'layer-1': 0,
'layer-2': 1,
'layer-2-1': 1,
'layer-2-1-1': 3,
'layer-2-1-2': 2,
'layer-2-1-3': 1,
'layer-2-2': 1,
'layer-2-2-1': 1,
'layer-2-2-2': 2,
'layer-2-2-3': 3,
'layer-2-2-3-1': 3,
'layer-2-2-3-2': 4,
'layer-2-2-4': 5,
'layer-2-3': 6,
'layer-2-3-1': 6,
'layer-2-3-2': 7,
'layer-2-3-3': 8,
'layer-3': 0,
'layer-4': 9
}
}
];

for (const testCase of TEST_CASES) {
const resolver = layerIndexResolver();

const layerManager = new LayerManager(gl, {});
layerManager.setLayers(testCase.layers);
const layers = layerManager.getLayers();

t.comment(testCase.title);
for (const layer of layers) {
const result = resolver(layer, !layer.isComposite && layer.props.visible);
const expected = testCase.expected[layer.id];
t.is(result, expected, layer.id);
}
}

t.end();
});
4 changes: 2 additions & 2 deletions test/modules/core/passes/shadow-pass.spec.js
Expand Up @@ -39,7 +39,7 @@ test('ShadowPass#render', t => {
layerManager.setLayers([layer]);

const shadowPass = new ShadowPass(gl, {pixelRatio: 1.0});
shadowPass.render(gl, {
shadowPass.render({
viewports: [viewport],
layers: layerManager.getLayers(),
onViewportActive: layerManager.activateViewport,
Expand All @@ -64,7 +64,7 @@ test('ShadowPass#getModuleParameters', t => {
const shadowPass = new ShadowPass(gl, {pixelRatio: 1.0});
const moduleParameters = shadowPass.getModuleParameters(layer);

t.equal(moduleParameters.pickingActive, 0, `ShadowPass has no active picking module`);
t.equal(moduleParameters.drawToShadowMap, true, `ShadowPass has module parameters`);
shadowPass.delete();
t.end();
});

0 comments on commit c0e1f85

Please sign in to comment.