@deck.gl/extensions 9.3.6 → 9.4.0-alpha.1

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.
package/dist/dist.dev.js CHANGED
@@ -4113,6 +4113,20 @@ in vec2 mask_texCoords;
4113
4113
 
4114
4114
  // src/utils/projection-utils.ts
4115
4115
  var import_core19 = __toESM(require_core(), 1);
4116
+ var MERCATOR_REFERENCE_VIEWPORT = new import_core19.WebMercatorViewport({
4117
+ width: 1,
4118
+ height: 1,
4119
+ longitude: 0,
4120
+ latitude: 0,
4121
+ zoom: 0
4122
+ });
4123
+ function lngLatToMercatorCommon(lngLat) {
4124
+ const [x, y] = MERCATOR_REFERENCE_VIEWPORT.projectPosition(lngLat);
4125
+ return [x, y];
4126
+ }
4127
+ function getMercatorReferenceViewport(viewport) {
4128
+ return viewport.isGeospatial ? MERCATOR_REFERENCE_VIEWPORT : viewport;
4129
+ }
4116
4130
  function joinLayerBounds(layers, viewport) {
4117
4131
  const bounds = [Infinity, Infinity, -Infinity, -Infinity];
4118
4132
  for (const layer of layers) {
@@ -4138,11 +4152,11 @@ in vec2 mask_texCoords;
4138
4152
  if (bounds[2] <= bounds[0] || bounds[3] <= bounds[1]) {
4139
4153
  return null;
4140
4154
  }
4141
- const centerWorld = viewport.unprojectPosition([
4155
+ const centerWorld = isGeospatial ? MERCATOR_REFERENCE_VIEWPORT.unprojectPosition([
4142
4156
  (bounds[0] + bounds[2]) / 2,
4143
4157
  (bounds[1] + bounds[3]) / 2,
4144
4158
  0
4145
- ]);
4159
+ ]) : viewport.unprojectPosition([(bounds[0] + bounds[2]) / 2, (bounds[1] + bounds[3]) / 2, 0]);
4146
4160
  let { width, height, zoom } = opts;
4147
4161
  if (zoom === void 0) {
4148
4162
  width = width - border * 2;
@@ -4483,10 +4497,10 @@ in vec2 mask_texCoords;
4483
4497
  MaskExtension.extensionName = "MaskExtension";
4484
4498
 
4485
4499
  // src/terrain/terrain-extension.ts
4486
- var import_core27 = __toESM(require_core(), 1);
4500
+ var import_core29 = __toESM(require_core(), 1);
4487
4501
 
4488
4502
  // src/terrain/terrain-effect.ts
4489
- var import_core26 = __toESM(require_core(), 1);
4503
+ var import_core28 = __toESM(require_core(), 1);
4490
4504
 
4491
4505
  // src/terrain/shader-module.ts
4492
4506
  var import_core23 = __toESM(require_core(), 1);
@@ -4519,12 +4533,22 @@ uniform sampler2D terrain_map;
4519
4533
  var terrainModule = {
4520
4534
  name: "terrain",
4521
4535
  dependencies: [import_core23.project],
4522
- // eslint-disable-next-line prefer-template
4523
- vs: uniformBlock5 + /* glsl */
4524
- "out vec3 commonPos;",
4525
- // eslint-disable-next-line prefer-template
4526
- fs: uniformBlock5 + /* glsl */
4527
- "in vec3 commonPos;",
4536
+ vs: `${uniformBlock5}
4537
+ out vec3 commonPos;
4538
+ // In globe mode, absolute Mercator position for terrain FBO UV lookups
4539
+ out vec2 terrainMercPos;
4540
+ out float terrainHeight;
4541
+
4542
+ vec2 terrain_globe_to_mercator(vec3 globePosition) {
4543
+ float D = length(globePosition);
4544
+ float sinLat = clamp(globePosition.z / D, -0.999998, 0.999998);
4545
+ float x = atan(globePosition.x, -globePosition.y);
4546
+ float y = atanh(sinLat);
4547
+ return (vec2(x, y) + PI) * WORLD_SCALE;
4548
+ }
4549
+ `,
4550
+ fs: `${uniformBlock5}in vec2 terrainMercPos;
4551
+ in float terrainHeight;`,
4528
4552
  inject: {
4529
4553
  "vs:#main-start": (
4530
4554
  /* glsl */
@@ -4539,19 +4563,35 @@ if (terrain.mode == TERRAIN_MODE_SKIP) {
4539
4563
  /* glsl */
4540
4564
  `
4541
4565
  commonPos = geometry.position.xyz;
4566
+ terrainHeight = commonPos.z + project.commonOrigin.z;
4567
+ if (project.projectionMode == PROJECTION_MODE_GLOBE) {
4568
+ terrainMercPos = terrain_globe_to_mercator(commonPos);
4569
+ terrainHeight = length(commonPos) - GLOBE_RADIUS;
4570
+ } else {
4571
+ terrainMercPos = commonPos.xy;
4572
+ }
4542
4573
  if (terrain.mode == TERRAIN_MODE_WRITE_HEIGHT_MAP) {
4543
- vec2 texCoords = (commonPos.xy - terrain.bounds.xy) / terrain.bounds.zw;
4574
+ vec2 texCoords = (terrainMercPos - terrain.bounds.xy) / terrain.bounds.zw;
4544
4575
  position = vec4(texCoords * 2.0 - 1.0, 0.0, 1.0);
4545
- commonPos.z += project.commonOrigin.z;
4546
4576
  }
4547
4577
  if (terrain.mode == TERRAIN_MODE_USE_HEIGHT_MAP) {
4548
4578
  vec3 anchor = geometry.worldPosition;
4549
4579
  anchor.z = 0.0;
4550
4580
  vec3 anchorCommon = project_position(anchor);
4551
- vec2 texCoords = (anchorCommon.xy - terrain.bounds.xy) / terrain.bounds.zw;
4581
+ vec2 anchorMercPos = project.projectionMode == PROJECTION_MODE_GLOBE
4582
+ ? terrain_globe_to_mercator(anchorCommon)
4583
+ : anchorCommon.xy;
4584
+ vec2 texCoords = (anchorMercPos - terrain.bounds.xy) / terrain.bounds.zw;
4552
4585
  if (texCoords.x >= 0.0 && texCoords.y >= 0.0 && texCoords.x <= 1.0 && texCoords.y <= 1.0) {
4553
4586
  float terrainZ = texture(terrain_map, texCoords).r;
4554
- geometry.position.z += terrainZ;
4587
+ if (project.projectionMode == PROJECTION_MODE_GLOBE) {
4588
+ // Height map is written in Mercator common space (units = TILE_SIZE / EARTH_CIRCUMFERENCE / cos(lat))
4589
+ // Convert to globe radial units (units = GLOBE_RADIUS / EARTH_RADIUS)
4590
+ terrainZ *= cos(radians(geometry.worldPosition.y)) * PI;
4591
+ geometry.position.xyz += normalize(geometry.position.xyz) * terrainZ;
4592
+ } else {
4593
+ geometry.position.z += terrainZ;
4594
+ }
4555
4595
  position = project_common_position_to_clipspace(geometry.position);
4556
4596
  }
4557
4597
  }
@@ -4561,7 +4601,7 @@ if (terrain.mode == TERRAIN_MODE_USE_HEIGHT_MAP) {
4561
4601
  /* glsl */
4562
4602
  `
4563
4603
  if (terrain.mode == TERRAIN_MODE_WRITE_HEIGHT_MAP) {
4564
- fragColor = vec4(commonPos.z, 0.0, 0.0, 1.0);
4604
+ fragColor = vec4(terrainHeight, 0.0, 0.0, 1.0);
4565
4605
  return;
4566
4606
  }
4567
4607
  `
@@ -4570,7 +4610,7 @@ if (terrain.mode == TERRAIN_MODE_WRITE_HEIGHT_MAP) {
4570
4610
  /* glsl */
4571
4611
  `
4572
4612
  if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_USE_COVER_ONLY)) {
4573
- vec2 texCoords = (commonPos.xy - terrain.bounds.xy) / terrain.bounds.zw;
4613
+ vec2 texCoords = (terrainMercPos - terrain.bounds.xy) / terrain.bounds.zw;
4574
4614
  vec4 pixel = texture(terrain_map, texCoords);
4575
4615
  if (terrain.mode == TERRAIN_MODE_USE_COVER_ONLY) {
4576
4616
  color = pixel;
@@ -4627,7 +4667,7 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US
4627
4667
  return {
4628
4668
  mode,
4629
4669
  terrain_map: sampler,
4630
- // Convert bounds to the common space, as [minX, minY, width, height]
4670
+ // Convert bounds to common space, as [minX, minY, width, height]
4631
4671
  bounds: bounds ? [
4632
4672
  bounds[0] - commonOrigin[0],
4633
4673
  bounds[1] - commonOrigin[1],
@@ -4648,6 +4688,9 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US
4648
4688
  }
4649
4689
  };
4650
4690
 
4691
+ // src/terrain/terrain-cover.ts
4692
+ var import_core24 = __toESM(require_core(), 1);
4693
+
4651
4694
  // ../../node_modules/@luma.gl/webgl/dist/constants/webgl-constants.js
4652
4695
  var GLEnum;
4653
4696
  (function(GLEnum2) {
@@ -5398,8 +5441,8 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US
5398
5441
  if (!this.targetBounds) {
5399
5442
  shouldRedraw = true;
5400
5443
  this.targetBounds = this.tile.boundingBox;
5401
- const bottomLeftCommon = viewport.projectPosition(this.targetBounds[0]);
5402
- const topRightCommon = viewport.projectPosition(this.targetBounds[1]);
5444
+ const bottomLeftCommon = lngLatToMercatorCommon(this.targetBounds[0]);
5445
+ const topRightCommon = lngLatToMercatorCommon(this.targetBounds[1]);
5403
5446
  this.targetBoundsCommon = [
5404
5447
  bottomLeftCommon[0],
5405
5448
  bottomLeftCommon[1],
@@ -5410,7 +5453,10 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US
5410
5453
  } else if (this.targetBounds !== targetLayer.getBounds()) {
5411
5454
  shouldRedraw = true;
5412
5455
  this.targetBounds = targetLayer.getBounds();
5413
- this.targetBoundsCommon = joinLayerBounds([targetLayer], viewport);
5456
+ this.targetBoundsCommon = joinLayerBounds(
5457
+ [targetLayer],
5458
+ getMercatorReferenceViewport(viewport)
5459
+ );
5414
5460
  }
5415
5461
  if (!this.targetBoundsCommon) {
5416
5462
  return false;
@@ -5421,7 +5467,7 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US
5421
5467
  } else {
5422
5468
  const oldZoom = this.renderViewport?.zoom;
5423
5469
  shouldRedraw = shouldRedraw || newZoom !== oldZoom;
5424
- const newBounds = getRenderBounds(this.targetBoundsCommon, viewport);
5470
+ const newBounds = viewport instanceof import_core24._GlobeViewport ? this.targetBoundsCommon : getRenderBounds(this.targetBoundsCommon, viewport);
5425
5471
  const oldBounds = this.bounds;
5426
5472
  shouldRedraw = shouldRedraw || !oldBounds || newBounds.some((x, i) => x !== oldBounds[i]);
5427
5473
  this.bounds = newBounds;
@@ -5498,7 +5544,7 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US
5498
5544
  }
5499
5545
 
5500
5546
  // src/terrain/terrain-pass.ts
5501
- var import_core24 = __toESM(require_core(), 1);
5547
+ var import_core25 = __toESM(require_core(), 1);
5502
5548
  var TERRAIN_BLENDING = {
5503
5549
  blendColorOperation: "max",
5504
5550
  blendColorSrcFactor: "one",
@@ -5507,7 +5553,7 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US
5507
5553
  blendAlphaSrcFactor: "one",
5508
5554
  blendAlphaDstFactor: "one"
5509
5555
  };
5510
- var TerrainPass = class extends import_core24._LayersPass {
5556
+ var TerrainPass = class extends import_core25._LayersPass {
5511
5557
  getRenderableLayers(viewport, opts) {
5512
5558
  const { layers } = opts;
5513
5559
  const result = [];
@@ -5572,8 +5618,8 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US
5572
5618
  };
5573
5619
 
5574
5620
  // src/terrain/terrain-picking-pass.ts
5575
- var import_core25 = __toESM(require_core(), 1);
5576
- var TerrainPickingPass = class extends import_core25._PickLayersPass {
5621
+ var import_core26 = __toESM(require_core(), 1);
5622
+ var TerrainPickingPass = class extends import_core26._PickLayersPass {
5577
5623
  constructor() {
5578
5624
  super(...arguments);
5579
5625
  /** Save layer index for use when drawing to terrain cover.
@@ -5649,6 +5695,7 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US
5649
5695
  };
5650
5696
 
5651
5697
  // src/terrain/height-map-builder.ts
5698
+ var import_core27 = __toESM(require_core(), 1);
5652
5699
  var MAP_MAX_SIZE = 2048;
5653
5700
  var HeightMapBuilder = class {
5654
5701
  constructor(device) {
@@ -5696,13 +5743,13 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US
5696
5743
  if (layersChanged) {
5697
5744
  this.layers = layers;
5698
5745
  this.layersBounds = layers.map((layer) => layer.getBounds());
5699
- this.layersBoundsCommon = joinLayerBounds(layers, viewport);
5746
+ this.layersBoundsCommon = joinLayerBounds(layers, getMercatorReferenceViewport(viewport));
5700
5747
  }
5701
5748
  const viewportChanged = !this.lastViewport || !viewport.equals(this.lastViewport);
5702
5749
  if (!this.layersBoundsCommon) {
5703
5750
  this.renderViewport = null;
5704
5751
  } else if (layersChanged || viewportChanged) {
5705
- const bounds = getRenderBounds(this.layersBoundsCommon, viewport);
5752
+ const bounds = viewport instanceof import_core27._GlobeViewport ? this.layersBoundsCommon : getRenderBounds(this.layersBoundsCommon, viewport);
5706
5753
  if (bounds[2] <= bounds[0] || bounds[3] <= bounds[1]) {
5707
5754
  this.renderViewport = null;
5708
5755
  return false;
@@ -5712,17 +5759,16 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US
5712
5759
  const scale2 = viewport.scale;
5713
5760
  const pixelWidth = (bounds[2] - bounds[0]) * scale2;
5714
5761
  const pixelHeight = (bounds[3] - bounds[1]) * scale2;
5762
+ const centerMerc = viewport.isGeospatial ? lngLatToMercatorCommon([
5763
+ viewport.longitude ?? 0,
5764
+ viewport.latitude ?? 0
5765
+ ]) : [viewport.center[0], viewport.center[1]];
5715
5766
  this.renderViewport = pixelWidth > 0 || pixelHeight > 0 ? makeViewport({
5716
5767
  // It's not important whether the geometry is visible in this viewport, because
5717
5768
  // vertices will not use the standard project_to_clipspace in the DRAW_TO_HEIGHT_MAP shader
5718
5769
  // However the viewport must have the same center and zoom as the screen viewport
5719
5770
  // So that projection uniforms used for calculating z are the same
5720
- bounds: [
5721
- viewport.center[0] - 1,
5722
- viewport.center[1] - 1,
5723
- viewport.center[0] + 1,
5724
- viewport.center[1] + 1
5725
- ],
5771
+ bounds: [centerMerc[0] - 1, centerMerc[1] - 1, centerMerc[0] + 1, centerMerc[1] + 1],
5726
5772
  zoom: viewport.zoom,
5727
5773
  width: Math.min(pixelWidth, MAP_MAX_SIZE),
5728
5774
  height: Math.min(pixelHeight, MAP_MAX_SIZE),
@@ -5764,7 +5810,7 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US
5764
5810
  if (HeightMapBuilder.isSupported(device)) {
5765
5811
  this.heightMap = new HeightMapBuilder(device);
5766
5812
  } else {
5767
- import_core26.log.warn("Terrain offset mode is not supported by this browser")();
5813
+ import_core28.log.warn("Terrain offset mode is not supported by this browser")();
5768
5814
  }
5769
5815
  deck._addDefaultShaderModule(terrainModule);
5770
5816
  }
@@ -5933,7 +5979,7 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US
5933
5979
  var defaultProps8 = {
5934
5980
  terrainDrawMode: void 0
5935
5981
  };
5936
- var TerrainExtension = class extends import_core27.LayerExtension {
5982
+ var TerrainExtension = class extends import_core29.LayerExtension {
5937
5983
  getShaders() {
5938
5984
  return {
5939
5985
  modules: [terrainModule]
@@ -35,7 +35,7 @@ export declare const patternShaders: {
35
35
  readonly name: "geometry";
36
36
  readonly source: "const SMOOTH_EDGE_RADIUS: f32 = 0.5;\n\nstruct VertexGeometry {\n position: vec4<f32>,\n worldPosition: vec3<f32>,\n worldPositionAlt: vec3<f32>,\n normal: vec3<f32>,\n uv: vec2<f32>,\n pickingColor: vec3<f32>,\n};\n\nvar<private> geometry_: VertexGeometry = VertexGeometry(\n vec4<f32>(0.0, 0.0, 1.0, 0.0),\n vec3<f32>(0.0, 0.0, 0.0),\n vec3<f32>(0.0, 0.0, 0.0),\n vec3<f32>(0.0, 0.0, 0.0),\n vec2<f32>(0.0, 0.0),\n vec3<f32>(0.0, 0.0, 0.0)\n);\n\nstruct FragmentGeometry {\n uv: vec2<f32>,\n};\n\nvar<private> fragmentGeometry: FragmentGeometry;\n\nfn smoothedge(edge: f32, x: f32) -> f32 {\n return smoothstep(edge - SMOOTH_EDGE_RADIUS, edge + SMOOTH_EDGE_RADIUS, x);\n}\n";
37
37
  readonly vs: "#define SMOOTH_EDGE_RADIUS 0.5\n\nstruct VertexGeometry {\n vec4 position;\n vec3 worldPosition;\n vec3 worldPositionAlt;\n vec3 normal;\n vec2 uv;\n vec3 pickingColor;\n} geometry = VertexGeometry(\n vec4(0.0, 0.0, 1.0, 0.0),\n vec3(0.0),\n vec3(0.0),\n vec3(0.0),\n vec2(0.0),\n vec3(0.0)\n);\n";
38
- readonly fs: "#define SMOOTH_EDGE_RADIUS 0.5\n\nstruct FragmentGeometry {\n vec2 uv;\n} geometry;\n\nfloat smoothedge(float edge, float x) {\n return smoothstep(edge - SMOOTH_EDGE_RADIUS, edge + SMOOTH_EDGE_RADIUS, x);\n}\n";
38
+ readonly fs: "#define SMOOTH_EDGE_RADIUS 0.5\n\nstruct FragmentGeometry {\n vec2 uv;\n};\nFragmentGeometry geometry;\n\nfloat smoothedge(float edge, float x) {\n return smoothstep(edge - SMOOTH_EDGE_RADIUS, edge + SMOOTH_EDGE_RADIUS, x);\n}\n";
39
39
  }];
40
40
  readonly source: string;
41
41
  readonly vs: string;
package/dist/index.cjs CHANGED
@@ -2354,6 +2354,20 @@ var MaskPass = class extends import_core17._LayersPass {
2354
2354
 
2355
2355
  // dist/utils/projection-utils.js
2356
2356
  var import_core18 = require("@deck.gl/core");
2357
+ var MERCATOR_REFERENCE_VIEWPORT = new import_core18.WebMercatorViewport({
2358
+ width: 1,
2359
+ height: 1,
2360
+ longitude: 0,
2361
+ latitude: 0,
2362
+ zoom: 0
2363
+ });
2364
+ function lngLatToMercatorCommon(lngLat) {
2365
+ const [x, y] = MERCATOR_REFERENCE_VIEWPORT.projectPosition(lngLat);
2366
+ return [x, y];
2367
+ }
2368
+ function getMercatorReferenceViewport(viewport) {
2369
+ return viewport.isGeospatial ? MERCATOR_REFERENCE_VIEWPORT : viewport;
2370
+ }
2357
2371
  function joinLayerBounds(layers, viewport) {
2358
2372
  const bounds = [Infinity, Infinity, -Infinity, -Infinity];
2359
2373
  for (const layer of layers) {
@@ -2379,11 +2393,11 @@ function makeViewport(opts) {
2379
2393
  if (bounds[2] <= bounds[0] || bounds[3] <= bounds[1]) {
2380
2394
  return null;
2381
2395
  }
2382
- const centerWorld = viewport.unprojectPosition([
2396
+ const centerWorld = isGeospatial ? MERCATOR_REFERENCE_VIEWPORT.unprojectPosition([
2383
2397
  (bounds[0] + bounds[2]) / 2,
2384
2398
  (bounds[1] + bounds[3]) / 2,
2385
2399
  0
2386
- ]);
2400
+ ]) : viewport.unprojectPosition([(bounds[0] + bounds[2]) / 2, (bounds[1] + bounds[3]) / 2, 0]);
2387
2401
  let { width, height, zoom } = opts;
2388
2402
  if (zoom === void 0) {
2389
2403
  width = width - border * 2;
@@ -2709,10 +2723,10 @@ MaskExtension.extensionName = "MaskExtension";
2709
2723
  var mask_extension_default = MaskExtension;
2710
2724
 
2711
2725
  // dist/terrain/terrain-extension.js
2712
- var import_core26 = require("@deck.gl/core");
2726
+ var import_core28 = require("@deck.gl/core");
2713
2727
 
2714
2728
  // dist/terrain/terrain-effect.js
2715
- var import_core25 = require("@deck.gl/core");
2729
+ var import_core27 = require("@deck.gl/core");
2716
2730
 
2717
2731
  // dist/terrain/shader-module.js
2718
2732
  var import_core22 = require("@deck.gl/core");
@@ -2745,12 +2759,22 @@ uniform sampler2D terrain_map;
2745
2759
  var terrainModule = {
2746
2760
  name: "terrain",
2747
2761
  dependencies: [import_core22.project],
2748
- // eslint-disable-next-line prefer-template
2749
- vs: uniformBlock5 + /* glsl */
2750
- "out vec3 commonPos;",
2751
- // eslint-disable-next-line prefer-template
2752
- fs: uniformBlock5 + /* glsl */
2753
- "in vec3 commonPos;",
2762
+ vs: `${uniformBlock5}
2763
+ out vec3 commonPos;
2764
+ // In globe mode, absolute Mercator position for terrain FBO UV lookups
2765
+ out vec2 terrainMercPos;
2766
+ out float terrainHeight;
2767
+
2768
+ vec2 terrain_globe_to_mercator(vec3 globePosition) {
2769
+ float D = length(globePosition);
2770
+ float sinLat = clamp(globePosition.z / D, -0.999998, 0.999998);
2771
+ float x = atan(globePosition.x, -globePosition.y);
2772
+ float y = atanh(sinLat);
2773
+ return (vec2(x, y) + PI) * WORLD_SCALE;
2774
+ }
2775
+ `,
2776
+ fs: `${uniformBlock5}in vec2 terrainMercPos;
2777
+ in float terrainHeight;`,
2754
2778
  inject: {
2755
2779
  "vs:#main-start": (
2756
2780
  /* glsl */
@@ -2765,19 +2789,35 @@ if (terrain.mode == TERRAIN_MODE_SKIP) {
2765
2789
  /* glsl */
2766
2790
  `
2767
2791
  commonPos = geometry.position.xyz;
2792
+ terrainHeight = commonPos.z + project.commonOrigin.z;
2793
+ if (project.projectionMode == PROJECTION_MODE_GLOBE) {
2794
+ terrainMercPos = terrain_globe_to_mercator(commonPos);
2795
+ terrainHeight = length(commonPos) - GLOBE_RADIUS;
2796
+ } else {
2797
+ terrainMercPos = commonPos.xy;
2798
+ }
2768
2799
  if (terrain.mode == TERRAIN_MODE_WRITE_HEIGHT_MAP) {
2769
- vec2 texCoords = (commonPos.xy - terrain.bounds.xy) / terrain.bounds.zw;
2800
+ vec2 texCoords = (terrainMercPos - terrain.bounds.xy) / terrain.bounds.zw;
2770
2801
  position = vec4(texCoords * 2.0 - 1.0, 0.0, 1.0);
2771
- commonPos.z += project.commonOrigin.z;
2772
2802
  }
2773
2803
  if (terrain.mode == TERRAIN_MODE_USE_HEIGHT_MAP) {
2774
2804
  vec3 anchor = geometry.worldPosition;
2775
2805
  anchor.z = 0.0;
2776
2806
  vec3 anchorCommon = project_position(anchor);
2777
- vec2 texCoords = (anchorCommon.xy - terrain.bounds.xy) / terrain.bounds.zw;
2807
+ vec2 anchorMercPos = project.projectionMode == PROJECTION_MODE_GLOBE
2808
+ ? terrain_globe_to_mercator(anchorCommon)
2809
+ : anchorCommon.xy;
2810
+ vec2 texCoords = (anchorMercPos - terrain.bounds.xy) / terrain.bounds.zw;
2778
2811
  if (texCoords.x >= 0.0 && texCoords.y >= 0.0 && texCoords.x <= 1.0 && texCoords.y <= 1.0) {
2779
2812
  float terrainZ = texture(terrain_map, texCoords).r;
2780
- geometry.position.z += terrainZ;
2813
+ if (project.projectionMode == PROJECTION_MODE_GLOBE) {
2814
+ // Height map is written in Mercator common space (units = TILE_SIZE / EARTH_CIRCUMFERENCE / cos(lat))
2815
+ // Convert to globe radial units (units = GLOBE_RADIUS / EARTH_RADIUS)
2816
+ terrainZ *= cos(radians(geometry.worldPosition.y)) * PI;
2817
+ geometry.position.xyz += normalize(geometry.position.xyz) * terrainZ;
2818
+ } else {
2819
+ geometry.position.z += terrainZ;
2820
+ }
2781
2821
  position = project_common_position_to_clipspace(geometry.position);
2782
2822
  }
2783
2823
  }
@@ -2787,7 +2827,7 @@ if (terrain.mode == TERRAIN_MODE_USE_HEIGHT_MAP) {
2787
2827
  /* glsl */
2788
2828
  `
2789
2829
  if (terrain.mode == TERRAIN_MODE_WRITE_HEIGHT_MAP) {
2790
- fragColor = vec4(commonPos.z, 0.0, 0.0, 1.0);
2830
+ fragColor = vec4(terrainHeight, 0.0, 0.0, 1.0);
2791
2831
  return;
2792
2832
  }
2793
2833
  `
@@ -2796,7 +2836,7 @@ if (terrain.mode == TERRAIN_MODE_WRITE_HEIGHT_MAP) {
2796
2836
  /* glsl */
2797
2837
  `
2798
2838
  if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_USE_COVER_ONLY)) {
2799
- vec2 texCoords = (commonPos.xy - terrain.bounds.xy) / terrain.bounds.zw;
2839
+ vec2 texCoords = (terrainMercPos - terrain.bounds.xy) / terrain.bounds.zw;
2800
2840
  vec4 pixel = texture(terrain_map, texCoords);
2801
2841
  if (terrain.mode == TERRAIN_MODE_USE_COVER_ONLY) {
2802
2842
  color = pixel;
@@ -2845,7 +2885,7 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US
2845
2885
  return {
2846
2886
  mode,
2847
2887
  terrain_map: sampler,
2848
- // Convert bounds to the common space, as [minX, minY, width, height]
2888
+ // Convert bounds to common space, as [minX, minY, width, height]
2849
2889
  bounds: bounds ? [
2850
2890
  bounds[0] - commonOrigin[0],
2851
2891
  bounds[1] - commonOrigin[1],
@@ -2866,6 +2906,9 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US
2866
2906
  }
2867
2907
  };
2868
2908
 
2909
+ // dist/terrain/terrain-cover.js
2910
+ var import_core23 = require("@deck.gl/core");
2911
+
2869
2912
  // dist/terrain/utils.js
2870
2913
  var import_constants = require("@luma.gl/webgl/constants");
2871
2914
  function createRenderTarget(device, opts) {
@@ -2958,8 +3001,8 @@ var TerrainCover = class {
2958
3001
  if (!this.targetBounds) {
2959
3002
  shouldRedraw = true;
2960
3003
  this.targetBounds = this.tile.boundingBox;
2961
- const bottomLeftCommon = viewport.projectPosition(this.targetBounds[0]);
2962
- const topRightCommon = viewport.projectPosition(this.targetBounds[1]);
3004
+ const bottomLeftCommon = lngLatToMercatorCommon(this.targetBounds[0]);
3005
+ const topRightCommon = lngLatToMercatorCommon(this.targetBounds[1]);
2963
3006
  this.targetBoundsCommon = [
2964
3007
  bottomLeftCommon[0],
2965
3008
  bottomLeftCommon[1],
@@ -2970,7 +3013,7 @@ var TerrainCover = class {
2970
3013
  } else if (this.targetBounds !== targetLayer.getBounds()) {
2971
3014
  shouldRedraw = true;
2972
3015
  this.targetBounds = targetLayer.getBounds();
2973
- this.targetBoundsCommon = joinLayerBounds([targetLayer], viewport);
3016
+ this.targetBoundsCommon = joinLayerBounds([targetLayer], getMercatorReferenceViewport(viewport));
2974
3017
  }
2975
3018
  if (!this.targetBoundsCommon) {
2976
3019
  return false;
@@ -2981,7 +3024,7 @@ var TerrainCover = class {
2981
3024
  } else {
2982
3025
  const oldZoom = (_a = this.renderViewport) == null ? void 0 : _a.zoom;
2983
3026
  shouldRedraw = shouldRedraw || newZoom !== oldZoom;
2984
- const newBounds = getRenderBounds(this.targetBoundsCommon, viewport);
3027
+ const newBounds = viewport instanceof import_core23._GlobeViewport ? this.targetBoundsCommon : getRenderBounds(this.targetBoundsCommon, viewport);
2985
3028
  const oldBounds = this.bounds;
2986
3029
  shouldRedraw = shouldRedraw || !oldBounds || newBounds.some((x, i) => x !== oldBounds[i]);
2987
3030
  this.bounds = newBounds;
@@ -3058,7 +3101,7 @@ function intersect(b1, b2) {
3058
3101
  }
3059
3102
 
3060
3103
  // dist/terrain/terrain-pass.js
3061
- var import_core23 = require("@deck.gl/core");
3104
+ var import_core24 = require("@deck.gl/core");
3062
3105
  var TERRAIN_BLENDING = {
3063
3106
  blendColorOperation: "max",
3064
3107
  blendColorSrcFactor: "one",
@@ -3067,7 +3110,7 @@ var TERRAIN_BLENDING = {
3067
3110
  blendAlphaSrcFactor: "one",
3068
3111
  blendAlphaDstFactor: "one"
3069
3112
  };
3070
- var TerrainPass = class extends import_core23._LayersPass {
3113
+ var TerrainPass = class extends import_core24._LayersPass {
3071
3114
  getRenderableLayers(viewport, opts) {
3072
3115
  const { layers } = opts;
3073
3116
  const result = [];
@@ -3132,8 +3175,8 @@ var TerrainPass = class extends import_core23._LayersPass {
3132
3175
  };
3133
3176
 
3134
3177
  // dist/terrain/terrain-picking-pass.js
3135
- var import_core24 = require("@deck.gl/core");
3136
- var TerrainPickingPass = class extends import_core24._PickLayersPass {
3178
+ var import_core25 = require("@deck.gl/core");
3179
+ var TerrainPickingPass = class extends import_core25._PickLayersPass {
3137
3180
  constructor() {
3138
3181
  super(...arguments);
3139
3182
  this.drawParameters = {};
@@ -3204,6 +3247,7 @@ var TerrainPickingPass = class extends import_core24._PickLayersPass {
3204
3247
  };
3205
3248
 
3206
3249
  // dist/terrain/height-map-builder.js
3250
+ var import_core26 = require("@deck.gl/core");
3207
3251
  var MAP_MAX_SIZE = 2048;
3208
3252
  var HeightMapBuilder = class {
3209
3253
  static isSupported(device) {
@@ -3244,13 +3288,13 @@ var HeightMapBuilder = class {
3244
3288
  if (layersChanged) {
3245
3289
  this.layers = layers;
3246
3290
  this.layersBounds = layers.map((layer) => layer.getBounds());
3247
- this.layersBoundsCommon = joinLayerBounds(layers, viewport);
3291
+ this.layersBoundsCommon = joinLayerBounds(layers, getMercatorReferenceViewport(viewport));
3248
3292
  }
3249
3293
  const viewportChanged = !this.lastViewport || !viewport.equals(this.lastViewport);
3250
3294
  if (!this.layersBoundsCommon) {
3251
3295
  this.renderViewport = null;
3252
3296
  } else if (layersChanged || viewportChanged) {
3253
- const bounds = getRenderBounds(this.layersBoundsCommon, viewport);
3297
+ const bounds = viewport instanceof import_core26._GlobeViewport ? this.layersBoundsCommon : getRenderBounds(this.layersBoundsCommon, viewport);
3254
3298
  if (bounds[2] <= bounds[0] || bounds[3] <= bounds[1]) {
3255
3299
  this.renderViewport = null;
3256
3300
  return false;
@@ -3260,17 +3304,16 @@ var HeightMapBuilder = class {
3260
3304
  const scale = viewport.scale;
3261
3305
  const pixelWidth = (bounds[2] - bounds[0]) * scale;
3262
3306
  const pixelHeight = (bounds[3] - bounds[1]) * scale;
3307
+ const centerMerc = viewport.isGeospatial ? lngLatToMercatorCommon([
3308
+ viewport.longitude ?? 0,
3309
+ viewport.latitude ?? 0
3310
+ ]) : [viewport.center[0], viewport.center[1]];
3263
3311
  this.renderViewport = pixelWidth > 0 || pixelHeight > 0 ? makeViewport({
3264
3312
  // It's not important whether the geometry is visible in this viewport, because
3265
3313
  // vertices will not use the standard project_to_clipspace in the DRAW_TO_HEIGHT_MAP shader
3266
3314
  // However the viewport must have the same center and zoom as the screen viewport
3267
3315
  // So that projection uniforms used for calculating z are the same
3268
- bounds: [
3269
- viewport.center[0] - 1,
3270
- viewport.center[1] - 1,
3271
- viewport.center[0] + 1,
3272
- viewport.center[1] + 1
3273
- ],
3316
+ bounds: [centerMerc[0] - 1, centerMerc[1] - 1, centerMerc[0] + 1, centerMerc[1] + 1],
3274
3317
  zoom: viewport.zoom,
3275
3318
  width: Math.min(pixelWidth, MAP_MAX_SIZE),
3276
3319
  height: Math.min(pixelHeight, MAP_MAX_SIZE),
@@ -3309,7 +3352,7 @@ var TerrainEffect = class {
3309
3352
  if (HeightMapBuilder.isSupported(device)) {
3310
3353
  this.heightMap = new HeightMapBuilder(device);
3311
3354
  } else {
3312
- import_core25.log.warn("Terrain offset mode is not supported by this browser")();
3355
+ import_core27.log.warn("Terrain offset mode is not supported by this browser")();
3313
3356
  }
3314
3357
  deck._addDefaultShaderModule(terrainModule);
3315
3358
  }
@@ -3477,7 +3520,7 @@ var TerrainEffect = class {
3477
3520
  var defaultProps8 = {
3478
3521
  terrainDrawMode: void 0
3479
3522
  };
3480
- var TerrainExtension = class extends import_core26.LayerExtension {
3523
+ var TerrainExtension = class extends import_core28.LayerExtension {
3481
3524
  getShaders() {
3482
3525
  return {
3483
3526
  modules: [terrainModule]