From 1f1b155b5c0d91ecd58b47937b7d1c896f5f72a8 Mon Sep 17 00:00:00 2001 From: felixpalmer Date: Mon, 2 Sep 2024 15:55:36 +0200 Subject: [PATCH] Aggregation layers UBO (#9114) --- .../grid-layer/grid-cell-layer-vertex.glsl.ts | 21 ++++-------- .../src/grid-layer/grid-cell-layer.ts | 28 +++++++++------- .../src/grid-layer/grid-layer-uniforms.ts | 33 +++++++++++++++++++ .../hexagon-cell-layer-vertex.glsl.ts | 23 ++++--------- .../src/hexagon-layer/hexagon-cell-layer.ts | 28 +++++++++------- .../hexagon-layer/hexagon-layer-uniforms.ts | 30 +++++++++++++++++ .../screen-grid-cell-layer.ts | 15 +++++---- .../screen-grid-layer-uniforms.ts | 27 +++++++++++++++ .../screen-grid-layer-vertex.glsl.ts | 11 ++----- .../screengrid-cell-layer.spec.ts | 15 ++++----- 10 files changed, 154 insertions(+), 77 deletions(-) create mode 100644 modules/aggregation-layers/src/grid-layer/grid-layer-uniforms.ts create mode 100644 modules/aggregation-layers/src/hexagon-layer/hexagon-layer-uniforms.ts create mode 100644 modules/aggregation-layers/src/screen-grid-layer/screen-grid-layer-uniforms.ts diff --git a/modules/aggregation-layers/src/grid-layer/grid-cell-layer-vertex.glsl.ts b/modules/aggregation-layers/src/grid-layer/grid-cell-layer-vertex.glsl.ts index a177fcf5ac5..d249e3ea545 100644 --- a/modules/aggregation-layers/src/grid-layer/grid-cell-layer-vertex.glsl.ts +++ b/modules/aggregation-layers/src/grid-layer/grid-cell-layer-vertex.glsl.ts @@ -14,16 +14,7 @@ in float instanceElevationValues; in float instanceColorValues; in vec3 instancePickingColors; -// Custom uniforms -uniform float opacity; -uniform bool extruded; -uniform float coverage; -uniform vec2 cellOriginCommon; -uniform vec2 cellSizeCommon; -uniform vec2 colorDomain; uniform sampler2D colorRange; -uniform vec2 elevationDomain; -uniform vec2 elevationRange; // Result out vec4 vColor; @@ -46,14 +37,14 @@ void main(void) { return; } - vec2 commonPosition = (instancePositions + (positions.xy + 1.0) / 2.0 * coverage) * cellSizeCommon + cellOriginCommon - project.commonOrigin.xy; + vec2 commonPosition = (instancePositions + (positions.xy + 1.0) / 2.0 * column.coverage) * grid.sizeCommon + grid.originCommon - project.commonOrigin.xy; geometry.position = vec4(commonPosition, 0.0, 1.0); geometry.normal = project_normal(normals); // calculate z, if 3d not enabled set to 0 float elevation = 0.0; - if (extruded) { - elevation = interp(instanceElevationValues, elevationDomain, elevationRange); + if (column.extruded) { + elevation = interp(instanceElevationValues, grid.elevationDomain, grid.elevationRange); elevation = project_size(elevation); // cylindar gemoetry height are between -1.0 to 1.0, transform it to between 0, 1 geometry.position.z = (positions.z + 1.0) / 2.0 * elevation; @@ -62,9 +53,9 @@ void main(void) { gl_Position = project_common_position_to_clipspace(geometry.position); DECKGL_FILTER_GL_POSITION(gl_Position, geometry); - vColor = interp(instanceColorValues, colorDomain, colorRange); - vColor.a *= opacity; - if (extruded) { + vColor = interp(instanceColorValues, grid.colorDomain, colorRange); + vColor.a *= layer.opacity; + if (column.extruded) { vColor.rgb = lighting_getLightColor(vColor.rgb, project.cameraPosition, geometry.position.xyz, geometry.normal); } DECKGL_FILTER_COLOR(vColor, geometry); diff --git a/modules/aggregation-layers/src/grid-layer/grid-cell-layer.ts b/modules/aggregation-layers/src/grid-layer/grid-cell-layer.ts index db3a10ebec0..42de63edccb 100644 --- a/modules/aggregation-layers/src/grid-layer/grid-cell-layer.ts +++ b/modules/aggregation-layers/src/grid-layer/grid-cell-layer.ts @@ -8,6 +8,7 @@ import {ColumnLayer} from '@deck.gl/layers'; import {CubeGeometry} from '@luma.gl/engine'; import {colorRangeToTexture} from '../common/utils/color-utils'; import vs from './grid-cell-layer-vertex.glsl'; +import {GridProps, gridUniforms} from './grid-layer-uniforms'; /** Proprties added by GridCellLayer. */ type GridCellLayerProps = { @@ -30,10 +31,9 @@ export class GridCellLayer extends ColumnLayer< }; getShaders() { - return { - ...super.getShaders(), - vs - }; + const shaders = super.getShaders(); + shaders.modules.push(gridUniforms); + return {...shaders, vs}; } initializeState() { @@ -74,7 +74,9 @@ export class GridCellLayer extends ColumnLayer< if (oldProps.colorRange !== props.colorRange) { this.state.colorTexture?.destroy(); this.state.colorTexture = colorRangeToTexture(this.context.device, props.colorRange); - model.setBindings({colorRange: this.state.colorTexture}); + + const gridProps: Partial = {colorRange: this.state.colorTexture}; + model.shaderInputs.setProps({grid: gridProps}); } } @@ -96,15 +98,17 @@ export class GridCellLayer extends ColumnLayer< const {cellOriginCommon, cellSizeCommon, elevationRange, elevationScale, extruded, coverage} = this.props; const fillModel = this.state.fillModel!; - fillModel.setUniforms(uniforms); - fillModel.setUniforms({ - extruded, - coverage, + + const gridProps: Omit = { colorDomain, elevationDomain, - cellOriginCommon, - cellSizeCommon, - elevationRange: [elevationRange[0] * elevationScale, elevationRange[1] * elevationScale] + elevationRange: [elevationRange[0] * elevationScale, elevationRange[1] * elevationScale], + originCommon: cellOriginCommon, + sizeCommon: cellSizeCommon + }; + fillModel.shaderInputs.setProps({ + column: {extruded, coverage}, + grid: gridProps }); fillModel.draw(this.context.renderPass); } diff --git a/modules/aggregation-layers/src/grid-layer/grid-layer-uniforms.ts b/modules/aggregation-layers/src/grid-layer/grid-layer-uniforms.ts new file mode 100644 index 00000000000..09e01ef58da --- /dev/null +++ b/modules/aggregation-layers/src/grid-layer/grid-layer-uniforms.ts @@ -0,0 +1,33 @@ +import {Texture} from '@luma.gl/core'; +import type {ShaderModule} from '@luma.gl/shadertools'; + +const uniformBlock = /* glsl */ `\ +uniform gridUniforms { + vec2 colorDomain; + vec2 elevationDomain; + vec2 elevationRange; + vec2 originCommon; + vec2 sizeCommon; +} grid; +`; + +export type GridProps = { + colorDomain: [number, number]; + colorRange: Texture; + elevationDomain: [number, number]; + elevationRange: [number, number]; + originCommon: [number, number]; + sizeCommon: [number, number]; +}; + +export const gridUniforms = { + name: 'grid', + vs: uniformBlock, + uniformTypes: { + colorDomain: 'vec2', + elevationDomain: 'vec2', + elevationRange: 'vec2', + originCommon: 'vec2', + sizeCommon: 'vec2' + } +} as const satisfies ShaderModule; diff --git a/modules/aggregation-layers/src/hexagon-layer/hexagon-cell-layer-vertex.glsl.ts b/modules/aggregation-layers/src/hexagon-layer/hexagon-cell-layer-vertex.glsl.ts index c2aa0a974e0..b82a10bfd3a 100644 --- a/modules/aggregation-layers/src/hexagon-layer/hexagon-cell-layer-vertex.glsl.ts +++ b/modules/aggregation-layers/src/hexagon-layer/hexagon-cell-layer-vertex.glsl.ts @@ -16,16 +16,7 @@ in float instanceElevationValues; in float instanceColorValues; in vec3 instancePickingColors; -// Custom uniforms -uniform float opacity; -uniform bool extruded; -uniform float coverage; -uniform float radius; -uniform vec2 hexOriginCommon; -uniform vec2 colorDomain; uniform sampler2D colorRange; -uniform vec2 elevationDomain; -uniform vec2 elevationRange; // Result out vec4 vColor; @@ -50,15 +41,15 @@ void main(void) { return; } - vec2 commonPosition = hexbinCentroid(instancePositions, radius) + (hexOriginCommon - project.commonOrigin.xy); - commonPosition += positions.xy * radius * coverage; + vec2 commonPosition = hexbinCentroid(instancePositions, column.radius) + (hexagon.originCommon - project.commonOrigin.xy); + commonPosition += positions.xy * column.radius * column.coverage; geometry.position = vec4(commonPosition, 0.0, 1.0); geometry.normal = project_normal(normals); // calculate z, if 3d not enabled set to 0 float elevation = 0.0; - if (extruded) { - elevation = interp(instanceElevationValues, elevationDomain, elevationRange); + if (column.extruded) { + elevation = interp(instanceElevationValues, hexagon.elevationDomain, hexagon.elevationRange); elevation = project_size(elevation); // cylindar gemoetry height are between -1.0 to 1.0, transform it to between 0, 1 geometry.position.z = (positions.z + 1.0) / 2.0 * elevation; @@ -67,9 +58,9 @@ void main(void) { gl_Position = project_common_position_to_clipspace(geometry.position); DECKGL_FILTER_GL_POSITION(gl_Position, geometry); - vColor = interp(instanceColorValues, colorDomain, colorRange); - vColor.a *= opacity; - if (extruded) { + vColor = interp(instanceColorValues, hexagon.colorDomain, colorRange); + vColor.a *= layer.opacity; + if (column.extruded) { vColor.rgb = lighting_getLightColor(vColor.rgb, project.cameraPosition, geometry.position.xyz, geometry.normal); } DECKGL_FILTER_COLOR(vColor, geometry); diff --git a/modules/aggregation-layers/src/hexagon-layer/hexagon-cell-layer.ts b/modules/aggregation-layers/src/hexagon-layer/hexagon-cell-layer.ts index a5c34630bf0..0484c7a53d8 100644 --- a/modules/aggregation-layers/src/hexagon-layer/hexagon-cell-layer.ts +++ b/modules/aggregation-layers/src/hexagon-layer/hexagon-cell-layer.ts @@ -7,6 +7,7 @@ import {UpdateParameters, Color} from '@deck.gl/core'; import {ColumnLayer} from '@deck.gl/layers'; import {colorRangeToTexture} from '../common/utils/color-utils'; import vs from './hexagon-cell-layer-vertex.glsl'; +import {HexagonProps, hexagonUniforms} from './hexagon-layer-uniforms'; /** Proprties added by HexagonCellLayer. */ export type _HexagonCellLayerProps = { @@ -28,10 +29,9 @@ export default class HexagonCellLayer extends Colum }; getShaders() { - return { - ...super.getShaders(), - vs - }; + const shaders = super.getShaders(); + shaders.modules.push(hexagonUniforms); + return {...shaders, vs}; } initializeState() { @@ -72,7 +72,9 @@ export default class HexagonCellLayer extends Colum if (oldProps.colorRange !== props.colorRange) { this.state.colorTexture?.destroy(); this.state.colorTexture = colorRangeToTexture(this.context.device, props.colorRange); - model.setBindings({colorRange: this.state.colorTexture}); + + const hexagonProps: Partial = {colorRange: this.state.colorTexture}; + model.shaderInputs.setProps({hexagon: hexagonProps}); } } @@ -96,15 +98,17 @@ export default class HexagonCellLayer extends Colum fillModel.setIndexBuffer(null); } fillModel.setVertexCount(this.state.fillVertexCount); - fillModel.setUniforms(uniforms); - fillModel.setUniforms({ - extruded, - coverage, + + const hexagonProps: Omit = { colorDomain, elevationDomain, - radius, - hexOriginCommon, - elevationRange: [elevationRange[0] * elevationScale, elevationRange[1] * elevationScale] + elevationRange: [elevationRange[0] * elevationScale, elevationRange[1] * elevationScale], + originCommon: hexOriginCommon + }; + + fillModel.shaderInputs.setProps({ + column: {extruded, coverage, radius}, + hexagon: hexagonProps }); fillModel.draw(this.context.renderPass); } diff --git a/modules/aggregation-layers/src/hexagon-layer/hexagon-layer-uniforms.ts b/modules/aggregation-layers/src/hexagon-layer/hexagon-layer-uniforms.ts new file mode 100644 index 00000000000..8c64e1919ff --- /dev/null +++ b/modules/aggregation-layers/src/hexagon-layer/hexagon-layer-uniforms.ts @@ -0,0 +1,30 @@ +import {Texture} from '@luma.gl/core'; +import type {ShaderModule} from '@luma.gl/shadertools'; + +const uniformBlock = /* glsl */ `\ +uniform hexagonUniforms { + vec2 colorDomain; + vec2 elevationDomain; + vec2 elevationRange; + vec2 originCommon; +} hexagon; +`; + +export type HexagonProps = { + colorDomain: [number, number]; + colorRange: Texture; + elevationDomain: [number, number]; + elevationRange: [number, number]; + originCommon: [number, number]; +}; + +export const hexagonUniforms = { + name: 'hexagon', + vs: uniformBlock, + uniformTypes: { + colorDomain: 'vec2', + elevationDomain: 'vec2', + elevationRange: 'vec2', + originCommon: 'vec2' + } +} as const satisfies ShaderModule; diff --git a/modules/aggregation-layers/src/screen-grid-layer/screen-grid-cell-layer.ts b/modules/aggregation-layers/src/screen-grid-layer/screen-grid-cell-layer.ts index e5c8394c9a2..5669605b29e 100644 --- a/modules/aggregation-layers/src/screen-grid-layer/screen-grid-cell-layer.ts +++ b/modules/aggregation-layers/src/screen-grid-layer/screen-grid-cell-layer.ts @@ -24,6 +24,7 @@ import {Layer, picking, UpdateParameters, DefaultProps, Color} from '@deck.gl/co import {defaultColorRange, colorRangeToTexture} from '../common/utils/color-utils'; import vs from './screen-grid-layer-vertex.glsl'; import fs from './screen-grid-layer-fragment.glsl'; +import {ScreenGridProps, screenGridUniforms} from './screen-grid-layer-uniforms'; import {ShaderModule} from '@luma.gl/shadertools'; const defaultProps: DefaultProps<_ScreenGridCellLayerProps> = { @@ -52,7 +53,7 @@ export default class ScreenGridCellLayer extends La }; getShaders(): {vs: string; fs: string; modules: ShaderModule[]} { - return {vs, fs, modules: [picking]}; + return super.getShaders({vs, fs, modules: [picking, screenGridUniforms]}); } initializeState() { @@ -81,7 +82,8 @@ export default class ScreenGridCellLayer extends La if (oldProps.colorRange !== props.colorRange) { this.state.colorTexture?.destroy(); this.state.colorTexture = colorRangeToTexture(this.context.device, props.colorRange); - model.setBindings({colorRange: this.state.colorTexture}); + const screenGridProps: Partial = {colorRange: this.state.colorTexture}; + model.shaderInputs.setProps({screenGrid: screenGridProps}); } if ( @@ -93,10 +95,11 @@ export default class ScreenGridCellLayer extends La const {cellSizePixels: gridSize, cellMarginPixels} = this.props; const cellSize = Math.max(gridSize - cellMarginPixels, 0); - model.setUniforms({ + const screenGridProps: Partial = { gridSizeClipspace: [(gridSize / width) * 2, (gridSize / height) * 2], cellSizeClipspace: [(cellSize / width) * 2, (cellSize / height) * 2] - }); + }; + model.shaderInputs.setProps({screenGrid: screenGridProps}); } } @@ -111,8 +114,8 @@ export default class ScreenGridCellLayer extends La const colorDomain = this.props.colorDomain(); const model = this.state.model!; - model.setUniforms(uniforms); - model.setUniforms({colorDomain}); + const screenGridProps: Partial = {colorDomain}; + model.shaderInputs.setProps({screenGrid: screenGridProps}); model.draw(this.context.renderPass); } diff --git a/modules/aggregation-layers/src/screen-grid-layer/screen-grid-layer-uniforms.ts b/modules/aggregation-layers/src/screen-grid-layer/screen-grid-layer-uniforms.ts new file mode 100644 index 00000000000..2a0091c1d15 --- /dev/null +++ b/modules/aggregation-layers/src/screen-grid-layer/screen-grid-layer-uniforms.ts @@ -0,0 +1,27 @@ +import {Texture} from '@luma.gl/core'; +import type {ShaderModule} from '@luma.gl/shadertools'; + +const uniformBlock = /* glsl */ `\ +uniform screenGridUniforms { + vec2 cellSizeClipspace; + vec2 gridSizeClipspace; + vec2 colorDomain; +} screenGrid; +`; + +export type ScreenGridProps = { + cellSizeClipspace: [number, number]; + gridSizeClipspace: [number, number]; + colorDomain: [number, number]; + colorRange: Texture; +}; + +export const screenGridUniforms = { + name: 'screenGrid', + vs: uniformBlock, + uniformTypes: { + cellSizeClipspace: 'vec2', + gridSizeClipspace: 'vec2', + colorDomain: 'vec2' + } +} as const satisfies ShaderModule; diff --git a/modules/aggregation-layers/src/screen-grid-layer/screen-grid-layer-vertex.glsl.ts b/modules/aggregation-layers/src/screen-grid-layer/screen-grid-layer-vertex.glsl.ts index 4b35cbd8556..f3a387976f4 100644 --- a/modules/aggregation-layers/src/screen-grid-layer/screen-grid-layer-vertex.glsl.ts +++ b/modules/aggregation-layers/src/screen-grid-layer/screen-grid-layer-vertex.glsl.ts @@ -28,28 +28,23 @@ in vec2 instancePositions; in float instanceWeights; in vec3 instancePickingColors; -uniform float opacity; -uniform ivec2 binCount; -uniform vec2 gridSizeClipspace; -uniform vec2 cellSizeClipspace; -uniform vec2 colorDomain; uniform sampler2D colorRange; out vec4 vColor; flat out int vIsValid; void main(void) { - vec2 pos = instancePositions * gridSizeClipspace + positions * cellSizeClipspace; + vec2 pos = instancePositions * screenGrid.gridSizeClipspace + positions * screenGrid.cellSizeClipspace; pos.x = pos.x - 1.0; pos.y = 1.0 - pos.y; gl_Position = vec4(pos, 0., 1.); vIsValid = isnan(instanceWeights) ? 0 : 1; - float r = min(max((instanceWeights - colorDomain.x) / (colorDomain.y - colorDomain.x), 0.), 1.); + float r = min(max((instanceWeights - screenGrid.colorDomain.x) / (screenGrid.colorDomain.y - screenGrid.colorDomain.x), 0.), 1.); vec4 rangeColor = texture(colorRange, vec2(r, 0.5)); - vColor = vec4(rangeColor.rgb, rangeColor.a * opacity); + vColor = vec4(rangeColor.rgb, rangeColor.a * layer.opacity); // Set color to be rendered to picking fbo (also used to check for selection highlight). picking_setPickingColor(instancePickingColors); diff --git a/test/modules/aggregation-layers/screengrid-cell-layer.spec.ts b/test/modules/aggregation-layers/screengrid-cell-layer.spec.ts index 69b5c64eaf3..0b1df5c999a 100644 --- a/test/modules/aggregation-layers/screengrid-cell-layer.spec.ts +++ b/test/modules/aggregation-layers/screengrid-cell-layer.spec.ts @@ -19,7 +19,7 @@ // THE SOFTWARE. /* eslint-disable func-style, no-console, max-len */ import test from 'tape-promise/tape'; -import {device} from '@deck.gl/test-utils'; +import {device, getLayerUniforms} from '@deck.gl/test-utils'; import ScreenGridCellLayer from '@deck.gl/aggregation-layers/screen-grid-layer/screen-grid-cell-layer'; import {testLayer} from '@deck.gl/test-utils'; @@ -50,12 +50,14 @@ test('ScreenGridCellLayer#constructor', t => { cellSizePixels: 50 // default 100 }, onBeforeUpdate({layer}) { - cellSize = layer.state.model.uniforms.cellSizeClipspace; + const uniforms = getLayerUniforms(layer); + cellSize = uniforms.cellSizeClipspace; }, onAfterUpdate({layer}) { t.ok(layer.state, 'should update layer state'); + const uniforms = getLayerUniforms(layer); t.notDeepEqual( - layer.state.model.uniforms.cellSizeClipspace, + uniforms.cellSizeClipspace, cellSize, 'should update cellSizeClipspace uniform' ); @@ -66,11 +68,8 @@ test('ScreenGridCellLayer#constructor', t => { colorDomain: () => [5, 50] }, onAfterUpdate({layer, oldState}) { - t.deepEqual( - layer.state.model.uniforms.colorDomain, - [5, 50], - 'should update colorDomain uniform' - ); + const uniforms = getLayerUniforms(layer); + t.deepEqual(uniforms.colorDomain, [5, 50], 'should update colorDomain uniform'); } } ]