@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
package/dist/dist.dev.js CHANGED
@@ -247,33 +247,43 @@ var __exports__ = (() => {
247
247
 
248
248
  // src/data-filter/shader-module.ts
249
249
  var vs2 = glsl`
250
- uniform DATAFILTER_TYPE filter_min;
251
- uniform DATAFILTER_TYPE filter_softMin;
252
- uniform DATAFILTER_TYPE filter_softMax;
253
- uniform DATAFILTER_TYPE filter_max;
254
250
  uniform bool filter_useSoftMargin;
255
251
  uniform bool filter_enabled;
256
252
  uniform bool filter_transformSize;
257
253
  uniform ivec4 filter_categoryBitMask;
258
254
 
259
- #ifdef NON_INSTANCED_MODEL
260
- #define DATAFILTER_ATTRIB filterValues
261
- #define DATAFILTER_ATTRIB_64LOW filterValues64Low
262
- #define DATACATEGORY_ATTRIB filterCategoryValues
263
- #else
264
- #define DATAFILTER_ATTRIB instanceFilterValues
265
- #define DATAFILTER_ATTRIB_64LOW instanceFilterValues64Low
266
- #define DATACATEGORY_ATTRIB instanceFilterCategoryValues
255
+ #ifdef DATAFILTER_TYPE
256
+ uniform DATAFILTER_TYPE filter_min;
257
+ uniform DATAFILTER_TYPE filter_softMin;
258
+ uniform DATAFILTER_TYPE filter_softMax;
259
+ uniform DATAFILTER_TYPE filter_max;
260
+
261
+ #ifdef NON_INSTANCED_MODEL
262
+ #define DATAFILTER_ATTRIB filterValues
263
+ #define DATAFILTER_ATTRIB_64LOW filterValues64Low
264
+ #else
265
+ #define DATAFILTER_ATTRIB instanceFilterValues
266
+ #define DATAFILTER_ATTRIB_64LOW instanceFilterValues64Low
267
+ #endif
268
+
269
+ in DATAFILTER_TYPE DATAFILTER_ATTRIB;
270
+ #ifdef DATAFILTER_DOUBLE
271
+ in DATAFILTER_TYPE DATAFILTER_ATTRIB_64LOW;
272
+
273
+ uniform DATAFILTER_TYPE filter_min64High;
274
+ uniform DATAFILTER_TYPE filter_max64High;
275
+ #endif
267
276
  #endif
268
277
 
269
- in DATAFILTER_TYPE DATAFILTER_ATTRIB;
270
- #ifdef DATAFILTER_DOUBLE
271
- in DATAFILTER_TYPE DATAFILTER_ATTRIB_64LOW;
272
278
 
273
- uniform DATAFILTER_TYPE filter_min64High;
274
- uniform DATAFILTER_TYPE filter_max64High;
279
+ #ifdef DATACATEGORY_TYPE
280
+ #ifdef NON_INSTANCED_MODEL
281
+ #define DATACATEGORY_ATTRIB filterCategoryValues
282
+ #else
283
+ #define DATACATEGORY_ATTRIB instanceFilterCategoryValues
284
+ #endif
285
+ in DATACATEGORY_TYPE DATACATEGORY_ATTRIB;
275
286
  #endif
276
- in DATACATEGORY_TYPE DATACATEGORY_ATTRIB;
277
287
 
278
288
  out float dataFilter_value;
279
289
 
@@ -289,30 +299,44 @@ float dataFilter_reduceValue(vec3 value) {
289
299
  float dataFilter_reduceValue(vec4 value) {
290
300
  return min(min(value.x, value.y), min(value.z, value.w));
291
301
  }
292
- void dataFilter_setValue(DATAFILTER_TYPE valueFromMin, DATAFILTER_TYPE valueFromMax, DATACATEGORY_TYPE category) {
293
- if (filter_enabled) {
302
+
303
+ #ifdef DATAFILTER_TYPE
304
+ void dataFilter_setValue(DATAFILTER_TYPE valueFromMin, DATAFILTER_TYPE valueFromMax) {
294
305
  if (filter_useSoftMargin) {
295
- dataFilter_value = dataFilter_reduceValue(
296
- smoothstep(filter_min, filter_softMin, valueFromMin) *
297
- (1.0 - smoothstep(filter_softMax, filter_max, valueFromMax))
306
+ // smoothstep results are undefined if edge0 ≥ edge1
307
+ // Fallback to ignore filterSoftRange if it is truncated by filterRange
308
+ DATAFILTER_TYPE leftInRange = mix(
309
+ smoothstep(filter_min, filter_softMin, valueFromMin),
310
+ step(filter_min, valueFromMin),
311
+ step(filter_softMin, filter_min)
298
312
  );
313
+ DATAFILTER_TYPE rightInRange = mix(
314
+ 1.0 - smoothstep(filter_softMax, filter_max, valueFromMax),
315
+ step(valueFromMax, filter_max),
316
+ step(filter_max, filter_softMax)
317
+ );
318
+ dataFilter_value = dataFilter_reduceValue(leftInRange * rightInRange);
299
319
  } else {
300
320
  dataFilter_value = dataFilter_reduceValue(
301
321
  step(filter_min, valueFromMin) * step(valueFromMax, filter_max)
302
322
  );
303
323
  }
324
+ }
325
+ #endif
304
326
 
327
+ #ifdef DATACATEGORY_ATTRIB
328
+ void dataFilter_setCategoryValue(DATACATEGORY_TYPE category) {
305
329
  #if DATACATEGORY_CHANNELS == 1 // One 128-bit mask
306
- int dataFilter_masks = filter_categoryBitMask[int(category / 32.0)];
330
+ int dataFilter_masks = filter_categoryBitMask[int(category / 32.0)];
307
331
  #elif DATACATEGORY_CHANNELS == 2 // Two 64-bit masks
308
- ivec2 dataFilter_masks = ivec2(
309
- filter_categoryBitMask[int(category.x / 32.0)],
310
- filter_categoryBitMask[int(category.y / 32.0) + 2]
311
- );
332
+ ivec2 dataFilter_masks = ivec2(
333
+ filter_categoryBitMask[int(category.x / 32.0)],
334
+ filter_categoryBitMask[int(category.y / 32.0) + 2]
335
+ );
312
336
  #elif DATACATEGORY_CHANNELS == 3 // Three 32-bit masks
313
- ivec3 dataFilter_masks = filter_categoryBitMask.xyz;
337
+ ivec3 dataFilter_masks = filter_categoryBitMask.xyz;
314
338
  #else // Four 32-bit masks
315
- ivec4 dataFilter_masks = filter_categoryBitMask;
339
+ ivec4 dataFilter_masks = filter_categoryBitMask;
316
340
  #endif
317
341
 
318
342
  // Shift mask and extract relevant bits
@@ -320,14 +344,12 @@ void dataFilter_setValue(DATAFILTER_TYPE valueFromMin, DATAFILTER_TYPE valueFrom
320
344
  dataFilter_bits = mod(floor(dataFilter_bits), 2.0);
321
345
 
322
346
  #if DATACATEGORY_CHANNELS == 1
323
- if(dataFilter_bits == 0.0) dataFilter_value = 0.0;
347
+ if(dataFilter_bits == 0.0) dataFilter_value = 0.0;
324
348
  #else
325
349
  if(any(equal(dataFilter_bits, DATACATEGORY_TYPE(0.0)))) dataFilter_value = 0.0;
326
350
  #endif
327
- } else {
328
- dataFilter_value = 1.0;
329
351
  }
330
- }
352
+ #endif
331
353
  `;
332
354
  var fs2 = glsl`
333
355
  uniform bool filter_transformColor;
@@ -390,15 +412,23 @@ in float dataFilter_value;
390
412
  }
391
413
  var inject2 = {
392
414
  "vs:#main-start": glsl`
393
- #ifdef DATAFILTER_DOUBLE
394
- dataFilter_setValue(
395
- DATAFILTER_ATTRIB - filter_min64High + DATAFILTER_ATTRIB_64LOW,
396
- DATAFILTER_ATTRIB - filter_max64High + DATAFILTER_ATTRIB_64LOW,
397
- DATACATEGORY_ATTRIB
398
- );
399
- #else
400
- dataFilter_setValue(DATAFILTER_ATTRIB, DATAFILTER_ATTRIB, DATACATEGORY_ATTRIB);
401
- #endif
415
+ dataFilter_value = 1.0;
416
+ if (filter_enabled) {
417
+ #ifdef DATAFILTER_ATTRIB
418
+ #ifdef DATAFILTER_DOUBLE
419
+ dataFilter_setValue(
420
+ DATAFILTER_ATTRIB - filter_min64High + DATAFILTER_ATTRIB_64LOW,
421
+ DATAFILTER_ATTRIB - filter_max64High + DATAFILTER_ATTRIB_64LOW
422
+ );
423
+ #else
424
+ dataFilter_setValue(DATAFILTER_ATTRIB, DATAFILTER_ATTRIB);
425
+ #endif
426
+ #endif
427
+
428
+ #ifdef DATACATEGORY_ATTRIB
429
+ dataFilter_setCategoryValue(DATACATEGORY_ATTRIB);
430
+ #endif
431
+ }
402
432
  `,
403
433
  "vs:#main-end": glsl`
404
434
  if (dataFilter_value == 0.0) {
@@ -1196,7 +1226,7 @@ void main() {
1196
1226
  filterTransformColor: true
1197
1227
  };
1198
1228
  var defaultOptions = {
1199
- categorySize: 1,
1229
+ categorySize: 0,
1200
1230
  filterSize: 1,
1201
1231
  fp64: false,
1202
1232
  countItems: false
@@ -1213,48 +1243,55 @@ void main() {
1213
1243
  }
1214
1244
  getShaders(extension) {
1215
1245
  const { categorySize, filterSize, fp64: fp642 } = extension.opts;
1216
- return {
1217
- modules: [fp642 ? shaderModule64 : shaderModule],
1218
- defines: {
1219
- DATACATEGORY_TYPE: DATA_TYPE_FROM_SIZE[categorySize],
1220
- DATACATEGORY_CHANNELS: categorySize,
1221
- DATAFILTER_TYPE: DATA_TYPE_FROM_SIZE[filterSize],
1222
- DATAFILTER_DOUBLE: Boolean(fp642)
1223
- }
1224
- };
1246
+ const defines = {};
1247
+ if (categorySize) {
1248
+ defines.DATACATEGORY_TYPE = DATA_TYPE_FROM_SIZE[categorySize];
1249
+ defines.DATACATEGORY_CHANNELS = categorySize;
1250
+ }
1251
+ if (filterSize) {
1252
+ defines.DATAFILTER_TYPE = DATA_TYPE_FROM_SIZE[filterSize];
1253
+ defines.DATAFILTER_DOUBLE = Boolean(fp642);
1254
+ }
1255
+ return { modules: [fp642 ? shaderModule64 : shaderModule], defines };
1225
1256
  }
1226
1257
  initializeState(context, extension) {
1227
1258
  const attributeManager = this.getAttributeManager();
1228
1259
  const { categorySize, filterSize, fp64: fp642 } = extension.opts;
1229
1260
  if (attributeManager) {
1230
- attributeManager.add({
1231
- filterValues: {
1232
- size: filterSize,
1233
- type: fp642 ? "float64" : "float32",
1234
- accessor: "getFilterValue",
1235
- shaderAttributes: {
1236
- filterValues: {
1237
- divisor: 0
1238
- },
1239
- instanceFilterValues: {
1240
- divisor: 1
1261
+ if (filterSize) {
1262
+ attributeManager.add({
1263
+ filterValues: {
1264
+ size: filterSize,
1265
+ type: fp642 ? "float64" : "float32",
1266
+ accessor: "getFilterValue",
1267
+ shaderAttributes: {
1268
+ filterValues: {
1269
+ divisor: 0
1270
+ },
1271
+ instanceFilterValues: {
1272
+ divisor: 1
1273
+ }
1241
1274
  }
1242
1275
  }
1243
- },
1244
- filterCategoryValues: {
1245
- size: categorySize,
1246
- accessor: "getFilterCategory",
1247
- transform: categorySize === 1 ? (d) => extension._getCategoryKey.call(this, d, 0) : (d) => d.map((x, i) => extension._getCategoryKey.call(this, x, i)),
1248
- shaderAttributes: {
1249
- filterCategoryValues: {
1250
- divisor: 0
1251
- },
1252
- instanceFilterCategoryValues: {
1253
- divisor: 1
1276
+ });
1277
+ }
1278
+ if (categorySize) {
1279
+ attributeManager.add({
1280
+ filterCategoryValues: {
1281
+ size: categorySize,
1282
+ accessor: "getFilterCategory",
1283
+ transform: categorySize === 1 ? (d) => extension._getCategoryKey.call(this, d, 0) : (d) => d.map((x, i) => extension._getCategoryKey.call(this, x, i)),
1284
+ shaderAttributes: {
1285
+ filterCategoryValues: {
1286
+ divisor: 0
1287
+ },
1288
+ instanceFilterCategoryValues: {
1289
+ divisor: 1
1290
+ }
1254
1291
  }
1255
1292
  }
1256
- }
1257
- });
1293
+ });
1294
+ }
1258
1295
  }
1259
1296
  const { device } = this.context;
1260
1297
  if (attributeManager && extension.opts.countItems) {
@@ -1291,7 +1328,7 @@ void main() {
1291
1328
  const attributeManager = this.getAttributeManager();
1292
1329
  const { categorySize } = extension.opts;
1293
1330
  if (this.state.filterModel) {
1294
- const filterNeedsUpdate = attributeManager.attributes.filterValues.needsUpdate() || attributeManager.attributes.filterCategoryValues?.needsUpdate() || props.filterEnabled !== oldProps.filterEnabled || props.filterRange !== oldProps.filterRange || props.filterSoftRange !== oldProps.filterSoftRange || props.filterCategories !== oldProps.filterCategories;
1331
+ const filterNeedsUpdate = attributeManager.attributes.filterValues?.needsUpdate() || attributeManager.attributes.filterCategoryValues?.needsUpdate() || props.filterEnabled !== oldProps.filterEnabled || props.filterRange !== oldProps.filterRange || props.filterSoftRange !== oldProps.filterSoftRange || props.filterCategories !== oldProps.filterCategories;
1295
1332
  if (filterNeedsUpdate) {
1296
1333
  this.setState({ filterNeedsUpdate });
1297
1334
  }
@@ -1327,7 +1364,7 @@ void main() {
1327
1364
  this.context.device.clearWebGL({ framebuffer: filterFBO, color: [0, 0, 0, 0] });
1328
1365
  filterModel.updateModuleSettings(params.moduleParameters);
1329
1366
  filterModel.setAttributes({
1330
- ...filterValues.getValue(),
1367
+ ...filterValues?.getValue(),
1331
1368
  ...filterCategoryValues?.getValue(),
1332
1369
  ...filterIndices?.getValue()
1333
1370
  });
@@ -2101,11 +2138,7 @@ vec4_dot_fp64(a, tmp, out_val[i]);
2101
2138
  printRowMajor: true,
2102
2139
  _cartographicRadians: false
2103
2140
  };
2104
- globalThis.mathgl = globalThis.mathgl || {
2105
- config: {
2106
- ...DEFAULT_CONFIG
2107
- }
2108
- };
2141
+ globalThis.mathgl = globalThis.mathgl || { config: { ...DEFAULT_CONFIG } };
2109
2142
  var config = globalThis.mathgl.config;
2110
2143
  function isArray(value) {
2111
2144
  return Array.isArray(value) || ArrayBuffer.isView(value) && !(value instanceof DataView);
@@ -2533,7 +2566,7 @@ vec4_dot_fp64(a, tmp, out_val[i]);
2533
2566
  return out;
2534
2567
  }
2535
2568
  function str(a) {
2536
- return "vec3(".concat(a[0], ", ").concat(a[1], ", ").concat(a[2], ")");
2569
+ return `vec3(${a[0]}, ${a[1]}, ${a[2]})`;
2537
2570
  }
2538
2571
  function exactEquals(a, b) {
2539
2572
  return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];
@@ -2883,6 +2916,7 @@ in float instanceOffsets;
2883
2916
  }
2884
2917
  prevP = p;
2885
2918
  }
2919
+ result[geometrySize - 1] = 0;
2886
2920
  return result;
2887
2921
  }
2888
2922
  };
@@ -3191,7 +3225,7 @@ in vec2 clip_commonPosition;
3191
3225
  ClipExtension.extensionName = "ClipExtension";
3192
3226
 
3193
3227
  // src/collision-filter/collision-filter-extension.ts
3194
- var import_core20 = __toESM(require_core(), 1);
3228
+ var import_core16 = __toESM(require_core(), 1);
3195
3229
 
3196
3230
  // src/collision-filter/shader-module.ts
3197
3231
  var import_core12 = __toESM(require_core(), 1);
@@ -3292,7 +3326,7 @@ float collision_isVisible(vec2 texCoords, vec3 pickingColor) {
3292
3326
  };
3293
3327
 
3294
3328
  // src/collision-filter/collision-filter-effect.ts
3295
- var import_core19 = __toESM(require_core(), 1);
3329
+ var import_core15 = __toESM(require_core(), 1);
3296
3330
 
3297
3331
  // src/collision-filter/collision-filter-pass.ts
3298
3332
  var import_core13 = __toESM(require_core(), 1);
@@ -3300,16 +3334,11 @@ float collision_isVisible(vec2 texCoords, vec3 pickingColor) {
3300
3334
  renderCollisionMap(target, options) {
3301
3335
  const padding = 1;
3302
3336
  const clearColor = [0, 0, 0, 0];
3303
- return this.device.withParametersWebGL(
3304
- {
3305
- scissorTest: true,
3306
- scissor: [padding, padding, target.width - 2 * padding, target.height - 2 * padding],
3307
- blend: false,
3308
- depthTest: true,
3309
- depthRange: [0, 1]
3310
- },
3311
- () => this.render({ ...options, clearColor, target, pass: "collision" })
3312
- );
3337
+ const scissorRect = [padding, padding, target.width - 2 * padding, target.height - 2 * padding];
3338
+ this.render({ ...options, clearColor, scissorRect, target, pass: "collision" });
3339
+ }
3340
+ getLayerParameters(layer, layerIndex, viewport) {
3341
+ return { ...layer.props.parameters, blend: false, depthRange: [0, 1], depthTest: true };
3313
3342
  }
3314
3343
  getModuleParameters() {
3315
3344
  return {
@@ -3323,62 +3352,377 @@ float collision_isVisible(vec2 texCoords, vec3 pickingColor) {
3323
3352
  }
3324
3353
  };
3325
3354
 
3326
- // src/mask/mask-effect.ts
3327
- var import_core16 = __toESM(require_core(), 1);
3328
-
3329
- // src/mask/mask-pass.ts
3330
- var import_core14 = __toESM(require_core(), 1);
3331
- var MaskPass = class extends import_core14._LayersPass {
3332
- constructor(device, props) {
3333
- super(device, props);
3334
- const { mapSize = 2048 } = props;
3335
- this.maskMap = device.createTexture({
3355
+ // src/collision-filter/collision-filter-effect.ts
3356
+ var DOWNSCALE = 2;
3357
+ var CollisionFilterEffect = class {
3358
+ constructor() {
3359
+ this.id = "collision-filter-effect";
3360
+ this.props = null;
3361
+ this.useInPicking = true;
3362
+ this.order = 1;
3363
+ this.channels = {};
3364
+ this.collisionFBOs = {};
3365
+ }
3366
+ setup(context) {
3367
+ this.context = context;
3368
+ const { device } = context;
3369
+ this.dummyCollisionMap = device.createTexture({ width: 1, height: 1 });
3370
+ this.collisionFilterPass = new CollisionFilterPass(device, { id: "default-collision-filter" });
3371
+ }
3372
+ preRender({
3373
+ effects: allEffects,
3374
+ layers,
3375
+ layerFilter,
3376
+ viewports,
3377
+ onViewportActive,
3378
+ views,
3379
+ isPicking,
3380
+ preRenderStats = {}
3381
+ }) {
3382
+ const { device } = this.context;
3383
+ if (isPicking) {
3384
+ return;
3385
+ }
3386
+ const collisionLayers = layers.filter(
3387
+ ({ props: { visible, collisionEnabled } }) => visible && collisionEnabled
3388
+ );
3389
+ if (collisionLayers.length === 0) {
3390
+ this.channels = {};
3391
+ return;
3392
+ }
3393
+ const effects = allEffects?.filter((e) => e.useInPicking && preRenderStats[e.id]);
3394
+ const maskEffectRendered = preRenderStats["mask-effect"]?.didRender;
3395
+ const channels = this._groupByCollisionGroup(device, collisionLayers);
3396
+ const viewport = viewports[0];
3397
+ const viewportChanged = !this.lastViewport || !this.lastViewport.equals(viewport) || maskEffectRendered;
3398
+ for (const collisionGroup in channels) {
3399
+ const collisionFBO = this.collisionFBOs[collisionGroup];
3400
+ const renderInfo = channels[collisionGroup];
3401
+ const [width, height] = device.canvasContext.getPixelSize();
3402
+ collisionFBO.resize({
3403
+ width: width / DOWNSCALE,
3404
+ height: height / DOWNSCALE
3405
+ });
3406
+ this._render(renderInfo, {
3407
+ effects,
3408
+ layerFilter,
3409
+ onViewportActive,
3410
+ views,
3411
+ viewport,
3412
+ viewportChanged
3413
+ });
3414
+ }
3415
+ }
3416
+ _render(renderInfo, {
3417
+ effects,
3418
+ layerFilter,
3419
+ onViewportActive,
3420
+ views,
3421
+ viewport,
3422
+ viewportChanged
3423
+ }) {
3424
+ const { collisionGroup } = renderInfo;
3425
+ const oldRenderInfo = this.channels[collisionGroup];
3426
+ if (!oldRenderInfo) {
3427
+ return;
3428
+ }
3429
+ const needsRender = viewportChanged || renderInfo === oldRenderInfo || !(0, import_core15._deepEqual)(oldRenderInfo.layers, renderInfo.layers, 1) || renderInfo.layerBounds.some((b, i) => !equals(b, oldRenderInfo.layerBounds[i])) || renderInfo.allLayersLoaded !== oldRenderInfo.allLayersLoaded || renderInfo.layers.some((layer) => layer.props.transitions);
3430
+ this.channels[collisionGroup] = renderInfo;
3431
+ if (needsRender) {
3432
+ this.lastViewport = viewport;
3433
+ const collisionFBO = this.collisionFBOs[collisionGroup];
3434
+ this.collisionFilterPass.renderCollisionMap(collisionFBO, {
3435
+ pass: "collision-filter",
3436
+ isPicking: true,
3437
+ layers: renderInfo.layers,
3438
+ effects,
3439
+ layerFilter,
3440
+ viewports: viewport ? [viewport] : [],
3441
+ onViewportActive,
3442
+ views,
3443
+ moduleParameters: {
3444
+ dummyCollisionMap: this.dummyCollisionMap,
3445
+ devicePixelRatio: collisionFBO.device.canvasContext.getDevicePixelRatio() / DOWNSCALE
3446
+ }
3447
+ });
3448
+ }
3449
+ }
3450
+ _groupByCollisionGroup(device, collisionLayers) {
3451
+ const channelMap = {};
3452
+ for (const layer of collisionLayers) {
3453
+ const { collisionGroup } = layer.props;
3454
+ let channelInfo = channelMap[collisionGroup];
3455
+ if (!channelInfo) {
3456
+ channelInfo = { collisionGroup, layers: [], layerBounds: [], allLayersLoaded: true };
3457
+ channelMap[collisionGroup] = channelInfo;
3458
+ }
3459
+ channelInfo.layers.push(layer);
3460
+ channelInfo.layerBounds.push(layer.getBounds());
3461
+ if (!layer.isLoaded) {
3462
+ channelInfo.allLayersLoaded = false;
3463
+ }
3464
+ }
3465
+ for (const collisionGroup of Object.keys(channelMap)) {
3466
+ if (!this.collisionFBOs[collisionGroup]) {
3467
+ this.createFBO(device, collisionGroup);
3468
+ }
3469
+ if (!this.channels[collisionGroup]) {
3470
+ this.channels[collisionGroup] = channelMap[collisionGroup];
3471
+ }
3472
+ }
3473
+ for (const collisionGroup of Object.keys(this.collisionFBOs)) {
3474
+ if (!channelMap[collisionGroup]) {
3475
+ this.destroyFBO(collisionGroup);
3476
+ }
3477
+ }
3478
+ return channelMap;
3479
+ }
3480
+ getModuleParameters(layer) {
3481
+ const { collisionGroup } = layer.props;
3482
+ const { collisionFBOs, dummyCollisionMap } = this;
3483
+ return { collisionFBO: collisionFBOs[collisionGroup], dummyCollisionMap };
3484
+ }
3485
+ cleanup() {
3486
+ if (this.dummyCollisionMap) {
3487
+ this.dummyCollisionMap.delete();
3488
+ this.dummyCollisionMap = void 0;
3489
+ }
3490
+ this.channels = {};
3491
+ for (const collisionGroup of Object.keys(this.collisionFBOs)) {
3492
+ this.destroyFBO(collisionGroup);
3493
+ }
3494
+ this.collisionFBOs = {};
3495
+ this.lastViewport = void 0;
3496
+ }
3497
+ createFBO(device, collisionGroup) {
3498
+ const { width, height } = device.gl.canvas;
3499
+ const collisionMap = device.createTexture({
3336
3500
  format: "rgba8unorm",
3337
- width: mapSize,
3338
- height: mapSize,
3501
+ width,
3502
+ height,
3339
3503
  sampler: {
3340
- minFilter: "linear",
3341
- magFilter: "linear",
3504
+ minFilter: "nearest",
3505
+ magFilter: "nearest",
3342
3506
  addressModeU: "clamp-to-edge",
3343
3507
  addressModeV: "clamp-to-edge"
3344
3508
  }
3345
3509
  });
3346
- this.fbo = device.createFramebuffer({
3347
- id: "maskmap",
3348
- width: mapSize,
3349
- height: mapSize,
3350
- colorAttachments: [this.maskMap]
3510
+ const depthStencilAttachment = device.createTexture({
3511
+ format: "depth16unorm",
3512
+ width,
3513
+ height,
3514
+ mipmaps: false,
3515
+ dataFormat: 6402,
3516
+ type: 5125
3517
+ });
3518
+ this.collisionFBOs[collisionGroup] = device.createFramebuffer({
3519
+ id: `collision-${collisionGroup}`,
3520
+ width,
3521
+ height,
3522
+ colorAttachments: [collisionMap],
3523
+ depthStencilAttachment
3351
3524
  });
3352
3525
  }
3353
- render(options) {
3354
- const colorMask = [false, false, false, false];
3355
- colorMask[options.channel] = true;
3356
- const clearColor = [255, 255, 255, 255];
3357
- return this.device.withParametersWebGL(
3358
- {
3359
- blend: true,
3360
- blendFunc: [GLEnum.ZERO, GLEnum.ONE],
3361
- blendEquation: GLEnum.FUNC_SUBTRACT,
3362
- colorMask,
3363
- depthTest: false
3364
- },
3365
- () => super.render({ ...options, clearColor, target: this.fbo, pass: "mask" })
3366
- );
3367
- }
3368
- shouldDrawLayer(layer) {
3369
- return layer.props.operation.includes("mask");
3370
- }
3371
- delete() {
3372
- this.fbo.delete();
3373
- this.maskMap.delete();
3526
+ destroyFBO(collisionGroup) {
3527
+ const fbo = this.collisionFBOs[collisionGroup];
3528
+ fbo.colorAttachments[0]?.destroy();
3529
+ fbo.depthStencilAttachment?.destroy();
3530
+ fbo.destroy();
3531
+ delete this.collisionFBOs[collisionGroup];
3374
3532
  }
3375
3533
  };
3376
3534
 
3377
- // src/utils/projection-utils.ts
3378
- var import_core15 = __toESM(require_core(), 1);
3379
- function joinLayerBounds(layers, viewport) {
3380
- const bounds = [Infinity, Infinity, -Infinity, -Infinity];
3381
- for (const layer of layers) {
3535
+ // src/collision-filter/collision-filter-extension.ts
3536
+ var defaultProps6 = {
3537
+ getCollisionPriority: { type: "accessor", value: 0 },
3538
+ collisionEnabled: true,
3539
+ collisionGroup: { type: "string", value: "default" },
3540
+ collisionTestProps: {}
3541
+ };
3542
+ var CollisionFilterExtension = class extends import_core16.LayerExtension {
3543
+ getShaders() {
3544
+ return { modules: [shader_module_default2] };
3545
+ }
3546
+ draw({ uniforms, context, moduleParameters }) {
3547
+ const { collisionEnabled } = this.props;
3548
+ const { collisionFBO, drawToCollisionMap } = moduleParameters;
3549
+ const enabled = collisionEnabled && Boolean(collisionFBO);
3550
+ uniforms.collision_enabled = enabled;
3551
+ if (drawToCollisionMap) {
3552
+ this.props = this.clone(this.props.collisionTestProps).props;
3553
+ }
3554
+ }
3555
+ initializeState(context, extension) {
3556
+ if (this.getAttributeManager() === null) {
3557
+ return;
3558
+ }
3559
+ this.context.deck?._addDefaultEffect(new CollisionFilterEffect());
3560
+ const attributeManager = this.getAttributeManager();
3561
+ attributeManager.add({
3562
+ collisionPriorities: {
3563
+ size: 1,
3564
+ accessor: "getCollisionPriority",
3565
+ shaderAttributes: {
3566
+ collisionPriorities: { divisor: 0 },
3567
+ instanceCollisionPriorities: { divisor: 1 }
3568
+ }
3569
+ }
3570
+ });
3571
+ }
3572
+ getNeedsPickingBuffer() {
3573
+ return this.props.collisionEnabled;
3574
+ }
3575
+ };
3576
+ CollisionFilterExtension.defaultProps = defaultProps6;
3577
+ CollisionFilterExtension.extensionName = "CollisionFilterExtension";
3578
+
3579
+ // src/mask/mask-extension.ts
3580
+ var import_core22 = __toESM(require_core(), 1);
3581
+
3582
+ // src/mask/shader-module.ts
3583
+ var import_core17 = __toESM(require_core(), 1);
3584
+ var vs4 = glsl`
3585
+ uniform vec4 mask_bounds;
3586
+ uniform bool mask_maskByInstance;
3587
+ vec2 mask_getCoords(vec4 position) {
3588
+ return (position.xy - mask_bounds.xy) / (mask_bounds.zw - mask_bounds.xy);
3589
+ }
3590
+ `;
3591
+ var fs3 = glsl`
3592
+ uniform sampler2D mask_texture;
3593
+ uniform int mask_channel;
3594
+ uniform bool mask_enabled;
3595
+ uniform bool mask_inverted;
3596
+ bool mask_isInBounds(vec2 texCoords) {
3597
+ if (!mask_enabled) {
3598
+ return true;
3599
+ }
3600
+ vec4 maskColor = texture(mask_texture, texCoords);
3601
+ float maskValue = 1.0;
3602
+ if (mask_channel == 0) {
3603
+ maskValue = maskColor.r;
3604
+ } else if (mask_channel == 1) {
3605
+ maskValue = maskColor.g;
3606
+ } else if (mask_channel == 2) {
3607
+ maskValue = maskColor.b;
3608
+ } else if (mask_channel == 3) {
3609
+ maskValue = maskColor.a;
3610
+ }
3611
+
3612
+ if (mask_inverted) {
3613
+ return maskValue >= 0.5;
3614
+ } else {
3615
+ return maskValue < 0.5;
3616
+ }
3617
+ }
3618
+ `;
3619
+ var inject5 = {
3620
+ "vs:#decl": glsl`
3621
+ out vec2 mask_texCoords;
3622
+ `,
3623
+ "vs:#main-end": glsl`
3624
+ vec4 mask_common_position;
3625
+ if (mask_maskByInstance) {
3626
+ mask_common_position = project_position(vec4(geometry.worldPosition, 1.0));
3627
+ } else {
3628
+ mask_common_position = geometry.position;
3629
+ }
3630
+ mask_texCoords = mask_getCoords(mask_common_position);
3631
+ `,
3632
+ "fs:#decl": glsl`
3633
+ in vec2 mask_texCoords;
3634
+ `,
3635
+ "fs:#main-start": glsl`
3636
+ if (mask_enabled) {
3637
+ bool mask = mask_isInBounds(mask_texCoords);
3638
+
3639
+ // Debug: show extent of render target
3640
+ // fragColor = vec4(mask_texCoords, 0.0, 1.0);
3641
+ fragColor = texture(mask_texture, mask_texCoords);
3642
+
3643
+ if (!mask) discard;
3644
+ }
3645
+ `
3646
+ };
3647
+ var getMaskUniforms = (opts) => {
3648
+ if (opts && "maskMap" in opts) {
3649
+ return {
3650
+ mask_texture: opts.maskMap
3651
+ };
3652
+ }
3653
+ return {};
3654
+ };
3655
+ var shader_module_default3 = {
3656
+ name: "mask",
3657
+ dependencies: [import_core17.project],
3658
+ vs: vs4,
3659
+ fs: fs3,
3660
+ inject: inject5,
3661
+ getUniforms: getMaskUniforms
3662
+ };
3663
+
3664
+ // src/mask/mask-effect.ts
3665
+ var import_core20 = __toESM(require_core(), 1);
3666
+
3667
+ // src/mask/mask-pass.ts
3668
+ var import_core18 = __toESM(require_core(), 1);
3669
+ var MASK_BLENDING = {
3670
+ blendColorOperation: "subtract",
3671
+ blendColorSrcFactor: "zero",
3672
+ blendColorDstFactor: "one",
3673
+ blendAlphaOperation: "subtract",
3674
+ blendAlphaSrcFactor: "zero",
3675
+ blendAlphaDstFactor: "one"
3676
+ };
3677
+ var MaskPass = class extends import_core18._LayersPass {
3678
+ constructor(device, props) {
3679
+ super(device, props);
3680
+ const { mapSize = 2048 } = props;
3681
+ this.maskMap = device.createTexture({
3682
+ format: "rgba8unorm",
3683
+ width: mapSize,
3684
+ height: mapSize,
3685
+ sampler: {
3686
+ minFilter: "linear",
3687
+ magFilter: "linear",
3688
+ addressModeU: "clamp-to-edge",
3689
+ addressModeV: "clamp-to-edge"
3690
+ }
3691
+ });
3692
+ this.fbo = device.createFramebuffer({
3693
+ id: "maskmap",
3694
+ width: mapSize,
3695
+ height: mapSize,
3696
+ colorAttachments: [this.maskMap]
3697
+ });
3698
+ }
3699
+ render(options) {
3700
+ const colorMask = 2 ** options.channel;
3701
+ const clearColor = [255, 255, 255, 255];
3702
+ super.render({ ...options, clearColor, colorMask, target: this.fbo, pass: "mask" });
3703
+ }
3704
+ getLayerParameters(layer, layerIndex, viewport) {
3705
+ return {
3706
+ ...layer.props.parameters,
3707
+ blend: true,
3708
+ depthTest: false,
3709
+ ...MASK_BLENDING
3710
+ };
3711
+ }
3712
+ shouldDrawLayer(layer) {
3713
+ return layer.props.operation.includes("mask");
3714
+ }
3715
+ delete() {
3716
+ this.fbo.delete();
3717
+ this.maskMap.delete();
3718
+ }
3719
+ };
3720
+
3721
+ // src/utils/projection-utils.ts
3722
+ var import_core19 = __toESM(require_core(), 1);
3723
+ function joinLayerBounds(layers, viewport) {
3724
+ const bounds = [Infinity, Infinity, -Infinity, -Infinity];
3725
+ for (const layer of layers) {
3382
3726
  const layerBounds = layer.getBounds();
3383
3727
  if (layerBounds) {
3384
3728
  const bottomLeftCommon = layer.projectPosition(layerBounds[0], { viewport, autoOffset: false });
@@ -3424,7 +3768,7 @@ float collision_isVisible(vec2 texCoords, vec3 pickingColor) {
3424
3768
  zoom += Math.log2(r);
3425
3769
  }
3426
3770
  }
3427
- return isGeospatial ? new import_core15.WebMercatorViewport({
3771
+ return isGeospatial ? new import_core19.WebMercatorViewport({
3428
3772
  id: viewport.id,
3429
3773
  x: border,
3430
3774
  y: border,
@@ -3434,7 +3778,7 @@ float collision_isVisible(vec2 texCoords, vec3 pickingColor) {
3434
3778
  latitude: centerWorld[1],
3435
3779
  zoom,
3436
3780
  orthographic: true
3437
- }) : new import_core15.OrthographicViewport({
3781
+ }) : new import_core19.OrthographicViewport({
3438
3782
  id: viewport.id,
3439
3783
  x: border,
3440
3784
  y: border,
@@ -3503,14 +3847,23 @@ float collision_isVisible(vec2 texCoords, vec3 pickingColor) {
3503
3847
  this.channels = [];
3504
3848
  this.masks = null;
3505
3849
  }
3506
- preRender(device, { layers, layerFilter, viewports, onViewportActive, views, isPicking }) {
3850
+ setup({ device }) {
3851
+ this.dummyMaskMap = device.createTexture({
3852
+ width: 1,
3853
+ height: 1
3854
+ });
3855
+ this.maskPass = new MaskPass(device, { id: "default-mask" });
3856
+ this.maskMap = this.maskPass.maskMap;
3857
+ }
3858
+ preRender({
3859
+ layers,
3860
+ layerFilter,
3861
+ viewports,
3862
+ onViewportActive,
3863
+ views,
3864
+ isPicking
3865
+ }) {
3507
3866
  let didRender = false;
3508
- if (!this.dummyMaskMap) {
3509
- this.dummyMaskMap = device.createTexture({
3510
- width: 1,
3511
- height: 1
3512
- });
3513
- }
3514
3867
  if (isPicking) {
3515
3868
  return { didRender };
3516
3869
  }
@@ -3521,15 +3874,11 @@ float collision_isVisible(vec2 texCoords, vec3 pickingColor) {
3521
3874
  return { didRender };
3522
3875
  }
3523
3876
  this.masks = {};
3524
- if (!this.maskPass) {
3525
- this.maskPass = new MaskPass(device, { id: "default-mask" });
3526
- this.maskMap = this.maskPass.maskMap;
3527
- }
3528
3877
  const channelMap = this._sortMaskChannels(maskLayers);
3529
3878
  const viewport = viewports[0];
3530
3879
  const viewportChanged = !this.lastViewport || !this.lastViewport.equals(viewport);
3531
3880
  if (viewport.resolution !== void 0) {
3532
- import_core16.log.warn("MaskExtension is not supported in GlobeView")();
3881
+ import_core20.log.warn("MaskExtension is not supported in GlobeView")();
3533
3882
  return { didRender };
3534
3883
  }
3535
3884
  for (const maskId in channelMap) {
@@ -3607,7 +3956,7 @@ float collision_isVisible(vec2 texCoords, vec3 pickingColor) {
3607
3956
  let channelInfo = channelMap[id];
3608
3957
  if (!channelInfo) {
3609
3958
  if (++channelCount > 4) {
3610
- import_core16.log.warn("Too many mask layers. The max supported is 4")();
3959
+ import_core20.log.warn("Too many mask layers. The max supported is 4")();
3611
3960
  continue;
3612
3961
  }
3613
3962
  channelInfo = {
@@ -3660,314 +4009,6 @@ float collision_isVisible(vec2 texCoords, vec3 pickingColor) {
3660
4009
  }
3661
4010
  };
3662
4011
 
3663
- // src/collision-filter/collision-filter-effect.ts
3664
- var DOWNSCALE = 2;
3665
- var CollisionFilterEffect = class {
3666
- constructor() {
3667
- this.id = "collision-filter-effect";
3668
- this.props = null;
3669
- this.useInPicking = true;
3670
- this.order = 1;
3671
- this.channels = {};
3672
- this.collisionFBOs = {};
3673
- }
3674
- preRender(device, {
3675
- effects: allEffects,
3676
- layers,
3677
- layerFilter,
3678
- viewports,
3679
- onViewportActive,
3680
- views,
3681
- isPicking,
3682
- preRenderStats = {}
3683
- }) {
3684
- if (!this.dummyCollisionMap) {
3685
- this.dummyCollisionMap = device.createTexture({ width: 1, height: 1 });
3686
- }
3687
- if (isPicking) {
3688
- return;
3689
- }
3690
- const collisionLayers = layers.filter(
3691
- ({ props: { visible, collisionEnabled } }) => visible && collisionEnabled
3692
- );
3693
- if (collisionLayers.length === 0) {
3694
- this.channels = {};
3695
- return;
3696
- }
3697
- if (!this.collisionFilterPass) {
3698
- this.collisionFilterPass = new CollisionFilterPass(device, { id: "default-collision-filter" });
3699
- }
3700
- const effects = allEffects?.filter((e) => e.constructor === MaskEffect);
3701
- const maskEffectRendered = preRenderStats["mask-effect"]?.didRender;
3702
- const channels = this._groupByCollisionGroup(device, collisionLayers);
3703
- const viewport = viewports[0];
3704
- const viewportChanged = !this.lastViewport || !this.lastViewport.equals(viewport) || maskEffectRendered;
3705
- for (const collisionGroup in channels) {
3706
- const collisionFBO = this.collisionFBOs[collisionGroup];
3707
- const renderInfo = channels[collisionGroup];
3708
- const [width, height] = device.canvasContext.getPixelSize();
3709
- collisionFBO.resize({
3710
- width: width / DOWNSCALE,
3711
- height: height / DOWNSCALE
3712
- });
3713
- this._render(renderInfo, {
3714
- effects,
3715
- layerFilter,
3716
- onViewportActive,
3717
- views,
3718
- viewport,
3719
- viewportChanged
3720
- });
3721
- }
3722
- }
3723
- _render(renderInfo, {
3724
- effects,
3725
- layerFilter,
3726
- onViewportActive,
3727
- views,
3728
- viewport,
3729
- viewportChanged
3730
- }) {
3731
- const { collisionGroup } = renderInfo;
3732
- const oldRenderInfo = this.channels[collisionGroup];
3733
- if (!oldRenderInfo) {
3734
- return;
3735
- }
3736
- const needsRender = viewportChanged || renderInfo === oldRenderInfo || !(0, import_core19._deepEqual)(oldRenderInfo.layers, renderInfo.layers, 1) || renderInfo.layerBounds.some((b, i) => !equals(b, oldRenderInfo.layerBounds[i])) || renderInfo.allLayersLoaded !== oldRenderInfo.allLayersLoaded || renderInfo.layers.some((layer) => layer.props.transitions);
3737
- this.channels[collisionGroup] = renderInfo;
3738
- if (needsRender) {
3739
- this.lastViewport = viewport;
3740
- const collisionFBO = this.collisionFBOs[collisionGroup];
3741
- this.collisionFilterPass.renderCollisionMap(collisionFBO, {
3742
- pass: "collision-filter",
3743
- isPicking: true,
3744
- layers: renderInfo.layers,
3745
- effects,
3746
- layerFilter,
3747
- viewports: viewport ? [viewport] : [],
3748
- onViewportActive,
3749
- views,
3750
- moduleParameters: {
3751
- dummyCollisionMap: this.dummyCollisionMap,
3752
- devicePixelRatio: collisionFBO.device.canvasContext.getDevicePixelRatio() / DOWNSCALE
3753
- }
3754
- });
3755
- }
3756
- }
3757
- _groupByCollisionGroup(device, collisionLayers) {
3758
- const channelMap = {};
3759
- for (const layer of collisionLayers) {
3760
- const { collisionGroup } = layer.props;
3761
- let channelInfo = channelMap[collisionGroup];
3762
- if (!channelInfo) {
3763
- channelInfo = { collisionGroup, layers: [], layerBounds: [], allLayersLoaded: true };
3764
- channelMap[collisionGroup] = channelInfo;
3765
- }
3766
- channelInfo.layers.push(layer);
3767
- channelInfo.layerBounds.push(layer.getBounds());
3768
- if (!layer.isLoaded) {
3769
- channelInfo.allLayersLoaded = false;
3770
- }
3771
- }
3772
- for (const collisionGroup of Object.keys(channelMap)) {
3773
- if (!this.collisionFBOs[collisionGroup]) {
3774
- this.createFBO(device, collisionGroup);
3775
- }
3776
- if (!this.channels[collisionGroup]) {
3777
- this.channels[collisionGroup] = channelMap[collisionGroup];
3778
- }
3779
- }
3780
- for (const collisionGroup of Object.keys(this.collisionFBOs)) {
3781
- if (!channelMap[collisionGroup]) {
3782
- this.destroyFBO(collisionGroup);
3783
- }
3784
- }
3785
- return channelMap;
3786
- }
3787
- getModuleParameters(layer) {
3788
- const { collisionGroup } = layer.props;
3789
- const { collisionFBOs, dummyCollisionMap } = this;
3790
- return { collisionFBO: collisionFBOs[collisionGroup], dummyCollisionMap };
3791
- }
3792
- cleanup() {
3793
- if (this.dummyCollisionMap) {
3794
- this.dummyCollisionMap.delete();
3795
- this.dummyCollisionMap = void 0;
3796
- }
3797
- this.channels = {};
3798
- for (const collisionGroup of Object.keys(this.collisionFBOs)) {
3799
- this.destroyFBO(collisionGroup);
3800
- }
3801
- this.collisionFBOs = {};
3802
- this.lastViewport = void 0;
3803
- }
3804
- createFBO(device, collisionGroup) {
3805
- const { width, height } = device.gl.canvas;
3806
- const collisionMap = device.createTexture({
3807
- format: "rgba8unorm",
3808
- width,
3809
- height,
3810
- sampler: {
3811
- minFilter: "nearest",
3812
- magFilter: "nearest",
3813
- addressModeU: "clamp-to-edge",
3814
- addressModeV: "clamp-to-edge"
3815
- }
3816
- });
3817
- const depthStencilAttachment = device.createTexture({
3818
- format: "depth16unorm",
3819
- width,
3820
- height,
3821
- mipmaps: false,
3822
- dataFormat: 6402,
3823
- type: 5125
3824
- });
3825
- this.collisionFBOs[collisionGroup] = device.createFramebuffer({
3826
- id: `collision-${collisionGroup}`,
3827
- width,
3828
- height,
3829
- colorAttachments: [collisionMap],
3830
- depthStencilAttachment
3831
- });
3832
- }
3833
- destroyFBO(collisionGroup) {
3834
- const fbo = this.collisionFBOs[collisionGroup];
3835
- fbo.colorAttachments[0]?.destroy();
3836
- fbo.depthStencilAttachment?.destroy();
3837
- fbo.destroy();
3838
- delete this.collisionFBOs[collisionGroup];
3839
- }
3840
- };
3841
-
3842
- // src/collision-filter/collision-filter-extension.ts
3843
- var defaultProps6 = {
3844
- getCollisionPriority: { type: "accessor", value: 0 },
3845
- collisionEnabled: true,
3846
- collisionGroup: { type: "string", value: "default" },
3847
- collisionTestProps: {}
3848
- };
3849
- var CollisionFilterExtension = class extends import_core20.LayerExtension {
3850
- getShaders() {
3851
- return { modules: [shader_module_default2] };
3852
- }
3853
- draw({ uniforms, context, moduleParameters }) {
3854
- const { collisionEnabled } = this.props;
3855
- const { collisionFBO, drawToCollisionMap } = moduleParameters;
3856
- const enabled = collisionEnabled && Boolean(collisionFBO);
3857
- uniforms.collision_enabled = enabled;
3858
- if (drawToCollisionMap) {
3859
- this.props = this.clone(this.props.collisionTestProps).props;
3860
- }
3861
- }
3862
- initializeState(context, extension) {
3863
- if (this.getAttributeManager() === null) {
3864
- return;
3865
- }
3866
- this.context.deck?._addDefaultEffect(new CollisionFilterEffect());
3867
- const attributeManager = this.getAttributeManager();
3868
- attributeManager.add({
3869
- collisionPriorities: {
3870
- size: 1,
3871
- accessor: "getCollisionPriority",
3872
- shaderAttributes: {
3873
- collisionPriorities: { divisor: 0 },
3874
- instanceCollisionPriorities: { divisor: 1 }
3875
- }
3876
- }
3877
- });
3878
- }
3879
- getNeedsPickingBuffer() {
3880
- return this.props.collisionEnabled;
3881
- }
3882
- };
3883
- CollisionFilterExtension.defaultProps = defaultProps6;
3884
- CollisionFilterExtension.extensionName = "CollisionFilterExtension";
3885
-
3886
- // src/mask/mask-extension.ts
3887
- var import_core22 = __toESM(require_core(), 1);
3888
-
3889
- // src/mask/shader-module.ts
3890
- var import_core21 = __toESM(require_core(), 1);
3891
- var vs4 = glsl`
3892
- uniform vec4 mask_bounds;
3893
- uniform bool mask_maskByInstance;
3894
- vec2 mask_getCoords(vec4 position) {
3895
- return (position.xy - mask_bounds.xy) / (mask_bounds.zw - mask_bounds.xy);
3896
- }
3897
- `;
3898
- var fs3 = glsl`
3899
- uniform sampler2D mask_texture;
3900
- uniform int mask_channel;
3901
- uniform bool mask_enabled;
3902
- uniform bool mask_inverted;
3903
- bool mask_isInBounds(vec2 texCoords) {
3904
- if (!mask_enabled) {
3905
- return true;
3906
- }
3907
- vec4 maskColor = texture(mask_texture, texCoords);
3908
- float maskValue = 1.0;
3909
- if (mask_channel == 0) {
3910
- maskValue = maskColor.r;
3911
- } else if (mask_channel == 1) {
3912
- maskValue = maskColor.g;
3913
- } else if (mask_channel == 2) {
3914
- maskValue = maskColor.b;
3915
- } else if (mask_channel == 3) {
3916
- maskValue = maskColor.a;
3917
- }
3918
-
3919
- if (mask_inverted) {
3920
- return maskValue >= 0.5;
3921
- } else {
3922
- return maskValue < 0.5;
3923
- }
3924
- }
3925
- `;
3926
- var inject5 = {
3927
- "vs:#decl": glsl`
3928
- out vec2 mask_texCoords;
3929
- `,
3930
- "vs:#main-end": glsl`
3931
- vec4 mask_common_position;
3932
- if (mask_maskByInstance) {
3933
- mask_common_position = project_position(vec4(geometry.worldPosition, 1.0));
3934
- } else {
3935
- mask_common_position = geometry.position;
3936
- }
3937
- mask_texCoords = mask_getCoords(mask_common_position);
3938
- `,
3939
- "fs:#decl": glsl`
3940
- in vec2 mask_texCoords;
3941
- `,
3942
- "fs:#main-start": glsl`
3943
- if (mask_enabled) {
3944
- bool mask = mask_isInBounds(mask_texCoords);
3945
-
3946
- // Debug: show extent of render target
3947
- // fragColor = vec4(mask_texCoords, 0.0, 1.0);
3948
- fragColor = texture(mask_texture, mask_texCoords);
3949
-
3950
- if (!mask) discard;
3951
- }
3952
- `
3953
- };
3954
- var getMaskUniforms = (opts) => {
3955
- if (opts && "maskMap" in opts) {
3956
- return {
3957
- mask_texture: opts.maskMap
3958
- };
3959
- }
3960
- return {};
3961
- };
3962
- var shader_module_default3 = {
3963
- name: "mask",
3964
- dependencies: [import_core21.project],
3965
- vs: vs4,
3966
- fs: fs3,
3967
- inject: inject5,
3968
- getUniforms: getMaskUniforms
3969
- };
3970
-
3971
4012
  // src/mask/mask-extension.ts
3972
4013
  var defaultProps7 = {
3973
4014
  maskId: "",
@@ -4152,16 +4193,18 @@ if ((terrain_mode == TERRAIN_MODE_USE_COVER) || (terrain_mode == TERRAIN_MODE_US
4152
4193
  id: opts.id,
4153
4194
  colorAttachments: [
4154
4195
  device.createTexture({
4196
+ id: opts.id,
4155
4197
  ...opts.float && {
4156
4198
  format: "rgba32float",
4157
4199
  type: GLEnum.FLOAT
4158
4200
  },
4159
4201
  mipmaps: false,
4160
- sampler: {
4202
+ sampler: opts.interpolate === false ? {
4203
+ minFilter: "nearest",
4204
+ magFilter: "nearest"
4205
+ } : {
4161
4206
  minFilter: "linear",
4162
- magFilter: "linear",
4163
- addressModeU: "clamp-to-edge",
4164
- addressModeV: "clamp-to-edge"
4207
+ magFilter: "linear"
4165
4208
  }
4166
4209
  })
4167
4210
  ]
@@ -4285,7 +4328,8 @@ if ((terrain_mode == TERRAIN_MODE_USE_COVER) || (terrain_mode == TERRAIN_MODE_US
4285
4328
  }
4286
4329
  if (!this.pickingFbo) {
4287
4330
  this.pickingFbo = createRenderTarget(this.targetLayer.context.device, {
4288
- id: `${this.id}-picking`
4331
+ id: `${this.id}-picking`,
4332
+ interpolate: false
4289
4333
  });
4290
4334
  }
4291
4335
  return this.pickingFbo;
@@ -4333,6 +4377,14 @@ if ((terrain_mode == TERRAIN_MODE_USE_COVER) || (terrain_mode == TERRAIN_MODE_US
4333
4377
 
4334
4378
  // src/terrain/terrain-pass.ts
4335
4379
  var import_core24 = __toESM(require_core(), 1);
4380
+ var TERRAIN_BLENDING = {
4381
+ blendColorOperation: "max",
4382
+ blendColorSrcFactor: "one",
4383
+ blendColorDstFactor: "one",
4384
+ blendAlphaOperation: "max",
4385
+ blendAlphaSrcFactor: "one",
4386
+ blendAlphaDstFactor: "one"
4387
+ };
4336
4388
  var TerrainPass = class extends import_core24._LayersPass {
4337
4389
  getRenderableLayers(viewport, opts) {
4338
4390
  const { layers } = opts;
@@ -4353,23 +4405,15 @@ if ((terrain_mode == TERRAIN_MODE_USE_COVER) || (terrain_mode == TERRAIN_MODE_US
4353
4405
  return;
4354
4406
  }
4355
4407
  target.resize(viewport);
4356
- this.device.withParametersWebGL(
4357
- {
4358
- clearColor: [0, 0, 0, 0],
4359
- blend: true,
4360
- blendFunc: [GLEnum.ONE, GLEnum.ONE],
4361
- blendEquation: GLEnum.MAX,
4362
- depthTest: false
4363
- },
4364
- () => this.render({
4365
- ...opts,
4366
- target,
4367
- pass: "terrain-height-map",
4368
- layers: opts.layers,
4369
- viewports: [viewport],
4370
- effects: []
4371
- })
4372
- );
4408
+ this.render({
4409
+ ...opts,
4410
+ target,
4411
+ pass: "terrain-height-map",
4412
+ layers: opts.layers,
4413
+ viewports: [viewport],
4414
+ effects: [],
4415
+ clearColor: [0, 0, 0, 0]
4416
+ });
4373
4417
  }
4374
4418
  renderTerrainCover(terrainCover, opts) {
4375
4419
  const target = terrainCover.getRenderFramebuffer();
@@ -4379,20 +4423,23 @@ if ((terrain_mode == TERRAIN_MODE_USE_COVER) || (terrain_mode == TERRAIN_MODE_US
4379
4423
  }
4380
4424
  const layers = terrainCover.filterLayers(opts.layers);
4381
4425
  target.resize(viewport);
4382
- this.device.withParametersWebGL(
4383
- {
4384
- clearColor: [0, 0, 0, 0],
4385
- depthTest: false
4386
- },
4387
- () => this.render({
4388
- ...opts,
4389
- target,
4390
- pass: `terrain-cover-${terrainCover.id}`,
4391
- layers,
4392
- effects: [],
4393
- viewports: [viewport]
4394
- })
4395
- );
4426
+ this.render({
4427
+ ...opts,
4428
+ target,
4429
+ pass: `terrain-cover-${terrainCover.id}`,
4430
+ layers,
4431
+ effects: [],
4432
+ viewports: [viewport],
4433
+ clearColor: [0, 0, 0, 0]
4434
+ });
4435
+ }
4436
+ getLayerParameters(layer, layerIndex, viewport) {
4437
+ return {
4438
+ ...layer.props.parameters,
4439
+ blend: true,
4440
+ depthTest: false,
4441
+ ...layer.props.operation.includes("terrain") && TERRAIN_BLENDING
4442
+ };
4396
4443
  }
4397
4444
  };
4398
4445
 
@@ -4430,30 +4477,27 @@ if ((terrain_mode == TERRAIN_MODE_USE_COVER) || (terrain_mode == TERRAIN_MODE_US
4430
4477
  layers.unshift(terrainLayer);
4431
4478
  }
4432
4479
  target.resize(viewport);
4433
- this.device.withParametersWebGL(
4434
- {
4435
- depthTest: false
4436
- },
4437
- () => this.render({
4438
- ...opts,
4439
- pickingFBO: target,
4440
- pass: `terrain-cover-picking-${terrainCover.id}`,
4441
- layers,
4442
- effects: [],
4443
- viewports: [viewport],
4444
- cullRect: void 0,
4445
- deviceRect: viewport,
4446
- pickZ: false
4447
- })
4448
- );
4480
+ this.render({
4481
+ ...opts,
4482
+ pickingFBO: target,
4483
+ pass: `terrain-cover-picking-${terrainCover.id}`,
4484
+ layers,
4485
+ effects: [],
4486
+ viewports: [viewport],
4487
+ cullRect: void 0,
4488
+ deviceRect: viewport,
4489
+ pickZ: false
4490
+ });
4449
4491
  }
4450
4492
  getLayerParameters(layer, layerIndex, viewport) {
4493
+ let parameters2;
4451
4494
  if (this.drawParameters[layer.id]) {
4452
- return this.drawParameters[layer.id];
4495
+ parameters2 = this.drawParameters[layer.id];
4496
+ } else {
4497
+ parameters2 = super.getLayerParameters(layer, layerIndex, viewport);
4498
+ parameters2.blend = true;
4453
4499
  }
4454
- const parameters2 = super.getLayerParameters(layer, layerIndex, viewport);
4455
- parameters2.blend = true;
4456
- return parameters2;
4500
+ return { ...parameters2, depthTest: false };
4457
4501
  }
4458
4502
  };
4459
4503
 
@@ -4538,7 +4582,7 @@ if ((terrain_mode == TERRAIN_MODE_USE_COVER) || (terrain_mode == TERRAIN_MODE_US
4538
4582
  this.isDrapingEnabled = false;
4539
4583
  this.terrainCovers = /* @__PURE__ */ new Map();
4540
4584
  }
4541
- initialize(device) {
4585
+ setup({ device, deck }) {
4542
4586
  this.dummyHeightMap = device.createTexture({
4543
4587
  width: 1,
4544
4588
  height: 1,
@@ -4551,17 +4595,9 @@ if ((terrain_mode == TERRAIN_MODE_USE_COVER) || (terrain_mode == TERRAIN_MODE_US
4551
4595
  } else {
4552
4596
  import_core26.log.warn("Terrain offset mode is not supported by this browser")();
4553
4597
  }
4554
- (0, import_core26.getShaderAssembler)().addDefaultModule(terrainModule);
4555
- }
4556
- preRender(device, opts) {
4557
- if (!this.dummyHeightMap) {
4558
- this.initialize(device);
4559
- for (const layer of opts.layers) {
4560
- if (layer.props.operation.includes("terrain")) {
4561
- layer.setChangeFlags({ extensionsChanged: true });
4562
- }
4563
- }
4564
- }
4598
+ deck._addDefaultShaderModule(terrainModule);
4599
+ }
4600
+ preRender(opts) {
4565
4601
  if (opts.pickZ) {
4566
4602
  this.isDrapingEnabled = false;
4567
4603
  return;
@@ -4599,7 +4635,7 @@ if ((terrain_mode == TERRAIN_MODE_USE_COVER) || (terrain_mode == TERRAIN_MODE_US
4599
4635
  terrainSkipRender: terrainDrawMode === "drape" || !layer.props.operation.includes("draw")
4600
4636
  };
4601
4637
  }
4602
- cleanup() {
4638
+ cleanup({ deck }) {
4603
4639
  if (this.dummyHeightMap) {
4604
4640
  this.dummyHeightMap.delete();
4605
4641
  this.dummyHeightMap = void 0;
@@ -4612,7 +4648,7 @@ if ((terrain_mode == TERRAIN_MODE_USE_COVER) || (terrain_mode == TERRAIN_MODE_US
4612
4648
  terrainCover.delete();
4613
4649
  }
4614
4650
  this.terrainCovers.clear();
4615
- (0, import_core26.getShaderAssembler)().removeDefaultModule(terrainModule);
4651
+ deck._removeDefaultShaderModule(terrainModule);
4616
4652
  }
4617
4653
  _updateHeightMap(terrainLayers, viewport, opts) {
4618
4654
  if (!this.heightMap) {