Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ export class GridCellLayer<ExtraPropsT extends {} = {}> extends ColumnLayer<
protected _updateGeometry() {
const geometry = new CubeGeometry();
this._setFillGeometry(geometry);
this._setWireframeGeometry(geometry);
}

draw({uniforms}) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,6 @@ export default class HexagonCellLayer<ExtraPropsT extends {} = {}> extends Colum
const elevationCutoff = this.props.elevationCutoff || [-Infinity, Infinity];
const fillModel = this.state.fillModel!;

fillModel.setVertexCount(this.state.fillVertexCount);

const hexagonProps: Omit<HexagonProps, 'colorRange'> = {
colorDomain: [
Math.max(colorDomain[0], colorCutoff[0]), // instanceColorValue that maps to colorRange[0]
Expand Down
56 changes: 39 additions & 17 deletions modules/layers/src/column-layer/column-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,9 @@ export default class ColumnLayer<DataT = any, ExtraPropsT extends {} = {}> exten

state!: {
fillModel?: Model;
strokeModel?: Model;
wireframeModel?: Model;
models?: Model[];
fillVertexCount: number;
edgeDistance: number;
};

Expand Down Expand Up @@ -320,13 +320,15 @@ export default class ColumnLayer<DataT = any, ExtraPropsT extends {} = {}> exten

const instanceCount = this.getNumInstances();
this.state.fillModel!.setInstanceCount(instanceCount);
this.state.strokeModel!.setInstanceCount(instanceCount);
this.state.wireframeModel!.setInstanceCount(instanceCount);

if (
regenerateModels ||
props.diskResolution !== oldProps.diskResolution ||
props.vertices !== oldProps.vertices ||
(props.extruded || props.stroked) !== (oldProps.extruded || oldProps.stroked)
props.extruded !== oldProps.extruded ||
props.stroked !== oldProps.stroked
) {
this._updateGeometry(props);
}
Expand Down Expand Up @@ -370,6 +372,12 @@ export default class ColumnLayer<DataT = any, ExtraPropsT extends {} = {}> exten
bufferLayout,
isInstanced: true
});
const strokeModel = new Model(this.context.device, {
...shaders,
id: `${this.props.id}-stroke`,
bufferLayout,
isInstanced: true
});
const wireframeModel = new Model(this.context.device, {
...shaders,
id: `${this.props.id}-wireframe`,
Expand All @@ -379,8 +387,9 @@ export default class ColumnLayer<DataT = any, ExtraPropsT extends {} = {}> exten

return {
fillModel,
strokeModel,
wireframeModel,
models: [wireframeModel, fillModel]
models: [wireframeModel, fillModel, strokeModel]
};
}

Expand All @@ -389,10 +398,6 @@ export default class ColumnLayer<DataT = any, ExtraPropsT extends {} = {}> exten
const positionAttribute = geometry.attributes.POSITION;
const normalAttribute = geometry.attributes.NORMAL;

this.setState({
fillVertexCount: positionAttribute.value.length / 3
});

// The fill model renders a triangle-strip with degenerate triangles and does not
// use indices. Give it a separate Geometry without `indices` so that later buffer
// layout rebuilds (e.g. binary-data transitions, HMR) cannot re-attach the
Expand All @@ -404,7 +409,21 @@ export default class ColumnLayer<DataT = any, ExtraPropsT extends {} = {}> exten
})
);

this._setWireframeGeometry(geometry);
if (!extruded && stroked) {
const fillVertexCount = positionAttribute.value.length / 3;
this._setStrokeGeometry(
new Geometry({
topology: 'triangle-strip',
// remove the cap
vertexCount: fillVertexCount - diskResolution - 1,
attributes: {POSITION: positionAttribute, NORMAL: normalAttribute}
})
);
}

if (extruded) {
this._setWireframeGeometry(geometry);
}
}

protected _setFillGeometry(geometry: Geometry): void {
Expand All @@ -415,6 +434,14 @@ export default class ColumnLayer<DataT = any, ExtraPropsT extends {} = {}> exten
fillModel.setGeometry(fillGeometry);
}

protected _setStrokeGeometry(geometry: Geometry): void {
const strokeGeometry = makeInterleavedGeometry(geometry, {
attributes: ['POSITION', 'NORMAL']
});
const strokeModel = this.state.strokeModel!;
strokeModel.setGeometry(strokeGeometry);
}

protected _setWireframeGeometry(geometry: Geometry): void {
const wireframeGeometry = makeInterleavedGeometry(geometry, {
attributes: ['POSITION', 'NORMAL']
Expand Down Expand Up @@ -442,8 +469,9 @@ export default class ColumnLayer<DataT = any, ExtraPropsT extends {} = {}> exten
angle
} = this.props;
const fillModel = this.state.fillModel!;
const strokeModel = this.state.strokeModel!;
const wireframeModel = this.state.wireframeModel!;
const {fillVertexCount, edgeDistance} = this.state;
const {edgeDistance} = this.state;

const columnProps: Omit<ColumnProps, 'isStroke'> = {
radius,
Expand Down Expand Up @@ -473,8 +501,6 @@ export default class ColumnLayer<DataT = any, ExtraPropsT extends {} = {}> exten
}

if (filled) {
// model.setProps({isIndexed: false});
fillModel.setVertexCount(fillVertexCount);
fillModel.shaderInputs.setProps({
column: {
...columnProps,
Expand All @@ -485,17 +511,13 @@ export default class ColumnLayer<DataT = any, ExtraPropsT extends {} = {}> exten
}
// When drawing 2d: draw fill before stroke so that the outline is always on top
if (!extruded && stroked) {
// model.setProps({isIndexed: false});
// The width of the stroke is achieved by flattening the side of the cylinder.
// Skip the last 1/3 of the vertices which is the top.
fillModel.setVertexCount((fillVertexCount * 2) / 3);
fillModel.shaderInputs.setProps({
strokeModel.shaderInputs.setProps({
column: {
...columnProps,
isStroke: true
}
});
fillModel.draw(this.context.renderPass);
strokeModel.draw(this.context.renderPass);
}
}
}
1 change: 0 additions & 1 deletion modules/layers/src/column-layer/grid-cell-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ export default class GridCellLayer<DataT = any, ExtraPropsT extends {} = {}> ext
protected _updateGeometry() {
const geometry = new CubeGeometry();
this._setFillGeometry(geometry);
this._setWireframeGeometry(geometry);
}

draw({uniforms}) {
Expand Down
19 changes: 9 additions & 10 deletions test/modules/aggregation-layers/grid-layer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,15 @@ test('GridLayer', () => {
onBeforeUpdate: ({testCase}) => console.log(testCase.title),
onAfterUpdate({layer, subLayer}) {
expect(layer.state.aggregator, 'should have aggregator').toBeTruthy();
for (const model of subLayer?.getModels() || []) {
const bufferNames = model.bufferLayout.map(layout => layout.name);
expect(
bufferNames.filter(name => name === 'geometry'),
`${model.id} has one geometry buffer layout`
).toHaveLength(1);
expect(new Set(bufferNames).size, `${model.id} has unique buffer layouts`).toBe(
bufferNames.length
);
}
const model = subLayer?.state.fillModel!;
const bufferNames = model.bufferLayout.map(layout => layout.name);
expect(
bufferNames.filter(name => name === 'geometry'),
`${model.id} has one geometry buffer layout`
).toHaveLength(1);
expect(new Set(bufferNames).size, `${model.id} has unique buffer layouts`).toBe(
bufferNames.length
);
}
});

Expand Down
63 changes: 29 additions & 34 deletions test/modules/layers/column-layer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,37 @@ import {ColumnLayer, GridCellLayer} from '@deck.gl/layers';
import {testLayer} from '@deck.gl/test-utils/vitest';

function expectUniqueGeometryLayout(layer: ColumnLayer): void {
for (const model of layer.getModels()) {
const bufferNames = model.bufferLayout.map(layout => layout.name);
expect(new Set(bufferNames).size, `${model.id} has unique buffer layouts`).toBe(
bufferNames.length
);
expect(
bufferNames.filter(name => name === 'geometry'),
`${model.id} has one geometry buffer layout`
).toHaveLength(1);
const model = layer.state.fillModel!;
const bufferNames = model.bufferLayout.map(layout => layout.name);
expect(new Set(bufferNames).size, `${model.id} has unique buffer layouts`).toBe(
bufferNames.length
);
expect(
bufferNames.filter(name => name === 'geometry'),
`${model.id} has one geometry buffer layout`
).toHaveLength(1);

const geometryLayout = model.bufferLayout.find(layout => layout.name === 'geometry');
const attachedGeometryLayout = model._gpuGeometry?.bufferLayout.find(
layout => layout.name === 'geometry'
);
expect(
geometryLayout?.attributes?.map(attribute => attribute.attribute),
`${model.id} geometry attributes`
).toEqual(['positions', 'normals']);
expect(
attachedGeometryLayout,
`${model.id} has an attached geometry buffer layout`
).toBeTruthy();
expect(geometryLayout, `${model.id} layout matches its attached geometry`).toEqual(
attachedGeometryLayout
);
const geometryLayout = model.bufferLayout.find(layout => layout.name === 'geometry');
const attachedGeometryLayout = model._gpuGeometry?.bufferLayout.find(
layout => layout.name === 'geometry'
);
expect(
geometryLayout?.attributes?.map(attribute => attribute.attribute),
`${model.id} geometry attributes`
).toEqual(['positions', 'normals']);
expect(attachedGeometryLayout, `${model.id} has an attached geometry buffer layout`).toBeTruthy();
expect(geometryLayout, `${model.id} layout matches its attached geometry`).toEqual(
attachedGeometryLayout
);

const pipelineBufferNames = model.pipeline.bufferLayout.map(layout => layout.name);
expect(
new Set(pipelineBufferNames).size,
`${model.id} pipeline has unique buffer layouts`
).toBe(pipelineBufferNames.length);
expect(
pipelineBufferNames.filter(name => name === 'geometry'),
`${model.id} pipeline has one geometry buffer layout`
).toHaveLength(1);
}
const pipelineBufferNames = model.pipeline.bufferLayout.map(layout => layout.name);
expect(new Set(pipelineBufferNames).size, `${model.id} pipeline has unique buffer layouts`).toBe(
pipelineBufferNames.length
);
expect(
pipelineBufferNames.filter(name => name === 'geometry'),
`${model.id} pipeline has one geometry buffer layout`
).toHaveLength(1);
}

// Regression test for #9463 / #10021: with binary data the fill model must
Expand Down