maplibre-gl 2.1.8 → 2.2.0-pre.2
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/build/generate-style-spec.ts +2 -0
- package/dist/maplibre-gl-csp-worker.js +1 -1
- package/dist/maplibre-gl-csp-worker.js.map +1 -1
- package/dist/maplibre-gl-csp.js +1 -1
- package/dist/maplibre-gl-csp.js.map +1 -1
- package/dist/maplibre-gl-dev.js +1517 -290
- package/dist/maplibre-gl.css +1 -1
- package/dist/maplibre-gl.d.ts +3476 -3112
- package/dist/maplibre-gl.js +4 -4
- package/dist/maplibre-gl.js.map +1 -1
- package/dist/package.json +1 -1
- package/package.json +15 -15
- package/src/css/maplibre-gl.css +20 -0
- package/src/css/svg/maplibregl-ctrl-terrain.svg +7 -0
- package/src/data/bucket/fill_extrusion_attributes.ts +4 -0
- package/src/data/bucket/fill_extrusion_bucket.ts +28 -4
- package/src/data/dem_data.test.ts +14 -1
- package/src/data/dem_data.ts +13 -0
- package/src/geo/transform.test.ts +56 -1
- package/src/geo/transform.ts +199 -47
- package/src/index.ts +2 -0
- package/src/render/draw_background.ts +6 -6
- package/src/render/draw_circle.ts +6 -2
- package/src/render/draw_collision_debug.ts +5 -1
- package/src/render/draw_debug.ts +5 -5
- package/src/render/draw_fill.ts +5 -2
- package/src/render/draw_fill_extrusion.ts +3 -2
- package/src/render/draw_heatmap.ts +2 -3
- package/src/render/draw_hillshade.ts +8 -7
- package/src/render/draw_line.ts +7 -5
- package/src/render/draw_raster.ts +8 -6
- package/src/render/draw_symbol.test.ts +34 -10
- package/src/render/draw_symbol.ts +23 -12
- package/src/render/draw_terrain.ts +123 -0
- package/src/render/painter.ts +52 -14
- package/src/render/program/hillshade_program.ts +7 -2
- package/src/render/program/line_program.ts +24 -10
- package/src/render/program/program_uniforms.ts +5 -1
- package/src/render/program/terrain_program.ts +83 -0
- package/src/render/program.ts +29 -5
- package/src/render/render_to_texture.test.ts +41 -0
- package/src/render/render_to_texture.ts +154 -0
- package/src/render/terrain.test.ts +53 -0
- package/src/render/terrain.ts +369 -0
- package/src/render/vertex_array_object.ts +21 -4
- package/src/shaders/_prelude.vertex.glsl +76 -0
- package/src/shaders/_prelude.vertex.glsl.g.ts +1 -1
- package/src/shaders/circle.fragment.glsl +2 -1
- package/src/shaders/circle.fragment.glsl.g.ts +1 -1
- package/src/shaders/circle.vertex.glsl +6 -2
- package/src/shaders/circle.vertex.glsl.g.ts +1 -1
- package/src/shaders/collision_box.vertex.glsl +1 -1
- package/src/shaders/collision_box.vertex.glsl.g.ts +1 -1
- package/src/shaders/debug.vertex.glsl +1 -1
- package/src/shaders/debug.vertex.glsl.g.ts +1 -1
- package/src/shaders/fill_extrusion.vertex.glsl +16 -2
- package/src/shaders/fill_extrusion.vertex.glsl.g.ts +1 -1
- package/src/shaders/fill_extrusion_pattern.vertex.glsl +15 -2
- package/src/shaders/fill_extrusion_pattern.vertex.glsl.g.ts +1 -1
- package/src/shaders/line.vertex.glsl +7 -3
- package/src/shaders/line.vertex.glsl.g.ts +1 -1
- package/src/shaders/line_gradient.vertex.glsl +7 -3
- package/src/shaders/line_gradient.vertex.glsl.g.ts +1 -1
- package/src/shaders/line_pattern.vertex.glsl +7 -3
- package/src/shaders/line_pattern.vertex.glsl.g.ts +1 -1
- package/src/shaders/line_sdf.vertex.glsl +7 -4
- package/src/shaders/line_sdf.vertex.glsl.g.ts +1 -1
- package/src/shaders/shaders.ts +11 -1
- package/src/shaders/symbol_icon.vertex.glsl +8 -8
- package/src/shaders/symbol_icon.vertex.glsl.g.ts +1 -1
- package/src/shaders/symbol_sdf.vertex.glsl +8 -5
- package/src/shaders/symbol_sdf.vertex.glsl.g.ts +1 -1
- package/src/shaders/symbol_text_and_icon.vertex.glsl +8 -5
- package/src/shaders/symbol_text_and_icon.vertex.glsl.g.ts +1 -1
- package/src/shaders/terrain.fragment.glsl +7 -0
- package/src/shaders/terrain.fragment.glsl.g.ts +2 -0
- package/src/shaders/terrain.vertex.glsl +12 -0
- package/src/shaders/terrain.vertex.glsl.g.ts +2 -0
- package/src/shaders/terrain_coords.fragment.glsl +11 -0
- package/src/shaders/terrain_coords.fragment.glsl.g.ts +2 -0
- package/src/shaders/terrain_depth.fragment.glsl +15 -0
- package/src/shaders/terrain_depth.fragment.glsl.g.ts +2 -0
- package/src/source/canvas_source.test.ts +1 -1
- package/src/source/geojson_source.test.ts +25 -0
- package/src/source/geojson_source.ts +1 -8
- package/src/source/geojson_worker_source.test.ts +19 -23
- package/src/source/geojson_worker_source.ts +19 -70
- package/src/source/raster_dem_tile_source.ts +4 -3
- package/src/source/raster_dem_tile_worker_source.ts +0 -1
- package/src/source/source_cache.test.ts +83 -0
- package/src/source/source_cache.ts +72 -11
- package/src/source/terrain_source_cache.test.ts +89 -0
- package/src/source/terrain_source_cache.ts +201 -0
- package/src/source/tile.ts +15 -0
- package/src/source/tile_id.ts +9 -0
- package/src/style/pauseable_placement.ts +3 -1
- package/src/style/style.test.ts +16 -0
- package/src/style/style.ts +57 -3
- package/src/style/validate_style.ts +2 -0
- package/src/style-spec/CHANGELOG.md +6 -0
- package/src/style-spec/error/validation_error.ts +1 -1
- package/src/style-spec/package.json +2 -2
- package/src/style-spec/reference/v8.json +42 -0
- package/src/style-spec/types.g.ts +7 -0
- package/src/style-spec/validate/validate.ts +2 -0
- package/src/style-spec/validate/validate_terrain.test.ts +46 -0
- package/src/style-spec/validate/validate_terrain.ts +41 -0
- package/src/style-spec/validate_style.min.ts +2 -0
- package/src/style-spec/validate_style.ts +1 -0
- package/src/symbol/collision_index.ts +28 -12
- package/src/symbol/placement.ts +24 -9
- package/src/symbol/projection.ts +42 -27
- package/src/ui/camera.ts +2 -0
- package/src/ui/control/terrain_control.ts +77 -0
- package/src/ui/default_locale.ts +3 -2
- package/src/ui/events.ts +18 -3
- package/src/ui/handler_manager.ts +33 -3
- package/src/ui/map.ts +36 -6
- package/src/ui/marker.test.ts +21 -0
- package/src/ui/marker.ts +14 -0
- package/src/util/primitives.ts +14 -11
|
@@ -58,6 +58,7 @@ function drawExtrusionTiles(painter, source, layer, coords, depthMode, stencilMo
|
|
|
58
58
|
const bucket: FillExtrusionBucket = (tile.getBucket(layer) as any);
|
|
59
59
|
if (!bucket) continue;
|
|
60
60
|
|
|
61
|
+
const terrainData = painter.style.terrain && painter.style.terrain.getTerrainData(coord);
|
|
61
62
|
const programConfiguration = bucket.programConfigurations.get(layer.id);
|
|
62
63
|
const program = painter.useProgram(image ? 'fillExtrusionPattern' : 'fillExtrusion', programConfiguration);
|
|
63
64
|
|
|
@@ -86,8 +87,8 @@ function drawExtrusionTiles(painter, source, layer, coords, depthMode, stencilMo
|
|
|
86
87
|
fillExtrusionUniformValues(matrix, painter, shouldUseVerticalGradient, opacity);
|
|
87
88
|
|
|
88
89
|
program.draw(context, context.gl.TRIANGLES, depthMode, stencilMode, colorMode, CullFaceMode.backCCW,
|
|
89
|
-
uniformValues, layer.id, bucket.layoutVertexBuffer, bucket.indexBuffer,
|
|
90
|
+
uniformValues, terrainData, layer.id, bucket.layoutVertexBuffer, bucket.indexBuffer,
|
|
90
91
|
bucket.segments, layer.paint, painter.transform.zoom,
|
|
91
|
-
programConfiguration);
|
|
92
|
+
programConfiguration, painter.style.terrain && bucket.centroidVertexBuffer);
|
|
92
93
|
}
|
|
93
94
|
}
|
|
@@ -53,8 +53,7 @@ function drawHeatmap(painter: Painter, sourceCache: SourceCache, layer: HeatmapS
|
|
|
53
53
|
const {zoom} = painter.transform;
|
|
54
54
|
|
|
55
55
|
program.draw(context, gl.TRIANGLES, DepthMode.disabled, stencilMode, colorMode, CullFaceMode.disabled,
|
|
56
|
-
heatmapUniformValues(coord.posMatrix,
|
|
57
|
-
tile, zoom, layer.paint.get('heatmap-intensity')),
|
|
56
|
+
heatmapUniformValues(coord.posMatrix, tile, zoom, layer.paint.get('heatmap-intensity')), null,
|
|
58
57
|
layer.id, bucket.layoutVertexBuffer, bucket.indexBuffer,
|
|
59
58
|
bucket.segments, layer.paint, painter.transform.zoom,
|
|
60
59
|
programConfiguration);
|
|
@@ -125,7 +124,7 @@ function renderTextureToMap(painter, layer) {
|
|
|
125
124
|
|
|
126
125
|
painter.useProgram('heatmapTexture').draw(context, gl.TRIANGLES,
|
|
127
126
|
DepthMode.disabled, StencilMode.disabled, painter.colorModeForRenderPass(), CullFaceMode.disabled,
|
|
128
|
-
heatmapTextureUniformValues(painter, layer, 0, 1),
|
|
127
|
+
heatmapTextureUniformValues(painter, layer, 0, 1), null,
|
|
129
128
|
layer.id, painter.viewportBuffer, painter.quadTriangleIndexBuffer,
|
|
130
129
|
painter.viewportSegments, layer.paint, painter.transform.zoom);
|
|
131
130
|
}
|
|
@@ -27,32 +27,33 @@ function drawHillshade(painter: Painter, sourceCache: SourceCache, layer: Hillsh
|
|
|
27
27
|
|
|
28
28
|
for (const coord of coords) {
|
|
29
29
|
const tile = sourceCache.getTile(coord);
|
|
30
|
-
if (tile.needsHillshadePrepare && painter.renderPass === 'offscreen') {
|
|
30
|
+
if (typeof tile.needsHillshadePrepare !== 'undefined' && tile.needsHillshadePrepare && painter.renderPass === 'offscreen') {
|
|
31
31
|
prepareHillshade(painter, tile, layer, depthMode, StencilMode.disabled, colorMode);
|
|
32
32
|
} else if (painter.renderPass === 'translucent') {
|
|
33
|
-
renderHillshade(painter, tile, layer, depthMode, stencilModes[coord.overscaledZ], colorMode);
|
|
33
|
+
renderHillshade(painter, coord, tile, layer, depthMode, stencilModes[coord.overscaledZ], colorMode);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
context.viewport.set([0, 0, painter.width, painter.height]);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
function renderHillshade(painter, tile, layer, depthMode, stencilMode, colorMode) {
|
|
40
|
+
function renderHillshade(painter, coord, tile, layer, depthMode, stencilMode, colorMode) {
|
|
41
41
|
const context = painter.context;
|
|
42
42
|
const gl = context.gl;
|
|
43
43
|
const fbo = tile.fbo;
|
|
44
44
|
if (!fbo) return;
|
|
45
45
|
|
|
46
46
|
const program = painter.useProgram('hillshade');
|
|
47
|
+
const terrainData = painter.style.terrain && painter.style.terrain.getTerrainData(coord);
|
|
47
48
|
|
|
48
49
|
context.activeTexture.set(gl.TEXTURE0);
|
|
49
50
|
gl.bindTexture(gl.TEXTURE_2D, fbo.colorAttachment.get());
|
|
50
51
|
|
|
51
|
-
const
|
|
52
|
-
|
|
52
|
+
const terrainCoord = terrainData ? coord : null;
|
|
53
53
|
program.draw(context, gl.TRIANGLES, depthMode, stencilMode, colorMode, CullFaceMode.disabled,
|
|
54
|
-
|
|
54
|
+
hillshadeUniformValues(painter, tile, layer, terrainCoord), terrainData, layer.id, painter.rasterBoundsBuffer,
|
|
55
55
|
painter.quadTriangleIndexBuffer, painter.rasterBoundsSegments);
|
|
56
|
+
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
// hillshade rendering is done in two steps. the prepare step first calculates the slope of the terrain in the x and y
|
|
@@ -97,7 +98,7 @@ function prepareHillshade(painter, tile, layer, depthMode, stencilMode, colorMod
|
|
|
97
98
|
painter.useProgram('hillshadePrepare').draw(context, gl.TRIANGLES,
|
|
98
99
|
depthMode, stencilMode, colorMode, CullFaceMode.disabled,
|
|
99
100
|
hillshadeUniformPrepareValues(tile.tileID, dem),
|
|
100
|
-
layer.id, painter.rasterBoundsBuffer,
|
|
101
|
+
null, layer.id, painter.rasterBoundsBuffer,
|
|
101
102
|
painter.quadTriangleIndexBuffer, painter.rasterBoundsSegments);
|
|
102
103
|
|
|
103
104
|
tile.needsHillshadePrepare = false;
|
package/src/render/draw_line.ts
CHANGED
|
@@ -56,6 +56,7 @@ export default function drawLine(painter: Painter, sourceCache: SourceCache, lay
|
|
|
56
56
|
const prevProgram = painter.context.program.get();
|
|
57
57
|
const program = painter.useProgram(programId, programConfiguration);
|
|
58
58
|
const programChanged = firstTile || program.program !== prevProgram;
|
|
59
|
+
const terrainData = painter.style.terrain && painter.style.terrain.getTerrainData(coord);
|
|
59
60
|
|
|
60
61
|
const constantPattern = patternProperty.constantOr(null);
|
|
61
62
|
if (constantPattern && tile.imageAtlas) {
|
|
@@ -65,10 +66,11 @@ export default function drawLine(painter: Painter, sourceCache: SourceCache, lay
|
|
|
65
66
|
if (posTo && posFrom) programConfiguration.setConstantPatternPositions(posTo, posFrom);
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
const terrainCoord = terrainData ? coord : null;
|
|
70
|
+
const uniformValues = image ? linePatternUniformValues(painter, tile, layer, crossfade, terrainCoord) :
|
|
71
|
+
dasharray ? lineSDFUniformValues(painter, tile, layer, dasharray, crossfade, terrainCoord) :
|
|
72
|
+
gradient ? lineGradientUniformValues(painter, tile, layer, bucket.lineClipsArray.length, terrainCoord) :
|
|
73
|
+
lineUniformValues(painter, tile, layer, terrainCoord);
|
|
72
74
|
|
|
73
75
|
if (image) {
|
|
74
76
|
context.activeTexture.set(gl.TEXTURE0);
|
|
@@ -113,7 +115,7 @@ export default function drawLine(painter: Painter, sourceCache: SourceCache, lay
|
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
program.draw(context, gl.TRIANGLES, depthMode,
|
|
116
|
-
painter.stencilModeForClipping(coord), colorMode, CullFaceMode.disabled, uniformValues,
|
|
118
|
+
painter.stencilModeForClipping(coord), colorMode, CullFaceMode.disabled, uniformValues, terrainData,
|
|
117
119
|
layer.id, bucket.layoutVertexBuffer, bucket.indexBuffer, bucket.segments,
|
|
118
120
|
layer.paint, painter.transform.zoom, programConfiguration, bucket.layoutVertexBuffer2);
|
|
119
121
|
|
|
@@ -39,12 +39,11 @@ function drawRaster(painter: Painter, sourceCache: SourceCache, layer: RasterSty
|
|
|
39
39
|
layer.paint.get('raster-opacity') === 1 ? DepthMode.ReadWrite : DepthMode.ReadOnly, gl.LESS);
|
|
40
40
|
|
|
41
41
|
const tile = sourceCache.getTile(coord);
|
|
42
|
-
const posMatrix = painter.transform.calculatePosMatrix(coord.toUnwrapped(), align);
|
|
43
42
|
|
|
44
43
|
tile.registerFadeDuration(layer.paint.get('raster-fade-duration'));
|
|
45
44
|
|
|
46
45
|
const parentTile = sourceCache.findLoadedParent(coord, 0),
|
|
47
|
-
fade = getFadeValues(tile, parentTile, sourceCache, layer, painter.transform);
|
|
46
|
+
fade = getFadeValues(tile, parentTile, sourceCache, layer, painter.transform, painter.style.terrain);
|
|
48
47
|
|
|
49
48
|
let parentScaleBy, parentTL;
|
|
50
49
|
|
|
@@ -64,24 +63,27 @@ function drawRaster(painter: Painter, sourceCache: SourceCache, layer: RasterSty
|
|
|
64
63
|
tile.texture.bind(textureFilter, gl.CLAMP_TO_EDGE, gl.LINEAR_MIPMAP_NEAREST);
|
|
65
64
|
}
|
|
66
65
|
|
|
66
|
+
const terrainData = painter.style.terrain && painter.style.terrain.getTerrainData(coord);
|
|
67
|
+
const terrainCoord = terrainData ? coord : null;
|
|
68
|
+
const posMatrix = terrainCoord ? terrainCoord.posMatrix : painter.transform.calculatePosMatrix(coord.toUnwrapped(), align);
|
|
67
69
|
const uniformValues = rasterUniformValues(posMatrix, parentTL || [0, 0], parentScaleBy || 1, fade, layer);
|
|
68
70
|
|
|
69
71
|
if (source instanceof ImageSource) {
|
|
70
72
|
program.draw(context, gl.TRIANGLES, depthMode, StencilMode.disabled, colorMode, CullFaceMode.disabled,
|
|
71
|
-
uniformValues, layer.id, source.boundsBuffer,
|
|
73
|
+
uniformValues, terrainData, layer.id, source.boundsBuffer,
|
|
72
74
|
painter.quadTriangleIndexBuffer, source.boundsSegments);
|
|
73
75
|
} else {
|
|
74
76
|
program.draw(context, gl.TRIANGLES, depthMode, stencilModes[coord.overscaledZ], colorMode, CullFaceMode.disabled,
|
|
75
|
-
uniformValues, layer.id, painter.rasterBoundsBuffer,
|
|
77
|
+
uniformValues, terrainData, layer.id, painter.rasterBoundsBuffer,
|
|
76
78
|
painter.quadTriangleIndexBuffer, painter.rasterBoundsSegments);
|
|
77
79
|
}
|
|
78
80
|
}
|
|
79
81
|
}
|
|
80
82
|
|
|
81
|
-
function getFadeValues(tile, parentTile, sourceCache, layer, transform) {
|
|
83
|
+
function getFadeValues(tile, parentTile, sourceCache, layer, transform, terrain) {
|
|
82
84
|
const fadeDuration = layer.paint.get('raster-fade-duration');
|
|
83
85
|
|
|
84
|
-
if (fadeDuration > 0) {
|
|
86
|
+
if (!terrain && fadeDuration > 0) {
|
|
85
87
|
const now = browser.now();
|
|
86
88
|
const sinceTile = (now - tile.timeAdded) / fadeDuration;
|
|
87
89
|
const sinceParent = parentTile ? (now - parentTile.timeAdded) / fadeDuration : -1;
|
|
@@ -10,9 +10,13 @@ import drawSymbol from './draw_symbol';
|
|
|
10
10
|
import * as symbolProjection from '../symbol/projection';
|
|
11
11
|
import type ZoomHistory from '../style/zoom_history';
|
|
12
12
|
import type Map from '../ui/map';
|
|
13
|
-
import
|
|
13
|
+
import Transform from '../geo/transform';
|
|
14
14
|
import type EvaluationParameters from '../style/evaluation_parameters';
|
|
15
15
|
import type {SymbolLayerSpecification} from '../style-spec/types.g';
|
|
16
|
+
import Style from '../style/style';
|
|
17
|
+
import TerrainSourceCache from '../source/terrain_source_cache';
|
|
18
|
+
import {Evented} from '../util/evented';
|
|
19
|
+
import {RequestManager} from '../util/request_manager';
|
|
16
20
|
|
|
17
21
|
jest.mock('./painter');
|
|
18
22
|
jest.mock('./program');
|
|
@@ -21,6 +25,22 @@ jest.mock('../source/tile');
|
|
|
21
25
|
jest.mock('../data/bucket/symbol_bucket');
|
|
22
26
|
jest.mock('../symbol/projection');
|
|
23
27
|
|
|
28
|
+
class StubMap extends Evented {
|
|
29
|
+
transform: Transform;
|
|
30
|
+
painter: Painter;
|
|
31
|
+
_requestManager: RequestManager;
|
|
32
|
+
|
|
33
|
+
constructor() {
|
|
34
|
+
super();
|
|
35
|
+
this.transform = new Transform();
|
|
36
|
+
this._requestManager = {
|
|
37
|
+
transformRequest: (url) => {
|
|
38
|
+
return {url};
|
|
39
|
+
}
|
|
40
|
+
} as any as RequestManager;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
24
44
|
describe('drawSymbol', () => {
|
|
25
45
|
test('should not do anything', () => {
|
|
26
46
|
const mockPainter = new Painter(null, null);
|
|
@@ -37,12 +57,13 @@ describe('drawSymbol', () => {
|
|
|
37
57
|
painterMock.context = {
|
|
38
58
|
gl: {},
|
|
39
59
|
activeTexture: {
|
|
40
|
-
set: () => {}
|
|
60
|
+
set: () => { }
|
|
41
61
|
}
|
|
42
62
|
} as any;
|
|
43
63
|
painterMock.renderPass = 'translucent';
|
|
44
64
|
painterMock.transform = {pitch: 0, labelPlaneMatrix: mat4.create()} as any as Transform;
|
|
45
65
|
painterMock.options = {} as any;
|
|
66
|
+
painterMock.style = {terrainSourceCache: {getTerrain: () => null}} as any as Style;
|
|
46
67
|
|
|
47
68
|
const layerSpec = {
|
|
48
69
|
id: 'mock-layer',
|
|
@@ -58,12 +79,12 @@ describe('drawSymbol', () => {
|
|
|
58
79
|
|
|
59
80
|
const tileId = new OverscaledTileID(1, 0, 1, 0, 0);
|
|
60
81
|
tileId.posMatrix = mat4.create();
|
|
61
|
-
const programMock = new Program(null, null, null, null, null, null);
|
|
82
|
+
const programMock = new Program(null, null, null, null, null, null, null);
|
|
62
83
|
(painterMock.useProgram as jest.Mock).mockReturnValue(programMock);
|
|
63
84
|
const bucketMock = new SymbolBucket(null);
|
|
64
85
|
bucketMock.icon = {
|
|
65
86
|
programConfigurations: {
|
|
66
|
-
get: () => {}
|
|
87
|
+
get: () => { }
|
|
67
88
|
},
|
|
68
89
|
segments: {
|
|
69
90
|
get: () => [1]
|
|
@@ -76,7 +97,7 @@ describe('drawSymbol', () => {
|
|
|
76
97
|
const tile = new Tile(tileId, 256);
|
|
77
98
|
tile.tileID = tileId;
|
|
78
99
|
tile.imageAtlasTexture = {
|
|
79
|
-
bind: () => {}
|
|
100
|
+
bind: () => { }
|
|
80
101
|
} as any;
|
|
81
102
|
(tile.getBucket as jest.Mock).mockReturnValue(bucketMock);
|
|
82
103
|
const sourceCacheMock = new SourceCache(null, null, null);
|
|
@@ -94,7 +115,7 @@ describe('drawSymbol', () => {
|
|
|
94
115
|
painterMock.context = {
|
|
95
116
|
gl: {},
|
|
96
117
|
activeTexture: {
|
|
97
|
-
set: () => {}
|
|
118
|
+
set: () => { }
|
|
98
119
|
}
|
|
99
120
|
} as any;
|
|
100
121
|
painterMock.renderPass = 'translucent';
|
|
@@ -119,12 +140,12 @@ describe('drawSymbol', () => {
|
|
|
119
140
|
|
|
120
141
|
const tileId = new OverscaledTileID(1, 0, 1, 0, 0);
|
|
121
142
|
tileId.posMatrix = mat4.create();
|
|
122
|
-
const programMock = new Program(null, null, null, null, null, null);
|
|
143
|
+
const programMock = new Program(null, null, null, null, null, null, null);
|
|
123
144
|
(painterMock.useProgram as jest.Mock).mockReturnValue(programMock);
|
|
124
145
|
const bucketMock = new SymbolBucket(null);
|
|
125
146
|
bucketMock.icon = {
|
|
126
147
|
programConfigurations: {
|
|
127
|
-
get: () => {}
|
|
148
|
+
get: () => { }
|
|
128
149
|
},
|
|
129
150
|
segments: {
|
|
130
151
|
get: () => [1]
|
|
@@ -137,16 +158,19 @@ describe('drawSymbol', () => {
|
|
|
137
158
|
const tile = new Tile(tileId, 256);
|
|
138
159
|
tile.tileID = tileId;
|
|
139
160
|
tile.imageAtlasTexture = {
|
|
140
|
-
bind: () => {}
|
|
161
|
+
bind: () => { }
|
|
141
162
|
} as any;
|
|
142
163
|
(tile.getBucket as jest.Mock).mockReturnValue(bucketMock);
|
|
143
164
|
const sourceCacheMock = new SourceCache(null, null, null);
|
|
144
165
|
(sourceCacheMock.getTile as jest.Mock).mockReturnValue(tile);
|
|
145
166
|
sourceCacheMock.map = {showCollisionBoxes: false} as any as Map;
|
|
167
|
+
painterMock.style = {
|
|
168
|
+
terrainSourceCache: new TerrainSourceCache(new Style(new StubMap() as any as Map))
|
|
169
|
+
} as any as Style;
|
|
146
170
|
|
|
147
171
|
const spy = jest.spyOn(symbolProjection, 'updateLineLabels');
|
|
148
172
|
drawSymbol(painterMock, sourceCacheMock, layer, [tileId], null);
|
|
149
173
|
|
|
150
|
-
expect(spy.mock.calls[0][
|
|
174
|
+
expect(spy.mock.calls[0][9]).toBeFalsy(); // rotateToLine === false
|
|
151
175
|
});
|
|
152
176
|
});
|
|
@@ -9,7 +9,7 @@ import {mat4} from 'gl-matrix';
|
|
|
9
9
|
import StencilMode from '../gl/stencil_mode';
|
|
10
10
|
import DepthMode from '../gl/depth_mode';
|
|
11
11
|
import CullFaceMode from '../gl/cull_face_mode';
|
|
12
|
-
import
|
|
12
|
+
import {addDynamicAttributes} from '../data/bucket/symbol_bucket';
|
|
13
13
|
|
|
14
14
|
import {getAnchorAlignment, WritingMode} from '../symbol/shaping';
|
|
15
15
|
import ONE_EM from '../symbol/one_em';
|
|
@@ -31,6 +31,9 @@ import type {OverscaledTileID} from '../source/tile_id';
|
|
|
31
31
|
import type {UniformValues} from './uniform_binding';
|
|
32
32
|
import type {SymbolSDFUniformsType} from '../render/program/symbol_program';
|
|
33
33
|
import type {CrossTileID, VariableOffset} from '../symbol/placement';
|
|
34
|
+
import type SymbolBucket from '../data/bucket/symbol_bucket';
|
|
35
|
+
import type {SymbolBuffers} from '../data/bucket/symbol_bucket';
|
|
36
|
+
import type {TerrainData} from '../render/terrain';
|
|
34
37
|
import type {SymbolLayerSpecification} from '../style-spec/types.g';
|
|
35
38
|
import type Transform from '../geo/transform';
|
|
36
39
|
import type ColorMode from '../gl/color_mode';
|
|
@@ -39,6 +42,7 @@ import type Program from './program';
|
|
|
39
42
|
type SymbolTileRenderState = {
|
|
40
43
|
segments: SegmentVector;
|
|
41
44
|
sortKey: number;
|
|
45
|
+
terrainData: TerrainData;
|
|
42
46
|
state: {
|
|
43
47
|
program: Program<any>;
|
|
44
48
|
buffers: SymbolBuffers;
|
|
@@ -145,8 +149,9 @@ function updateVariableAnchors(coords: Array<OverscaledTileID>,
|
|
|
145
149
|
|
|
146
150
|
if (size) {
|
|
147
151
|
const tileScale = Math.pow(2, tr.zoom - tile.tileID.overscaledZ);
|
|
152
|
+
const getElevation = painter.style.terrain ? (x: number, y: number) => painter.style.terrain.getElevation(coord, x, y) : null;
|
|
148
153
|
updateVariableAnchorsForBucket(bucket, rotateWithMap, pitchWithMap, variableOffsets,
|
|
149
|
-
tr, labelPlaneMatrix, coord.posMatrix, tileScale, size, updateTextFitIcon);
|
|
154
|
+
tr, labelPlaneMatrix, coord.posMatrix, tileScale, size, updateTextFitIcon, getElevation);
|
|
150
155
|
}
|
|
151
156
|
}
|
|
152
157
|
}
|
|
@@ -161,7 +166,8 @@ function updateVariableAnchorsForBucket(
|
|
|
161
166
|
posMatrix: mat4,
|
|
162
167
|
tileScale: number,
|
|
163
168
|
size: EvaluatedZoomSize,
|
|
164
|
-
updateTextFitIcon: boolean
|
|
169
|
+
updateTextFitIcon: boolean,
|
|
170
|
+
getElevation: (x: number, y: number) => number) {
|
|
165
171
|
const placedSymbols = bucket.text.placedSymbolArray;
|
|
166
172
|
const dynamicTextLayoutVertexArray = bucket.text.dynamicLayoutVertexArray;
|
|
167
173
|
const dynamicIconLayoutVertexArray = bucket.icon.dynamicLayoutVertexArray;
|
|
@@ -179,7 +185,7 @@ function updateVariableAnchorsForBucket(
|
|
|
179
185
|
symbolProjection.hideGlyphs(symbol.numGlyphs, dynamicTextLayoutVertexArray);
|
|
180
186
|
} else {
|
|
181
187
|
const tileAnchor = new Point(symbol.anchorX, symbol.anchorY);
|
|
182
|
-
const projectedAnchor = symbolProjection.project(tileAnchor, pitchWithMap ? posMatrix : labelPlaneMatrix);
|
|
188
|
+
const projectedAnchor = symbolProjection.project(tileAnchor, pitchWithMap ? posMatrix : labelPlaneMatrix, getElevation);
|
|
183
189
|
const perspectiveRatio = symbolProjection.getPerspectiveRatio(transform.cameraToCenterDistance, projectedAnchor.signedDistanceFromCamera);
|
|
184
190
|
let renderTextSize = evaluateSizeForFeature(bucket.textSizeData, size, symbol) * perspectiveRatio / ONE_EM;
|
|
185
191
|
if (pitchWithMap) {
|
|
@@ -196,7 +202,7 @@ function updateVariableAnchorsForBucket(
|
|
|
196
202
|
// calculated above. In the (somewhat weird) case of pitch-aligned text, we add an equivalent
|
|
197
203
|
// tile-unit based shift to the anchor before projecting to the label plane.
|
|
198
204
|
const shiftedAnchor = pitchWithMap ?
|
|
199
|
-
symbolProjection.project(tileAnchor.add(shift), labelPlaneMatrix).point :
|
|
205
|
+
symbolProjection.project(tileAnchor.add(shift), labelPlaneMatrix, getElevation).point :
|
|
200
206
|
projectedAnchor.point.add(rotateWithMap ?
|
|
201
207
|
shift.rotate(-transform.angle) :
|
|
202
208
|
shift);
|
|
@@ -295,6 +301,7 @@ function drawLayerSymbols(
|
|
|
295
301
|
|
|
296
302
|
const program = painter.useProgram(getSymbolProgramName(isSDF, isText, bucket), programConfiguration);
|
|
297
303
|
const size = evaluateSizeForZoom(sizeData, tr.zoom);
|
|
304
|
+
const terrainData = painter.style.terrain && painter.style.terrain.getTerrainData(coord);
|
|
298
305
|
|
|
299
306
|
let texSize: [number, number];
|
|
300
307
|
let texSizeIcon: [number, number] = [0, 0];
|
|
@@ -331,8 +338,9 @@ function drawLayerSymbols(
|
|
|
331
338
|
bucket.hasIconData();
|
|
332
339
|
|
|
333
340
|
if (alongLine) {
|
|
341
|
+
const getElevation = painter.style.terrain ? (x: number, y: number) => painter.style.terrain.getElevation(coord, x, y) : null;
|
|
334
342
|
const rotateToLine = layer.layout.get('text-rotation-alignment') === 'map';
|
|
335
|
-
symbolProjection.updateLineLabels(bucket, coord.posMatrix, painter, isText, labelPlaneMatrix, glCoordMatrix, pitchWithMap, keepUpright, rotateToLine);
|
|
343
|
+
symbolProjection.updateLineLabels(bucket, coord.posMatrix, painter, isText, labelPlaneMatrix, glCoordMatrix, pitchWithMap, keepUpright, rotateToLine, getElevation);
|
|
336
344
|
}
|
|
337
345
|
|
|
338
346
|
const matrix = painter.translatePosMatrix(coord.posMatrix, tile, translate, translateAnchor),
|
|
@@ -377,14 +385,16 @@ function drawLayerSymbols(
|
|
|
377
385
|
tileRenderState.push({
|
|
378
386
|
segments: new SegmentVector([segment]),
|
|
379
387
|
sortKey: segment.sortKey,
|
|
380
|
-
state
|
|
388
|
+
state,
|
|
389
|
+
terrainData
|
|
381
390
|
});
|
|
382
391
|
}
|
|
383
392
|
} else {
|
|
384
393
|
tileRenderState.push({
|
|
385
394
|
segments: buffers.segments,
|
|
386
395
|
sortKey: 0,
|
|
387
|
-
state
|
|
396
|
+
state,
|
|
397
|
+
terrainData
|
|
388
398
|
});
|
|
389
399
|
}
|
|
390
400
|
}
|
|
@@ -409,11 +419,11 @@ function drawLayerSymbols(
|
|
|
409
419
|
const uniformValues = state.uniformValues;
|
|
410
420
|
if (state.hasHalo) {
|
|
411
421
|
uniformValues['u_is_halo'] = 1;
|
|
412
|
-
drawSymbolElements(state.buffers, segmentState.segments, layer, painter, state.program, depthMode, stencilMode, colorMode, uniformValues);
|
|
422
|
+
drawSymbolElements(state.buffers, segmentState.segments, layer, painter, state.program, depthMode, stencilMode, colorMode, uniformValues, segmentState.terrainData);
|
|
413
423
|
}
|
|
414
424
|
uniformValues['u_is_halo'] = 0;
|
|
415
425
|
}
|
|
416
|
-
drawSymbolElements(state.buffers, segmentState.segments, layer, painter, state.program, depthMode, stencilMode, colorMode, state.uniformValues);
|
|
426
|
+
drawSymbolElements(state.buffers, segmentState.segments, layer, painter, state.program, depthMode, stencilMode, colorMode, state.uniformValues, segmentState.terrainData);
|
|
417
427
|
}
|
|
418
428
|
}
|
|
419
429
|
|
|
@@ -426,11 +436,12 @@ function drawSymbolElements(
|
|
|
426
436
|
depthMode: Readonly<DepthMode>,
|
|
427
437
|
stencilMode: StencilMode,
|
|
428
438
|
colorMode: Readonly<ColorMode>,
|
|
429
|
-
uniformValues: UniformValues<SymbolSDFUniformsType | SymbolIconUniformsType
|
|
439
|
+
uniformValues: UniformValues<SymbolSDFUniformsType | SymbolIconUniformsType>,
|
|
440
|
+
terrainData: TerrainData) {
|
|
430
441
|
const context = painter.context;
|
|
431
442
|
const gl = context.gl;
|
|
432
443
|
program.draw(context, gl.TRIANGLES, depthMode, stencilMode, colorMode, CullFaceMode.disabled,
|
|
433
|
-
uniformValues, layer.id, buffers.layoutVertexBuffer,
|
|
444
|
+
uniformValues, terrainData, layer.id, buffers.layoutVertexBuffer,
|
|
434
445
|
buffers.indexBuffer, segments, layer.paint,
|
|
435
446
|
painter.transform.zoom, buffers.programConfigurations.get(layer.id),
|
|
436
447
|
buffers.dynamicLayoutVertexBuffer, buffers.opacityVertexBuffer);
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import StencilMode from '../gl/stencil_mode';
|
|
2
|
+
import DepthMode from '../gl/depth_mode';
|
|
3
|
+
import {terrainUniformValues, terrainDepthUniformValues, terrainCoordsUniformValues} from './program/terrain_program';
|
|
4
|
+
import type Painter from './painter';
|
|
5
|
+
import type Tile from '../source/tile';
|
|
6
|
+
import CullFaceMode from '../gl/cull_face_mode';
|
|
7
|
+
import Texture from './texture';
|
|
8
|
+
import Color from '../style-spec/util/color';
|
|
9
|
+
import ColorMode from '../gl/color_mode';
|
|
10
|
+
import Terrain from './terrain';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Redraw the Depth Framebuffer
|
|
14
|
+
* @param {Painter} painter - the painter
|
|
15
|
+
* @param {Terrain} terrain - the terrain
|
|
16
|
+
*/
|
|
17
|
+
function drawDepth(painter: Painter, terrain: Terrain) {
|
|
18
|
+
const context = painter.context;
|
|
19
|
+
const gl = context.gl;
|
|
20
|
+
const colorMode = ColorMode.unblended;
|
|
21
|
+
const depthMode = new DepthMode(gl.LEQUAL, DepthMode.ReadWrite, [0, 1]);
|
|
22
|
+
const mesh = terrain.getTerrainMesh();
|
|
23
|
+
const tiles = terrain.sourceCache.getRenderableTiles();
|
|
24
|
+
const program = painter.useProgram('terrainDepth');
|
|
25
|
+
context.bindFramebuffer.set(terrain.getFramebuffer('depth').framebuffer);
|
|
26
|
+
context.viewport.set([0, 0, painter.width / devicePixelRatio, painter.height / devicePixelRatio]);
|
|
27
|
+
context.clear({color: Color.transparent, depth: 1});
|
|
28
|
+
for (const tile of tiles) {
|
|
29
|
+
const terrainData = terrain.getTerrainData(tile.tileID);
|
|
30
|
+
const posMatrix = painter.transform.calculatePosMatrix(tile.tileID.toUnwrapped());
|
|
31
|
+
const uniformValues = terrainDepthUniformValues(posMatrix);
|
|
32
|
+
program.draw(context, gl.TRIANGLES, depthMode, StencilMode.disabled, colorMode, CullFaceMode.backCCW, uniformValues, terrainData, 'terrain', mesh.vertexBuffer, mesh.indexBuffer, mesh.segments);
|
|
33
|
+
}
|
|
34
|
+
context.bindFramebuffer.set(null);
|
|
35
|
+
context.viewport.set([0, 0, painter.width, painter.height]);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Redraw the Coords Framebuffers
|
|
40
|
+
* @param {Painter} painter - the painter
|
|
41
|
+
* @param {Terrain} terrain - the terrain
|
|
42
|
+
*/
|
|
43
|
+
function drawCoords(painter: Painter, terrain: Terrain) {
|
|
44
|
+
const context = painter.context;
|
|
45
|
+
const gl = context.gl;
|
|
46
|
+
const colorMode = ColorMode.unblended;
|
|
47
|
+
const depthMode = new DepthMode(gl.LEQUAL, DepthMode.ReadWrite, [0, 1]);
|
|
48
|
+
const mesh = terrain.getTerrainMesh();
|
|
49
|
+
const coords = terrain.getCoordsTexture();
|
|
50
|
+
const tiles = terrain.sourceCache.getRenderableTiles();
|
|
51
|
+
|
|
52
|
+
// draw tile-coords into framebuffer
|
|
53
|
+
const program = painter.useProgram('terrainCoords');
|
|
54
|
+
context.bindFramebuffer.set(terrain.getFramebuffer('coords').framebuffer);
|
|
55
|
+
context.viewport.set([0, 0, painter.width / devicePixelRatio, painter.height / devicePixelRatio]);
|
|
56
|
+
context.clear({color: Color.transparent, depth: 1});
|
|
57
|
+
terrain.coordsIndex = [];
|
|
58
|
+
for (const tile of tiles) {
|
|
59
|
+
const terrainData = terrain.getTerrainData(tile.tileID);
|
|
60
|
+
context.activeTexture.set(gl.TEXTURE0);
|
|
61
|
+
gl.bindTexture(gl.TEXTURE_2D, coords.texture);
|
|
62
|
+
const posMatrix = painter.transform.calculatePosMatrix(tile.tileID.toUnwrapped());
|
|
63
|
+
const uniformValues = terrainCoordsUniformValues(posMatrix, 255 - terrain.coordsIndex.length);
|
|
64
|
+
program.draw(context, gl.TRIANGLES, depthMode, StencilMode.disabled, colorMode, CullFaceMode.backCCW, uniformValues, terrainData, 'terrain', mesh.vertexBuffer, mesh.indexBuffer, mesh.segments);
|
|
65
|
+
terrain.coordsIndex.push(tile.tileID.key);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
context.bindFramebuffer.set(null);
|
|
69
|
+
context.viewport.set([0, 0, painter.width, painter.height]);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Render, e.g. drape, a render-to-texture tile onto the 3d mesh on screen.
|
|
74
|
+
* @param {Painter} painter - the painter
|
|
75
|
+
* @param {Terrain} terrain - the source cache
|
|
76
|
+
* @param {Tile} tile - the tile
|
|
77
|
+
*/
|
|
78
|
+
function drawTerrain(painter: Painter, terrain: Terrain, tile: Tile) {
|
|
79
|
+
const context = painter.context;
|
|
80
|
+
const gl = context.gl;
|
|
81
|
+
const colorMode = painter.colorModeForRenderPass();
|
|
82
|
+
const depthMode = new DepthMode(gl.LEQUAL, DepthMode.ReadWrite, painter.depthRangeFor3D);
|
|
83
|
+
const program = painter.useProgram('terrain');
|
|
84
|
+
const mesh = terrain.getTerrainMesh();
|
|
85
|
+
const terrainData = terrain.getTerrainData(tile.tileID);
|
|
86
|
+
|
|
87
|
+
context.bindFramebuffer.set(null);
|
|
88
|
+
context.viewport.set([0, 0, painter.width, painter.height]);
|
|
89
|
+
context.activeTexture.set(gl.TEXTURE0);
|
|
90
|
+
gl.bindTexture(gl.TEXTURE_2D, terrain.getRTTFramebuffer().colorAttachment.get());
|
|
91
|
+
const posMatrix = painter.transform.calculatePosMatrix(tile.tileID.toUnwrapped());
|
|
92
|
+
const uniformValues = terrainUniformValues(posMatrix);
|
|
93
|
+
program.draw(context, gl.TRIANGLES, depthMode, StencilMode.disabled, colorMode, CullFaceMode.backCCW, uniformValues, terrainData, 'terrain', mesh.vertexBuffer, mesh.indexBuffer, mesh.segments);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* prepare the render-to-texture tile.
|
|
98
|
+
* E.g. creates the necessary textures and attach them to the render-to-texture-framebuffer.
|
|
99
|
+
* @param {Painter} painter - the painter
|
|
100
|
+
* @param {Terrain} terrain - the terrain
|
|
101
|
+
* @param {Tile} tile - the tile
|
|
102
|
+
* @param {number} stack number of a layer-groop. see painter.ts
|
|
103
|
+
*/
|
|
104
|
+
function prepareTerrain(painter: Painter, terrain: Terrain, tile: Tile, stack: number) {
|
|
105
|
+
const context = painter.context;
|
|
106
|
+
const size = tile.tileSize * terrain.qualityFactor;
|
|
107
|
+
if (!tile.textures[stack]) {
|
|
108
|
+
tile.textures[stack] = painter.getTileTexture(size) || new Texture(context, {width: size, height: size, data: null}, context.gl.RGBA);
|
|
109
|
+
tile.textures[stack].bind(context.gl.LINEAR, context.gl.CLAMP_TO_EDGE);
|
|
110
|
+
if (stack === 0) terrain.sourceCache.renderHistory.push(tile.tileID.key);
|
|
111
|
+
}
|
|
112
|
+
const fb = terrain.getRTTFramebuffer();
|
|
113
|
+
fb.colorAttachment.set(tile.textures[stack].texture);
|
|
114
|
+
context.bindFramebuffer.set(fb.framebuffer);
|
|
115
|
+
context.viewport.set([0, 0, size, size]);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export {
|
|
119
|
+
prepareTerrain,
|
|
120
|
+
drawTerrain,
|
|
121
|
+
drawDepth,
|
|
122
|
+
drawCoords
|
|
123
|
+
};
|