@deck.gl/extensions 8.9.0-beta.1 → 8.9.0-beta.3

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 (116) hide show
  1. package/dist/dist.dev.js +285 -464
  2. package/dist/es5/clip/clip.js.map +1 -1
  3. package/dist/es5/{collide/collide-effect.js → collision-filter/collision-filter-effect.js} +81 -73
  4. package/dist/es5/collision-filter/collision-filter-effect.js.map +1 -0
  5. package/dist/es5/{collide/collide-pass.js → collision-filter/collision-filter-pass.js} +13 -13
  6. package/dist/es5/collision-filter/collision-filter-pass.js.map +1 -0
  7. package/dist/es5/{collide/collide.js → collision-filter/collision-filter.js} +30 -30
  8. package/dist/es5/collision-filter/collision-filter.js.map +1 -0
  9. package/dist/es5/collision-filter/shader-module.js +39 -0
  10. package/dist/es5/collision-filter/shader-module.js.map +1 -0
  11. package/dist/es5/data-filter/shader-module.js.map +1 -1
  12. package/dist/es5/index.js +4 -4
  13. package/dist/es5/index.js.map +1 -1
  14. package/dist/es5/mask/mask-effect.js +16 -9
  15. package/dist/es5/mask/mask-effect.js.map +1 -1
  16. package/dist/es5/terrain/height-map-builder.js +1 -1
  17. package/dist/es5/terrain/height-map-builder.js.map +1 -1
  18. package/dist/es5/terrain/shader-module.js.map +1 -1
  19. package/dist/es5/terrain/terrain-cover.js +1 -1
  20. package/dist/es5/terrain/terrain-cover.js.map +1 -1
  21. package/dist/es5/terrain/terrain-effect.js +7 -7
  22. package/dist/es5/terrain/terrain-effect.js.map +1 -1
  23. package/dist/es5/terrain/terrain.js +7 -7
  24. package/dist/es5/terrain/terrain.js.map +1 -1
  25. package/dist/es5/{common → utils}/projection-utils.js +3 -1
  26. package/dist/es5/utils/projection-utils.js.map +1 -0
  27. package/dist/esm/clip/clip.js.map +1 -1
  28. package/dist/esm/{collide/collide-effect.js → collision-filter/collision-filter-effect.js} +72 -66
  29. package/dist/esm/collision-filter/collision-filter-effect.js.map +1 -0
  30. package/dist/esm/{collide/collide-pass.js → collision-filter/collision-filter-pass.js} +5 -5
  31. package/dist/esm/collision-filter/collision-filter-pass.js.map +1 -0
  32. package/dist/esm/collision-filter/collision-filter.js +78 -0
  33. package/dist/esm/collision-filter/collision-filter.js.map +1 -0
  34. package/dist/esm/collision-filter/shader-module.js +32 -0
  35. package/dist/esm/collision-filter/shader-module.js.map +1 -0
  36. package/dist/esm/data-filter/shader-module.js.map +1 -1
  37. package/dist/esm/index.js +2 -2
  38. package/dist/esm/index.js.map +1 -1
  39. package/dist/esm/mask/mask-effect.js +15 -9
  40. package/dist/esm/mask/mask-effect.js.map +1 -1
  41. package/dist/esm/terrain/height-map-builder.js +1 -1
  42. package/dist/esm/terrain/height-map-builder.js.map +1 -1
  43. package/dist/esm/terrain/shader-module.js.map +1 -1
  44. package/dist/esm/terrain/terrain-cover.js +1 -1
  45. package/dist/esm/terrain/terrain-cover.js.map +1 -1
  46. package/dist/esm/terrain/terrain-effect.js +6 -7
  47. package/dist/esm/terrain/terrain-effect.js.map +1 -1
  48. package/dist/esm/terrain/terrain.js +7 -7
  49. package/dist/esm/terrain/terrain.js.map +1 -1
  50. package/dist/esm/{common → utils}/projection-utils.js +3 -1
  51. package/dist/esm/utils/projection-utils.js.map +1 -0
  52. package/dist.min.js +59 -62
  53. package/package.json +2 -2
  54. package/src/clip/clip.ts +1 -1
  55. package/src/{collide/collide-effect.ts → collision-filter/collision-filter-effect.ts} +83 -79
  56. package/src/{collide/collide-pass.ts → collision-filter/collision-filter-pass.ts} +6 -6
  57. package/src/collision-filter/collision-filter.ts +83 -0
  58. package/src/collision-filter/shader-module.ts +113 -0
  59. package/src/data-filter/shader-module.ts +1 -1
  60. package/src/index.ts +3 -3
  61. package/src/mask/mask-effect.ts +23 -14
  62. package/src/terrain/height-map-builder.ts +2 -2
  63. package/src/terrain/shader-module.ts +4 -1
  64. package/src/terrain/terrain-cover.ts +2 -2
  65. package/src/terrain/terrain-effect.ts +6 -7
  66. package/src/terrain/terrain.ts +10 -10
  67. package/src/{common → utils}/projection-utils.ts +4 -2
  68. package/typed/clip/clip.d.ts +4 -1
  69. package/typed/clip/clip.d.ts.map +1 -1
  70. package/typed/collide/collide-effect.d.ts +1 -1
  71. package/typed/collide/collide-effect.d.ts.map +1 -1
  72. package/typed/collision-filter/collision-filter-effect.d.ts +28 -0
  73. package/typed/collision-filter/collision-filter-effect.d.ts.map +1 -0
  74. package/typed/collision-filter/collision-filter-pass.d.ts +14 -0
  75. package/typed/collision-filter/collision-filter-pass.d.ts.map +1 -0
  76. package/typed/collision-filter/collision-filter.d.ts +41 -0
  77. package/typed/collision-filter/collision-filter.d.ts.map +1 -0
  78. package/typed/collision-filter/shader-module.d.ts +4 -0
  79. package/typed/collision-filter/shader-module.d.ts.map +1 -0
  80. package/typed/data-filter/shader-module.d.ts.map +1 -1
  81. package/typed/index.d.ts +3 -3
  82. package/typed/index.d.ts.map +1 -1
  83. package/typed/mask/mask-effect.d.ts +3 -3
  84. package/typed/mask/mask-effect.d.ts.map +1 -1
  85. package/typed/terrain/height-map-builder.d.ts +2 -2
  86. package/typed/terrain/height-map-builder.d.ts.map +1 -1
  87. package/typed/terrain/height-map.d.ts +1 -1
  88. package/typed/terrain/shader-module.d.ts +1 -1
  89. package/typed/terrain/shader-module.d.ts.map +1 -1
  90. package/typed/terrain/terrain-cover.d.ts +2 -2
  91. package/typed/terrain/terrain-cover.d.ts.map +1 -1
  92. package/typed/terrain/terrain-effect.d.ts.map +1 -1
  93. package/typed/terrain/terrain.d.ts +2 -2
  94. package/typed/terrain/terrain.d.ts.map +1 -1
  95. package/typed/utils/projection-utils.d.ts +27 -0
  96. package/typed/utils/projection-utils.d.ts.map +1 -0
  97. package/dist/es5/collide/collide-effect.js.map +0 -1
  98. package/dist/es5/collide/collide-pass.js.map +0 -1
  99. package/dist/es5/collide/collide.js.map +0 -1
  100. package/dist/es5/collide/shader-module.js +0 -39
  101. package/dist/es5/collide/shader-module.js.map +0 -1
  102. package/dist/es5/common/projection-utils.js.map +0 -1
  103. package/dist/es5/mask/utils.js +0 -136
  104. package/dist/es5/mask/utils.js.map +0 -1
  105. package/dist/esm/collide/collide-effect.js.map +0 -1
  106. package/dist/esm/collide/collide-pass.js.map +0 -1
  107. package/dist/esm/collide/collide.js +0 -78
  108. package/dist/esm/collide/collide.js.map +0 -1
  109. package/dist/esm/collide/shader-module.js +0 -32
  110. package/dist/esm/collide/shader-module.js.map +0 -1
  111. package/dist/esm/common/projection-utils.js.map +0 -1
  112. package/dist/esm/mask/utils.js +0 -109
  113. package/dist/esm/mask/utils.js.map +0 -1
  114. package/src/collide/collide.ts +0 -79
  115. package/src/collide/shader-module.ts +0 -113
  116. package/src/mask/utils.ts +0 -148
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@deck.gl/extensions",
3
3
  "description": "Plug-and-play functionalities for deck.gl layers",
4
4
  "license": "MIT",
5
- "version": "8.9.0-beta.1",
5
+ "version": "8.9.0-beta.3",
6
6
  "publishConfig": {
7
7
  "access": "public"
8
8
  },
@@ -40,5 +40,5 @@
40
40
  "@math.gl/web-mercator": "^3.6.2",
41
41
  "gl-matrix": "^3.0.0"
42
42
  },
43
- "gitHead": "47223d1ea084c3f9b0c9f0f9736682850bb5db85"
43
+ "gitHead": "da509f9b00415a8d0700951663b65b59077c0cae"
44
44
  }
package/src/clip/clip.ts CHANGED
@@ -97,7 +97,7 @@ varying vec2 clip_commonPosition;
97
97
 
98
98
  /** Adds support for clipping rendered layers by rectangular bounds. */
99
99
  export default class ClipExtension extends LayerExtension {
100
- static defaultProps: any = defaultProps;
100
+ static defaultProps = defaultProps;
101
101
  static extensionName = 'ClipExtension';
102
102
 
103
103
  getShaders(this: Layer<ClipExtensionProps>) {
@@ -2,35 +2,35 @@ import {Framebuffer, Renderbuffer, Texture2D, cssToDeviceRatio} from '@luma.gl/c
2
2
  import {equals} from '@math.gl/core';
3
3
  import {_deepEqual as deepEqual} from '@deck.gl/core';
4
4
  import type {Effect, Layer, PreRenderOptions, Viewport} from '@deck.gl/core';
5
- import CollidePass from './collide-pass';
5
+ import CollisionFilterPass from './collision-filter-pass';
6
6
  import MaskEffect, {MaskPreRenderStats} from '../mask/mask-effect';
7
7
  // import {debugFBO} from '../utils/debug';
8
8
 
9
- type CollideExtensionProps = {
10
- collideTestProps?: {};
11
- collideGroup: string;
9
+ type CollisionFilterExtensionProps = {
10
+ collisionTestProps?: {};
11
+ collisionGroup: string;
12
12
  };
13
13
 
14
- // Factor by which to downscale Collide FBO relative to canvas
14
+ // Factor by which to downscale Collision FBO relative to canvas
15
15
  const DOWNSCALE = 2;
16
16
 
17
17
  type RenderInfo = {
18
- collideGroup: string;
19
- layers: Layer<CollideExtensionProps>[];
18
+ collisionGroup: string;
19
+ layers: Layer<CollisionFilterExtensionProps>[];
20
20
  layerBounds: ([number[], number[]] | null)[];
21
+ allLayersLoaded: boolean;
21
22
  };
22
23
 
23
- // Class to manage collide effect
24
- export default class CollideEffect implements Effect {
25
- id = 'collide-effect';
24
+ export default class CollisionFilterEffect implements Effect {
25
+ id = 'collision-filter-effect';
26
26
  props = null;
27
27
  useInPicking = true;
28
28
  order = 1;
29
29
 
30
30
  private channels: Record<string, RenderInfo> = {};
31
- private collidePass?: CollidePass;
32
- private collideFBOs: Record<string, Framebuffer> = {};
33
- private dummyCollideMap?: Texture2D;
31
+ private collisionFilterPass?: CollisionFilterPass;
32
+ private collisionFBOs: Record<string, Framebuffer> = {};
33
+ private dummyCollisionMap?: Texture2D;
34
34
  private lastViewport?: Viewport;
35
35
 
36
36
  preRender(
@@ -42,30 +42,30 @@ export default class CollideEffect implements Effect {
42
42
  viewports,
43
43
  onViewportActive,
44
44
  views,
45
- pass,
45
+ isPicking,
46
46
  preRenderStats = {}
47
47
  }: PreRenderOptions
48
48
  ): void {
49
- if (!this.dummyCollideMap) {
50
- this.dummyCollideMap = new Texture2D(gl, {width: 1, height: 1});
49
+ if (!this.dummyCollisionMap) {
50
+ this.dummyCollisionMap = new Texture2D(gl, {width: 1, height: 1});
51
51
  }
52
52
 
53
- if (pass.startsWith('picking')) {
53
+ if (isPicking) {
54
54
  // Do not update on picking pass
55
55
  return;
56
56
  }
57
57
 
58
- const collideLayers = layers.filter(
58
+ const collisionLayers = layers.filter(
59
59
  // @ts-ignore
60
- ({props: {visible, collideEnabled}}) => visible && collideEnabled
61
- ) as Layer<CollideExtensionProps>[];
62
- if (collideLayers.length === 0) {
60
+ ({props: {visible, collisionEnabled}}) => visible && collisionEnabled
61
+ ) as Layer<CollisionFilterExtensionProps>[];
62
+ if (collisionLayers.length === 0) {
63
63
  this.channels = {};
64
64
  return;
65
65
  }
66
66
 
67
- if (!this.collidePass) {
68
- this.collidePass = new CollidePass(gl, {id: 'default-collide'});
67
+ if (!this.collisionFilterPass) {
68
+ this.collisionFilterPass = new CollisionFilterPass(gl, {id: 'default-collision-filter'});
69
69
  }
70
70
 
71
71
  // Detect if mask has rendered. TODO: better dependency system for Effects
@@ -73,17 +73,17 @@ export default class CollideEffect implements Effect {
73
73
  const maskEffectRendered = (preRenderStats['mask-effect'] as MaskPreRenderStats)?.didRender;
74
74
 
75
75
  // Collect layers to render
76
- const channels = this._groupByCollideGroup(gl, collideLayers);
76
+ const channels = this._groupByCollisionGroup(gl, collisionLayers);
77
77
 
78
78
  const viewport = viewports[0];
79
79
  const viewportChanged =
80
80
  !this.lastViewport || !this.lastViewport.equals(viewport) || maskEffectRendered;
81
81
 
82
82
  // Resize framebuffers to match canvas
83
- for (const collideGroup in channels) {
84
- const collideFBO = this.collideFBOs[collideGroup];
85
- const renderInfo = channels[collideGroup];
86
- collideFBO.resize({
83
+ for (const collisionGroup in channels) {
84
+ const collisionFBO = this.collisionFBOs[collisionGroup];
85
+ const renderInfo = channels[collisionGroup];
86
+ collisionFBO.resize({
87
87
  width: gl.canvas.width / DOWNSCALE,
88
88
  height: gl.canvas.height / DOWNSCALE
89
89
  });
@@ -97,7 +97,7 @@ export default class CollideEffect implements Effect {
97
97
  });
98
98
  }
99
99
 
100
- // debugFBO(this.collideFBOs[Object.keys(channels)[0]], {minimap: true});
100
+ // debugFBO(this.collisionFBOs[Object.keys(channels)[0]], {minimap: true});
101
101
  }
102
102
 
103
103
  private _render(
@@ -118,8 +118,8 @@ export default class CollideEffect implements Effect {
118
118
  viewportChanged: boolean;
119
119
  }
120
120
  ) {
121
- const {collideGroup} = renderInfo;
122
- const oldRenderInfo = this.channels[collideGroup];
121
+ const {collisionGroup} = renderInfo;
122
+ const oldRenderInfo = this.channels[collisionGroup];
123
123
  if (!oldRenderInfo) {
124
124
  return;
125
125
  }
@@ -131,17 +131,22 @@ export default class CollideEffect implements Effect {
131
131
  // If sublayers have changed
132
132
  !deepEqual(oldRenderInfo.layers, renderInfo.layers, 0) ||
133
133
  // If a sublayer's bounds have been updated
134
- renderInfo.layerBounds.some((b, i) => !equals(b, oldRenderInfo.layerBounds[i]));
134
+ renderInfo.layerBounds.some((b, i) => !equals(b, oldRenderInfo.layerBounds[i])) ||
135
+ // If a sublayer's isLoaded state has been updated
136
+ renderInfo.allLayersLoaded !== oldRenderInfo.allLayersLoaded ||
137
+ // Some prop is in transition
138
+ renderInfo.layers.some(layer => layer.props.transitions);
135
139
 
136
- this.channels[collideGroup] = renderInfo;
140
+ this.channels[collisionGroup] = renderInfo;
137
141
 
138
142
  if (needsRender) {
139
143
  this.lastViewport = viewport;
140
- const collideFBO = this.collideFBOs[collideGroup];
144
+ const collisionFBO = this.collisionFBOs[collisionGroup];
141
145
 
142
- // Rerender collide FBO
143
- this.collidePass!.renderCollideMap(collideFBO, {
144
- pass: 'collide',
146
+ // Rerender collision FBO
147
+ this.collisionFilterPass!.renderCollisionMap(collisionFBO, {
148
+ pass: 'collision-filter',
149
+ isPicking: true,
145
150
  layers: renderInfo.layers,
146
151
  effects,
147
152
  layerFilter,
@@ -150,49 +155,48 @@ export default class CollideEffect implements Effect {
150
155
  views,
151
156
  moduleParameters: {
152
157
  // To avoid feedback loop forming between Framebuffer and active Texture.
153
- dummyCollideMap: this.dummyCollideMap,
154
- devicePixelRatio: cssToDeviceRatio(collideFBO.gl) / DOWNSCALE
158
+ dummyCollisionMap: this.dummyCollisionMap,
159
+ devicePixelRatio: cssToDeviceRatio(collisionFBO.gl) / DOWNSCALE
155
160
  }
156
161
  });
157
162
  }
158
163
  }
159
164
 
160
165
  /**
161
- * Group layers by collideGroup
162
- * Returns a map from collideGroup to render info
166
+ * Group layers by collisionGroup
167
+ * Returns a map from collisionGroup to render info
163
168
  */
164
- private _groupByCollideGroup(
169
+ private _groupByCollisionGroup(
165
170
  gl: WebGLRenderingContext,
166
- collideLayers: Layer<CollideExtensionProps>[]
171
+ collisionLayers: Layer<CollisionFilterExtensionProps>[]
167
172
  ): Record<string, RenderInfo> {
168
173
  const channelMap = {};
169
- for (const layer of collideLayers) {
170
- const {collideGroup} = layer.props;
171
- let channelInfo = channelMap[collideGroup];
174
+ for (const layer of collisionLayers) {
175
+ const {collisionGroup} = layer.props;
176
+ let channelInfo = channelMap[collisionGroup];
172
177
  if (!channelInfo) {
173
- channelInfo = {
174
- collideGroup,
175
- layers: [],
176
- layerBounds: []
177
- };
178
- channelMap[collideGroup] = channelInfo;
178
+ channelInfo = {collisionGroup, layers: [], layerBounds: [], allLayersLoaded: true};
179
+ channelMap[collisionGroup] = channelInfo;
179
180
  }
180
181
  channelInfo.layers.push(layer);
181
182
  channelInfo.layerBounds.push(layer.getBounds());
183
+ if (!layer.isLoaded) {
184
+ channelInfo.allLayersLoaded = false;
185
+ }
182
186
  }
183
187
 
184
188
  // Create any new passes and remove any old ones
185
- for (const collideGroup of Object.keys(channelMap)) {
186
- if (!this.collideFBOs[collideGroup]) {
187
- this.createFBO(gl, collideGroup);
189
+ for (const collisionGroup of Object.keys(channelMap)) {
190
+ if (!this.collisionFBOs[collisionGroup]) {
191
+ this.createFBO(gl, collisionGroup);
188
192
  }
189
- if (!this.channels[collideGroup]) {
190
- this.channels[collideGroup] = channelMap[collideGroup];
193
+ if (!this.channels[collisionGroup]) {
194
+ this.channels[collisionGroup] = channelMap[collisionGroup];
191
195
  }
192
196
  }
193
- for (const collideGroup of Object.keys(this.collideFBOs)) {
194
- if (!channelMap[collideGroup]) {
195
- this.destroyFBO(collideGroup);
197
+ for (const collisionGroup of Object.keys(this.collisionFBOs)) {
198
+ if (!channelMap[collisionGroup]) {
199
+ this.destroyFBO(collisionGroup);
196
200
  }
197
201
  }
198
202
 
@@ -200,30 +204,30 @@ export default class CollideEffect implements Effect {
200
204
  }
201
205
 
202
206
  getModuleParameters(layer: Layer): {
203
- collideFBO: Framebuffer;
204
- dummyCollideMap: Texture2D;
207
+ collisionFBO: Framebuffer;
208
+ dummyCollisionMap: Texture2D;
205
209
  } {
206
- const {collideGroup} = (layer as Layer<CollideExtensionProps>).props;
207
- const {collideFBOs, dummyCollideMap} = this;
208
- return {collideFBO: collideFBOs[collideGroup], dummyCollideMap};
210
+ const {collisionGroup} = (layer as Layer<CollisionFilterExtensionProps>).props;
211
+ const {collisionFBOs, dummyCollisionMap} = this;
212
+ return {collisionFBO: collisionFBOs[collisionGroup], dummyCollisionMap};
209
213
  }
210
214
 
211
215
  cleanup(): void {
212
- if (this.dummyCollideMap) {
213
- this.dummyCollideMap.delete();
214
- this.dummyCollideMap = undefined;
216
+ if (this.dummyCollisionMap) {
217
+ this.dummyCollisionMap.delete();
218
+ this.dummyCollisionMap = undefined;
215
219
  }
216
220
  this.channels = {};
217
- for (const collideGroup of Object.keys(this.collideFBOs)) {
218
- this.destroyFBO(collideGroup);
221
+ for (const collisionGroup of Object.keys(this.collisionFBOs)) {
222
+ this.destroyFBO(collisionGroup);
219
223
  }
220
- this.collideFBOs = {};
224
+ this.collisionFBOs = {};
221
225
  this.lastViewport = undefined;
222
226
  }
223
227
 
224
- createFBO(gl: WebGLRenderingContext, collideGroup: string) {
228
+ createFBO(gl: WebGLRenderingContext, collisionGroup: string) {
225
229
  const {width, height} = gl.canvas;
226
- const collideMap = new Texture2D(gl, {
230
+ const collisionMap = new Texture2D(gl, {
227
231
  width,
228
232
  height,
229
233
  parameters: {
@@ -235,23 +239,23 @@ export default class CollideEffect implements Effect {
235
239
  });
236
240
 
237
241
  const depthBuffer = new Renderbuffer(gl, {format: gl.DEPTH_COMPONENT16, width, height});
238
- this.collideFBOs[collideGroup] = new Framebuffer(gl, {
239
- id: `Collide-${collideGroup}`,
242
+ this.collisionFBOs[collisionGroup] = new Framebuffer(gl, {
243
+ id: `Collision-${collisionGroup}`,
240
244
  width,
241
245
  height,
242
246
  attachments: {
243
- [gl.COLOR_ATTACHMENT0]: collideMap,
247
+ [gl.COLOR_ATTACHMENT0]: collisionMap,
244
248
  [gl.DEPTH_ATTACHMENT]: depthBuffer
245
249
  }
246
250
  });
247
251
  }
248
252
 
249
- destroyFBO(collideGroup: string) {
250
- const fbo = this.collideFBOs[collideGroup];
253
+ destroyFBO(collisionGroup: string) {
254
+ const fbo = this.collisionFBOs[collisionGroup];
251
255
  for (const attachment of Object.values(fbo.attachments as Texture2D[])) {
252
256
  attachment.delete();
253
257
  }
254
258
  fbo.delete();
255
- delete this.collideFBOs[collideGroup];
259
+ delete this.collisionFBOs[collisionGroup];
256
260
  }
257
261
  }
@@ -1,10 +1,10 @@
1
1
  import {Framebuffer, withParameters} from '@luma.gl/core';
2
2
  import {_LayersPass as LayersPass, LayersPassRenderOptions} from '@deck.gl/core';
3
3
 
4
- type CollidePassRenderOptions = LayersPassRenderOptions & {};
4
+ type CollisionFilterPassRenderOptions = LayersPassRenderOptions & {};
5
5
 
6
- export default class CollidePass extends LayersPass {
7
- renderCollideMap(target: Framebuffer, options: CollidePassRenderOptions) {
6
+ export default class CollisionFilterPass extends LayersPass {
7
+ renderCollisionMap(target: Framebuffer, options: CollisionFilterPassRenderOptions) {
8
8
  const gl = this.gl;
9
9
 
10
10
  const padding = 1;
@@ -19,14 +19,14 @@ export default class CollidePass extends LayersPass {
19
19
  depthTest: true,
20
20
  depthRange: [0, 1]
21
21
  },
22
- () => this.render({...options, target, pass: 'collide'})
22
+ () => this.render({...options, target, pass: 'collision'})
23
23
  );
24
24
  }
25
25
 
26
26
  getModuleParameters() {
27
- // Draw picking colors into collide FBO
27
+ // Draw picking colors into collision FBO
28
28
  return {
29
- drawToCollideMap: true,
29
+ drawToCollisionMap: true,
30
30
  pickingActive: 1,
31
31
  pickingAttribute: false,
32
32
  lightSources: {}
@@ -0,0 +1,83 @@
1
+ import {Accessor, Layer, LayerContext, LayerExtension} from '@deck.gl/core';
2
+ import collision from './shader-module';
3
+ import CollisionFilterEffect from './collision-filter-effect';
4
+
5
+ const defaultProps = {
6
+ getCollisionPriority: {type: 'accessor', value: 0},
7
+ collisionEnabled: true,
8
+ collisionGroup: {type: 'string', value: 'default'},
9
+ collisionTestProps: {}
10
+ };
11
+
12
+ export type CollisionFilterExtensionProps<DataT = any> = {
13
+ /**
14
+ * Accessor for collision priority. Must return a number in the range -1000 -> 1000. Features with higher values are shown preferentially.
15
+ */
16
+ getCollisionPriority?: Accessor<DataT, number>;
17
+
18
+ /**
19
+ * Enable/disable collisions. If collisions are disabled, all objects are rendered.
20
+ * @default true
21
+ */
22
+ collisionEnabled: boolean;
23
+
24
+ /**
25
+ * Collision group this layer belongs to. If it is not set, the 'default' collision group is used
26
+ */
27
+ collisionGroup?: string;
28
+
29
+ /**
30
+ * Props to override when rendering collision map
31
+ */
32
+ collisionTestProps?: {};
33
+ };
34
+
35
+ /** Allows layers to hide overlapping objects. */
36
+ export default class CollisionFilterExtension extends LayerExtension {
37
+ static defaultProps = defaultProps;
38
+ static extensionName = 'CollisionFilterExtension';
39
+
40
+ getShaders(this: Layer<CollisionFilterExtensionProps>): any {
41
+ return {modules: [collision]};
42
+ }
43
+
44
+ /* eslint-disable camelcase */
45
+ draw(this: Layer<CollisionFilterExtensionProps>, {uniforms, context, moduleParameters}: any) {
46
+ const {collisionEnabled} = this.props;
47
+ const {collisionFBO, drawToCollisionMap} = moduleParameters;
48
+ const enabled = collisionEnabled && Boolean(collisionFBO);
49
+ uniforms.collision_enabled = enabled;
50
+
51
+ if (drawToCollisionMap) {
52
+ // Override any props with those defined in collisionTestProps
53
+ // @ts-ignore
54
+ this.props = this.clone(this.props.collisionTestProps).props;
55
+ }
56
+ }
57
+
58
+ initializeState(
59
+ this: Layer<CollisionFilterExtensionProps>,
60
+ context: LayerContext,
61
+ extension: this
62
+ ) {
63
+ if (this.getAttributeManager() === null) {
64
+ return;
65
+ }
66
+ this.context.deck?._addDefaultEffect(new CollisionFilterEffect());
67
+ const attributeManager = this.getAttributeManager();
68
+ attributeManager!.add({
69
+ collisionPriorities: {
70
+ size: 1,
71
+ accessor: 'getCollisionPriority',
72
+ shaderAttributes: {
73
+ collisionPriorities: {divisor: 0},
74
+ instanceCollisionPriorities: {divisor: 1}
75
+ }
76
+ }
77
+ });
78
+ }
79
+
80
+ getNeedsPickingBuffer(this: Layer<CollisionFilterExtensionProps>): boolean {
81
+ return this.props.collisionEnabled;
82
+ }
83
+ }
@@ -0,0 +1,113 @@
1
+ import {Framebuffer, Texture2D} from '@luma.gl/core';
2
+ import {project} from '@deck.gl/core';
3
+ import type {_ShaderModule as ShaderModule} from '@deck.gl/core';
4
+
5
+ const vs = `
6
+ #ifdef NON_INSTANCED_MODEL
7
+ attribute float collisionPriorities;
8
+ #else
9
+ attribute float instanceCollisionPriorities;
10
+ #endif
11
+
12
+ uniform sampler2D collision_texture;
13
+ uniform bool collision_sort;
14
+ uniform bool collision_enabled;
15
+
16
+ vec2 collision_getCoords(vec4 position) {
17
+ vec4 collision_clipspace = project_common_position_to_clipspace(position);
18
+ return (1.0 + collision_clipspace.xy / collision_clipspace.w) / 2.0;
19
+ }
20
+
21
+ float collision_match(vec2 tex, vec3 pickingColor) {
22
+ vec4 collision_pickingColor = texture2D(collision_texture, tex);
23
+ float delta = dot(abs(collision_pickingColor.rgb - pickingColor), vec3(1.0));
24
+ float e = 0.001;
25
+ return step(delta, e);
26
+ }
27
+
28
+ float collision_isVisible(vec2 texCoords, vec3 pickingColor) {
29
+ if (!collision_enabled) {
30
+ return 1.0;
31
+ }
32
+
33
+ // Visibility test, sample area of 5x5 pixels in order to fade in/out.
34
+ // Due to the locality, the lookups will be cached
35
+ // This reduces the flicker present when objects are shown/hidden
36
+ const int N = 2;
37
+ float accumulator = 0.0;
38
+ vec2 step = vec2(1.0 / project_uViewportSize);
39
+
40
+ const float floatN = float(N);
41
+ vec2 delta = -floatN * step;
42
+ for(int i = -N; i <= N; i++) {
43
+ delta.x = -step.x * floatN;
44
+ for(int j = -N; j <= N; j++) {
45
+ accumulator += collision_match(texCoords + delta, pickingColor);
46
+ delta.x += step.x;
47
+ }
48
+ delta.y += step.y;
49
+ }
50
+
51
+ float W = 2.0 * floatN + 1.0;
52
+ return pow(accumulator / (W * W), 2.2);
53
+ }
54
+ `;
55
+
56
+ const inject = {
57
+ 'vs:#decl': `
58
+ float collision_fade = 1.0;
59
+ `,
60
+ 'vs:DECKGL_FILTER_GL_POSITION': `
61
+ if (collision_sort) {
62
+ #ifdef NON_INSTANCED_MODEL
63
+ float collisionPriority = collisionPriorities;
64
+ #else
65
+ float collisionPriority = instanceCollisionPriorities;
66
+ #endif
67
+ position.z = -0.001 * collisionPriority * position.w; // Support range -1000 -> 1000
68
+ }
69
+
70
+ if (collision_enabled) {
71
+ vec4 collision_common_position = project_position(vec4(geometry.worldPosition, 1.0));
72
+ vec2 collision_texCoords = collision_getCoords(collision_common_position);
73
+ collision_fade = collision_isVisible(collision_texCoords, geometry.pickingColor / 255.0);
74
+ if (collision_fade < 0.0001) {
75
+ position = vec4(0.);
76
+ }
77
+ }
78
+ `,
79
+ 'vs:DECKGL_FILTER_COLOR': `
80
+ color.a *= collision_fade;
81
+ `
82
+ };
83
+
84
+ type CollisionModuleSettings = {
85
+ collisionFBO?: Framebuffer;
86
+ drawToCollisionMap?: boolean;
87
+ dummyCollisionMap?: Texture2D;
88
+ };
89
+
90
+ /* eslint-disable camelcase */
91
+ type CollisionUniforms = {collision_sort?: boolean; collision_texture?: Framebuffer | Texture2D};
92
+
93
+ const getCollisionUniforms = (
94
+ opts: CollisionModuleSettings | {},
95
+ uniforms: Record<string, any>
96
+ ): CollisionUniforms => {
97
+ if (!opts || !('dummyCollisionMap' in opts)) {
98
+ return {};
99
+ }
100
+ const {collisionFBO, drawToCollisionMap, dummyCollisionMap} = opts;
101
+ return {
102
+ collision_sort: Boolean(drawToCollisionMap),
103
+ collision_texture: !drawToCollisionMap && collisionFBO ? collisionFBO : dummyCollisionMap
104
+ };
105
+ };
106
+
107
+ export default {
108
+ name: 'collision',
109
+ dependencies: [project],
110
+ vs,
111
+ inject,
112
+ getUniforms: getCollisionUniforms
113
+ } as ShaderModule;
@@ -1,4 +1,4 @@
1
- import {_ShaderModule as ShaderModule} from '@deck.gl/core/typed';
1
+ import {_ShaderModule as ShaderModule} from '@deck.gl/core';
2
2
 
3
3
  import type {DataFilterExtensionProps} from './data-filter';
4
4
 
package/src/index.ts CHANGED
@@ -4,9 +4,9 @@ export {default as Fp64Extension} from './fp64/fp64';
4
4
  export {default as PathStyleExtension} from './path-style/path-style';
5
5
  export {default as FillStyleExtension} from './fill-style/fill-style';
6
6
  export {default as ClipExtension} from './clip/clip';
7
- export {default as CollideExtension} from './collide/collide';
7
+ export {default as CollisionFilterExtension} from './collision-filter/collision-filter';
8
8
  export {default as MaskExtension} from './mask/mask';
9
- export {default as TerrainExtension} from './terrain/terrain';
9
+ export {default as _TerrainExtension} from './terrain/terrain';
10
10
 
11
11
  // Shader module
12
12
  export {default as project64} from './fp64/project64';
@@ -17,6 +17,6 @@ export type {DataFilterExtensionProps} from './data-filter/data-filter';
17
17
  export type {PathStyleExtensionProps} from './path-style/path-style';
18
18
  export type {FillStyleExtensionProps} from './fill-style/fill-style';
19
19
  export type {ClipExtensionProps} from './clip/clip';
20
- export type {CollideExtensionProps} from './collide/collide';
20
+ export type {CollisionFilterExtensionProps} from './collision-filter/collision-filter';
21
21
  export type {MaskExtensionProps} from './mask/mask';
22
22
  export type {TerrainExtensionProps} from './terrain/terrain';
@@ -2,13 +2,13 @@ import {Layer, Viewport, Effect, PreRenderOptions, CoordinateSystem, log} from '
2
2
  import {Texture2D} from '@luma.gl/core';
3
3
  import {equals} from '@math.gl/core';
4
4
  import MaskPass from './mask-pass';
5
- import {getMaskBounds, getMaskViewport, MaskBounds} from './utils';
5
+ import {joinLayerBounds, getRenderBounds, makeViewport, Bounds} from '../utils/projection-utils';
6
6
  // import {debugFBO} from '../utils/debug';
7
7
 
8
8
  type Mask = {
9
9
  /** The channel index */
10
10
  index: number;
11
- bounds: MaskBounds;
11
+ bounds: Bounds;
12
12
  coordinateOrigin: [number, number, number];
13
13
  coordinateSystem: CoordinateSystem;
14
14
  };
@@ -17,9 +17,9 @@ type Channel = {
17
17
  id: string;
18
18
  index: number;
19
19
  layers: Layer[];
20
- bounds: MaskBounds;
21
- maskBounds: MaskBounds;
22
- layerBounds: MaskBounds[];
20
+ bounds: Bounds | null;
21
+ maskBounds: Bounds;
22
+ layerBounds: Bounds[];
23
23
  coordinateOrigin: [number, number, number];
24
24
  coordinateSystem: CoordinateSystem;
25
25
  };
@@ -44,7 +44,7 @@ export default class MaskEffect implements Effect {
44
44
 
45
45
  preRender(
46
46
  gl: WebGLRenderingContext,
47
- {layers, layerFilter, viewports, onViewportActive, views, pass}: PreRenderOptions
47
+ {layers, layerFilter, viewports, onViewportActive, views, isPicking}: PreRenderOptions
48
48
  ): MaskPreRenderStats {
49
49
  let didRender = false;
50
50
  if (!this.dummyMaskMap) {
@@ -54,7 +54,7 @@ export default class MaskEffect implements Effect {
54
54
  });
55
55
  }
56
56
 
57
- if (pass.startsWith('picking')) {
57
+ if (isPicking) {
58
58
  // Do not update on picking pass
59
59
  return {didRender};
60
60
  }
@@ -78,6 +78,11 @@ export default class MaskEffect implements Effect {
78
78
  const viewport = viewports[0];
79
79
  const viewportChanged = !this.lastViewport || !this.lastViewport.equals(viewport);
80
80
 
81
+ if (viewport.resolution !== undefined) {
82
+ log.warn('MaskExtension is not supported in GlobeView')();
83
+ return {didRender};
84
+ }
85
+
81
86
  for (const maskId in channelMap) {
82
87
  const result = this._renderChannel(channelMap[maskId], {
83
88
  layerFilter,
@@ -131,18 +136,22 @@ export default class MaskEffect implements Effect {
131
136
  // Recalculate mask bounds
132
137
  this.lastViewport = viewport;
133
138
 
134
- channelInfo.bounds = getMaskBounds({layers: channelInfo.layers, viewport});
139
+ const layerBounds = joinLayerBounds(channelInfo.layers, viewport);
140
+ channelInfo.bounds = layerBounds && getRenderBounds(layerBounds, viewport);
135
141
 
136
142
  if (maskChanged || !equals(channelInfo.bounds, oldChannelInfo.bounds)) {
137
143
  // Rerender mask FBO
138
144
  const {maskPass, maskMap} = this;
139
145
 
140
- const maskViewport = getMaskViewport({
141
- bounds: channelInfo.bounds,
142
- viewport,
143
- width: maskMap.width,
144
- height: maskMap.height
145
- });
146
+ const maskViewport =
147
+ layerBounds &&
148
+ makeViewport({
149
+ bounds: channelInfo.bounds!,
150
+ viewport,
151
+ width: maskMap.width,
152
+ height: maskMap.height,
153
+ border: 1
154
+ });
146
155
 
147
156
  channelInfo.maskBounds = maskViewport ? maskViewport.getBounds() : [0, 0, 1, 1];
148
157