From bf4f23288cbfa6a73ee699025792f9aba6308798 Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Wed, 7 Sep 2022 14:36:26 +0200 Subject: [PATCH 01/17] [WIP] investigate cause of bug --- .../src/heatmap-layer/heatmap-layer.ts | 10 ++- .../src/heatmap-layer/triangle-layer.ts | 19 ++++- modules/extensions/src/mask/shader-module.ts | 8 +- test/apps/mask/app.js | 82 +++++-------------- 4 files changed, 49 insertions(+), 70 deletions(-) diff --git a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts index 7034a10ba27..547166d53a2 100644 --- a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts @@ -276,6 +276,14 @@ export default class HeatmapLayer extends Aggrega colorTexture, colorDomain } = this.state; + console.log( + 'weightsTexture', + weightsTexture.textureUnit, + 'maxWeightsTexture', + maxWeightsTexture.textureUnit, + 'colorTexture', + colorTexture.textureUnit + ); const {updateTriggers, intensity, threshold, aggregation} = this.props; const TriangleLayerClass = this.getSubLayerClass('triangle', TriangleLayer); @@ -299,7 +307,7 @@ export default class HeatmapLayer extends Aggrega maxTexture: maxWeightsTexture, colorTexture, aggregationMode: AGGREGATION_MODE[aggregation] || 0, - texture: weightsTexture, + texture: weightsTexture, /// <-- PROBLEM intensity, threshold, colorDomain diff --git a/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts b/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts index cf28b4b865b..612e3937647 100644 --- a/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts @@ -19,7 +19,7 @@ // THE SOFTWARE. import GL from '@luma.gl/constants'; -import {Model, Geometry, Texture2D} from '@luma.gl/core'; +import {Model, Geometry, Texture2D, UpdateParameters} from '@luma.gl/core'; import {Layer, LayerContext, project32} from '@deck.gl/core'; import vs from './triangle-layer-vertex.glsl'; import fs from './triangle-layer-fragment.glsl'; @@ -39,7 +39,8 @@ export default class TriangleLayer extends Layer<_TriangleLayerProps> { static layerName = 'TriangleLayer'; getShaders() { - return {vs, fs, modules: [project32]}; + return super.getShaders({vs, fs, modules: [project32]}); + // return {vs, fs, modules: [project32]}; } initializeState({gl}: LayerContext): void { @@ -53,6 +54,16 @@ export default class TriangleLayer extends Layer<_TriangleLayerProps> { }); } + updateState(opts: UpdateParameters) { + super.updateState(opts); + const {changeFlags} = opts; + if (changeFlags.extensionsChanged) { + this.setState({ + model: this._getModel(opts.context.gl) + }); + } + } + _getModel(gl: WebGLRenderingContext): Model { const {vertexCount} = this.props; @@ -75,9 +86,9 @@ export default class TriangleLayer extends Layer<_TriangleLayerProps> { model .setUniforms({ ...uniforms, - texture, - maxTexture, colorTexture, + texture, // <---- PROBLEM (put second to avoid warning :/) + maxTexture, intensity, threshold, aggregationMode, diff --git a/modules/extensions/src/mask/shader-module.ts b/modules/extensions/src/mask/shader-module.ts index 0e9ca572baa..5b65f231d1c 100644 --- a/modules/extensions/src/mask/shader-module.ts +++ b/modules/extensions/src/mask/shader-module.ts @@ -49,15 +49,15 @@ varying vec2 mask_texCoords; 'fs:#decl': ` varying vec2 mask_texCoords; `, - 'fs:#main-start': ` + 'fs:#main-end': ` if (mask_enabled) { bool mask = mask_isInBounds(mask_texCoords); // Debug: show extent of render target - // gl_FragColor = vec4(mask_texCoords, 0.0, 1.0); - gl_FragColor = texture2D(mask_texture, mask_texCoords); + gl_FragColor = vec4(mask_texCoords, 0.0, 1.0); + // gl_FragColor = vec4(1.0); - if (!mask) discard; + // if (!mask) discard; } ` }; diff --git a/test/apps/mask/app.js b/test/apps/mask/app.js index 1218b1a11b8..cf2eff9f9bf 100644 --- a/test/apps/mask/app.js +++ b/test/apps/mask/app.js @@ -6,6 +6,7 @@ import DeckGL from '@deck.gl/react'; import {OPERATION} from '@deck.gl/core'; import {GeoJsonLayer, SolidPolygonLayer} from '@deck.gl/layers'; import {ScatterplotLayer, ArcLayer} from '@deck.gl/layers'; +import {HeatmapLayer} from '@deck.gl/aggregation-layers'; import {MVTLayer} from '@deck.gl/geo-layers'; import {MaskExtension} from '@deck.gl/extensions'; import {scaleLinear} from 'd3-scale'; @@ -154,26 +155,14 @@ export default function App({data, strokeWidth = 1, mapStyle = MAP_STYLE}) { getPolygon: d => d }), // Boundary around USA (masked by selected state) - new SolidPolygonLayer({ - id: 'masked-layer', - data: [{polygon: rectangle}], - getFillColor: [...TARGET_COLOR, 200], - maskId: maskEnabled && 'mask', - extensions: [new MaskExtension()] - }), - new MVTLayer({ - id: 'mvt-layer', - data: 'https://tiles-a.basemaps.cartocdn.com/vectortiles/carto.streets/v1/{z}/{x}/{y}.mvt', - maskId: maskEnabled && 'mask', - extensions: [new MaskExtension()], - maxZoom: 14, - getFillColor: [255, 255, 255], - getLineColor: [192, 192, 192], - getLineWidth: 1, - getPointRadius: 2, - lineWidthUnits: 'pixels', - pointRadiusUnits: 'pixels' - }), + false && + new SolidPolygonLayer({ + id: 'masked-layer', + data: [{polygon: rectangle}], + getFillColor: [...TARGET_COLOR, 200], + maskId: maskEnabled && 'mask', + extensions: [new MaskExtension()] + }), // US states (used to select & define masks) new GeoJsonLayer({ id: 'us-states', @@ -190,55 +179,26 @@ export default function App({data, strokeWidth = 1, mapStyle = MAP_STYLE}) { highlightColor: [255, 255, 255, 150] }), // Rings around target (clipped by mask) - new ScatterplotLayer({ - id: 'targets-ring', - data: targets, - lineWidthMinPixels: 2, - filled: true, - stroked: true, - radiusScale: 100000, - getFillColor: [255, 255, 255, 150], - getLineColor: [0, 0, 0, 100], - parameters: {depthTest: false}, - extensions: [new MaskExtension()], - maskId: maskEnabled && 'mask2', - maskByInstance: false - }), new ScatterplotLayer({ id: 'sources', data: sources, radiusScale: 3000, + radiusMinPixels: 10, getFillColor: d => (d.gain > 0 ? TARGET_COLOR : SOURCE_COLOR), extensions: [new MaskExtension()], maskId: maskEnabled && 'mask2' }), - new ScatterplotLayer({ - id: 'targets', - data: targets, - pickable: true, - onClick: ({object}) => { - console.log(object); - }, - autoHighlight: true, - highlightColor: [255, 255, 255, 150], - radiusScale: 3000, - getFillColor: d => (d.net > 0 ? TARGET_COLOR : SOURCE_COLOR), - extensions: [new MaskExtension()], - maskId: maskEnabled && 'mask2' - }), - new ArcLayer({ - id: 'arc', - data: arcs, - getWidth: strokeWidth, - opacity: 0.7, - getSourcePosition: d => d.source, - getTargetPosition: d => d.target, - getSourceColor: SOURCE_COLOR, - getTargetColor: TARGET_COLOR, - extensions: [new MaskExtension()], - maskId: maskEnabled && 'mask', - maskByInstance: true - }) + false && + new HeatmapLayer({ + id: 'sources-heatmap', + data: sources, + radiusMinPixels: 10, + getPosition: d => d.position, + getWeight: d => Math.abs(d.gain), + extensions: maskEnabled ? [new MaskExtension()] : [], + maskId: maskEnabled && 'mask2', + maskByInstance: false + }) ]; return ( From 341b3f775a90239bd39c8aabc9391d6223326bd2 Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Wed, 9 Nov 2022 11:09:57 +0100 Subject: [PATCH 02/17] Debug view with mask FBO --- modules/core/src/effects/mask/mask-effect.ts | 53 ++++++++++---------- modules/extensions/src/mask/shader-module.ts | 4 +- test/apps/mask/app.js | 2 +- test/apps/mask/index.html | 43 ++++++++++------ 4 files changed, 58 insertions(+), 44 deletions(-) diff --git a/modules/core/src/effects/mask/mask-effect.ts b/modules/core/src/effects/mask/mask-effect.ts index e0aff856cd7..cf31d623100 100644 --- a/modules/core/src/effects/mask/mask-effect.ts +++ b/modules/core/src/effects/mask/mask-effect.ts @@ -1,5 +1,5 @@ import {Texture2D} from '@luma.gl/core'; -// import {readPixelsToArray} from '@luma.gl/core'; +import {readPixelsToArray} from '@luma.gl/core'; import {equals} from '@math.gl/core'; import MaskPass from '../../passes/mask-pass'; import {OPERATION} from '../../lib/constants'; @@ -84,31 +84,32 @@ export default class MaskEffect implements Effect { }); } - // // Debug show FBO contents on screen - // const color = readPixelsToArray(this.maskMap); - // let canvas = document.getElementById('fbo-canvas'); - // if (!canvas) { - // canvas = document.createElement('canvas'); - // canvas.id = 'fbo-canvas'; - // canvas.width = this.maskMap.width; - // canvas.height = this.maskMap.height; - // canvas.style.zIndex = 100; - // canvas.style.position = 'absolute'; - // canvas.style.right = 0; - // canvas.style.border = 'blue 1px solid'; - // canvas.style.width = '256px'; - // canvas.style.transform = 'scaleY(-1)'; - // document.body.appendChild(canvas); - // } - // const ctx = canvas.getContext('2d'); - // const imageData = ctx.createImageData(this.maskMap.width, this.maskMap.height); - // for (let i = 0; i < color.length; i += 4) { - // imageData.data[i + 0] = color[i + 0]; - // imageData.data[i + 1] = color[i + 1]; - // imageData.data[i + 2] = color[i + 2]; - // imageData.data[i + 3] = color[i + 3] + 128; - // } - // ctx.putImageData(imageData, 0, 0); + // Debug show FBO contents on screen + const color = readPixelsToArray(this.maskMap); + let canvas = document.getElementById('fbo-canvas'); + if (!canvas) { + canvas = document.createElement('canvas'); + canvas.id = 'fbo-canvas'; + canvas.width = this.maskMap.width; + canvas.height = this.maskMap.height; + canvas.style.zIndex = 100; + canvas.style.position = 'absolute'; + canvas.style.right = 0; + canvas.style.top = 0; + canvas.style.border = 'blue 1px solid'; + canvas.style.width = '256px'; + canvas.style.transform = 'scaleY(-1)'; + document.body.appendChild(canvas); + } + const ctx = canvas.getContext('2d'); + const imageData = ctx.createImageData(this.maskMap.width, this.maskMap.height); + for (let i = 0; i < color.length; i += 4) { + imageData.data[i + 0] = color[i + 0]; + imageData.data[i + 1] = color[i + 1]; + imageData.data[i + 2] = color[i + 2]; + imageData.data[i + 3] = color[i + 3] + 128; + } + ctx.putImageData(imageData, 0, 0); } private _renderChannel( diff --git a/modules/extensions/src/mask/shader-module.ts b/modules/extensions/src/mask/shader-module.ts index 5b65f231d1c..03f05075610 100644 --- a/modules/extensions/src/mask/shader-module.ts +++ b/modules/extensions/src/mask/shader-module.ts @@ -54,10 +54,12 @@ varying vec2 mask_texCoords; bool mask = mask_isInBounds(mask_texCoords); // Debug: show extent of render target - gl_FragColor = vec4(mask_texCoords, 0.0, 1.0); + // gl_FragColor = vec4(mask_texCoords, 0.0, 1.0); // gl_FragColor = vec4(1.0); // if (!mask) discard; + // Debug (mask out in blue, not discard) + if (!mask) gl_FragColor = vec4(0.0, 0.0, 1.0, 0.1); } ` }; diff --git a/test/apps/mask/app.js b/test/apps/mask/app.js index cf2eff9f9bf..06cc42cf269 100644 --- a/test/apps/mask/app.js +++ b/test/apps/mask/app.js @@ -188,7 +188,7 @@ export default function App({data, strokeWidth = 1, mapStyle = MAP_STYLE}) { extensions: [new MaskExtension()], maskId: maskEnabled && 'mask2' }), - false && + true && new HeatmapLayer({ id: 'sources-heatmap', data: sources, diff --git a/test/apps/mask/index.html b/test/apps/mask/index.html index 22fe02abf4e..f259e56759f 100644 --- a/test/apps/mask/index.html +++ b/test/apps/mask/index.html @@ -1,18 +1,29 @@ - + - - - deck.gl Example - - - - -
- - - + + + deck.gl Example + + + + +
+ + + From 1bc6a1e669acac57d79f7cd2bfa2b385dc7a1ee1 Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Wed, 9 Nov 2022 14:36:06 +0100 Subject: [PATCH 03/17] Force masking in weightsTransform --- .../src/heatmap-layer/heatmap-layer.ts | 37 +++++++++++++++++++ .../src/heatmap-layer/triangle-layer.ts | 1 + .../src/heatmap-layer/weights-vs.glsl.ts | 1 + modules/extensions/src/mask/shader-module.ts | 4 +- 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts index 547166d53a2..9af39c81d1b 100644 --- a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts @@ -19,6 +19,7 @@ // THE SOFTWARE. /* global setTimeout clearTimeout */ +import {readPixelsToArray} from '@luma.gl/core'; import GL from '@luma.gl/constants'; import { getBounds, @@ -605,6 +606,11 @@ export default class HeatmapLayer extends Aggrega } const uniforms = { + // Force mask (trouble is getting these from mask extension... + mask_enabled: true, + mask_bounds: [77.87691066740754, 304.98062194849194, 94.83216756252682, 321.93587884361136], + + // radiusPixels, commonBounds, textureWidth: textureSize, @@ -631,6 +637,7 @@ export default class HeatmapLayer extends Aggrega }); }); this._updateMaxWeightValue(); + this._debug(); // reset filtering parameters (TODO: remove once luma issue#1193 is fixed) weightsTexture.setParameters({ @@ -639,6 +646,36 @@ export default class HeatmapLayer extends Aggrega }); } + _debug() { + // Debug show FBO contents on screen + const {weightsTexture} = this.state; + const color = readPixelsToArray(weightsTexture); + let canvas = document.getElementById('weights-canvas') as HTMLCanvasElement; + if (!canvas) { + canvas = document.createElement('canvas'); + canvas.id = 'weights-canvas'; + canvas.width = weightsTexture.width; + canvas.height = weightsTexture.height; + canvas.style.zIndex = '100'; + canvas.style.position = 'absolute'; + canvas.style.right = '0'; + canvas.style.top = '256px'; + canvas.style.border = 'blue 1px solid'; + canvas.style.width = '256px'; + canvas.style.transform = 'scaleY(-1)'; + document.body.appendChild(canvas); + } + const ctx = canvas.getContext('2d')!; + const imageData = ctx.createImageData(weightsTexture.width, weightsTexture.height); + for (let i = 0; i < color.length; i += 4) { + imageData.data[i + 0] = color[i + 0]; + imageData.data[i + 1] = color[i + 1]; + imageData.data[i + 2] = color[i + 2]; + imageData.data[i + 3] = 255; //color[i + 3]; + } + ctx.putImageData(imageData, 0, 0); + } + _debouncedUpdateWeightmap(fromTimer = false) { let {updateTimer} = this.state; const {debounceTimeout} = this.props; diff --git a/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts b/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts index 612e3937647..aad302778a5 100644 --- a/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts @@ -86,6 +86,7 @@ export default class TriangleLayer extends Layer<_TriangleLayerProps> { model .setUniforms({ ...uniforms, + mask_enabled: false, // <-- masking happens in weightsTransform colorTexture, texture, // <---- PROBLEM (put second to avoid warning :/) maxTexture, diff --git a/modules/aggregation-layers/src/heatmap-layer/weights-vs.glsl.ts b/modules/aggregation-layers/src/heatmap-layer/weights-vs.glsl.ts index 41f11e4e510..d18d176f69b 100644 --- a/modules/aggregation-layers/src/heatmap-layer/weights-vs.glsl.ts +++ b/modules/aggregation-layers/src/heatmap-layer/weights-vs.glsl.ts @@ -15,6 +15,7 @@ void main() gl_PointSize = radiusTexels * 2.; vec3 commonPosition = project_position(positions, positions64Low); + geometry.position = vec4(commonPosition, 1.0); // map xy from commonBounds to [-1, 1] gl_Position.xy = (commonPosition.xy - commonBounds.xy) / (commonBounds.zw - commonBounds.xy) ; diff --git a/modules/extensions/src/mask/shader-module.ts b/modules/extensions/src/mask/shader-module.ts index 03f05075610..88c157153de 100644 --- a/modules/extensions/src/mask/shader-module.ts +++ b/modules/extensions/src/mask/shader-module.ts @@ -57,9 +57,9 @@ varying vec2 mask_texCoords; // gl_FragColor = vec4(mask_texCoords, 0.0, 1.0); // gl_FragColor = vec4(1.0); - // if (!mask) discard; + if (!mask) discard; // Debug (mask out in blue, not discard) - if (!mask) gl_FragColor = vec4(0.0, 0.0, 1.0, 0.1); + // if (!mask) gl_FragColor = vec4(0.0, 0.0, 1.0, 0.1); } ` }; From 758013a29e23892fb08f67fe8b388cd2663ff1ed Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Wed, 9 Nov 2022 15:07:19 +0100 Subject: [PATCH 04/17] Get mask somewhat working in Heatmap --- .../src/aggregation-layer.ts | 10 ++++++ .../src/heatmap-layer/heatmap-layer.ts | 31 ++++++++++--------- test/apps/mask/app.js | 12 ++++--- 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/modules/aggregation-layers/src/aggregation-layer.ts b/modules/aggregation-layers/src/aggregation-layer.ts index ee2858a7d06..b289dcfb838 100644 --- a/modules/aggregation-layers/src/aggregation-layer.ts +++ b/modules/aggregation-layers/src/aggregation-layer.ts @@ -86,6 +86,16 @@ export default abstract class AggregationLayer< pickingActive: 0, devicePixelRatio: cssToDeviceRatio(gl) }); + + // @ts-ignore + const effects = this.context.deck?.effectManager?.getEffects(); + // HACK needed to get maskChannels & maskMap + if (effects) { + for (const effect of effects) { + Object.assign(moduleSettings, effect.getModuleParameters?.(this)); + } + } + return moduleSettings; } diff --git a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts index 9af39c81d1b..a20f97d4f7a 100644 --- a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts @@ -277,14 +277,6 @@ export default class HeatmapLayer extends Aggrega colorTexture, colorDomain } = this.state; - console.log( - 'weightsTexture', - weightsTexture.textureUnit, - 'maxWeightsTexture', - maxWeightsTexture.textureUnit, - 'colorTexture', - colorTexture.textureUnit - ); const {updateTriggers, intensity, threshold, aggregation} = this.props; const TriangleLayerClass = this.getSubLayerClass('triangle', TriangleLayer); @@ -616,6 +608,20 @@ export default class HeatmapLayer extends Aggrega textureWidth: textureSize, weightsScale }; + + // Process extensions for transform + const moduleSettings = this.getModuleSettings(); + const parameters = { + blend: true, + depthTest: false, + blendFunc: [GL.ONE, GL.ONE], + blendEquation: GL.FUNC_ADD + }; + const opts = {moduleParameters: moduleSettings, uniforms, parameters, context: this.context}; + for (const extension of this.props.extensions) { + extension.draw.call(this, opts, extension); + } + // Attribute manager sets data array count as instaceCount on model // we need to set that as elementCount on 'weightsTransform' weightsTransform.update({ @@ -625,15 +631,10 @@ export default class HeatmapLayer extends Aggrega withParameters(this.context.gl, {clearColor: [0, 0, 0, 0]}, () => { weightsTransform.run({ uniforms, - parameters: { - blend: true, - depthTest: false, - blendFunc: [GL.ONE, GL.ONE], - blendEquation: GL.FUNC_ADD - }, + parameters, clearRenderTarget: true, attributes: this.getAttributes(), - moduleSettings: this.getModuleSettings() + moduleSettings }); }); this._updateMaxWeightValue(); diff --git a/test/apps/mask/app.js b/test/apps/mask/app.js index 06cc42cf269..9b0e9289ef6 100644 --- a/test/apps/mask/app.js +++ b/test/apps/mask/app.js @@ -128,11 +128,13 @@ export default function App({data, strokeWidth = 1, mapStyle = MAP_STYLE}) { }, [selectedCounty2]); const onClickState = useCallback((info, evt) => { - if (evt.srcEvent.shiftKey) { - selectCounty2(info.object); - } else { - selectCounty(info.object); - } + // if (evt.srcEvent.shiftKey) { + // selectCounty2(info.object); + // } else { + // selectCounty(info.object); + // } + selectCounty(info.object); + selectCounty2(info.object); }, []); const onDataLoad = useCallback(geojson => { From ae62f72a26682db41113e328e2c5863807829d72 Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Wed, 9 Nov 2022 16:09:08 +0100 Subject: [PATCH 05/17] Primitive method of updating weights --- .../src/heatmap-layer/heatmap-layer.ts | 13 ++++++++----- modules/core/src/effects/mask/mask-effect.ts | 14 +++++++++----- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts index a20f97d4f7a..ea414e4f3a4 100644 --- a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts @@ -197,6 +197,7 @@ export default class HeatmapLayer extends Aggrega state!: AggregationLayer['state'] & { supported: boolean; colorDomain?: number[]; + maskRenderCount: number; isWeightMapDirty?: boolean; weightsTexture?: Texture2D; zoom?: number; @@ -239,6 +240,12 @@ export default class HeatmapLayer extends Aggrega const {props, oldProps} = opts; const changeFlags = this._getChangeFlags(opts); + const {maskRenderCount} = this.getModuleSettings(); + if (maskRenderCount !== this.state.maskRenderCount) { + changeFlags.dataChanged = 'mask'; + this.setState({maskRenderCount}); + } + if (changeFlags.dataChanged || changeFlags.viewportChanged) { // if data is changed, do not debounce and immediately update the weight map changeFlags.boundsChanged = this._updateBounds(changeFlags.dataChanged); @@ -259,6 +266,7 @@ export default class HeatmapLayer extends Aggrega } if (this.state.isWeightMapDirty) { + console.log('updating weightmap'); this._updateWeightmap(); } @@ -598,11 +606,6 @@ export default class HeatmapLayer extends Aggrega } const uniforms = { - // Force mask (trouble is getting these from mask extension... - mask_enabled: true, - mask_bounds: [77.87691066740754, 304.98062194849194, 94.83216756252682, 321.93587884361136], - - // radiusPixels, commonBounds, textureWidth: textureSize, diff --git a/modules/core/src/effects/mask/mask-effect.ts b/modules/core/src/effects/mask/mask-effect.ts index cf31d623100..9ed39b2d6d0 100644 --- a/modules/core/src/effects/mask/mask-effect.ts +++ b/modules/core/src/effects/mask/mask-effect.ts @@ -40,6 +40,7 @@ export default class MaskEffect implements Effect { private dummyMaskMap?: Texture2D; private channels: (Channel | null)[] = []; private masks: Record | null = null; + private maskRenderCount: number = 0; private maskPass?: MaskPass; private maskMap?: Texture2D; private lastViewport?: Viewport; @@ -86,22 +87,22 @@ export default class MaskEffect implements Effect { // Debug show FBO contents on screen const color = readPixelsToArray(this.maskMap); - let canvas = document.getElementById('fbo-canvas'); + let canvas = document.getElementById('fbo-canvas') as HTMLCanvasElement; if (!canvas) { canvas = document.createElement('canvas'); canvas.id = 'fbo-canvas'; canvas.width = this.maskMap.width; canvas.height = this.maskMap.height; - canvas.style.zIndex = 100; + canvas.style.zIndex = '100'; canvas.style.position = 'absolute'; - canvas.style.right = 0; - canvas.style.top = 0; + canvas.style.right = '0'; + canvas.style.top = '0'; canvas.style.border = 'blue 1px solid'; canvas.style.width = '256px'; canvas.style.transform = 'scaleY(-1)'; document.body.appendChild(canvas); } - const ctx = canvas.getContext('2d'); + const ctx = canvas.getContext('2d')!; const imageData = ctx.createImageData(this.maskMap.width, this.maskMap.height); for (let i = 0; i < color.length; i += 4) { imageData.data[i + 0] = color[i + 0]; @@ -177,6 +178,7 @@ export default class MaskEffect implements Effect { devicePixelRatio: 1 } }); + this.maskRenderCount++; } } @@ -242,10 +244,12 @@ export default class MaskEffect implements Effect { getModuleParameters(): { maskMap: Texture2D; + maskRenderCount: number; maskChannels: Record | null; } { return { maskMap: this.masks ? this.maskMap : this.dummyMaskMap, + maskRenderCount: this.maskRenderCount, maskChannels: this.masks }; } From 6a5aca713ee0746d1410712f21e69ac7c73babc9 Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Wed, 9 Nov 2022 17:05:34 +0100 Subject: [PATCH 06/17] shouldUpdateState when mask changes --- .../src/heatmap-layer/heatmap-layer.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts index ea414e4f3a4..17f29b9c62b 100644 --- a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts @@ -223,8 +223,10 @@ export default class HeatmapLayer extends Aggrega } shouldUpdateState({changeFlags}: UpdateParameters) { - // Need to be updated when viewport changes - return changeFlags.somethingChanged; + // Need to be updated when viewport or mask changes + const {maskRenderCount} = this.getModuleSettings(); + const maskChanged = maskRenderCount !== this.state.maskRenderCount; + return changeFlags.somethingChanged || maskChanged; } /* eslint-disable max-statements,complexity */ @@ -242,6 +244,7 @@ export default class HeatmapLayer extends Aggrega const {maskRenderCount} = this.getModuleSettings(); if (maskRenderCount !== this.state.maskRenderCount) { + // Treat new mask as if data had changed changeFlags.dataChanged = 'mask'; this.setState({maskRenderCount}); } @@ -266,7 +269,6 @@ export default class HeatmapLayer extends Aggrega } if (this.state.isWeightMapDirty) { - console.log('updating weightmap'); this._updateWeightmap(); } @@ -277,6 +279,7 @@ export default class HeatmapLayer extends Aggrega if (!this.state.supported) { return []; } + const { weightsTexture, triPositionBuffer, From 67a0e1877dadc950061844d68db59e5ac69a7e84 Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Wed, 9 Nov 2022 17:23:33 +0100 Subject: [PATCH 07/17] postEffect hack --- .../src/heatmap-layer/heatmap-layer.ts | 15 +++++++++++---- modules/core/src/passes/layers-pass.ts | 6 ++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts index 17f29b9c62b..d857e5f0731 100644 --- a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts @@ -223,10 +223,8 @@ export default class HeatmapLayer extends Aggrega } shouldUpdateState({changeFlags}: UpdateParameters) { - // Need to be updated when viewport or mask changes - const {maskRenderCount} = this.getModuleSettings(); - const maskChanged = maskRenderCount !== this.state.maskRenderCount; - return changeFlags.somethingChanged || maskChanged; + // Need to be updated when viewport changes + return changeFlags.somethingChanged; } /* eslint-disable max-statements,complexity */ @@ -238,6 +236,15 @@ export default class HeatmapLayer extends Aggrega this._updateHeatmapState(opts); } + postEffect() { + const {maskRenderCount} = this.getModuleSettings(); + const maskChanged = maskRenderCount !== this.state.maskRenderCount; + if (maskChanged) { + this.setState({maskRenderCount}); + this._updateWeightmap(); + } + } + _updateHeatmapState(opts: UpdateParameters) { const {props, oldProps} = opts; const changeFlags = this._getChangeFlags(opts); diff --git a/modules/core/src/passes/layers-pass.ts b/modules/core/src/passes/layers-pass.ts index 1bde034b6c1..0623be3c8ce 100644 --- a/modules/core/src/passes/layers-pass.ts +++ b/modules/core/src/passes/layers-pass.ts @@ -209,6 +209,12 @@ export default class LayersPass extends Pass { if (shouldDrawLayer && layer.props.pickable) { renderStatus.pickableCount++; } + + // Hack + if (layer.postEffect) { + layer.postEffect(); + } + if (layer.isComposite) { renderStatus.compositeCount++; } else if (shouldDrawLayer) { From f45bd014b5609e6963f27730614529cb3758ed64 Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Wed, 9 Nov 2022 17:28:00 +0100 Subject: [PATCH 08/17] Tidy --- .../aggregation-layers/src/heatmap-layer/heatmap-layer.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts index d857e5f0731..c6ca5aa1c3c 100644 --- a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts @@ -249,13 +249,6 @@ export default class HeatmapLayer extends Aggrega const {props, oldProps} = opts; const changeFlags = this._getChangeFlags(opts); - const {maskRenderCount} = this.getModuleSettings(); - if (maskRenderCount !== this.state.maskRenderCount) { - // Treat new mask as if data had changed - changeFlags.dataChanged = 'mask'; - this.setState({maskRenderCount}); - } - if (changeFlags.dataChanged || changeFlags.viewportChanged) { // if data is changed, do not debounce and immediately update the weight map changeFlags.boundsChanged = this._updateBounds(changeFlags.dataChanged); From d55c7b5e6ccbc176252fea07370e478ddd5cf615 Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Thu, 10 Nov 2022 11:06:17 +0100 Subject: [PATCH 09/17] Debounce heatmap mask updates --- modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts index c6ca5aa1c3c..10279651e1c 100644 --- a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts @@ -241,7 +241,7 @@ export default class HeatmapLayer extends Aggrega const maskChanged = maskRenderCount !== this.state.maskRenderCount; if (maskChanged) { this.setState({maskRenderCount}); - this._updateWeightmap(); + this._debouncedUpdateWeightmap(); } } From 672829dd4d9dc8ca869af76d6552d94065b0c25c Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Thu, 10 Nov 2022 12:59:03 +0100 Subject: [PATCH 10/17] maskByInstance:false support --- .../src/heatmap-layer/heatmap-layer.ts | 7 +++++++ .../src/heatmap-layer/triangle-layer-vertex.glsl.ts | 1 + .../src/heatmap-layer/triangle-layer.ts | 6 +++++- .../src/heatmap-layer/weights-vs.glsl.ts | 2 +- modules/extensions/src/mask/mask.ts | 13 ++++++++++++- 5 files changed, 26 insertions(+), 3 deletions(-) diff --git a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts index 10279651e1c..c3f16d0d218 100644 --- a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts @@ -628,6 +628,13 @@ export default class HeatmapLayer extends Aggrega extension.draw.call(this, opts, extension); } + // Only instance-based masking affects the weights transform + // @ts-ignore + if (uniforms.mask_enabled) { + // @ts-ignore + uniforms.mask_enabled = uniforms.mask_maskByInstance; + } + // Attribute manager sets data array count as instaceCount on model // we need to set that as elementCount on 'weightsTransform' weightsTransform.update({ diff --git a/modules/aggregation-layers/src/heatmap-layer/triangle-layer-vertex.glsl.ts b/modules/aggregation-layers/src/heatmap-layer/triangle-layer-vertex.glsl.ts index fd73723878a..902b256d1f8 100644 --- a/modules/aggregation-layers/src/heatmap-layer/triangle-layer-vertex.glsl.ts +++ b/modules/aggregation-layers/src/heatmap-layer/triangle-layer-vertex.glsl.ts @@ -38,6 +38,7 @@ varying float vIntensityMax; void main(void) { gl_Position = project_position_to_clipspace(positions, vec3(0.0), vec3(0.0)); + geometry.position = project_position(vec4(positions, 1.0)); vTexCoords = texCoords; vec4 maxTexture = texture2D(maxTexture, vec2(0.5)); float maxValue = aggregationMode < 0.5 ? maxTexture.r : maxTexture.g; diff --git a/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts b/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts index aad302778a5..fa44ae674ce 100644 --- a/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts @@ -83,10 +83,14 @@ export default class TriangleLayer extends Layer<_TriangleLayerProps> { const {texture, maxTexture, colorTexture, intensity, threshold, aggregationMode, colorDomain} = this.props; + if (uniforms.mask_enabled) { + // Instance based masking happens in weightsTransform + uniforms.mask_enabled = !uniforms.mask_maskByInstance; + } + model .setUniforms({ ...uniforms, - mask_enabled: false, // <-- masking happens in weightsTransform colorTexture, texture, // <---- PROBLEM (put second to avoid warning :/) maxTexture, diff --git a/modules/aggregation-layers/src/heatmap-layer/weights-vs.glsl.ts b/modules/aggregation-layers/src/heatmap-layer/weights-vs.glsl.ts index d18d176f69b..343668fe401 100644 --- a/modules/aggregation-layers/src/heatmap-layer/weights-vs.glsl.ts +++ b/modules/aggregation-layers/src/heatmap-layer/weights-vs.glsl.ts @@ -15,7 +15,7 @@ void main() gl_PointSize = radiusTexels * 2.; vec3 commonPosition = project_position(positions, positions64Low); - geometry.position = vec4(commonPosition, 1.0); + geometry.worldPosition = positions; // map xy from commonBounds to [-1, 1] gl_Position.xy = (commonPosition.xy - commonBounds.xy) / (commonBounds.zw - commonBounds.xy) ; diff --git a/modules/extensions/src/mask/mask.ts b/modules/extensions/src/mask/mask.ts index b9dac97079e..d8b4d505f21 100644 --- a/modules/extensions/src/mask/mask.ts +++ b/modules/extensions/src/mask/mask.ts @@ -1,7 +1,7 @@ import {COORDINATE_SYSTEM, LayerExtension, log} from '@deck.gl/core'; import mask from './shader-module'; -import type {Layer} from '@deck.gl/core'; +import type {CompositeLayer, Layer} from '@deck.gl/core'; const defaultProps = { maskId: '' @@ -25,6 +25,17 @@ export default class MaskExtension extends LayerExtension { static defaultProps = defaultProps; static extensionName = 'MaskExtension'; + // @ts-ignore + getSubLayerProps(this: CompositeLayer, extension: this): any { + // @ts-ignore + const newProps = super.getSubLayerProps(extension); + if ('maskByInstance' in this.props) { + // @ts-ignore + newProps.maskByInstance = this.props.maskByInstance; + } + return newProps; + } + getShaders(this: Layer): any { // Infer by geometry if 'maskByInstance' prop isn't explictly set let maskByInstance = 'instancePositions' in this.getAttributeManager()!.attributes; From 8b6de9bc36d43a4125038c717dd970b095a66f68 Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Thu, 10 Nov 2022 13:07:25 +0100 Subject: [PATCH 11/17] TS fixes --- modules/extensions/src/mask/mask.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/modules/extensions/src/mask/mask.ts b/modules/extensions/src/mask/mask.ts index d8b4d505f21..2c68f53fe70 100644 --- a/modules/extensions/src/mask/mask.ts +++ b/modules/extensions/src/mask/mask.ts @@ -25,12 +25,9 @@ export default class MaskExtension extends LayerExtension { static defaultProps = defaultProps; static extensionName = 'MaskExtension'; - // @ts-ignore - getSubLayerProps(this: CompositeLayer, extension: this): any { - // @ts-ignore - const newProps = super.getSubLayerProps(extension); + getSubLayerProps(this: CompositeLayer, extension: this): any { + const newProps = super.getSubLayerProps.call(this, extension); if ('maskByInstance' in this.props) { - // @ts-ignore newProps.maskByInstance = this.props.maskByInstance; } return newProps; From dd0faf5f2baff1a4806a142516a170f046cc0dcc Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Thu, 10 Nov 2022 13:10:30 +0100 Subject: [PATCH 12/17] Remove outdated notes --- modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts | 2 +- .../aggregation-layers/src/heatmap-layer/triangle-layer.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts index c3f16d0d218..3887ad7615f 100644 --- a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts @@ -311,7 +311,7 @@ export default class HeatmapLayer extends Aggrega maxTexture: maxWeightsTexture, colorTexture, aggregationMode: AGGREGATION_MODE[aggregation] || 0, - texture: weightsTexture, /// <-- PROBLEM + texture: weightsTexture, intensity, threshold, colorDomain diff --git a/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts b/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts index fa44ae674ce..b601f3740e7 100644 --- a/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts @@ -91,9 +91,9 @@ export default class TriangleLayer extends Layer<_TriangleLayerProps> { model .setUniforms({ ...uniforms, - colorTexture, - texture, // <---- PROBLEM (put second to avoid warning :/) + texture, maxTexture, + colorTexture, intensity, threshold, aggregationMode, From 63a1cac6842302356a643de6343dff359266936c Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Thu, 10 Nov 2022 13:14:01 +0100 Subject: [PATCH 13/17] Remove debug views --- .../src/heatmap-layer/heatmap-layer.ts | 32 ----------- modules/core/src/effects/mask/mask-effect.ts | 54 +++++++++---------- test/apps/mask/index.html | 5 -- 3 files changed, 27 insertions(+), 64 deletions(-) diff --git a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts index 3887ad7615f..27d69a225fc 100644 --- a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts @@ -19,7 +19,6 @@ // THE SOFTWARE. /* global setTimeout clearTimeout */ -import {readPixelsToArray} from '@luma.gl/core'; import GL from '@luma.gl/constants'; import { getBounds, @@ -651,7 +650,6 @@ export default class HeatmapLayer extends Aggrega }); }); this._updateMaxWeightValue(); - this._debug(); // reset filtering parameters (TODO: remove once luma issue#1193 is fixed) weightsTexture.setParameters({ @@ -660,36 +658,6 @@ export default class HeatmapLayer extends Aggrega }); } - _debug() { - // Debug show FBO contents on screen - const {weightsTexture} = this.state; - const color = readPixelsToArray(weightsTexture); - let canvas = document.getElementById('weights-canvas') as HTMLCanvasElement; - if (!canvas) { - canvas = document.createElement('canvas'); - canvas.id = 'weights-canvas'; - canvas.width = weightsTexture.width; - canvas.height = weightsTexture.height; - canvas.style.zIndex = '100'; - canvas.style.position = 'absolute'; - canvas.style.right = '0'; - canvas.style.top = '256px'; - canvas.style.border = 'blue 1px solid'; - canvas.style.width = '256px'; - canvas.style.transform = 'scaleY(-1)'; - document.body.appendChild(canvas); - } - const ctx = canvas.getContext('2d')!; - const imageData = ctx.createImageData(weightsTexture.width, weightsTexture.height); - for (let i = 0; i < color.length; i += 4) { - imageData.data[i + 0] = color[i + 0]; - imageData.data[i + 1] = color[i + 1]; - imageData.data[i + 2] = color[i + 2]; - imageData.data[i + 3] = 255; //color[i + 3]; - } - ctx.putImageData(imageData, 0, 0); - } - _debouncedUpdateWeightmap(fromTimer = false) { let {updateTimer} = this.state; const {debounceTimeout} = this.props; diff --git a/modules/core/src/effects/mask/mask-effect.ts b/modules/core/src/effects/mask/mask-effect.ts index 9ed39b2d6d0..8984c6da367 100644 --- a/modules/core/src/effects/mask/mask-effect.ts +++ b/modules/core/src/effects/mask/mask-effect.ts @@ -1,5 +1,5 @@ import {Texture2D} from '@luma.gl/core'; -import {readPixelsToArray} from '@luma.gl/core'; +// import {readPixelsToArray} from '@luma.gl/core'; import {equals} from '@math.gl/core'; import MaskPass from '../../passes/mask-pass'; import {OPERATION} from '../../lib/constants'; @@ -85,32 +85,32 @@ export default class MaskEffect implements Effect { }); } - // Debug show FBO contents on screen - const color = readPixelsToArray(this.maskMap); - let canvas = document.getElementById('fbo-canvas') as HTMLCanvasElement; - if (!canvas) { - canvas = document.createElement('canvas'); - canvas.id = 'fbo-canvas'; - canvas.width = this.maskMap.width; - canvas.height = this.maskMap.height; - canvas.style.zIndex = '100'; - canvas.style.position = 'absolute'; - canvas.style.right = '0'; - canvas.style.top = '0'; - canvas.style.border = 'blue 1px solid'; - canvas.style.width = '256px'; - canvas.style.transform = 'scaleY(-1)'; - document.body.appendChild(canvas); - } - const ctx = canvas.getContext('2d')!; - const imageData = ctx.createImageData(this.maskMap.width, this.maskMap.height); - for (let i = 0; i < color.length; i += 4) { - imageData.data[i + 0] = color[i + 0]; - imageData.data[i + 1] = color[i + 1]; - imageData.data[i + 2] = color[i + 2]; - imageData.data[i + 3] = color[i + 3] + 128; - } - ctx.putImageData(imageData, 0, 0); + // // Debug show FBO contents on screen + // const color = readPixelsToArray(this.maskMap); + // let canvas = document.getElementById('fbo-canvas') as HTMLCanvasElement; + // if (!canvas) { + // canvas = document.createElement('canvas'); + // canvas.id = 'fbo-canvas'; + // canvas.width = this.maskMap.width; + // canvas.height = this.maskMap.height; + // canvas.style.zIndex = '100'; + // canvas.style.position = 'absolute'; + // canvas.style.right = '0'; + // canvas.style.top = '0'; + // canvas.style.border = 'blue 1px solid'; + // canvas.style.width = '256px'; + // canvas.style.transform = 'scaleY(-1)'; + // document.body.appendChild(canvas); + // } + // const ctx = canvas.getContext('2d')!; + // const imageData = ctx.createImageData(this.maskMap.width, this.maskMap.height); + // for (let i = 0; i < color.length; i += 4) { + // imageData.data[i + 0] = color[i + 0]; + // imageData.data[i + 1] = color[i + 1]; + // imageData.data[i + 2] = color[i + 2]; + // imageData.data[i + 3] = color[i + 3] + 128; + // } + // ctx.putImageData(imageData, 0, 0); } private _renderChannel( diff --git a/test/apps/mask/index.html b/test/apps/mask/index.html index f259e56759f..e690c38e126 100644 --- a/test/apps/mask/index.html +++ b/test/apps/mask/index.html @@ -12,11 +12,6 @@ height: 100vh; overflow: hidden; } - #app { - width: 80%; - height: 100%; - position: relative; - } From 99cc55931a44effea384b596790a9ec78d04da9d Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Thu, 10 Nov 2022 13:29:04 +0100 Subject: [PATCH 14/17] Support toggling between maskByInstance modes --- modules/aggregation-layers/src/aggregation-layer.ts | 2 +- .../aggregation-layers/src/heatmap-layer/heatmap-layer.ts | 5 +---- .../aggregation-layers/src/heatmap-layer/triangle-layer.ts | 3 +-- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/modules/aggregation-layers/src/aggregation-layer.ts b/modules/aggregation-layers/src/aggregation-layer.ts index b289dcfb838..ce434b78927 100644 --- a/modules/aggregation-layers/src/aggregation-layer.ts +++ b/modules/aggregation-layers/src/aggregation-layer.ts @@ -53,7 +53,7 @@ export default abstract class AggregationLayer< updateState(opts: UpdateParameters) { super.updateState(opts); const {changeFlags} = opts; - if (changeFlags.extensionsChanged) { + if (changeFlags.extensionsChanged || changeFlags.propsChanged) { const shaders = this.getShaders({}); if (shaders && shaders.defines) { shaders.defines.NON_INSTANCED_MODEL = 1; diff --git a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts index 27d69a225fc..3b7a016cc4a 100644 --- a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts @@ -278,7 +278,6 @@ export default class HeatmapLayer extends Aggrega if (!this.state.supported) { return []; } - const { weightsTexture, triPositionBuffer, @@ -607,7 +606,7 @@ export default class HeatmapLayer extends Aggrega this.state.colorDomain = colorDomain || DEFAULT_COLOR_DOMAIN; } - const uniforms = { + const uniforms: any = { radiusPixels, commonBounds, textureWidth: textureSize, @@ -628,9 +627,7 @@ export default class HeatmapLayer extends Aggrega } // Only instance-based masking affects the weights transform - // @ts-ignore if (uniforms.mask_enabled) { - // @ts-ignore uniforms.mask_enabled = uniforms.mask_maskByInstance; } diff --git a/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts b/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts index b601f3740e7..0acebccd429 100644 --- a/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/triangle-layer.ts @@ -40,7 +40,6 @@ export default class TriangleLayer extends Layer<_TriangleLayerProps> { getShaders() { return super.getShaders({vs, fs, modules: [project32]}); - // return {vs, fs, modules: [project32]}; } initializeState({gl}: LayerContext): void { @@ -57,7 +56,7 @@ export default class TriangleLayer extends Layer<_TriangleLayerProps> { updateState(opts: UpdateParameters) { super.updateState(opts); const {changeFlags} = opts; - if (changeFlags.extensionsChanged) { + if (changeFlags.extensionsChanged || changeFlags.propsChanged) { this.setState({ model: this._getModel(opts.context.gl) }); From df1cbb31019ee423e9e909357fb9ca709983137f Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Thu, 10 Nov 2022 13:45:35 +0100 Subject: [PATCH 15/17] Note on masking in HeatmapLayer --- modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts | 3 +++ .../aggregation-layers/src/heatmap-layer/weights-vs.glsl.ts | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts index 3b7a016cc4a..768ccbe4da6 100644 --- a/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/heatmap-layer.ts @@ -627,6 +627,9 @@ export default class HeatmapLayer extends Aggrega } // Only instance-based masking affects the weights transform + // TODO: do we want to do this? On one hand it makes sense, + // but can result in starnge colors as the maxWeightValue is + // calculated on the unmasked dataset if (uniforms.mask_enabled) { uniforms.mask_enabled = uniforms.mask_maskByInstance; } diff --git a/modules/aggregation-layers/src/heatmap-layer/weights-vs.glsl.ts b/modules/aggregation-layers/src/heatmap-layer/weights-vs.glsl.ts index 343668fe401..98251fa9c36 100644 --- a/modules/aggregation-layers/src/heatmap-layer/weights-vs.glsl.ts +++ b/modules/aggregation-layers/src/heatmap-layer/weights-vs.glsl.ts @@ -14,11 +14,11 @@ void main() float radiusTexels = project_pixel_size(radiusPixels) * textureWidth / (commonBounds.z - commonBounds.x); gl_PointSize = radiusTexels * 2.; - vec3 commonPosition = project_position(positions, positions64Low); + geometry.position = project_position(vec4(positions, 1.0), positions64Low); geometry.worldPosition = positions; // map xy from commonBounds to [-1, 1] - gl_Position.xy = (commonPosition.xy - commonBounds.xy) / (commonBounds.zw - commonBounds.xy) ; + gl_Position.xy = (geometry.position.xy - commonBounds.xy) / (commonBounds.zw - commonBounds.xy) ; gl_Position.xy = (gl_Position.xy * 2.) - (1.); } `; From 18ad8741228ef91bd3120e2c2a546f263db65b6c Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Thu, 10 Nov 2022 14:10:56 +0100 Subject: [PATCH 16/17] Update test app --- modules/extensions/src/mask/shader-module.ts | 5 +-- test/apps/mask/app.js | 32 +++++++++----------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/modules/extensions/src/mask/shader-module.ts b/modules/extensions/src/mask/shader-module.ts index 88c157153de..4ebb24360ea 100644 --- a/modules/extensions/src/mask/shader-module.ts +++ b/modules/extensions/src/mask/shader-module.ts @@ -49,17 +49,14 @@ varying vec2 mask_texCoords; 'fs:#decl': ` varying vec2 mask_texCoords; `, - 'fs:#main-end': ` + 'fs:#main-start': ` if (mask_enabled) { bool mask = mask_isInBounds(mask_texCoords); // Debug: show extent of render target // gl_FragColor = vec4(mask_texCoords, 0.0, 1.0); - // gl_FragColor = vec4(1.0); if (!mask) discard; - // Debug (mask out in blue, not discard) - // if (!mask) gl_FragColor = vec4(0.0, 0.0, 1.0, 0.1); } ` }; diff --git a/test/apps/mask/app.js b/test/apps/mask/app.js index 9b0e9289ef6..05fcd757750 100644 --- a/test/apps/mask/app.js +++ b/test/apps/mask/app.js @@ -115,7 +115,7 @@ function getLayerData(data) { export default function App({data, strokeWidth = 1, mapStyle = MAP_STYLE}) { const {arcs, targets, sources} = useMemo(() => getLayerData(data), [data]); const [maskEnabled, setMaskEnabled] = useState(true); - const [showLayers, setShowLayers] = useState(true); + const [showLayers, setShowLayers] = useState(false); const [selectedCounty, selectCounty] = useState(null); const [selectedCounty2, selectCounty2] = useState(null); @@ -181,35 +181,33 @@ export default function App({data, strokeWidth = 1, mapStyle = MAP_STYLE}) { highlightColor: [255, 255, 255, 150] }), // Rings around target (clipped by mask) - new ScatterplotLayer({ - id: 'sources', - data: sources, - radiusScale: 3000, - radiusMinPixels: 10, - getFillColor: d => (d.gain > 0 ? TARGET_COLOR : SOURCE_COLOR), - extensions: [new MaskExtension()], - maskId: maskEnabled && 'mask2' - }), + false && + new ScatterplotLayer({ + id: 'sources', + data: sources, + radiusScale: 3000, + radiusMinPixels: 10, + getFillColor: d => (d.gain > 0 ? TARGET_COLOR : SOURCE_COLOR), + extensions: [new MaskExtension()], + maskId: maskEnabled && 'mask2' + }), true && new HeatmapLayer({ id: 'sources-heatmap', + weightsTextureSize: 512, data: sources, radiusMinPixels: 10, getPosition: d => d.position, getWeight: d => Math.abs(d.gain), extensions: maskEnabled ? [new MaskExtension()] : [], maskId: maskEnabled && 'mask2', - maskByInstance: false + maskByInstance: showLayers }) ]; return ( <> - +
@@ -223,7 +221,7 @@ export default function App({data, strokeWidth = 1, mapStyle = MAP_STYLE}) {
From 2802bdf08ab23bd39e7540054745b3d3f5ac4eaa Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Mon, 9 Jan 2023 16:24:02 +0100 Subject: [PATCH 17/17] Remove unneeded sublayer prop copy --- modules/extensions/src/mask/mask.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/modules/extensions/src/mask/mask.ts b/modules/extensions/src/mask/mask.ts index d3ff585c7f1..efe86376833 100644 --- a/modules/extensions/src/mask/mask.ts +++ b/modules/extensions/src/mask/mask.ts @@ -2,7 +2,7 @@ import {COORDINATE_SYSTEM, LayerExtension, log} from '@deck.gl/core'; import mask from './shader-module'; import MaskEffect from './mask-effect'; -import type {CompositeLayer, Layer} from '@deck.gl/core'; +import type {Layer} from '@deck.gl/core'; const defaultProps = { maskId: '', @@ -36,14 +36,6 @@ export default class MaskExtension extends LayerExtension { this.context.deck?._addDefaultEffect(new MaskEffect()); } - getSubLayerProps(this: CompositeLayer, extension: this): any { - const newProps = super.getSubLayerProps.call(this, extension); - if ('maskByInstance' in this.props) { - newProps.maskByInstance = this.props.maskByInstance; - } - return newProps; - } - getShaders(this: Layer): any { // Infer by geometry if 'maskByInstance' prop isn't explictly set let maskByInstance = 'instancePositions' in this.getAttributeManager()!.attributes;