@tangram.gl/tangram-renderer 0.0.0-stage → 0.0.0
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/README.md +59 -2
- package/dist/core.js +36923 -0
- package/dist/core.js.map +6 -0
- package/dist/index.js +32 -0
- package/dist/loaders-gl-worker.js +82 -0
- package/dist/loaders-gl-worker.js.map +6 -0
- package/dist/map-logic.js +2 -0
- package/dist/map-logic.js.map +6 -0
- package/dist/projected-basemaps-worker.js +3 -0
- package/dist/projected-basemaps-worker.js.map +6 -0
- package/dist/shader-modules.js +141 -0
- package/dist/shader-modules.js.map +6 -0
- package/dist/style-schema.js +126 -0
- package/dist/style-schema.js.map +6 -0
- package/dist/tangram-style.schema.json +882 -0
- package/dist/tangram.debug.mjs +37139 -0
- package/dist/tangram.debug.mjs.map +6 -0
- package/dist/tangram.min.mjs +4950 -0
- package/dist/types/builders/earcut.d.ts +15 -0
- package/dist/types/core.d.ts +29 -0
- package/dist/types/gl/constants.d.ts +2 -0
- package/dist/types/gl/globe_mesh.d.ts +48 -0
- package/dist/types/gl/glsl.d.ts +17 -0
- package/dist/types/gl/vertex-constants.d.ts +4 -0
- package/dist/types/gl/vertex-types.d.ts +34 -0
- package/dist/types/gl/vertex_data.d.ts +32 -0
- package/dist/types/gl/vertex_elements.d.ts +8 -0
- package/dist/types/gl/vertex_layout.d.ts +32 -0
- package/dist/types/glsl.d.ts +14 -0
- package/dist/types/gpu/luma_device_renderer.d.ts +66 -0
- package/dist/types/gpu/resource_lifecycle.d.ts +4 -0
- package/dist/types/gpu/tangram_gpu_backend.d.ts +151 -0
- package/dist/types/index.d.ts +155 -0
- package/dist/types/lights/light-definitions.d.ts +121 -0
- package/dist/types/map-logic/draped-terrain-bounds.d.ts +41 -0
- package/dist/types/map-logic/globe-terrain-preparation.d.ts +85 -0
- package/dist/types/map-logic/globe-terrain.d.ts +54 -0
- package/dist/types/map-logic/index.d.ts +33 -0
- package/dist/types/map-logic/label-identity.d.ts +22 -0
- package/dist/types/map-logic/label-placement.d.ts +32 -0
- package/dist/types/map-logic/screen-bounds.d.ts +15 -0
- package/dist/types/map-logic/terrain-data.d.ts +55 -0
- package/dist/types/map-logic/terrain-error.d.ts +51 -0
- package/dist/types/map-logic/terrain-ground-topology.d.ts +26 -0
- package/dist/types/map-logic/terrain-height-field.d.ts +59 -0
- package/dist/types/map-logic/terrain-navigation.d.ts +27 -0
- package/dist/types/map-logic/terrain-neighborhood.d.ts +5 -0
- package/dist/types/map-logic/terrain-query.d.ts +33 -0
- package/dist/types/map-logic/terrain-resource-budget.d.ts +51 -0
- package/dist/types/map-logic/terrain-transition-topology.d.ts +23 -0
- package/dist/types/map-logic/tile-build-queue.d.ts +51 -0
- package/dist/types/map-logic/tile-cache-policy.d.ts +46 -0
- package/dist/types/map-logic/tile-residency.d.ts +17 -0
- package/dist/types/map-logic/triangle-query-index.d.ts +87 -0
- package/dist/types/procedures/js-yaml.d.ts +15 -0
- package/dist/types/procedures/mesh-projector.d.ts +107 -0
- package/dist/types/procedures/mvt-dependencies.d.ts +20 -0
- package/dist/types/procedures/projected-coordinate-transform.d.ts +27 -0
- package/dist/types/procedures/projection-batch-executor.d.ts +53 -0
- package/dist/types/procedures/scene-yaml-legacy.d.ts +6 -0
- package/dist/types/procedures/terrain-draping.d.ts +165 -0
- package/dist/types/procedures/terrain-globe.d.ts +6 -0
- package/dist/types/procedures/terrain-styled-topology.d.ts +34 -0
- package/dist/types/procedures/web-mercator-legacy.d.ts +4 -0
- package/dist/types/procedures/web-mercator-math.d.ts +4 -0
- package/dist/types/scene/globals.d.ts +11 -0
- package/dist/types/scene/ground_footprint.d.ts +16 -0
- package/dist/types/scene/host_frame.d.ts +54 -0
- package/dist/types/scene/projection_math.d.ts +52 -0
- package/dist/types/scene/scene-resource-types.d.ts +177 -0
- package/dist/types/scene/scene_bundle.d.ts +69 -0
- package/dist/types/scene/visibility_adapter.d.ts +106 -0
- package/dist/types/selection/draped-terrain-surface.d.ts +78 -0
- package/dist/types/selection/terrain_surface.d.ts +149 -0
- package/dist/types/shader-modules/globe-horizon.d.ts +15 -0
- package/dist/types/shader-modules/height-decode.d.ts +13 -0
- package/dist/types/shader-modules/hillshade.d.ts +13 -0
- package/dist/types/shader-modules/index.d.ts +6 -0
- package/dist/types/shader-modules/planar.d.ts +12 -0
- package/dist/types/shader-modules/sphere-map.d.ts +13 -0
- package/dist/types/shader-modules/triplanar.d.ts +15 -0
- package/dist/types/sources/decoded_tile_store.d.ts +95 -0
- package/dist/types/sources/tile_source_metadata.d.ts +32 -0
- package/dist/types/styles/text/fontfaceobserver.d.ts +10 -0
- package/dist/types/tile/tile_id.d.ts +37 -0
- package/dist/types/tile/tile_traversal_adapter.d.ts +63 -0
- package/dist/types/types.d.ts +293 -0
- package/dist/types/utils/geo.d.ts +57 -0
- package/dist/types/utils/hash.d.ts +1 -0
- package/dist/types/utils/log.d.ts +27 -0
- package/dist/types/utils/props.d.ts +6 -0
- package/dist/types/utils/subscribe.d.ts +10 -0
- package/dist/types/utils/thread.d.ts +6 -0
- package/dist/types/utils/urls.d.ts +26 -0
- package/dist/types/utils/utils.d.ts +26 -0
- package/dist/types/utils/version.d.ts +2 -0
- package/dist/types/utils/worker-types.d.ts +68 -0
- package/dist/types/utils/worker_broker.d.ts +3 -0
- package/package.json +103 -3
- package/src/builders/common.ts +41 -0
- package/src/builders/earcut.d.ts +15 -0
- package/src/builders/geometry-types.ts +60 -0
- package/src/builders/points.ts +115 -0
- package/src/builders/polygons.ts +225 -0
- package/src/builders/polylines.ts +682 -0
- package/src/builders/wireframe.ts +31 -0
- package/src/core.d.ts +29 -0
- package/src/core.ts +33 -0
- package/src/experimental/loaders-gl-worker.ts +19 -0
- package/src/experimental/projected-basemaps-worker.ts +13 -0
- package/src/experimental/projected-mesh-cache.ts +137 -0
- package/src/experimental/projected-mesh-domain.ts +110 -0
- package/src/experimental/projected-mesh-refinement.ts +193 -0
- package/src/experimental/projected-mesh.ts +399 -0
- package/src/experimental/projected-normal.ts +26 -0
- package/src/experimental/projected-symbol-mesh.ts +74 -0
- package/src/gl/constants.ts +18 -0
- package/src/gl/context.ts +103 -0
- package/src/gl/extensions.ts +30 -0
- package/src/gl/globe_mesh.ts +285 -0
- package/src/gl/glsl.ts +257 -0
- package/src/gl/mesh-types.ts +56 -0
- package/src/gl/render_state.ts +111 -0
- package/src/gl/shader_program.ts +1310 -0
- package/src/gl/texture.ts +814 -0
- package/src/gl/uniform_buffer.ts +340 -0
- package/src/gl/vao.ts +154 -0
- package/src/gl/vbo_mesh.ts +349 -0
- package/src/gl/vertex-constants.ts +19 -0
- package/src/gl/vertex-types.ts +35 -0
- package/src/gl/vertex_data.ts +126 -0
- package/src/gl/vertex_elements.ts +54 -0
- package/src/gl/vertex_layout.ts +241 -0
- package/src/glsl.d.ts +14 -0
- package/src/gpu/luma_device_renderer.ts +579 -0
- package/src/gpu/pixel_readback.ts +51 -0
- package/src/gpu/resource_lifecycle.ts +32 -0
- package/src/gpu/tangram_gpu_backend.ts +195 -0
- package/src/index.d.ts +155 -0
- package/src/index.ts +105 -0
- package/src/labels/collision-types.ts +94 -0
- package/src/labels/collision.ts +273 -0
- package/src/labels/collision_grid.ts +61 -0
- package/src/labels/intersect.ts +30 -0
- package/src/labels/label-types.ts +91 -0
- package/src/labels/label.ts +207 -0
- package/src/labels/label_line.ts +801 -0
- package/src/labels/label_point.ts +131 -0
- package/src/labels/main-pass-types.ts +73 -0
- package/src/labels/main_pass.ts +221 -0
- package/src/labels/point_anchor.ts +100 -0
- package/src/labels/point_placement.ts +150 -0
- package/src/labels/projected-pass.ts +259 -0
- package/src/labels/repeat_group.ts +72 -0
- package/src/lights/ambient_light.glsl +18 -0
- package/src/lights/directional_light.glsl +39 -0
- package/src/lights/geographic-lights.ts +21 -0
- package/src/lights/light-definitions.ts +285 -0
- package/src/lights/light.ts +590 -0
- package/src/lights/lighting-uniforms.ts +80 -0
- package/src/lights/lighting-wgsl.ts +116 -0
- package/src/lights/material.glsl +237 -0
- package/src/lights/material.ts +145 -0
- package/src/lights/native-falloff.ts +37 -0
- package/src/lights/point_light.glsl +96 -0
- package/src/lights/spot_light.glsl +111 -0
- package/src/map-logic/draped-terrain-bounds.ts +71 -0
- package/src/map-logic/globe-terrain-preparation.ts +217 -0
- package/src/map-logic/globe-terrain.ts +296 -0
- package/src/map-logic/index.ts +37 -0
- package/src/map-logic/label-identity.ts +36 -0
- package/src/map-logic/label-placement.ts +117 -0
- package/src/map-logic/screen-bounds.ts +34 -0
- package/src/map-logic/terrain-data.ts +107 -0
- package/src/map-logic/terrain-error.ts +134 -0
- package/src/map-logic/terrain-ground-topology.ts +164 -0
- package/src/map-logic/terrain-height-field.ts +254 -0
- package/src/map-logic/terrain-navigation.ts +50 -0
- package/src/map-logic/terrain-neighborhood.ts +43 -0
- package/src/map-logic/terrain-query.ts +51 -0
- package/src/map-logic/terrain-resource-budget.ts +124 -0
- package/src/map-logic/terrain-transition-topology.ts +164 -0
- package/src/map-logic/tile-build-queue.ts +110 -0
- package/src/map-logic/tile-cache-policy.ts +89 -0
- package/src/map-logic/tile-residency.ts +50 -0
- package/src/map-logic/triangle-query-index.ts +265 -0
- package/src/procedures/js-yaml.d.ts +15 -0
- package/src/procedures/mesh-projector.ts +191 -0
- package/src/procedures/mlt-loaders.ts +55 -0
- package/src/procedures/mvt-dependencies.d.ts +20 -0
- package/src/procedures/mvt-legacy.ts +150 -0
- package/src/procedures/mvt-loaders.ts +53 -0
- package/src/procedures/mvt-parser.ts +48 -0
- package/src/procedures/mvt-properties.ts +36 -0
- package/src/procedures/mvt-tile-provider.ts +72 -0
- package/src/procedures/pmtiles-loader.ts +75 -0
- package/src/procedures/projected-coordinate-transform.ts +79 -0
- package/src/procedures/projection-batch-executor.ts +140 -0
- package/src/procedures/scene-yaml-legacy.ts +16 -0
- package/src/procedures/scene-yaml-loaders.ts +10 -0
- package/src/procedures/terrain-draping.ts +713 -0
- package/src/procedures/terrain-globe.ts +32 -0
- package/src/procedures/terrain-styled-topology.ts +184 -0
- package/src/procedures/web-mercator-legacy.ts +24 -0
- package/src/procedures/web-mercator-math.ts +50 -0
- package/src/scene/camera.ts +298 -0
- package/src/scene/camera_base.ts +116 -0
- package/src/scene/classic_scene.ts +20 -0
- package/src/scene/external_camera.ts +101 -0
- package/src/scene/globals.ts +120 -0
- package/src/scene/ground_footprint.ts +139 -0
- package/src/scene/host_frame.ts +326 -0
- package/src/scene/projected_tile_lod.ts +125 -0
- package/src/scene/projection_math.ts +142 -0
- package/src/scene/projection_shaders.ts +183 -0
- package/src/scene/renderer.ts +516 -0
- package/src/scene/scene-resource-types.ts +174 -0
- package/src/scene/scene.ts +2378 -0
- package/src/scene/scene_bundle.ts +304 -0
- package/src/scene/scene_debug.ts +129 -0
- package/src/scene/scene_loader.ts +402 -0
- package/src/scene/scene_worker.ts +528 -0
- package/src/scene/view.ts +683 -0
- package/src/scene/visibility_adapter.ts +319 -0
- package/src/scene/worker_url.ts +15 -0
- package/src/selection/draped-terrain-surface.ts +377 -0
- package/src/selection/selection-types.ts +79 -0
- package/src/selection/selection.ts +542 -0
- package/src/selection/selection_fragment.glsl +18 -0
- package/src/selection/selection_globals.glsl +9 -0
- package/src/selection/selection_pixels.ts +59 -0
- package/src/selection/selection_vertex.glsl +15 -0
- package/src/selection/terrain_surface.ts +298 -0
- package/src/shader-modules/globe-horizon.ts +52 -0
- package/src/shader-modules/height-decode.ts +41 -0
- package/src/shader-modules/hillshade.ts +70 -0
- package/src/shader-modules/index.ts +10 -0
- package/src/shader-modules/planar.ts +24 -0
- package/src/shader-modules/sphere-map.ts +38 -0
- package/src/shader-modules/triplanar.ts +45 -0
- package/src/sources/aligned_tile_source.ts +122 -0
- package/src/sources/data_source.ts +655 -0
- package/src/sources/decoded_tile_store.ts +245 -0
- package/src/sources/geojson.ts +300 -0
- package/src/sources/mvt.ts +247 -0
- package/src/sources/raster.ts +341 -0
- package/src/sources/shared_tile_source_adapter.ts +117 -0
- package/src/sources/sources.ts +10 -0
- package/src/sources/tile_source_adapter.ts +84 -0
- package/src/sources/tile_source_metadata.ts +65 -0
- package/src/sources/tile_source_state.ts +112 -0
- package/src/sources/topojson.ts +90 -0
- package/src/styles/feature_annotations.ts +16 -0
- package/src/styles/filter.ts +190 -0
- package/src/styles/geometry-style-types.ts +209 -0
- package/src/styles/globe_visibility_wgsl.ts +22 -0
- package/src/styles/layer-types.ts +45 -0
- package/src/styles/layer.ts +586 -0
- package/src/styles/lines/dasharray.ts +49 -0
- package/src/styles/lines/lines.ts +707 -0
- package/src/styles/lines/lines_wgsl.ts +224 -0
- package/src/styles/points/point-runtime-types.ts +125 -0
- package/src/styles/points/points.ts +1079 -0
- package/src/styles/points/points_fragment.glsl +126 -0
- package/src/styles/points/points_vertex.glsl +230 -0
- package/src/styles/points/points_wgsl.ts +189 -0
- package/src/styles/polygons/polygons.ts +268 -0
- package/src/styles/polygons/polygons_fragment.glsl +173 -0
- package/src/styles/polygons/polygons_vertex.glsl +213 -0
- package/src/styles/polygons/polygons_wgsl.ts +127 -0
- package/src/styles/property-types.ts +125 -0
- package/src/styles/raster/raster.ts +33 -0
- package/src/styles/raster/raster_globals.glsl +46 -0
- package/src/styles/style-mixing-types.ts +101 -0
- package/src/styles/style-runtime-types.ts +220 -0
- package/src/styles/style-schema.ts +133 -0
- package/src/styles/style.ts +1033 -0
- package/src/styles/style_globals.glsl +69 -0
- package/src/styles/style_manager.ts +464 -0
- package/src/styles/style_parser.ts +620 -0
- package/src/styles/text/font_manager.ts +180 -0
- package/src/styles/text/fontfaceobserver.d.ts +10 -0
- package/src/styles/text/text-types.ts +220 -0
- package/src/styles/text/text.ts +378 -0
- package/src/styles/text/text_canvas.ts +773 -0
- package/src/styles/text/text_labels.ts +436 -0
- package/src/styles/text/text_segments.ts +142 -0
- package/src/styles/text/text_settings.ts +228 -0
- package/src/styles/text/text_wgsl.ts +159 -0
- package/src/styles/text/text_wrap.ts +194 -0
- package/src/tile/globe_tile_preload.ts +40 -0
- package/src/tile/tangram_tileset_2d.ts +108 -0
- package/src/tile/tile-build-types.ts +155 -0
- package/src/tile/tile.ts +807 -0
- package/src/tile/tile_id.ts +172 -0
- package/src/tile/tile_manager.ts +889 -0
- package/src/tile/tile_pyramid.ts +119 -0
- package/src/tile/tile_resource_cache.ts +91 -0
- package/src/tile/tile_traversal_adapter.ts +132 -0
- package/src/types.ts +332 -0
- package/src/utils/debounce.ts +17 -0
- package/src/utils/debug_settings.ts +43 -0
- package/src/utils/errors.ts +12 -0
- package/src/utils/functions.ts +95 -0
- package/src/utils/geo.ts +364 -0
- package/src/utils/hash.ts +14 -0
- package/src/utils/log.ts +108 -0
- package/src/utils/media_capture.ts +193 -0
- package/src/utils/merge.ts +44 -0
- package/src/utils/obb.ts +134 -0
- package/src/utils/props.ts +43 -0
- package/src/utils/slice.ts +14 -0
- package/src/utils/subscribe.ts +58 -0
- package/src/utils/task.ts +154 -0
- package/src/utils/thread.ts +26 -0
- package/src/utils/urls.ts +223 -0
- package/src/utils/utils.ts +310 -0
- package/src/utils/vector.ts +197 -0
- package/src/utils/version.ts +8 -0
- package/src/utils/worker-types.ts +79 -0
- package/src/utils/worker_broker.ts +523 -0
|
@@ -0,0 +1,707 @@
|
|
|
1
|
+
// Tangram
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) 2013-2016 Brett Camper and Mapzen
|
|
4
|
+
// Copyright (c) 2026 vis.gl contributors
|
|
5
|
+
|
|
6
|
+
// Line rendering style
|
|
7
|
+
|
|
8
|
+
import type {LineStyleRuntime, GeometryFeature, GeometryDraw, RawGeometryDraw, GeometryContext, GeometryMeshVariant, LineFeatureStyle, GeometryBuildMesh, GeometryTile, GeometryTileData, GeometryExtrusion, GeometryOutlineDraw} from '../geometry-style-types';
|
|
9
|
+
import type {GeometryLine, GeometryPolygon, PolylineVertexIndices} from '../../builders/geometry-types';
|
|
10
|
+
import type {PropertyCache} from '../property-types';
|
|
11
|
+
import type UniformBuffer from '../../gl/uniform_buffer';
|
|
12
|
+
|
|
13
|
+
import log from '../../utils/log';
|
|
14
|
+
import {Style} from '../style';
|
|
15
|
+
import StyleParser from '../style_parser';
|
|
16
|
+
import gl from '../../gl/constants'; // web workers don't have access to GL context, so import all GL constants
|
|
17
|
+
import Texture from '../../gl/texture';
|
|
18
|
+
import VertexLayout from '../../gl/vertex_layout';
|
|
19
|
+
import {buildPolylines} from '../../builders/polylines';
|
|
20
|
+
import renderDashArray from './dasharray';
|
|
21
|
+
import Geo from '../../utils/geo';
|
|
22
|
+
|
|
23
|
+
import WorkerBroker from '../../utils/worker_broker';
|
|
24
|
+
import hashString from '../../utils/hash';
|
|
25
|
+
|
|
26
|
+
import polygons_vs from '../polygons/polygons_vertex.glsl';
|
|
27
|
+
import polygons_fs from '../polygons/polygons_fragment.glsl';
|
|
28
|
+
import {buildLinesWGSL} from './lines_wgsl';
|
|
29
|
+
import {GLOBE_PROJECTION_GLSL, TERRAIN_DRAPING_GLSL} from '../../scene/projection_shaders';
|
|
30
|
+
import {getProjectedRoadUnit} from '../../procedures/mesh-projector';
|
|
31
|
+
|
|
32
|
+
export const Lines: LineStyleRuntime = Object.create(Style);
|
|
33
|
+
|
|
34
|
+
const DASH_SCALE = 20; // adjustment factor for UV scale to for line dash patterns w/fractional pixel width
|
|
35
|
+
|
|
36
|
+
Object.assign(Lines, {
|
|
37
|
+
name: 'lines',
|
|
38
|
+
built_in: true,
|
|
39
|
+
vertex_shader_src: polygons_vs.replace('#pragma tangram: projection', GLOBE_PROJECTION_GLSL + TERRAIN_DRAPING_GLSL),
|
|
40
|
+
fragment_shader_src: polygons_fs,
|
|
41
|
+
selection: true, // enable feature selection
|
|
42
|
+
|
|
43
|
+
getWGSLShaderSource(this: LineStyleRuntime, selection = false) {
|
|
44
|
+
return buildLinesWGSL({ animated: this.animated === true, lighting: this.portable_lighting_mode,
|
|
45
|
+
lightCount: this.portable_light_count, cpuProjection: Boolean(this.cpu_projection), terrain: Boolean(this.terrain), selection });
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
setGL(this: LineStyleRuntime, gl_context: WebGLRenderingContext | null, uniform_blocks: Record<string, UniformBuffer> = {}, options = {}) {
|
|
49
|
+
if (Object.prototype.hasOwnProperty.call(this, 'line_uniform_buffer') &&
|
|
50
|
+
this.line_uniform_buffer) {
|
|
51
|
+
this.line_uniform_buffer.destroy();
|
|
52
|
+
this.line_uniform_buffer = null;
|
|
53
|
+
}
|
|
54
|
+
Style.setGL.call(this, gl_context, uniform_blocks, options);
|
|
55
|
+
if (this.shader_language === 'wgsl') {
|
|
56
|
+
if (typeof this.uniform_block_factory !== 'function') {
|
|
57
|
+
throw new Error('portable line styles require a uniform block factory');
|
|
58
|
+
}
|
|
59
|
+
this.line_uniform_buffer = this.uniform_block_factory({
|
|
60
|
+
id: `${this.name}-line-style`,
|
|
61
|
+
name: 'TangramLine',
|
|
62
|
+
binding: 5,
|
|
63
|
+
snapshotPerMesh: true,
|
|
64
|
+
uniforms: {
|
|
65
|
+
u_has_line_texture: 'bool',
|
|
66
|
+
u_texture_ratio: 'float',
|
|
67
|
+
u_v_scale_adjust: 'float',
|
|
68
|
+
u_has_dash: 'float',
|
|
69
|
+
u_dash_background_color: 'vec4'
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
this.uniform_blocks = Object.assign({}, this.uniform_blocks, {
|
|
73
|
+
TangramLine: this.line_uniform_buffer
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
destroy(this: LineStyleRuntime) {
|
|
79
|
+
Style.destroy.call(this);
|
|
80
|
+
if (Object.prototype.hasOwnProperty.call(this, 'line_uniform_buffer') &&
|
|
81
|
+
this.line_uniform_buffer) {
|
|
82
|
+
this.line_uniform_buffer.destroy();
|
|
83
|
+
this.line_uniform_buffer = null;
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
init(this: LineStyleRuntime) {
|
|
88
|
+
Style.init.apply(this, arguments as unknown as Parameters<typeof Style.init>);
|
|
89
|
+
this.defines.TANGRAM_CPU_PROJECTED = Boolean(this.cpu_projection);
|
|
90
|
+
const attributes = this.shaders?.attributes;
|
|
91
|
+
const hasAttributes = attributes && typeof attributes === 'object' ? Object.keys(attributes).length > 0 : Boolean(attributes);
|
|
92
|
+
const positionBlocks = this.shaders?.blocks?.position;
|
|
93
|
+
const hasPositionBlocks = Array.isArray(positionBlocks) ? positionBlocks.length > 0 : Boolean(positionBlocks);
|
|
94
|
+
if (this.cpu_projection && (hasAttributes || hasPositionBlocks)) {
|
|
95
|
+
throw new Error('CPU projected lines do not support custom vertex shader blocks');
|
|
96
|
+
}
|
|
97
|
+
this.defines.TANGRAM_PROJECTED_TRAFFIC = Boolean(this.cpu_projection && this.animated);
|
|
98
|
+
if (this.cpu_projection && this.animated) this.texcoords = true;
|
|
99
|
+
|
|
100
|
+
// Tell the shader we want a order in vertex attributes, and to extrude lines
|
|
101
|
+
this.defines.TANGRAM_EXTRUDE_LINES = true;
|
|
102
|
+
this.defines.TANGRAM_TEXTURE_COORDS = true; // texcoords attribute is set to static when not needed
|
|
103
|
+
|
|
104
|
+
// Additional single-allocated object used for holding outline style as it is processed
|
|
105
|
+
// Separate from this.feature_style so that outline properties do not overwrite calculated
|
|
106
|
+
// inline properties (outline call is made *within* the inline call)
|
|
107
|
+
// The scratch object is populated by the base parser before geometry is built.
|
|
108
|
+
this.outline_feature_style = {} as LineFeatureStyle;
|
|
109
|
+
this.inline_feature_style = this.feature_style; // save reference to main computed style object
|
|
110
|
+
|
|
111
|
+
this.dash_textures = {}; // cache previously rendered line dash pattern textures
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
// Calculate width or offset at zoom given in `context`
|
|
115
|
+
calcDistance (this: LineStyleRuntime, prop: PropertyCache | null | undefined, context: GeometryContext) {
|
|
116
|
+
return (StyleParser.evalCachedDistanceProperty(prop, context) as number) || 0;
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
// Calculate width or offset at next zoom (used for zoom-based interpolation in shader)
|
|
120
|
+
calcDistanceNextZoom (this: LineStyleRuntime, prop: PropertyCache | null | undefined, context: GeometryContext) {
|
|
121
|
+
context.zoom++;
|
|
122
|
+
let val = this.calcDistance(prop, context);
|
|
123
|
+
context.zoom--;
|
|
124
|
+
return val;
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
// Calculate width at current and next zoom, and scaling factor between
|
|
128
|
+
calcWidth (this: LineStyleRuntime, draw: GeometryDraw, style: LineFeatureStyle, context: GeometryContext) {
|
|
129
|
+
style.projected_pixel_scale = this.cpu_projection && draw.projected_pixel_width ?
|
|
130
|
+
1 / (context.units_per_meter_overzoom * context.meters_per_pixel) : 0;
|
|
131
|
+
// line width in meters
|
|
132
|
+
let width = this.calcDistance(draw.width, context);
|
|
133
|
+
if (width < 0) {
|
|
134
|
+
return; // skip lines with negative width
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
let next_width;
|
|
138
|
+
if (draw.next_width && !this.cpu_projection) {
|
|
139
|
+
next_width = this.calcDistanceNextZoom(draw.next_width, context);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
next_width = width / 2; // when width is static, width at next zoom is just half as many tile units
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if ((width === 0 && next_width === 0) || next_width < 0) {
|
|
146
|
+
return false; // skip lines that don't interpolate to a positive value at next zoom
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// these values are saved for later calculating the outline width, which needs to add the base line's width
|
|
150
|
+
style.width_unscaled = width;
|
|
151
|
+
style.next_width_unscaled = next_width;
|
|
152
|
+
|
|
153
|
+
// calculate relative change in line width between zooms
|
|
154
|
+
// interpolate from the line width at the zoom mid-point, towards/away from the previous/next integer zoom
|
|
155
|
+
// Projected scenes have an explicit style zoom independent of data/camera zoom.
|
|
156
|
+
// Bake that zoom's width; geographic shaders alone interpolate toward next zoom.
|
|
157
|
+
if (draw.next_width && !this.cpu_projection) {
|
|
158
|
+
next_width *= 2; // NB: a given width is twice as big in screen space at the next zoom
|
|
159
|
+
let mid_width = (width + next_width) * 0.5;
|
|
160
|
+
style.width = mid_width * context.units_per_meter_overzoom; // width at zoom mid-point
|
|
161
|
+
style.width_scale = 1 - (next_width / mid_width);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
style.width = width * context.units_per_meter_overzoom;
|
|
165
|
+
style.width_scale = 0;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// optional adjustment to texcoord width based on scale
|
|
169
|
+
if (draw.texcoords) {
|
|
170
|
+
// when drawing an outline, use the inline's texture scale
|
|
171
|
+
// (e.g. keeps dashed outline pattern locked to inline pattern)
|
|
172
|
+
if (draw.inline_texcoord_width) {
|
|
173
|
+
style.texcoord_width = draw.inline_texcoord_width;
|
|
174
|
+
}
|
|
175
|
+
// when drawing an inline, calculate UVs based on line width
|
|
176
|
+
else {
|
|
177
|
+
// UVs can't calc for zero-width, use next zoom width in that case
|
|
178
|
+
style.texcoord_width = (style.width_unscaled || style.next_width_unscaled) * context.units_per_meter_overzoom / context.tile.overzoom2; // shorten calcs
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return true;
|
|
183
|
+
},
|
|
184
|
+
|
|
185
|
+
// Calculate offset at current and next zoom, and scaling factor between
|
|
186
|
+
calcOffset (this: LineStyleRuntime, draw: GeometryDraw, style: LineFeatureStyle, context: GeometryContext) {
|
|
187
|
+
// Pre-calculated offset passed
|
|
188
|
+
// This happens when a line passes pre-computed offset values to its outline
|
|
189
|
+
if (draw.offset_precalc) {
|
|
190
|
+
style.offset = draw.offset_precalc;
|
|
191
|
+
// Inline parsing supplies both precalculated offset fields to the outline.
|
|
192
|
+
style.offset_scale = draw.offset_scale_precalc!;
|
|
193
|
+
}
|
|
194
|
+
// Offset to calculate
|
|
195
|
+
else if (draw.offset) {
|
|
196
|
+
let offset = this.calcDistance(draw.offset, context);
|
|
197
|
+
|
|
198
|
+
if (draw.next_offset && !this.cpu_projection) {
|
|
199
|
+
let next_offset = this.calcDistanceNextZoom(draw.next_offset, context) * 2;
|
|
200
|
+
|
|
201
|
+
if (Math.abs(offset) >= Math.abs(next_offset)) {
|
|
202
|
+
style.offset = offset * context.units_per_meter_overzoom;
|
|
203
|
+
if (offset !== 0) {
|
|
204
|
+
style.offset_scale = 1 - (next_offset / offset);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
style.offset_scale = 0;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
style.offset = next_offset * context.units_per_meter_overzoom;
|
|
212
|
+
if (next_offset !== 0) {
|
|
213
|
+
style.offset_scale = (1 - (offset / next_offset)) * -1;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
style.offset_scale = 0;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
style.offset = offset * context.units_per_meter_overzoom;
|
|
222
|
+
style.offset_scale = 0;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// No offset
|
|
226
|
+
else {
|
|
227
|
+
style.offset = 0;
|
|
228
|
+
style.offset_scale = 0;
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
|
|
232
|
+
_parseFeature (this: LineStyleRuntime, feature: GeometryFeature, draw: GeometryDraw, context: GeometryContext) {
|
|
233
|
+
var style = this.feature_style;
|
|
234
|
+
|
|
235
|
+
// calculate line width at current and next zoom
|
|
236
|
+
if (this.calcWidth(draw, style, context) === false) {
|
|
237
|
+
return; // missing or zero width
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// calculate line offset at current and next zoom
|
|
241
|
+
this.calcOffset(draw, style, context);
|
|
242
|
+
|
|
243
|
+
style.color = this.parseColor(draw.color, context);
|
|
244
|
+
if (!style.color) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
style.alpha = StyleParser.evalCachedProperty(draw.alpha, context) as number | undefined; // optional alpha override
|
|
249
|
+
|
|
250
|
+
style.variant = draw.variant; // pre-calculated mesh variant
|
|
251
|
+
|
|
252
|
+
// height defaults to feature height, but extrude style can dynamically adjust height by returning a number or array (instead of a boolean)
|
|
253
|
+
style.z = (StyleParser.evalCachedDistanceProperty(draw.z, context) as number) || StyleParser.defaults.z;
|
|
254
|
+
style.height = feature.properties.height || StyleParser.defaults.height;
|
|
255
|
+
style.extrude = StyleParser.evalProperty(draw.extrude, context) as GeometryExtrusion;
|
|
256
|
+
if (style.extrude) {
|
|
257
|
+
if (typeof style.extrude === 'number') {
|
|
258
|
+
style.height = style.extrude;
|
|
259
|
+
}
|
|
260
|
+
else if (Array.isArray(style.extrude)) {
|
|
261
|
+
style.height = style.extrude[1];
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Raise line height if extruded
|
|
266
|
+
if (style.extrude && style.height) {
|
|
267
|
+
style.z += style.height;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
style.z *= Geo.height_scale; // provide sub-meter precision of height values
|
|
271
|
+
|
|
272
|
+
style.cap = draw.cap;
|
|
273
|
+
style.join = draw.join;
|
|
274
|
+
|
|
275
|
+
style.miter_limit = draw.miter_limit;
|
|
276
|
+
style.tile_edges = draw.tile_edges; // usually activated for debugging, or rare visualization needs
|
|
277
|
+
|
|
278
|
+
// Construct an outline style
|
|
279
|
+
// Reusable outline style object, marked as already wrapped in cache objects (preprocessed = true)
|
|
280
|
+
style.outline = style.outline || {
|
|
281
|
+
width: {}, next_width: {},
|
|
282
|
+
preprocessed: true
|
|
283
|
+
} as GeometryOutlineDraw;
|
|
284
|
+
|
|
285
|
+
if (draw.outline && draw.outline.visible !== false && draw.outline.color && draw.outline.width) {
|
|
286
|
+
// outline width in meters
|
|
287
|
+
// NB: multiply by 2 because outline is applied on both sides of line
|
|
288
|
+
let outline_width = this.calcDistance(draw.outline.width, context) * 2;
|
|
289
|
+
let outline_next_width = this.calcDistanceNextZoom(draw.outline.next_width, context) * 2;
|
|
290
|
+
|
|
291
|
+
if ((outline_width === 0 && outline_next_width === 0) || outline_width < 0 || outline_next_width < 0) {
|
|
292
|
+
// skip lines that don't interpolate between zero or greater width
|
|
293
|
+
style.outline.width.value = null;
|
|
294
|
+
style.outline.next_width.value = null;
|
|
295
|
+
style.outline.color = null;
|
|
296
|
+
style.outline.inline_texcoord_width = null;
|
|
297
|
+
style.outline.texcoords = false;
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
// Maintain consistent outline width around the line fill
|
|
301
|
+
style.outline.width.value = outline_width + style.width_unscaled;
|
|
302
|
+
style.outline.next_width.value = outline_next_width + style.next_width_unscaled;
|
|
303
|
+
style.outline.inline_texcoord_width = style.texcoord_width;
|
|
304
|
+
|
|
305
|
+
// Offset is directly copied from fill to outline, no need to re-calculate it
|
|
306
|
+
style.outline.offset_precalc = style.offset;
|
|
307
|
+
style.outline.offset_scale_precalc = style.offset_scale;
|
|
308
|
+
style.outline.projected_pixel_width = draw.projected_pixel_width;
|
|
309
|
+
|
|
310
|
+
style.outline.color = draw.outline.color;
|
|
311
|
+
style.outline.alpha = draw.outline.alpha;
|
|
312
|
+
style.outline.interactive = draw.outline.interactive;
|
|
313
|
+
style.outline.cap = draw.outline.cap;
|
|
314
|
+
style.outline.join = draw.outline.join;
|
|
315
|
+
style.outline.miter_limit = draw.outline.miter_limit;
|
|
316
|
+
style.outline.texcoords = draw.outline.texcoords;
|
|
317
|
+
style.outline.extrude = draw.outline.extrude;
|
|
318
|
+
style.outline.z = draw.outline.z;
|
|
319
|
+
style.outline.style = draw.outline.style;
|
|
320
|
+
style.outline.variant = draw.outline.variant;
|
|
321
|
+
|
|
322
|
+
// Explicitly defined outline order, or inherited from inner line
|
|
323
|
+
if (draw.outline.order) {
|
|
324
|
+
style.outline.order = this.parseOrder(draw.outline.order, context);
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
style.outline.order = style.order;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Don't let outline be above inner line
|
|
331
|
+
if (style.outline.order > style.order) {
|
|
332
|
+
style.outline.order = style.order;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Outlines are always at half-layer intervals to avoid conflicting with inner lines
|
|
336
|
+
style.outline.order -= 0.5;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
style.outline.width.value = null;
|
|
341
|
+
style.outline.next_width.value = null;
|
|
342
|
+
style.outline.color = null;
|
|
343
|
+
style.outline.inline_texcoord_width = null;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
return style;
|
|
347
|
+
},
|
|
348
|
+
|
|
349
|
+
_preprocess (this: LineStyleRuntime, draw: RawGeometryDraw) {
|
|
350
|
+
if (this.cpu_projection && !draw.preprocessed) draw.projected_pixel_width = getProjectedRoadUnit(draw.width) === 'px';
|
|
351
|
+
draw.color = StyleParser.createColorPropertyCache(draw.color);
|
|
352
|
+
draw.alpha = StyleParser.createPropertyCache(draw.alpha);
|
|
353
|
+
draw.width = StyleParser.createPropertyCache(draw.width, StyleParser.parseUnits);
|
|
354
|
+
if (draw.width && (draw.width as PropertyCache).type !== StyleParser.CACHE_TYPE.STATIC) {
|
|
355
|
+
draw.next_width = StyleParser.createPropertyCache(draw.width, StyleParser.parseUnits);
|
|
356
|
+
}
|
|
357
|
+
draw.offset = draw.offset && StyleParser.createPropertyCache(draw.offset, StyleParser.parseUnits);
|
|
358
|
+
if (draw.offset && (draw.offset as PropertyCache).type !== StyleParser.CACHE_TYPE.STATIC) {
|
|
359
|
+
draw.next_offset = StyleParser.createPropertyCache(draw.offset, StyleParser.parseUnits);
|
|
360
|
+
}
|
|
361
|
+
draw.z = StyleParser.createPropertyCache(draw.z, StyleParser.parseUnits);
|
|
362
|
+
|
|
363
|
+
draw.dash = (draw.dash !== undefined ? draw.dash : this.dash);
|
|
364
|
+
draw.dash_key = draw.dash && this.dashTextureKey(draw.dash);
|
|
365
|
+
draw.dash_background_color = (draw.dash_background_color !== undefined ? draw.dash_background_color : this.dash_background_color);
|
|
366
|
+
draw.dash_background_color = draw.dash_background_color && StyleParser.parseColor(draw.dash_background_color);
|
|
367
|
+
draw.texture_merged = draw.dash_key || ((draw.texture !== undefined ? draw.texture : this.texture));
|
|
368
|
+
draw.texcoords = ((this.texcoords || draw.texture_merged) ? 1 : 0);
|
|
369
|
+
this.computeVariant(draw);
|
|
370
|
+
|
|
371
|
+
if (draw.outline) {
|
|
372
|
+
draw.outline.is_outline = true; // mark as outline (so mesh variant can be adjusted for render order, etc.)
|
|
373
|
+
draw.outline.style = draw.outline.style || this.name;
|
|
374
|
+
draw.outline.color = StyleParser.createColorPropertyCache(draw.outline.color);
|
|
375
|
+
draw.outline.alpha = StyleParser.createPropertyCache(draw.outline.alpha);
|
|
376
|
+
draw.outline.width = StyleParser.createPropertyCache(draw.outline.width, StyleParser.parseUnits);
|
|
377
|
+
draw.outline.next_width = StyleParser.createPropertyCache(draw.outline.width, StyleParser.parseUnits); // width re-computed for next zoom
|
|
378
|
+
|
|
379
|
+
draw.outline.interactive = (draw.outline.interactive != null) ? draw.outline.interactive : draw.interactive;
|
|
380
|
+
draw.outline.cap = draw.outline.cap || draw.cap;
|
|
381
|
+
draw.outline.join = draw.outline.join || draw.join;
|
|
382
|
+
draw.outline.miter_limit = (draw.outline.miter_limit != null) ? draw.outline.miter_limit : draw.miter_limit;
|
|
383
|
+
|
|
384
|
+
// always apply inline values for offset and extrusion/height to outline
|
|
385
|
+
draw.outline.offset = draw.offset;
|
|
386
|
+
draw.outline.extrude = draw.extrude;
|
|
387
|
+
draw.outline.z = draw.z;
|
|
388
|
+
|
|
389
|
+
// outline inherits dash pattern, but NOT explicit texture
|
|
390
|
+
let outline_style = this.styles[draw.outline.style];
|
|
391
|
+
if (outline_style) {
|
|
392
|
+
draw.outline.dash = (draw.outline.dash !== undefined ? draw.outline.dash : outline_style.dash);
|
|
393
|
+
draw.outline.texture = (draw.outline.texture !== undefined ? draw.outline.texture : outline_style.texture);
|
|
394
|
+
|
|
395
|
+
if (draw.outline.dash != null) { // dash was defined by outline draw or style
|
|
396
|
+
draw.outline.dash_key = draw.outline.dash && this.dashTextureKey(draw.outline.dash);
|
|
397
|
+
draw.outline.texture_merged = draw.outline.dash_key;
|
|
398
|
+
}
|
|
399
|
+
else if (draw.outline.dash === null) { // dash explicitly disabled by outline draw or style
|
|
400
|
+
draw.outline.dash_key = null;
|
|
401
|
+
draw.outline.texture_merged = draw.outline.texture;
|
|
402
|
+
}
|
|
403
|
+
else if (draw.outline.texture != null) { // texture was defined by outline draw or style
|
|
404
|
+
draw.outline.dash_key = null; // outline explicitly turning off dash
|
|
405
|
+
draw.outline.texture_merged = draw.outline.texture;
|
|
406
|
+
}
|
|
407
|
+
else { // no dash or texture defined for outline, inherit parent dash
|
|
408
|
+
draw.outline.dash = draw.dash;
|
|
409
|
+
draw.outline.dash_key = draw.outline.dash && this.dashTextureKey(draw.outline.dash);
|
|
410
|
+
draw.outline.texture_merged = draw.outline.dash_key;
|
|
411
|
+
}
|
|
412
|
+
draw.outline.dash_background_color = (draw.outline.dash_background_color !== undefined ? draw.outline.dash_background_color : outline_style.dash_background_color);
|
|
413
|
+
draw.outline.dash_background_color = (draw.outline.dash_background_color !== undefined ? draw.outline.dash_background_color : draw.dash_background_color);
|
|
414
|
+
draw.outline.dash_background_color = draw.outline.dash_background_color && StyleParser.parseColor(draw.outline.dash_background_color);
|
|
415
|
+
draw.outline.texcoords = ((outline_style.texcoords || draw.outline.texture_merged) ? 1 : 0);
|
|
416
|
+
|
|
417
|
+
// outline inherits draw blend order from parent inline, unless explicitly turned off with null
|
|
418
|
+
if (draw.outline.blend_order === undefined && draw.blend_order != null) {
|
|
419
|
+
draw.outline.blend_order = draw.blend_order;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
outline_style.computeVariant(draw.outline);
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
log({ level: 'warn', once: true }, `Layer group '${draw.layers.join(', ')}': ` +
|
|
426
|
+
`line 'outline' specifies non-existent draw style '${draw.outline.style}' (or maybe the style is ` +
|
|
427
|
+
'defined but is missing a \'base\' or has another error), skipping outlines for features matching this layer group');
|
|
428
|
+
draw.outline = null;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
// Preprocessing replaces authored values with the cache wrappers consumed above.
|
|
432
|
+
return draw as GeometryDraw;
|
|
433
|
+
},
|
|
434
|
+
|
|
435
|
+
// Unique string key for a dash pattern (used as texture name)
|
|
436
|
+
dashTextureKey (this: LineStyleRuntime, dash: number[]) {
|
|
437
|
+
return '__dash_' + JSON.stringify(dash);
|
|
438
|
+
},
|
|
439
|
+
|
|
440
|
+
// Return or render a dash pattern texture
|
|
441
|
+
getDashTexture (this: LineStyleRuntime, dash: number[]) {
|
|
442
|
+
let dash_key = this.dashTextureKey(dash);
|
|
443
|
+
|
|
444
|
+
if (this.dash_textures[dash_key] == null) {
|
|
445
|
+
this.dash_textures[dash_key] = true;
|
|
446
|
+
// Render line pattern
|
|
447
|
+
const dash_texture = renderDashArray(dash, { scale: DASH_SCALE });
|
|
448
|
+
Texture.create(this.resource_context, dash_key, {
|
|
449
|
+
data: dash_texture.pixels,
|
|
450
|
+
height: dash_texture.length,
|
|
451
|
+
width: 1,
|
|
452
|
+
filtering: 'nearest'
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
|
|
457
|
+
// Override
|
|
458
|
+
async endData (this: LineStyleRuntime, tile: GeometryTile) {
|
|
459
|
+
const tile_data: GeometryTileData | null = await Style.endData.call(this, tile);
|
|
460
|
+
if (tile_data) {
|
|
461
|
+
tile_data.uniforms.u_has_line_texture = false;
|
|
462
|
+
tile_data.uniforms.u_texture = Texture.default;
|
|
463
|
+
tile_data.uniforms.u_texture_ratio = 1;
|
|
464
|
+
tile_data.uniforms.u_v_scale_adjust = Geo.tile_scale;
|
|
465
|
+
tile_data.uniforms.u_has_dash = 0;
|
|
466
|
+
tile_data.uniforms.u_dash_background_color = [0, 0, 0, 0];
|
|
467
|
+
|
|
468
|
+
let pending = [];
|
|
469
|
+
for (let m in tile_data.meshes) {
|
|
470
|
+
let variant = tile_data.meshes[m].variant;
|
|
471
|
+
if (variant.texture) {
|
|
472
|
+
let uniforms = tile_data.meshes[m].uniforms = tile_data.meshes[m].uniforms || {};
|
|
473
|
+
uniforms.u_has_line_texture = true;
|
|
474
|
+
uniforms.u_texture = variant.texture;
|
|
475
|
+
uniforms.u_texture_ratio = 1;
|
|
476
|
+
|
|
477
|
+
if (variant.dash) {
|
|
478
|
+
uniforms.u_v_scale_adjust = Geo.tile_scale * DASH_SCALE;
|
|
479
|
+
uniforms.u_has_dash = (variant.dash_background_color != null ? 1 : 0);
|
|
480
|
+
uniforms.u_dash_background_color = variant.dash_background_color || [0, 0, 0, 0];
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
if (variant.dash_key && this.dash_textures[variant.dash_key] == null) {
|
|
484
|
+
this.dash_textures[variant.dash_key] = true;
|
|
485
|
+
try {
|
|
486
|
+
await (WorkerBroker as {postMessage(target: string, ...payloads: unknown[]): Promise<unknown>}).postMessage(this.main_thread_target+'.getDashTexture', variant.dash);
|
|
487
|
+
}
|
|
488
|
+
catch (e) {
|
|
489
|
+
log('trace', `${this.name}: line dash texture create failed because style no longer on main thread`);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (Texture.textures[variant.texture] == null) {
|
|
494
|
+
pending.push(
|
|
495
|
+
Texture.syncTexturesToWorker([variant.texture]).then(textures => {
|
|
496
|
+
// The enclosing branch supplies a named, immutable mesh texture.
|
|
497
|
+
let texture = textures[variant.texture as string];
|
|
498
|
+
if (texture) {
|
|
499
|
+
uniforms.u_texture_ratio = texture.height / texture.width;
|
|
500
|
+
}
|
|
501
|
+
})
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
else {
|
|
505
|
+
let texture = Texture.textures[variant.texture];
|
|
506
|
+
uniforms.u_texture_ratio = texture.height / texture.width;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
await Promise.all(pending);
|
|
511
|
+
}
|
|
512
|
+
return tile_data;
|
|
513
|
+
},
|
|
514
|
+
|
|
515
|
+
// Calculate and store mesh variant (unique by draw group but not feature)
|
|
516
|
+
computeVariant (this: LineStyleRuntime, draw: GeometryDraw | RawGeometryDraw) {
|
|
517
|
+
// Factors that determine a unique mesh rendering variant
|
|
518
|
+
// The first concatenation converts this numeric flag to the string hash input.
|
|
519
|
+
let key = (draw.offset ? 1 : 0) as string | number; // whether feature has a line offset
|
|
520
|
+
key += '/' + draw.texcoords; // whether feature has texture UVs
|
|
521
|
+
key += '/' + (draw.interactive ? 1 : 0); // whether feature has interactivity
|
|
522
|
+
key += '/' + ((draw.extrude || draw.z) ? 1 : 0); // whether feature has a z coordinate
|
|
523
|
+
key += '/' + draw.is_outline; // whether this is an outline of a line feature
|
|
524
|
+
|
|
525
|
+
if (draw.dash_key) { // whether feature has a line dash pattern
|
|
526
|
+
key += draw.dash_key;
|
|
527
|
+
if (draw.dash_background_color) {
|
|
528
|
+
key += draw.dash_background_color as unknown as string;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (draw.texture_merged) { // whether feature has a line texture
|
|
533
|
+
key += draw.texture_merged;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
const blend_order = this.getBlendOrderForDraw(draw);
|
|
537
|
+
key += '/' + blend_order;
|
|
538
|
+
|
|
539
|
+
// Create unique key
|
|
540
|
+
key = hashString(key as string);
|
|
541
|
+
draw.variant = key;
|
|
542
|
+
|
|
543
|
+
if (this.variants[key] == null) {
|
|
544
|
+
this.variants[key] = {
|
|
545
|
+
key,
|
|
546
|
+
blend_order,
|
|
547
|
+
mesh_order: (draw.is_outline ? 0 : 1), // outlines should be drawn first, so inline is on top
|
|
548
|
+
selection: (draw.interactive ? 1 : 0),
|
|
549
|
+
offset: (draw.offset ? 1 : 0),
|
|
550
|
+
z_or_offset: ((draw.offset || draw.extrude || draw.z) ? 1 : 0),
|
|
551
|
+
texcoords: draw.texcoords,
|
|
552
|
+
texture: draw.texture_merged,
|
|
553
|
+
dash: draw.dash,
|
|
554
|
+
dash_key: draw.dash_key,
|
|
555
|
+
dash_background_color: draw.dash_background_color as GeometryMeshVariant['dash_background_color']
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
},
|
|
559
|
+
|
|
560
|
+
// Override
|
|
561
|
+
// Create or return desired vertex layout permutation based on flags
|
|
562
|
+
vertexLayoutForMeshVariant (this: LineStyleRuntime, variant: GeometryMeshVariant) {
|
|
563
|
+
if (this.vertex_layouts[variant.key] == null) {
|
|
564
|
+
const portable = this.shader_language === 'wgsl';
|
|
565
|
+
// Attributes for this mesh variant
|
|
566
|
+
// WebGL can provide optional fields as constant vertex attributes. WebGPU
|
|
567
|
+
// requires every shader-declared input to be backed by a vertex buffer, so
|
|
568
|
+
// portable layouts write explicit zero values for unused line fields.
|
|
569
|
+
const attribs = [
|
|
570
|
+
{ name: 'a_position', size: 4, type: gl.SHORT, normalized: false },
|
|
571
|
+
{ name: 'a_extrude', size: 2, type: gl.SHORT, normalized: false },
|
|
572
|
+
{ name: 'a_offset', size: 2, type: gl.SHORT, normalized: false, static: ((portable || variant.offset) ? null : [0, 0]) },
|
|
573
|
+
{ name: 'a_z_and_offset_scale', size: 2, type: gl.SHORT, normalized: false, static: ((portable || variant.z_or_offset) ? null : [0, 0]) },
|
|
574
|
+
{
|
|
575
|
+
name: 'a_texcoord',
|
|
576
|
+
size: 2,
|
|
577
|
+
type: this.shader_language === 'wgsl' ? gl.FLOAT : gl.UNSIGNED_SHORT,
|
|
578
|
+
normalized: this.shader_language !== 'wgsl',
|
|
579
|
+
static: ((portable || variant.texcoords) ? null : [0, 0])
|
|
580
|
+
},
|
|
581
|
+
{ name: 'a_color', size: 4, type: gl.UNSIGNED_BYTE, normalized: true },
|
|
582
|
+
{ name: 'a_selection_color', size: 4, type: gl.UNSIGNED_BYTE, normalized: true, static: (variant.selection || this.shader_language === 'wgsl' ? null : [0, 0, 0, 0]) }
|
|
583
|
+
];
|
|
584
|
+
|
|
585
|
+
this.addCustomAttributesToAttributeList(attribs);
|
|
586
|
+
if (this.cpu_projection) {
|
|
587
|
+
attribs.push({name: 'a_projected_position', size: 3, type: gl.FLOAT, normalized: false});
|
|
588
|
+
attribs.push({name: 'a_projected_stroke', size: 4, type: gl.FLOAT, normalized: false});
|
|
589
|
+
attribs.push({name: 'a_projected_normals', size: 4, type: gl.FLOAT, normalized: false});
|
|
590
|
+
attribs.push({name: 'a_projected_widths', size: 2, type: gl.FLOAT, normalized: false});
|
|
591
|
+
}
|
|
592
|
+
this.vertex_layouts[variant.key] = new VertexLayout(attribs);
|
|
593
|
+
}
|
|
594
|
+
return this.vertex_layouts[variant.key];
|
|
595
|
+
},
|
|
596
|
+
|
|
597
|
+
// Override
|
|
598
|
+
meshVariantTypeForDraw (this: LineStyleRuntime, draw: Pick<GeometryDraw, 'variant'>) {
|
|
599
|
+
return this.variants[draw.variant]; // return pre-calculated mesh variant
|
|
600
|
+
},
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* A "template" that sets constant attibutes for each vertex, which is then modified per vertex or per feature.
|
|
604
|
+
* A plain JS array matching the order of the vertex layout.
|
|
605
|
+
*/
|
|
606
|
+
makeVertexTemplate(this: LineStyleRuntime, style: LineFeatureStyle, mesh: GeometryBuildMesh) {
|
|
607
|
+
let i = 0;
|
|
608
|
+
const portable = this.shader_language === 'wgsl';
|
|
609
|
+
|
|
610
|
+
// a_position.xy - vertex position
|
|
611
|
+
// a_position.z - line width scaling factor
|
|
612
|
+
// a_position.w - layer order
|
|
613
|
+
this.vertex_template[i++] = 0;
|
|
614
|
+
this.vertex_template[i++] = 0;
|
|
615
|
+
this.vertex_template[i++] = style.width_scale * 1024;
|
|
616
|
+
this.vertex_template[i++] = this.scaleOrder(style.order);
|
|
617
|
+
|
|
618
|
+
// a_extrude.xy - extrusion vector (vertex extrusion away from center of line)
|
|
619
|
+
this.vertex_template[i++] = 0;
|
|
620
|
+
this.vertex_template[i++] = 0;
|
|
621
|
+
|
|
622
|
+
// a_offset.xy - normal vector
|
|
623
|
+
// offset can be static or dynamic depending on style
|
|
624
|
+
if (portable || mesh.variant.offset) {
|
|
625
|
+
this.vertex_template[i++] = 0;
|
|
626
|
+
this.vertex_template[i++] = 0;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// a_z_and_offset_scale.xy
|
|
630
|
+
if (portable || mesh.variant.z_or_offset) {
|
|
631
|
+
this.vertex_template[i++] = style.z || 0; // feature z position
|
|
632
|
+
this.vertex_template[i++] = style.offset_scale * 1024; // line offset scaling factor
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// a_texcoord.uv - texture coordinates
|
|
636
|
+
if (portable || mesh.variant.texcoords) {
|
|
637
|
+
this.vertex_template[i++] = 0;
|
|
638
|
+
this.vertex_template[i++] = 0;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// a_color.rgba - feature color
|
|
642
|
+
this.vertex_template[i++] = style.color[0] * 255;
|
|
643
|
+
this.vertex_template[i++] = style.color[1] * 255;
|
|
644
|
+
this.vertex_template[i++] = style.color[2] * 255;
|
|
645
|
+
this.vertex_template[i++] = (style.alpha != null ? style.alpha : style.color[3]) * 255;
|
|
646
|
+
|
|
647
|
+
// a_selection_color.rgba - selection color
|
|
648
|
+
if (mesh.variant.selection || this.shader_language === 'wgsl') {
|
|
649
|
+
this.vertex_template[i++] = style.selection_color[0] * 255;
|
|
650
|
+
this.vertex_template[i++] = style.selection_color[1] * 255;
|
|
651
|
+
this.vertex_template[i++] = style.selection_color[2] * 255;
|
|
652
|
+
this.vertex_template[i++] = style.selection_color[3] * 255;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
this.addCustomAttributesToVertexTemplate(style, i);
|
|
656
|
+
if (this.cpu_projection) {
|
|
657
|
+
const index = mesh.vertex_data.vertex_layout.index.a_projected_position;
|
|
658
|
+
this.vertex_template[index] = this.vertex_template[index + 1] = this.vertex_template[index + 2] = 0;
|
|
659
|
+
const stroke = mesh.vertex_data.vertex_layout.index.a_projected_stroke;
|
|
660
|
+
this.vertex_template[stroke] = this.vertex_template[stroke + 1] = this.vertex_template[stroke + 2] = 0;
|
|
661
|
+
this.vertex_template[stroke + 3] = style.projected_pixel_scale ?? 0;
|
|
662
|
+
}
|
|
663
|
+
return this.vertex_template;
|
|
664
|
+
},
|
|
665
|
+
|
|
666
|
+
buildLines(this: LineStyleRuntime, lines: GeometryLine[], style: LineFeatureStyle, context: GeometryContext, options?: {closed_polygon?: boolean; remove_tile_edges?: boolean}) {
|
|
667
|
+
// Outline (build first so that blended geometry without a depth test is drawn first/under the inner line)
|
|
668
|
+
this.feature_style = this.outline_feature_style; // swap in outline-specific style holder
|
|
669
|
+
if (style.outline && style.outline.color != null && style.outline.width.value != null) {
|
|
670
|
+
var outline_style = this.styles[style.outline.style];
|
|
671
|
+
if (outline_style) {
|
|
672
|
+
outline_style.addFeature(context.feature, style.outline, context);
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// Main line
|
|
677
|
+
this.feature_style = this.inline_feature_style; // restore calculated style for inline
|
|
678
|
+
let mesh = this.getTileMesh(context.tile, this.meshVariantTypeForDraw(style));
|
|
679
|
+
let vertex_data = mesh.vertex_data;
|
|
680
|
+
let vertex_layout = vertex_data.vertex_layout;
|
|
681
|
+
let vertex_template = this.makeVertexTemplate(style, mesh);
|
|
682
|
+
const vertex_layout_index = this.shader_language === 'wgsl' && !mesh.variant.texcoords ?
|
|
683
|
+
Object.assign({}, vertex_layout.index, { a_texcoord: null }) :
|
|
684
|
+
vertex_layout.index;
|
|
685
|
+
return buildPolylines(
|
|
686
|
+
lines,
|
|
687
|
+
style,
|
|
688
|
+
vertex_data,
|
|
689
|
+
vertex_template,
|
|
690
|
+
// Extrusion is packed; a constant zero offset has no component index.
|
|
691
|
+
vertex_layout_index as unknown as PolylineVertexIndices,
|
|
692
|
+
(options && options.closed_polygon), // closed_polygon
|
|
693
|
+
(!style.tile_edges && options && options.remove_tile_edges), // remove_tile_edges
|
|
694
|
+
(Geo.tile_scale * context.tile.pad_scale * 2) // tile_edge_tolerance
|
|
695
|
+
);
|
|
696
|
+
},
|
|
697
|
+
|
|
698
|
+
buildPolygons(this: LineStyleRuntime, polygons: GeometryPolygon[], style: LineFeatureStyle, context: GeometryContext) {
|
|
699
|
+
// Render polygons as individual lines
|
|
700
|
+
let geom_count = 0;
|
|
701
|
+
for (let p=0; p < polygons.length; p++) {
|
|
702
|
+
geom_count += this.buildLines(polygons[p], style, context, { closed_polygon: true, remove_tile_edges: true });
|
|
703
|
+
}
|
|
704
|
+
return geom_count;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
} satisfies Partial<LineStyleRuntime>);
|