@deck.gl/extensions 9.0.0-beta.10 → 9.0.0-beta.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/collision-filter/collision-filter-effect.d.ts +4 -2
  2. package/dist/collision-filter/collision-filter-effect.d.ts.map +1 -1
  3. package/dist/collision-filter/collision-filter-effect.js +10 -9
  4. package/dist/collision-filter/collision-filter-pass.d.ts +3 -2
  5. package/dist/collision-filter/collision-filter-pass.d.ts.map +1 -1
  6. package/dist/collision-filter/collision-filter-pass.js +5 -7
  7. package/dist/data-filter/data-filter-extension.d.ts +5 -5
  8. package/dist/data-filter/data-filter-extension.d.ts.map +1 -1
  9. package/dist/data-filter/data-filter-extension.js +45 -38
  10. package/dist/data-filter/shader-module.d.ts +30 -0
  11. package/dist/data-filter/shader-module.d.ts.map +1 -1
  12. package/dist/data-filter/shader-module.js +40 -20
  13. package/dist/dist.dev.js +571 -535
  14. package/dist/index.cjs +517 -478
  15. package/dist/index.cjs.map +4 -4
  16. package/dist/mask/mask-effect.d.ts +5 -4
  17. package/dist/mask/mask-effect.d.ts.map +1 -1
  18. package/dist/mask/mask-effect.js +9 -11
  19. package/dist/mask/mask-pass.d.ts +45 -3
  20. package/dist/mask/mask-pass.d.ts.map +1 -1
  21. package/dist/mask/mask-pass.js +17 -9
  22. package/dist/path-style/path-style-extension.d.ts.map +1 -1
  23. package/dist/path-style/path-style-extension.js +1 -0
  24. package/dist/terrain/terrain-cover.d.ts.map +1 -1
  25. package/dist/terrain/terrain-cover.js +2 -1
  26. package/dist/terrain/terrain-effect.d.ts +4 -5
  27. package/dist/terrain/terrain-effect.d.ts.map +1 -1
  28. package/dist/terrain/terrain-effect.js +6 -16
  29. package/dist/terrain/terrain-pass.d.ts +42 -0
  30. package/dist/terrain/terrain-pass.d.ts.map +1 -1
  31. package/dist/terrain/terrain-pass.js +24 -16
  32. package/dist/terrain/terrain-picking-pass.d.ts.map +1 -1
  33. package/dist/terrain/terrain-picking-pass.js +9 -8
  34. package/dist/terrain/utils.d.ts +1 -0
  35. package/dist/terrain/utils.d.ts.map +1 -1
  36. package/dist/terrain/utils.js +10 -6
  37. package/dist.min.js +63 -40
  38. package/package.json +6 -6
  39. package/src/collision-filter/collision-filter-effect.ts +23 -23
  40. package/src/collision-filter/collision-filter-pass.ts +7 -11
  41. package/src/data-filter/data-filter-extension.ts +57 -49
  42. package/src/data-filter/shader-module.ts +109 -43
  43. package/src/mask/mask-effect.ts +30 -19
  44. package/src/mask/mask-pass.ts +22 -16
  45. package/src/path-style/path-style-extension.ts +1 -0
  46. package/src/terrain/terrain-cover.ts +2 -1
  47. package/src/terrain/terrain-effect.ts +8 -19
  48. package/src/terrain/terrain-pass.ts +37 -34
  49. package/src/terrain/terrain-picking-pass.ts +19 -23
  50. package/src/terrain/utils.ts +12 -6
@@ -22,7 +22,7 @@ import type {Framebuffer} from '@luma.gl/core';
22
22
  import type {Model} from '@luma.gl/engine';
23
23
  import type {Layer, LayerContext, Accessor, UpdateParameters} from '@deck.gl/core';
24
24
  import {_deepEqual as deepEqual, LayerExtension, log} from '@deck.gl/core';
25
- import {shaderModule, shaderModule64} from './shader-module';
25
+ import {Defines, shaderModule, shaderModule64} from './shader-module';
26
26
  import * as aggregator from './aggregator';
27
27
 
28
28
  const defaultProps = {
@@ -96,15 +96,15 @@ export type DataFilterExtensionProps<DataT = any> = {
96
96
 
97
97
  type DataFilterExtensionOptions = {
98
98
  /**
99
- * The size of the category filter (number of columns to filter by). The category filter can show/hide data based on 1-4 properties of each object.
100
- * @default 1
99
+ * The size of the category filter (number of columns to filter by). The category filter can show/hide data based on 1-4 properties of each object. Set to `0` to disable category filtering.
100
+ * @default 0
101
101
  */
102
- categorySize?: 1 | 2 | 3 | 4;
102
+ categorySize?: 0 | 1 | 2 | 3 | 4;
103
103
  /**
104
- * The size of the filter (number of columns to filter by). The data filter can show/hide data based on 1-4 numeric properties of each object.
104
+ * The size of the filter (number of columns to filter by). The data filter can show/hide data based on 1-4 numeric properties of each object. Set to `0` to disable numeric filtering.
105
105
  * @default 1
106
106
  */
107
- filterSize?: 1 | 2 | 3 | 4;
107
+ filterSize?: 0 | 1 | 2 | 3 | 4;
108
108
  /**
109
109
  * Use 64-bit precision instead of 32-bit.
110
110
  * @default false
@@ -118,17 +118,17 @@ type DataFilterExtensionOptions = {
118
118
  };
119
119
 
120
120
  const defaultOptions: Required<DataFilterExtensionOptions> = {
121
- categorySize: 1,
121
+ categorySize: 0,
122
122
  filterSize: 1,
123
123
  fp64: false,
124
124
  countItems: false
125
125
  };
126
126
 
127
127
  const DATA_TYPE_FROM_SIZE = {
128
- 1: 'float',
129
- 2: 'vec2',
130
- 3: 'vec3',
131
- 4: 'vec4'
128
+ 1: 'float' as const,
129
+ 2: 'vec2' as const,
130
+ 3: 'vec3' as const,
131
+ 4: 'vec4' as const
132
132
  };
133
133
 
134
134
  /** Adds GPU-based data filtering functionalities to layers. It allows the layer to show/hide objects based on user-defined properties. */
@@ -144,16 +144,17 @@ export default class DataFilterExtension extends LayerExtension<
144
144
 
145
145
  getShaders(this: Layer<DataFilterExtensionProps>, extension: this): any {
146
146
  const {categorySize, filterSize, fp64} = extension.opts;
147
+ const defines: Defines = {};
148
+ if (categorySize) {
149
+ defines.DATACATEGORY_TYPE = DATA_TYPE_FROM_SIZE[categorySize];
150
+ defines.DATACATEGORY_CHANNELS = categorySize;
151
+ }
152
+ if (filterSize) {
153
+ defines.DATAFILTER_TYPE = DATA_TYPE_FROM_SIZE[filterSize];
154
+ defines.DATAFILTER_DOUBLE = Boolean(fp64);
155
+ }
147
156
 
148
- return {
149
- modules: [fp64 ? shaderModule64 : shaderModule],
150
- defines: {
151
- DATACATEGORY_TYPE: DATA_TYPE_FROM_SIZE[categorySize],
152
- DATACATEGORY_CHANNELS: categorySize,
153
- DATAFILTER_TYPE: DATA_TYPE_FROM_SIZE[filterSize],
154
- DATAFILTER_DOUBLE: Boolean(fp64)
155
- }
156
- };
157
+ return {modules: [fp64 ? shaderModule64 : shaderModule], defines};
157
158
  }
158
159
 
159
160
  initializeState(this: Layer<DataFilterExtensionProps>, context: LayerContext, extension: this) {
@@ -161,37 +162,44 @@ export default class DataFilterExtension extends LayerExtension<
161
162
  const {categorySize, filterSize, fp64} = extension.opts;
162
163
 
163
164
  if (attributeManager) {
164
- attributeManager.add({
165
- filterValues: {
166
- size: filterSize,
167
- type: fp64 ? 'float64' : 'float32',
168
- accessor: 'getFilterValue',
169
- shaderAttributes: {
170
- filterValues: {
171
- divisor: 0
172
- },
173
- instanceFilterValues: {
174
- divisor: 1
165
+ if (filterSize) {
166
+ attributeManager.add({
167
+ filterValues: {
168
+ size: filterSize,
169
+ type: fp64 ? 'float64' : 'float32',
170
+ accessor: 'getFilterValue',
171
+ shaderAttributes: {
172
+ filterValues: {
173
+ divisor: 0
174
+ },
175
+ instanceFilterValues: {
176
+ divisor: 1
177
+ }
175
178
  }
176
179
  }
177
- },
178
- filterCategoryValues: {
179
- size: categorySize,
180
- accessor: 'getFilterCategory',
181
- transform:
182
- categorySize === 1
183
- ? d => extension._getCategoryKey.call(this, d, 0)
184
- : d => d.map((x, i) => extension._getCategoryKey.call(this, x, i)),
185
- shaderAttributes: {
186
- filterCategoryValues: {
187
- divisor: 0
188
- },
189
- instanceFilterCategoryValues: {
190
- divisor: 1
180
+ });
181
+ }
182
+
183
+ if (categorySize) {
184
+ attributeManager.add({
185
+ filterCategoryValues: {
186
+ size: categorySize,
187
+ accessor: 'getFilterCategory',
188
+ transform:
189
+ categorySize === 1
190
+ ? d => extension._getCategoryKey.call(this, d, 0)
191
+ : d => d.map((x, i) => extension._getCategoryKey.call(this, x, i)),
192
+ shaderAttributes: {
193
+ filterCategoryValues: {
194
+ divisor: 0
195
+ },
196
+ instanceFilterCategoryValues: {
197
+ divisor: 1
198
+ }
191
199
  }
192
200
  }
193
- }
194
- });
201
+ });
202
+ }
195
203
  }
196
204
 
197
205
  const {device} = this.context;
@@ -240,7 +248,7 @@ export default class DataFilterExtension extends LayerExtension<
240
248
  if (this.state.filterModel) {
241
249
  const filterNeedsUpdate =
242
250
  // attributeManager must be defined for filterModel to be set
243
- attributeManager!.attributes.filterValues.needsUpdate() ||
251
+ attributeManager!.attributes.filterValues?.needsUpdate() ||
244
252
  attributeManager!.attributes.filterCategoryValues?.needsUpdate() ||
245
253
  props.filterEnabled !== oldProps.filterEnabled ||
246
254
  props.filterRange !== oldProps.filterRange ||
@@ -294,7 +302,7 @@ export default class DataFilterExtension extends LayerExtension<
294
302
  filterModel.updateModuleSettings(params.moduleParameters);
295
303
  // @ts-expect-error filterValue and filterIndices should always have buffer value
296
304
  filterModel.setAttributes({
297
- ...filterValues.getValue(),
305
+ ...filterValues?.getValue(),
298
306
  ...filterCategoryValues?.getValue(),
299
307
  ...filterIndices?.getValue()
300
308
  });
@@ -5,34 +5,80 @@ import {glsl} from '../utils/syntax-tags';
5
5
  /*
6
6
  * data filter shader module
7
7
  */
8
+ export type Defines = {
9
+ // Defines passed externally
10
+ /**
11
+ * Primitive type of parameter used for category filtering. If undefined, category filtering disabled.
12
+ */
13
+ DATACATEGORY_TYPE?: 'float' | 'vec2' | 'vec3' | 'vec4';
14
+ /**
15
+ * Number of category filtering channels. Must match dimension of `DATACATEGORY_TYPE`
16
+ */
17
+ DATACATEGORY_CHANNELS?: 1 | 2 | 3 | 4;
18
+
19
+ /**
20
+ * Primitive type of parameter used for numeric filtering. If undefined, numeric filtering disabled.
21
+ */
22
+ DATAFILTER_TYPE?: 'float' | 'vec2' | 'vec3' | 'vec4';
23
+
24
+ /**
25
+ * Enable 64-bit precision in numeric filter.
26
+ */
27
+ DATAFILTER_DOUBLE?: boolean;
28
+
29
+ // Defines derived in shader
30
+ /**
31
+ * Numeric filter attribute
32
+ */
33
+ DATAFILTER_ATTRIB?: 'filterValues' | 'instanceFilterValues';
34
+ /**
35
+ * Numeric filter attribute (low bits). Only used when `DATAFILTER_DOUBLE = true`
36
+ */
37
+ DATAFILTER_ATTRIB_64LOW?: 'filterValues64Low' | 'instanceFilterValues64Low';
38
+ /**
39
+ * Category filter attribute
40
+ */
41
+ DATACATEGORY_ATTRIB?: 'filterCategoryValues' | 'instanceFilterCategoryValues';
42
+ };
43
+
8
44
  const vs = glsl`
9
- uniform DATAFILTER_TYPE filter_min;
10
- uniform DATAFILTER_TYPE filter_softMin;
11
- uniform DATAFILTER_TYPE filter_softMax;
12
- uniform DATAFILTER_TYPE filter_max;
13
45
  uniform bool filter_useSoftMargin;
14
46
  uniform bool filter_enabled;
15
47
  uniform bool filter_transformSize;
16
48
  uniform ivec4 filter_categoryBitMask;
17
49
 
18
- #ifdef NON_INSTANCED_MODEL
19
- #define DATAFILTER_ATTRIB filterValues
20
- #define DATAFILTER_ATTRIB_64LOW filterValues64Low
21
- #define DATACATEGORY_ATTRIB filterCategoryValues
22
- #else
23
- #define DATAFILTER_ATTRIB instanceFilterValues
24
- #define DATAFILTER_ATTRIB_64LOW instanceFilterValues64Low
25
- #define DATACATEGORY_ATTRIB instanceFilterCategoryValues
50
+ #ifdef DATAFILTER_TYPE
51
+ uniform DATAFILTER_TYPE filter_min;
52
+ uniform DATAFILTER_TYPE filter_softMin;
53
+ uniform DATAFILTER_TYPE filter_softMax;
54
+ uniform DATAFILTER_TYPE filter_max;
55
+
56
+ #ifdef NON_INSTANCED_MODEL
57
+ #define DATAFILTER_ATTRIB filterValues
58
+ #define DATAFILTER_ATTRIB_64LOW filterValues64Low
59
+ #else
60
+ #define DATAFILTER_ATTRIB instanceFilterValues
61
+ #define DATAFILTER_ATTRIB_64LOW instanceFilterValues64Low
62
+ #endif
63
+
64
+ in DATAFILTER_TYPE DATAFILTER_ATTRIB;
65
+ #ifdef DATAFILTER_DOUBLE
66
+ in DATAFILTER_TYPE DATAFILTER_ATTRIB_64LOW;
67
+
68
+ uniform DATAFILTER_TYPE filter_min64High;
69
+ uniform DATAFILTER_TYPE filter_max64High;
70
+ #endif
26
71
  #endif
27
72
 
28
- in DATAFILTER_TYPE DATAFILTER_ATTRIB;
29
- #ifdef DATAFILTER_DOUBLE
30
- in DATAFILTER_TYPE DATAFILTER_ATTRIB_64LOW;
31
73
 
32
- uniform DATAFILTER_TYPE filter_min64High;
33
- uniform DATAFILTER_TYPE filter_max64High;
74
+ #ifdef DATACATEGORY_TYPE
75
+ #ifdef NON_INSTANCED_MODEL
76
+ #define DATACATEGORY_ATTRIB filterCategoryValues
77
+ #else
78
+ #define DATACATEGORY_ATTRIB instanceFilterCategoryValues
79
+ #endif
80
+ in DATACATEGORY_TYPE DATACATEGORY_ATTRIB;
34
81
  #endif
35
- in DATACATEGORY_TYPE DATACATEGORY_ATTRIB;
36
82
 
37
83
  out float dataFilter_value;
38
84
 
@@ -48,30 +94,44 @@ float dataFilter_reduceValue(vec3 value) {
48
94
  float dataFilter_reduceValue(vec4 value) {
49
95
  return min(min(value.x, value.y), min(value.z, value.w));
50
96
  }
51
- void dataFilter_setValue(DATAFILTER_TYPE valueFromMin, DATAFILTER_TYPE valueFromMax, DATACATEGORY_TYPE category) {
52
- if (filter_enabled) {
97
+
98
+ #ifdef DATAFILTER_TYPE
99
+ void dataFilter_setValue(DATAFILTER_TYPE valueFromMin, DATAFILTER_TYPE valueFromMax) {
53
100
  if (filter_useSoftMargin) {
54
- dataFilter_value = dataFilter_reduceValue(
55
- smoothstep(filter_min, filter_softMin, valueFromMin) *
56
- (1.0 - smoothstep(filter_softMax, filter_max, valueFromMax))
101
+ // smoothstep results are undefined if edge0 ≥ edge1
102
+ // Fallback to ignore filterSoftRange if it is truncated by filterRange
103
+ DATAFILTER_TYPE leftInRange = mix(
104
+ smoothstep(filter_min, filter_softMin, valueFromMin),
105
+ step(filter_min, valueFromMin),
106
+ step(filter_softMin, filter_min)
107
+ );
108
+ DATAFILTER_TYPE rightInRange = mix(
109
+ 1.0 - smoothstep(filter_softMax, filter_max, valueFromMax),
110
+ step(valueFromMax, filter_max),
111
+ step(filter_max, filter_softMax)
57
112
  );
113
+ dataFilter_value = dataFilter_reduceValue(leftInRange * rightInRange);
58
114
  } else {
59
115
  dataFilter_value = dataFilter_reduceValue(
60
116
  step(filter_min, valueFromMin) * step(valueFromMax, filter_max)
61
117
  );
62
118
  }
119
+ }
120
+ #endif
63
121
 
122
+ #ifdef DATACATEGORY_ATTRIB
123
+ void dataFilter_setCategoryValue(DATACATEGORY_TYPE category) {
64
124
  #if DATACATEGORY_CHANNELS == 1 // One 128-bit mask
65
- int dataFilter_masks = filter_categoryBitMask[int(category / 32.0)];
125
+ int dataFilter_masks = filter_categoryBitMask[int(category / 32.0)];
66
126
  #elif DATACATEGORY_CHANNELS == 2 // Two 64-bit masks
67
- ivec2 dataFilter_masks = ivec2(
68
- filter_categoryBitMask[int(category.x / 32.0)],
69
- filter_categoryBitMask[int(category.y / 32.0) + 2]
70
- );
127
+ ivec2 dataFilter_masks = ivec2(
128
+ filter_categoryBitMask[int(category.x / 32.0)],
129
+ filter_categoryBitMask[int(category.y / 32.0) + 2]
130
+ );
71
131
  #elif DATACATEGORY_CHANNELS == 3 // Three 32-bit masks
72
- ivec3 dataFilter_masks = filter_categoryBitMask.xyz;
132
+ ivec3 dataFilter_masks = filter_categoryBitMask.xyz;
73
133
  #else // Four 32-bit masks
74
- ivec4 dataFilter_masks = filter_categoryBitMask;
134
+ ivec4 dataFilter_masks = filter_categoryBitMask;
75
135
  #endif
76
136
 
77
137
  // Shift mask and extract relevant bits
@@ -79,14 +139,12 @@ void dataFilter_setValue(DATAFILTER_TYPE valueFromMin, DATAFILTER_TYPE valueFrom
79
139
  dataFilter_bits = mod(floor(dataFilter_bits), 2.0);
80
140
 
81
141
  #if DATACATEGORY_CHANNELS == 1
82
- if(dataFilter_bits == 0.0) dataFilter_value = 0.0;
142
+ if(dataFilter_bits == 0.0) dataFilter_value = 0.0;
83
143
  #else
84
144
  if(any(equal(dataFilter_bits, DATACATEGORY_TYPE(0.0)))) dataFilter_value = 0.0;
85
145
  #endif
86
- } else {
87
- dataFilter_value = 1.0;
88
146
  }
89
- }
147
+ #endif
90
148
  `;
91
149
 
92
150
  const fs = glsl`
@@ -163,15 +221,23 @@ function getUniforms64(opts?: DataFilterModuleSettings | {}): Record<string, any
163
221
 
164
222
  const inject = {
165
223
  'vs:#main-start': glsl`
166
- #ifdef DATAFILTER_DOUBLE
167
- dataFilter_setValue(
168
- DATAFILTER_ATTRIB - filter_min64High + DATAFILTER_ATTRIB_64LOW,
169
- DATAFILTER_ATTRIB - filter_max64High + DATAFILTER_ATTRIB_64LOW,
170
- DATACATEGORY_ATTRIB
171
- );
172
- #else
173
- dataFilter_setValue(DATAFILTER_ATTRIB, DATAFILTER_ATTRIB, DATACATEGORY_ATTRIB);
174
- #endif
224
+ dataFilter_value = 1.0;
225
+ if (filter_enabled) {
226
+ #ifdef DATAFILTER_ATTRIB
227
+ #ifdef DATAFILTER_DOUBLE
228
+ dataFilter_setValue(
229
+ DATAFILTER_ATTRIB - filter_min64High + DATAFILTER_ATTRIB_64LOW,
230
+ DATAFILTER_ATTRIB - filter_max64High + DATAFILTER_ATTRIB_64LOW
231
+ );
232
+ #else
233
+ dataFilter_setValue(DATAFILTER_ATTRIB, DATAFILTER_ATTRIB);
234
+ #endif
235
+ #endif
236
+
237
+ #ifdef DATACATEGORY_ATTRIB
238
+ dataFilter_setCategoryValue(DATACATEGORY_ATTRIB);
239
+ #endif
240
+ }
175
241
  `,
176
242
 
177
243
  'vs:#main-end': glsl`
@@ -1,5 +1,13 @@
1
- import {Layer, Viewport, Effect, PreRenderOptions, CoordinateSystem, log} from '@deck.gl/core';
2
- import type {Device, Texture} from '@luma.gl/core';
1
+ import {
2
+ Layer,
3
+ Viewport,
4
+ Effect,
5
+ EffectContext,
6
+ PreRenderOptions,
7
+ CoordinateSystem,
8
+ log
9
+ } from '@deck.gl/core';
10
+ import type {Texture} from '@luma.gl/core';
3
11
  import {equals} from '@math.gl/core';
4
12
  import MaskPass from './mask-pass';
5
13
  import {joinLayerBounds, getRenderBounds, makeViewport, Bounds} from '../utils/projection-utils';
@@ -7,7 +15,7 @@ import {joinLayerBounds, getRenderBounds, makeViewport, Bounds} from '../utils/p
7
15
 
8
16
  type Mask = {
9
17
  /** The channel index */
10
- index: number;
18
+ index: 0 | 1 | 2 | 3;
11
19
  bounds: Bounds;
12
20
  coordinateOrigin: [number, number, number];
13
21
  coordinateSystem: CoordinateSystem;
@@ -15,7 +23,7 @@ type Mask = {
15
23
 
16
24
  type Channel = {
17
25
  id: string;
18
- index: number;
26
+ index: 0 | 1 | 2 | 3;
19
27
  layers: Layer[];
20
28
  bounds: Bounds | null;
21
29
  maskBounds: Bounds;
@@ -42,17 +50,25 @@ export default class MaskEffect implements Effect {
42
50
  private maskMap?: Texture;
43
51
  private lastViewport?: Viewport;
44
52
 
45
- preRender(
46
- device: Device,
47
- {layers, layerFilter, viewports, onViewportActive, views, isPicking}: PreRenderOptions
48
- ): MaskPreRenderStats {
53
+ setup({device}: EffectContext) {
54
+ this.dummyMaskMap = device.createTexture({
55
+ width: 1,
56
+ height: 1
57
+ });
58
+
59
+ this.maskPass = new MaskPass(device, {id: 'default-mask'});
60
+ this.maskMap = this.maskPass.maskMap;
61
+ }
62
+
63
+ preRender({
64
+ layers,
65
+ layerFilter,
66
+ viewports,
67
+ onViewportActive,
68
+ views,
69
+ isPicking
70
+ }: PreRenderOptions): MaskPreRenderStats {
49
71
  let didRender = false;
50
- if (!this.dummyMaskMap) {
51
- this.dummyMaskMap = device.createTexture({
52
- width: 1,
53
- height: 1
54
- });
55
- }
56
72
 
57
73
  if (isPicking) {
58
74
  // Do not update on picking pass
@@ -67,11 +83,6 @@ export default class MaskEffect implements Effect {
67
83
  }
68
84
  this.masks = {};
69
85
 
70
- if (!this.maskPass) {
71
- this.maskPass = new MaskPass(device, {id: 'default-mask'});
72
- this.maskMap = this.maskPass.maskMap;
73
- }
74
-
75
86
  // Map layers to channels
76
87
  const channelMap = this._sortMaskChannels(maskLayers);
77
88
  // TODO - support multiple views
@@ -1,10 +1,18 @@
1
- import type {Device, Framebuffer, Texture} from '@luma.gl/core';
2
- import {GL} from '@luma.gl/constants';
3
- import {_LayersPass as LayersPass, LayersPassRenderOptions} from '@deck.gl/core';
1
+ import type {Device, Framebuffer, RenderPipelineParameters, Texture} from '@luma.gl/core';
2
+ import {Layer, _LayersPass as LayersPass, LayersPassRenderOptions, Viewport} from '@deck.gl/core';
4
3
 
5
4
  type MaskPassRenderOptions = LayersPassRenderOptions & {
6
5
  /** The channel to render into, 0:red, 1:green, 2:blue, 3:alpha */
7
- channel: number;
6
+ channel: 0 | 1 | 2 | 3;
7
+ };
8
+
9
+ const MASK_BLENDING: RenderPipelineParameters = {
10
+ blendColorOperation: 'subtract',
11
+ blendColorSrcFactor: 'zero',
12
+ blendColorDstFactor: 'one',
13
+ blendAlphaOperation: 'subtract',
14
+ blendAlphaSrcFactor: 'zero',
15
+ blendAlphaDstFactor: 'one'
8
16
  };
9
17
 
10
18
  export default class MaskPass extends LayersPass {
@@ -37,20 +45,18 @@ export default class MaskPass extends LayersPass {
37
45
  }
38
46
 
39
47
  render(options: MaskPassRenderOptions) {
40
- const colorMask = [false, false, false, false];
41
- colorMask[options.channel] = true;
48
+ const colorMask = 2 ** options.channel;
42
49
  const clearColor = [255, 255, 255, 255];
50
+ super.render({...options, clearColor, colorMask, target: this.fbo, pass: 'mask'});
51
+ }
43
52
 
44
- return this.device.withParametersWebGL(
45
- {
46
- blend: true,
47
- blendFunc: [GL.ZERO, GL.ONE],
48
- blendEquation: GL.FUNC_SUBTRACT,
49
- colorMask,
50
- depthTest: false
51
- },
52
- () => super.render({...options, clearColor, target: this.fbo, pass: 'mask'})
53
- );
53
+ protected getLayerParameters(layer: Layer<{}>, layerIndex: number, viewport: Viewport) {
54
+ return {
55
+ ...layer.props.parameters,
56
+ blend: true,
57
+ depthTest: false,
58
+ ...MASK_BLENDING
59
+ };
54
60
  }
55
61
 
56
62
  shouldDrawLayer(layer) {
@@ -177,6 +177,7 @@ export default class PathStyleExtension extends LayerExtension<PathStyleExtensio
177
177
 
178
178
  prevP = p;
179
179
  }
180
+ result[geometrySize - 1] = 0;
180
181
  return result;
181
182
  }
182
183
  }
@@ -174,7 +174,8 @@ export class TerrainCover {
174
174
  }
175
175
  if (!this.pickingFbo) {
176
176
  this.pickingFbo = createRenderTarget(this.targetLayer.context.device, {
177
- id: `${this.id}-picking`
177
+ id: `${this.id}-picking`,
178
+ interpolate: false
178
179
  });
179
180
  }
180
181
  return this.pickingFbo;
@@ -1,5 +1,5 @@
1
- import {Device, Texture} from '@luma.gl/core';
2
- import {log, getShaderAssembler} from '@deck.gl/core';
1
+ import {Texture} from '@luma.gl/core';
2
+ import {log} from '@deck.gl/core';
3
3
 
4
4
  import {terrainModule, TerrainModuleSettings} from './shader-module';
5
5
  import {TerrainCover} from './terrain-cover';
@@ -7,7 +7,7 @@ import {TerrainPass} from './terrain-pass';
7
7
  import {TerrainPickingPass, TerrainPickingPassRenderOptions} from './terrain-picking-pass';
8
8
  import {HeightMapBuilder} from './height-map-builder';
9
9
 
10
- import type {Effect, PreRenderOptions, Layer, Viewport} from '@deck.gl/core';
10
+ import type {Effect, EffectContext, PreRenderOptions, Layer, Viewport} from '@deck.gl/core';
11
11
 
12
12
  /** Class to manage terrain effect */
13
13
  export class TerrainEffect implements Effect {
@@ -28,7 +28,7 @@ export class TerrainEffect implements Effect {
28
28
  /** One texture for each primitive terrain layer, into which the draped layers render */
29
29
  private terrainCovers: Map<string, TerrainCover> = new Map();
30
30
 
31
- initialize(device: Device) {
31
+ setup({device, deck}: EffectContext) {
32
32
  this.dummyHeightMap = device.createTexture({
33
33
  width: 1,
34
34
  height: 1,
@@ -43,21 +43,10 @@ export class TerrainEffect implements Effect {
43
43
  log.warn('Terrain offset mode is not supported by this browser')();
44
44
  }
45
45
 
46
- getShaderAssembler().addDefaultModule(terrainModule);
46
+ deck._addDefaultShaderModule(terrainModule);
47
47
  }
48
48
 
49
- preRender(device: Device, opts: PreRenderOptions): void {
50
- if (!this.dummyHeightMap) {
51
- // First time this effect is in use, initialize resources and register the shader module
52
- this.initialize(device);
53
- for (const layer of opts.layers) {
54
- // Force the terrain layer (and its descendents) to rebuild their models with the new shader
55
- if (layer.props.operation.includes('terrain')) {
56
- layer.setChangeFlags({extensionsChanged: true});
57
- }
58
- }
59
- }
60
-
49
+ preRender(opts: PreRenderOptions): void {
61
50
  // @ts-expect-error pickZ only defined in picking pass
62
51
  if (opts.pickZ) {
63
52
  // Do not update if picking attributes
@@ -106,7 +95,7 @@ export class TerrainEffect implements Effect {
106
95
  };
107
96
  }
108
97
 
109
- cleanup(): void {
98
+ cleanup({deck}: EffectContext): void {
110
99
  if (this.dummyHeightMap) {
111
100
  this.dummyHeightMap.delete();
112
101
  this.dummyHeightMap = undefined;
@@ -122,7 +111,7 @@ export class TerrainEffect implements Effect {
122
111
  }
123
112
  this.terrainCovers.clear();
124
113
 
125
- getShaderAssembler().removeDefaultModule(terrainModule);
114
+ deck._removeDefaultShaderModule(terrainModule);
126
115
  }
127
116
 
128
117
  private _updateHeightMap(terrainLayers: Layer[], viewport: Viewport, opts: PreRenderOptions) {