@deck.gl/extensions 9.3.7 → 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 +81 -35
- package/dist/fill-style/shader-module.d.ts +1 -1
- package/dist/index.cjs +78 -35
- package/dist/index.cjs.map +4 -4
- package/dist/mask/shader-module.d.ts +1 -1
- package/dist/terrain/height-map-builder.d.ts.map +1 -1
- package/dist/terrain/height-map-builder.js +16 -10
- package/dist/terrain/height-map-builder.js.map +1 -1
- package/dist/terrain/shader-module.d.ts +6 -6
- package/dist/terrain/shader-module.d.ts.map +1 -1
- package/dist/terrain/shader-module.js +38 -11
- package/dist/terrain/shader-module.js.map +1 -1
- package/dist/terrain/terrain-cover.d.ts.map +1 -1
- package/dist/terrain/terrain-cover.js +10 -5
- package/dist/terrain/terrain-cover.js.map +1 -1
- package/dist/utils/projection-utils.d.ts +4 -0
- package/dist/utils/projection-utils.d.ts.map +1 -1
- package/dist/utils/projection-utils.js +25 -5
- package/dist/utils/projection-utils.js.map +1 -1
- package/dist.min.js +95 -65
- package/package.json +3 -3
- package/src/terrain/height-map-builder.ts +25 -10
- package/src/terrain/shader-module.ts +38 -11
- package/src/terrain/terrain-cover.ts +21 -5
- package/src/utils/projection-utils.ts +28 -5
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Plug-and-play functionalities for deck.gl layers",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"version": "9.
|
|
6
|
+
"version": "9.4.0-alpha.1",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -43,9 +43,9 @@
|
|
|
43
43
|
"@math.gl/core": "^4.1.0"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
|
-
"@deck.gl/core": "~9.3.0",
|
|
46
|
+
"@deck.gl/core": "~9.3.0-beta.2",
|
|
47
47
|
"@luma.gl/core": "~9.3.3",
|
|
48
48
|
"@luma.gl/engine": "~9.3.3"
|
|
49
49
|
},
|
|
50
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "a30177af4ec82fd612d116d1528deac09f1800b4"
|
|
51
51
|
}
|
|
@@ -3,9 +3,17 @@
|
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
5
|
import {Device, Framebuffer} from '@luma.gl/core';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
joinLayerBounds,
|
|
8
|
+
getRenderBounds,
|
|
9
|
+
makeViewport,
|
|
10
|
+
getMercatorReferenceViewport,
|
|
11
|
+
lngLatToMercatorCommon,
|
|
12
|
+
Bounds
|
|
13
|
+
} from '../utils/projection-utils';
|
|
7
14
|
import {createRenderTarget} from './utils';
|
|
8
15
|
|
|
16
|
+
import {_GlobeViewport as GlobeViewport} from '@deck.gl/core';
|
|
9
17
|
import type {Viewport, Layer} from '@deck.gl/core';
|
|
10
18
|
|
|
11
19
|
const MAP_MAX_SIZE = 2048;
|
|
@@ -72,10 +80,10 @@ export class HeightMapBuilder {
|
|
|
72
80
|
);
|
|
73
81
|
|
|
74
82
|
if (layersChanged) {
|
|
75
|
-
// Recalculate cached bounds
|
|
83
|
+
// Recalculate cached bounds in absolute Mercator common space
|
|
76
84
|
this.layers = layers;
|
|
77
85
|
this.layersBounds = layers.map(layer => layer.getBounds());
|
|
78
|
-
this.layersBoundsCommon = joinLayerBounds(layers, viewport);
|
|
86
|
+
this.layersBoundsCommon = joinLayerBounds(layers, getMercatorReferenceViewport(viewport));
|
|
79
87
|
}
|
|
80
88
|
|
|
81
89
|
const viewportChanged = !this.lastViewport || !viewport.equals(this.lastViewport);
|
|
@@ -83,7 +91,11 @@ export class HeightMapBuilder {
|
|
|
83
91
|
if (!this.layersBoundsCommon) {
|
|
84
92
|
this.renderViewport = null;
|
|
85
93
|
} else if (layersChanged || viewportChanged) {
|
|
86
|
-
|
|
94
|
+
// On GlobeView, viewport bounds are sphere cartesian — skip intersection
|
|
95
|
+
const bounds =
|
|
96
|
+
viewport instanceof GlobeViewport
|
|
97
|
+
? this.layersBoundsCommon
|
|
98
|
+
: getRenderBounds(this.layersBoundsCommon, viewport);
|
|
87
99
|
if (bounds[2] <= bounds[0] || bounds[3] <= bounds[1]) {
|
|
88
100
|
this.renderViewport = null;
|
|
89
101
|
return false;
|
|
@@ -96,6 +108,14 @@ export class HeightMapBuilder {
|
|
|
96
108
|
const pixelWidth = (bounds[2] - bounds[0]) * scale;
|
|
97
109
|
const pixelHeight = (bounds[3] - bounds[1]) * scale;
|
|
98
110
|
|
|
111
|
+
// Use Mercator center — viewport.center on GlobeView is sphere cartesian
|
|
112
|
+
const centerMerc = viewport.isGeospatial
|
|
113
|
+
? lngLatToMercatorCommon([
|
|
114
|
+
(viewport as {longitude?: number}).longitude ?? 0,
|
|
115
|
+
(viewport as {latitude?: number}).latitude ?? 0
|
|
116
|
+
])
|
|
117
|
+
: [viewport.center[0], viewport.center[1]];
|
|
118
|
+
|
|
99
119
|
this.renderViewport =
|
|
100
120
|
pixelWidth > 0 || pixelHeight > 0
|
|
101
121
|
? makeViewport({
|
|
@@ -103,12 +123,7 @@ export class HeightMapBuilder {
|
|
|
103
123
|
// vertices will not use the standard project_to_clipspace in the DRAW_TO_HEIGHT_MAP shader
|
|
104
124
|
// However the viewport must have the same center and zoom as the screen viewport
|
|
105
125
|
// So that projection uniforms used for calculating z are the same
|
|
106
|
-
bounds: [
|
|
107
|
-
viewport.center[0] - 1,
|
|
108
|
-
viewport.center[1] - 1,
|
|
109
|
-
viewport.center[0] + 1,
|
|
110
|
-
viewport.center[1] + 1
|
|
111
|
-
],
|
|
126
|
+
bounds: [centerMerc[0] - 1, centerMerc[1] - 1, centerMerc[0] + 1, centerMerc[1] + 1],
|
|
112
127
|
zoom: viewport.zoom,
|
|
113
128
|
width: Math.min(pixelWidth, MAP_MAX_SIZE),
|
|
114
129
|
height: Math.min(pixelHeight, MAP_MAX_SIZE),
|
|
@@ -67,10 +67,21 @@ uniform sampler2D terrain_map;
|
|
|
67
67
|
export const terrainModule = {
|
|
68
68
|
name: 'terrain',
|
|
69
69
|
dependencies: [project],
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
vs: `${uniformBlock}
|
|
71
|
+
out vec3 commonPos;
|
|
72
|
+
// In globe mode, absolute Mercator position for terrain FBO UV lookups
|
|
73
|
+
out vec2 terrainMercPos;
|
|
74
|
+
out float terrainHeight;
|
|
75
|
+
|
|
76
|
+
vec2 terrain_globe_to_mercator(vec3 globePosition) {
|
|
77
|
+
float D = length(globePosition);
|
|
78
|
+
float sinLat = clamp(globePosition.z / D, -0.999998, 0.999998);
|
|
79
|
+
float x = atan(globePosition.x, -globePosition.y);
|
|
80
|
+
float y = atanh(sinLat);
|
|
81
|
+
return (vec2(x, y) + PI) * WORLD_SCALE;
|
|
82
|
+
}
|
|
83
|
+
`,
|
|
84
|
+
fs: `${uniformBlock}in vec2 terrainMercPos;\nin float terrainHeight;`,
|
|
74
85
|
inject: {
|
|
75
86
|
'vs:#main-start': /* glsl */ `
|
|
76
87
|
if (terrain.mode == TERRAIN_MODE_SKIP) {
|
|
@@ -80,32 +91,48 @@ if (terrain.mode == TERRAIN_MODE_SKIP) {
|
|
|
80
91
|
`,
|
|
81
92
|
'vs:DECKGL_FILTER_GL_POSITION': /* glsl */ `
|
|
82
93
|
commonPos = geometry.position.xyz;
|
|
94
|
+
terrainHeight = commonPos.z + project.commonOrigin.z;
|
|
95
|
+
if (project.projectionMode == PROJECTION_MODE_GLOBE) {
|
|
96
|
+
terrainMercPos = terrain_globe_to_mercator(commonPos);
|
|
97
|
+
terrainHeight = length(commonPos) - GLOBE_RADIUS;
|
|
98
|
+
} else {
|
|
99
|
+
terrainMercPos = commonPos.xy;
|
|
100
|
+
}
|
|
83
101
|
if (terrain.mode == TERRAIN_MODE_WRITE_HEIGHT_MAP) {
|
|
84
|
-
vec2 texCoords = (
|
|
102
|
+
vec2 texCoords = (terrainMercPos - terrain.bounds.xy) / terrain.bounds.zw;
|
|
85
103
|
position = vec4(texCoords * 2.0 - 1.0, 0.0, 1.0);
|
|
86
|
-
commonPos.z += project.commonOrigin.z;
|
|
87
104
|
}
|
|
88
105
|
if (terrain.mode == TERRAIN_MODE_USE_HEIGHT_MAP) {
|
|
89
106
|
vec3 anchor = geometry.worldPosition;
|
|
90
107
|
anchor.z = 0.0;
|
|
91
108
|
vec3 anchorCommon = project_position(anchor);
|
|
92
|
-
vec2
|
|
109
|
+
vec2 anchorMercPos = project.projectionMode == PROJECTION_MODE_GLOBE
|
|
110
|
+
? terrain_globe_to_mercator(anchorCommon)
|
|
111
|
+
: anchorCommon.xy;
|
|
112
|
+
vec2 texCoords = (anchorMercPos - terrain.bounds.xy) / terrain.bounds.zw;
|
|
93
113
|
if (texCoords.x >= 0.0 && texCoords.y >= 0.0 && texCoords.x <= 1.0 && texCoords.y <= 1.0) {
|
|
94
114
|
float terrainZ = texture(terrain_map, texCoords).r;
|
|
95
|
-
|
|
115
|
+
if (project.projectionMode == PROJECTION_MODE_GLOBE) {
|
|
116
|
+
// Height map is written in Mercator common space (units = TILE_SIZE / EARTH_CIRCUMFERENCE / cos(lat))
|
|
117
|
+
// Convert to globe radial units (units = GLOBE_RADIUS / EARTH_RADIUS)
|
|
118
|
+
terrainZ *= cos(radians(geometry.worldPosition.y)) * PI;
|
|
119
|
+
geometry.position.xyz += normalize(geometry.position.xyz) * terrainZ;
|
|
120
|
+
} else {
|
|
121
|
+
geometry.position.z += terrainZ;
|
|
122
|
+
}
|
|
96
123
|
position = project_common_position_to_clipspace(geometry.position);
|
|
97
124
|
}
|
|
98
125
|
}
|
|
99
126
|
`,
|
|
100
127
|
'fs:#main-start': /* glsl */ `
|
|
101
128
|
if (terrain.mode == TERRAIN_MODE_WRITE_HEIGHT_MAP) {
|
|
102
|
-
fragColor = vec4(
|
|
129
|
+
fragColor = vec4(terrainHeight, 0.0, 0.0, 1.0);
|
|
103
130
|
return;
|
|
104
131
|
}
|
|
105
132
|
`,
|
|
106
133
|
'fs:DECKGL_FILTER_COLOR': /* glsl */ `
|
|
107
134
|
if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_USE_COVER_ONLY)) {
|
|
108
|
-
vec2 texCoords = (
|
|
135
|
+
vec2 texCoords = (terrainMercPos - terrain.bounds.xy) / terrain.bounds.zw;
|
|
109
136
|
vec4 pixel = texture(terrain_map, texCoords);
|
|
110
137
|
if (terrain.mode == TERRAIN_MODE_USE_COVER_ONLY) {
|
|
111
138
|
color = pixel;
|
|
@@ -173,7 +200,7 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US
|
|
|
173
200
|
return {
|
|
174
201
|
mode,
|
|
175
202
|
terrain_map: sampler,
|
|
176
|
-
// Convert bounds to
|
|
203
|
+
// Convert bounds to common space, as [minX, minY, width, height]
|
|
177
204
|
bounds: bounds
|
|
178
205
|
? [
|
|
179
206
|
bounds[0] - commonOrigin[0],
|
|
@@ -4,10 +4,18 @@
|
|
|
4
4
|
|
|
5
5
|
import {Framebuffer} from '@luma.gl/core';
|
|
6
6
|
|
|
7
|
+
import {_GlobeViewport as GlobeViewport} from '@deck.gl/core';
|
|
7
8
|
import type {Layer, Viewport} from '@deck.gl/core';
|
|
8
9
|
|
|
9
10
|
import {createRenderTarget} from './utils';
|
|
10
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
getMercatorReferenceViewport,
|
|
13
|
+
joinLayerBounds,
|
|
14
|
+
lngLatToMercatorCommon,
|
|
15
|
+
makeViewport,
|
|
16
|
+
getRenderBounds,
|
|
17
|
+
Bounds
|
|
18
|
+
} from '../utils/projection-utils';
|
|
11
19
|
|
|
12
20
|
type TileHeader = {
|
|
13
21
|
boundingBox: [min: number[], max: number[]];
|
|
@@ -113,13 +121,14 @@ export class TerrainCover {
|
|
|
113
121
|
const targetLayer = this.targetLayer;
|
|
114
122
|
let shouldRedraw = false;
|
|
115
123
|
|
|
124
|
+
// Bounds in absolute Mercator common space (matches terrain cover FBO viewport)
|
|
116
125
|
if (this.tile && 'boundingBox' in this.tile) {
|
|
117
126
|
if (!this.targetBounds) {
|
|
118
127
|
shouldRedraw = true;
|
|
119
128
|
this.targetBounds = this.tile.boundingBox;
|
|
120
129
|
|
|
121
|
-
const bottomLeftCommon =
|
|
122
|
-
const topRightCommon =
|
|
130
|
+
const bottomLeftCommon = lngLatToMercatorCommon(this.targetBounds[0]);
|
|
131
|
+
const topRightCommon = lngLatToMercatorCommon(this.targetBounds[1]);
|
|
123
132
|
this.targetBoundsCommon = [
|
|
124
133
|
bottomLeftCommon[0],
|
|
125
134
|
bottomLeftCommon[1],
|
|
@@ -131,7 +140,10 @@ export class TerrainCover {
|
|
|
131
140
|
// console.log('bounds changed', this.bounds, '>>', newBounds);
|
|
132
141
|
shouldRedraw = true;
|
|
133
142
|
this.targetBounds = targetLayer.getBounds();
|
|
134
|
-
this.targetBoundsCommon = joinLayerBounds(
|
|
143
|
+
this.targetBoundsCommon = joinLayerBounds(
|
|
144
|
+
[targetLayer],
|
|
145
|
+
getMercatorReferenceViewport(viewport)
|
|
146
|
+
);
|
|
135
147
|
}
|
|
136
148
|
|
|
137
149
|
if (!this.targetBoundsCommon) {
|
|
@@ -146,7 +158,11 @@ export class TerrainCover {
|
|
|
146
158
|
} else {
|
|
147
159
|
const oldZoom = this.renderViewport?.zoom;
|
|
148
160
|
shouldRedraw = shouldRedraw || newZoom !== oldZoom;
|
|
149
|
-
|
|
161
|
+
// On GlobeView, viewport bounds are sphere cartesian — skip intersection
|
|
162
|
+
const newBounds =
|
|
163
|
+
viewport instanceof GlobeViewport
|
|
164
|
+
? this.targetBoundsCommon
|
|
165
|
+
: getRenderBounds(this.targetBoundsCommon, viewport);
|
|
150
166
|
const oldBounds = this.bounds;
|
|
151
167
|
shouldRedraw = shouldRedraw || !oldBounds || newBounds.some((x, i) => x !== oldBounds[i]);
|
|
152
168
|
this.bounds = newBounds;
|
|
@@ -8,6 +8,26 @@ import type {Layer, Viewport} from '@deck.gl/core';
|
|
|
8
8
|
/** Bounds in CARTESIAN coordinates */
|
|
9
9
|
export type Bounds = [minX: number, minY: number, maxX: number, maxY: number];
|
|
10
10
|
|
|
11
|
+
/** Fixed Mercator viewport for projection-independent coordinate conversion */
|
|
12
|
+
const MERCATOR_REFERENCE_VIEWPORT = new WebMercatorViewport({
|
|
13
|
+
width: 1,
|
|
14
|
+
height: 1,
|
|
15
|
+
longitude: 0,
|
|
16
|
+
latitude: 0,
|
|
17
|
+
zoom: 0
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
/** Project lng/lat to absolute Mercator common space. */
|
|
21
|
+
export function lngLatToMercatorCommon(lngLat: number[]): [number, number] {
|
|
22
|
+
const [x, y] = MERCATOR_REFERENCE_VIEWPORT.projectPosition(lngLat);
|
|
23
|
+
return [x, y];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Returns a Mercator viewport for bounds computation, bypassing GlobeView. */
|
|
27
|
+
export function getMercatorReferenceViewport(viewport: Viewport): Viewport {
|
|
28
|
+
return viewport.isGeospatial ? MERCATOR_REFERENCE_VIEWPORT : viewport;
|
|
29
|
+
}
|
|
30
|
+
|
|
11
31
|
/*
|
|
12
32
|
* Compute the union of bounds from multiple layers
|
|
13
33
|
* Returns bounds in CARTESIAN coordinates
|
|
@@ -63,11 +83,14 @@ export function makeViewport(opts: {
|
|
|
63
83
|
return null;
|
|
64
84
|
}
|
|
65
85
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
(
|
|
69
|
-
|
|
70
|
-
|
|
86
|
+
// Unproject through Mercator reference (GlobeView would give sphere coords)
|
|
87
|
+
const centerWorld = isGeospatial
|
|
88
|
+
? MERCATOR_REFERENCE_VIEWPORT.unprojectPosition([
|
|
89
|
+
(bounds[0] + bounds[2]) / 2,
|
|
90
|
+
(bounds[1] + bounds[3]) / 2,
|
|
91
|
+
0
|
|
92
|
+
])
|
|
93
|
+
: viewport.unprojectPosition([(bounds[0] + bounds[2]) / 2, (bounds[1] + bounds[3]) / 2, 0]);
|
|
71
94
|
|
|
72
95
|
let {width, height, zoom} = opts;
|
|
73
96
|
if (zoom === undefined) {
|