@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,285 @@
|
|
|
1
|
+
// tangram-layers
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import type VertexLayout from './vertex_layout';
|
|
6
|
+
|
|
7
|
+
type VertexAttribute = VertexLayout['dynamic_attribs'][number];
|
|
8
|
+
|
|
9
|
+
/** Packed triangle data after projection-aware refinement. */
|
|
10
|
+
export type GlobeMeshData = {
|
|
11
|
+
/** Interleaved vertices, with the original vertices retained at their original indices. */
|
|
12
|
+
vertices: Uint8Array;
|
|
13
|
+
/** Triangle indices, promoted to 32 bits when necessary. */
|
|
14
|
+
indices: Uint16Array | Uint32Array;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/** Limits for globe refinement in Tangram tile-local coordinates. */
|
|
18
|
+
export type GlobeMeshOptions = {
|
|
19
|
+
/** Actual source tile zoom, not the style zoom. */
|
|
20
|
+
tileZoom: number;
|
|
21
|
+
/** Tile-local units per tile edge. */
|
|
22
|
+
tileScale?: number;
|
|
23
|
+
/** Maximum Mercator angular edge span; conservatively bounds spherical span. */
|
|
24
|
+
maxAngularSpan?: number;
|
|
25
|
+
/** Maximum additional vertices; additional triangles are limited to twice this budget. */
|
|
26
|
+
maxAdditionalVertices?: number;
|
|
27
|
+
/** Optional expanded tile-space position for packed ribbons; never changes the preserved attributes. */
|
|
28
|
+
getPosition?: (vertex: DataView) => [number, number];
|
|
29
|
+
/** Optional packed height for topology checks on elevated surfaces; curvature still uses XY. */
|
|
30
|
+
getElevation?: (vertex: DataView) => number;
|
|
31
|
+
/** Optional additional edge decision; callers must use the same criterion across adjacent meshes. */
|
|
32
|
+
shouldSplitEdge?: (first: DataView, second: DataView) => boolean;
|
|
33
|
+
/** Fan partial-edge refinements around an interior vertex instead of introducing a long diagonal. */
|
|
34
|
+
splitRemainderInterior?: boolean;
|
|
35
|
+
/** Choose the shorter green-refinement diagonal; useful for floating terrain ribbons and thin MVT faces. */
|
|
36
|
+
splitRemainderShortest?: boolean;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const INTERPOLATED_ATTRIBUTES = new Set([
|
|
40
|
+
'a_position', 'a_normal', 'a_color', 'a_texcoord', 'a_extrude', 'a_offset',
|
|
41
|
+
'a_z_and_offset_scale', 'a_projected_position', 'a_projected_normal', 'a_projected_stroke', 'a_projected_normals', 'a_projected_widths'
|
|
42
|
+
]);
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Split long triangle edges before spherical projection. Shared indexed edges share
|
|
46
|
+
* midpoints; independent tile edges use the same quantized midpoint rule. Selection
|
|
47
|
+
* IDs and layer order remain flat. Unknown varying attributes are rejected rather
|
|
48
|
+
* than guessing their interpolation semantics. Camera state is deliberately absent.
|
|
49
|
+
*/
|
|
50
|
+
export function refineGlobeMesh(
|
|
51
|
+
vertices: Uint8Array,
|
|
52
|
+
indices: Uint16Array | Uint32Array | false,
|
|
53
|
+
layout: {stride: number; dynamic_attribs: VertexAttribute[]},
|
|
54
|
+
options: GlobeMeshOptions
|
|
55
|
+
): GlobeMeshData {
|
|
56
|
+
const tileScale = options.tileScale ?? 4096;
|
|
57
|
+
const angularSpan = options.maxAngularSpan ?? 4;
|
|
58
|
+
const budget = options.maxAdditionalVertices ?? 262144;
|
|
59
|
+
if (!Number.isInteger(options.tileZoom) || options.tileZoom < 0 || options.tileZoom > 30 ||
|
|
60
|
+
!Number.isFinite(tileScale) || tileScale <= 0 ||
|
|
61
|
+
!Number.isFinite(angularSpan) || angularSpan <= 0 || angularSpan > 180 ||
|
|
62
|
+
!Number.isInteger(budget) || budget < 0) {
|
|
63
|
+
throw new RangeError('Globe mesh: invalid refinement limits');
|
|
64
|
+
}
|
|
65
|
+
const maximumEdge = tileScale * 2 ** options.tileZoom * angularSpan / 360;
|
|
66
|
+
if (maximumEdge < 2) {
|
|
67
|
+
throw new RangeError('Globe mesh: refinement exceeds packed position precision');
|
|
68
|
+
}
|
|
69
|
+
const position = layout.dynamic_attribs.find(attribute => attribute.name === 'a_position');
|
|
70
|
+
if (!position || position.size < 2 || position.offset === undefined ||
|
|
71
|
+
layout.stride <= 0 || vertices.byteLength % layout.stride !== 0) {
|
|
72
|
+
throw new Error('Globe mesh: an aligned position layout is required');
|
|
73
|
+
}
|
|
74
|
+
const originalCount = vertices.byteLength / layout.stride;
|
|
75
|
+
const triangleIndices = indices || Uint32Array.from({length: originalCount}, (_, index) => index);
|
|
76
|
+
if (triangleIndices.length % 3 !== 0 || triangleIndices.some(index => index >= originalCount)) {
|
|
77
|
+
throw new Error('Globe mesh: invalid triangle indices');
|
|
78
|
+
}
|
|
79
|
+
const records: Uint8Array[] = [];
|
|
80
|
+
const positions: [number, number][] = [];
|
|
81
|
+
for (let index = 0; index < originalCount; index++) {
|
|
82
|
+
const record = vertices.subarray(index * layout.stride, (index + 1) * layout.stride);
|
|
83
|
+
records.push(record);
|
|
84
|
+
const view = new DataView(record.buffer, record.byteOffset, record.byteLength);
|
|
85
|
+
const point: [number, number] = options.getPosition ? options.getPosition(view) :
|
|
86
|
+
[readComponent(view, position, 0), readComponent(view, position, 1)];
|
|
87
|
+
if (!point.every(Number.isFinite)) {
|
|
88
|
+
throw new Error('Globe mesh: nonfinite position');
|
|
89
|
+
}
|
|
90
|
+
positions.push(point);
|
|
91
|
+
}
|
|
92
|
+
const midpoints = new Map<string, number>();
|
|
93
|
+
const output: number[] = [];
|
|
94
|
+
const pending: number[][] = [];
|
|
95
|
+
const maximumTriangles = triangleIndices.length / 3 + budget * 2;
|
|
96
|
+
// A LIFO worklist must start in reverse to preserve source triangle/feature draw order.
|
|
97
|
+
for (let index = triangleIndices.length - 3; index >= 0; index -= 3) {
|
|
98
|
+
pending.push([triangleIndices[index], triangleIndices[index + 1], triangleIndices[index + 2]]);
|
|
99
|
+
}
|
|
100
|
+
const isLong = (first: number, second: number): boolean => {
|
|
101
|
+
const distance = Math.hypot(positions[first][0] - positions[second][0], positions[first][1] - positions[second][1]);
|
|
102
|
+
return distance > maximumEdge || (distance >= 2 && Boolean(options.shouldSplitEdge?.(
|
|
103
|
+
new DataView(records[first].buffer, records[first].byteOffset, layout.stride),
|
|
104
|
+
new DataView(records[second].buffer, records[second].byteOffset, layout.stride))));
|
|
105
|
+
};
|
|
106
|
+
const getMidpoint = (first: number, second: number): number => {
|
|
107
|
+
const key = `${Math.min(first, second)}:${Math.max(first, second)}`;
|
|
108
|
+
const cached = midpoints.get(key);
|
|
109
|
+
if (cached !== undefined) {
|
|
110
|
+
return cached;
|
|
111
|
+
}
|
|
112
|
+
if (records.length >= originalCount + budget) {
|
|
113
|
+
throw new RangeError('Globe mesh: refinement vertex budget exceeded');
|
|
114
|
+
}
|
|
115
|
+
const record = interpolatePackedVertex(records[first], records[second], layout, 0.5);
|
|
116
|
+
const outputView = new DataView(record.buffer);
|
|
117
|
+
const midpoint = records.length;
|
|
118
|
+
records.push(record);
|
|
119
|
+
positions.push(options.getPosition ? options.getPosition(outputView) :
|
|
120
|
+
[readComponent(outputView, position, 0), readComponent(outputView, position, 1)]);
|
|
121
|
+
midpoints.set(key, midpoint);
|
|
122
|
+
return midpoint;
|
|
123
|
+
};
|
|
124
|
+
while (pending.length) {
|
|
125
|
+
const triangle = pending.pop()!;
|
|
126
|
+
const [first, second, third] = triangle;
|
|
127
|
+
const split = [isLong(first, second), isLong(second, third), isLong(third, first)];
|
|
128
|
+
const count = split.filter(Boolean).length;
|
|
129
|
+
if (count === 0) {
|
|
130
|
+
output.push(first, second, third);
|
|
131
|
+
}
|
|
132
|
+
else if (count === 3) {
|
|
133
|
+
const firstMidpoint = getMidpoint(first, second);
|
|
134
|
+
const secondMidpoint = getMidpoint(second, third);
|
|
135
|
+
const thirdMidpoint = getMidpoint(third, first);
|
|
136
|
+
pending.push([first, firstMidpoint, thirdMidpoint], [firstMidpoint, second, secondMidpoint],
|
|
137
|
+
[thirdMidpoint, secondMidpoint, third], [firstMidpoint, secondMidpoint, thirdMidpoint]);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
// Rotate the triangle to place the single split (or unsplit) edge first.
|
|
141
|
+
const edge = split.findIndex(value => value === (count === 1));
|
|
142
|
+
const start = triangle[edge];
|
|
143
|
+
const end = triangle[(edge + 1) % 3];
|
|
144
|
+
const opposite = triangle[(edge + 2) % 3];
|
|
145
|
+
if (options.splitRemainderInterior) {
|
|
146
|
+
// Repeated green triangulation can alternate long diagonals
|
|
147
|
+
// without converging. A centroid fan contracts interior edges
|
|
148
|
+
// and leaves every shared boundary midpoint unchanged.
|
|
149
|
+
const boundary = [start];
|
|
150
|
+
if (split[edge]) boundary.push(getMidpoint(start, end));
|
|
151
|
+
boundary.push(end);
|
|
152
|
+
if (split[(edge + 1) % 3]) boundary.push(getMidpoint(end, opposite));
|
|
153
|
+
boundary.push(opposite);
|
|
154
|
+
if (split[(edge + 2) % 3]) boundary.push(getMidpoint(opposite, start));
|
|
155
|
+
if (records.length >= originalCount + budget) {
|
|
156
|
+
throw new RangeError('Globe mesh: refinement vertex budget exceeded');
|
|
157
|
+
}
|
|
158
|
+
const record = interpolatePackedVertex(
|
|
159
|
+
interpolatePackedVertex(records[start], records[end], layout, 0.5),
|
|
160
|
+
records[opposite], layout, 1 / 3);
|
|
161
|
+
const view = new DataView(record.buffer);
|
|
162
|
+
const point: [number, number] = options.getPosition ? options.getPosition(view) :
|
|
163
|
+
[readComponent(view, position, 0), readComponent(view, position, 1)];
|
|
164
|
+
const cross = (first: number[], second: number[], third: number[]): number =>
|
|
165
|
+
(second[0] - first[0]) * (third[1] - first[1]) - (second[1] - first[1]) * (third[0] - first[0]);
|
|
166
|
+
const topologyPosition = (index: number): [number, number, number] => [
|
|
167
|
+
...positions[index], options.getElevation?.(new DataView(records[index].buffer,
|
|
168
|
+
records[index].byteOffset, layout.stride)) ?? 0];
|
|
169
|
+
const corners = [start, end, opposite].map(topologyPosition);
|
|
170
|
+
const axes = selectTrianglePlane(corners);
|
|
171
|
+
const flatten = (position: readonly [number, number, number]): [number, number] =>
|
|
172
|
+
[position[axes[0]], position[axes[1]]];
|
|
173
|
+
const centerPoint = flatten([...point, options.getElevation?.(view) ?? 0]);
|
|
174
|
+
const orientation = cross(flatten(corners[0]), flatten(corners[1]), flatten(corners[2]));
|
|
175
|
+
if (boundary.some((corner, boundaryEdge) =>
|
|
176
|
+
cross(flatten(topologyPosition(corner)), flatten(topologyPosition(boundary[(boundaryEdge + 1) % boundary.length])), centerPoint) * orientation <= 0)) {
|
|
177
|
+
throw new RangeError('Globe mesh: refinement exceeds packed position precision');
|
|
178
|
+
}
|
|
179
|
+
const center = records.length;
|
|
180
|
+
records.push(record);
|
|
181
|
+
positions.push(point);
|
|
182
|
+
for (let boundaryEdge = 0; boundaryEdge < boundary.length; boundaryEdge++) {
|
|
183
|
+
pending.push([boundary[boundaryEdge], boundary[(boundaryEdge + 1) % boundary.length], center]);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
else if (count === 1) {
|
|
187
|
+
const midpoint = getMidpoint(start, end);
|
|
188
|
+
pending.push([start, midpoint, opposite], [midpoint, end, opposite]);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
const endMidpoint = getMidpoint(end, opposite);
|
|
192
|
+
const startMidpoint = getMidpoint(opposite, start);
|
|
193
|
+
const distance = (first: number, second: number) => Math.hypot(positions[first][0] - positions[second][0], positions[first][1] - positions[second][1]);
|
|
194
|
+
pending.push([opposite, startMidpoint, endMidpoint]);
|
|
195
|
+
if (options.splitRemainderShortest && distance(start, endMidpoint) < distance(end, startMidpoint)) {
|
|
196
|
+
pending.push([start, end, endMidpoint], [start, endMidpoint, startMidpoint]);
|
|
197
|
+
} else {
|
|
198
|
+
pending.push([start, end, startMidpoint], [end, endMidpoint, startMidpoint]);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (pending.length + output.length / 3 > maximumTriangles) {
|
|
203
|
+
throw new RangeError('Globe mesh: refinement triangle budget exceeded');
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (records.length === originalCount) {
|
|
207
|
+
return {vertices, indices: triangleIndices};
|
|
208
|
+
}
|
|
209
|
+
const refinedVertices = new Uint8Array(records.length * layout.stride);
|
|
210
|
+
records.forEach((record, index) => refinedVertices.set(record, index * layout.stride));
|
|
211
|
+
return {
|
|
212
|
+
vertices: refinedVertices,
|
|
213
|
+
indices: records.length <= 65536 ? new Uint16Array(output) : new Uint32Array(output)
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** Choose the dominant source-space plane so vertical walls retain the same packed-precision checks as roofs. */
|
|
218
|
+
export function selectTrianglePlane(points: readonly (readonly [number, number, number])[]): readonly [0 | 1 | 2, 0 | 1 | 2] {
|
|
219
|
+
const planes = [[0, 1], [0, 2], [1, 2]] as const;
|
|
220
|
+
let selected: typeof planes[number] = planes[0];
|
|
221
|
+
let maximumArea = 0;
|
|
222
|
+
for (const plane of planes) {
|
|
223
|
+
const [first, second] = plane;
|
|
224
|
+
const area = Math.abs((points[1][first] - points[0][first]) * (points[2][second] - points[0][second]) -
|
|
225
|
+
(points[1][second] - points[0][second]) * (points[2][first] - points[0][first]));
|
|
226
|
+
if (area > maximumArea) {maximumArea = area; selected = plane;}
|
|
227
|
+
}
|
|
228
|
+
return selected;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** Preserve Tangram's packed interpolation and flat IDs at refinement or clipping intersections. */
|
|
232
|
+
export function interpolatePackedVertex(first: Uint8Array, second: Uint8Array,
|
|
233
|
+
layout: {stride: number; dynamic_attribs: VertexAttribute[]}, fraction: number): Uint8Array {
|
|
234
|
+
const record = first.slice();
|
|
235
|
+
const firstView = new DataView(first.buffer, first.byteOffset, layout.stride);
|
|
236
|
+
const secondView = new DataView(second.buffer, second.byteOffset, layout.stride);
|
|
237
|
+
const outputView = new DataView(record.buffer);
|
|
238
|
+
for (const attribute of layout.dynamic_attribs) {
|
|
239
|
+
for (let component = 0; component < attribute.size; component++) {
|
|
240
|
+
const firstValue = readComponent(firstView, attribute, component);
|
|
241
|
+
const secondValue = readComponent(secondView, attribute, component);
|
|
242
|
+
const flat = attribute.name === 'a_selection_color' || (attribute.name === 'a_position' && component === 3);
|
|
243
|
+
if (flat || !INTERPOLATED_ATTRIBUTES.has(attribute.name)) {
|
|
244
|
+
if (firstValue !== secondValue) throw new Error(`Globe mesh: varying flat attribute ${attribute.name} is unsupported`);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
// Keep the exact existing midpoint arithmetic, including integer rounding.
|
|
248
|
+
writeComponent(outputView, attribute, component, fraction === 0.5 ?
|
|
249
|
+
(firstValue + secondValue) / 2 : firstValue * (1 - fraction) + secondValue * fraction);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return record;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/** Read a component without assuming the interleaved buffer starts at byte zero. */
|
|
257
|
+
function readComponent(view: DataView, attribute: VertexAttribute, component: number): number {
|
|
258
|
+
const offset = attribute.offset ?? 0;
|
|
259
|
+
switch (attribute.type) {
|
|
260
|
+
case 0x1400: return view.getInt8(offset + component);
|
|
261
|
+
case 0x1401: return view.getUint8(offset + component);
|
|
262
|
+
case 0x1402: return view.getInt16(offset + component * 2, true);
|
|
263
|
+
case 0x1403: return view.getUint16(offset + component * 2, true);
|
|
264
|
+
case 0x1404: return view.getInt32(offset + component * 4, true);
|
|
265
|
+
case 0x1405: return view.getUint32(offset + component * 4, true);
|
|
266
|
+
case 0x1406: return view.getFloat32(offset + component * 4, true);
|
|
267
|
+
default: throw new Error(`Globe mesh: unsupported attribute type ${attribute.type}`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/** Interpolate in the attribute's packed domain, rounding integer coordinates consistently. */
|
|
272
|
+
function writeComponent(view: DataView, attribute: VertexAttribute, component: number, value: number): void {
|
|
273
|
+
const offset = attribute.offset ?? 0;
|
|
274
|
+
const integer = Math.round(value);
|
|
275
|
+
switch (attribute.type) {
|
|
276
|
+
case 0x1400: view.setInt8(offset + component, integer); break;
|
|
277
|
+
case 0x1401: view.setUint8(offset + component, integer); break;
|
|
278
|
+
case 0x1402: view.setInt16(offset + component * 2, integer, true); break;
|
|
279
|
+
case 0x1403: view.setUint16(offset + component * 2, integer, true); break;
|
|
280
|
+
case 0x1404: view.setInt32(offset + component * 4, integer, true); break;
|
|
281
|
+
case 0x1405: view.setUint32(offset + component * 4, integer, true); break;
|
|
282
|
+
case 0x1406: view.setFloat32(offset + component * 4, value, true); break;
|
|
283
|
+
default: throw new Error(`Globe mesh: unsupported attribute type ${attribute.type}`);
|
|
284
|
+
}
|
|
285
|
+
}
|
package/src/gl/glsl.ts
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
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
|
+
type UniformValue = number | string | boolean | number[] | string[] | number[][];
|
|
7
|
+
type ParsedUniform = {
|
|
8
|
+
type: string;
|
|
9
|
+
method: string;
|
|
10
|
+
name: string;
|
|
11
|
+
value: UniformValue;
|
|
12
|
+
path: (string | number)[];
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
interface GLSLNamespace {
|
|
16
|
+
parseUniforms(uniforms?: Record<string, unknown>): ParsedUniform[];
|
|
17
|
+
defineVariable(name: string, value: unknown): string | undefined;
|
|
18
|
+
defineUniform(name: string, value: unknown): string | undefined;
|
|
19
|
+
expandVec3(value: UniformValue, z?: number): number[] | undefined;
|
|
20
|
+
expandVec4(value: UniformValue, w?: number): number[] | undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const GLSL = {} as GLSLNamespace;
|
|
24
|
+
export default GLSL;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
Parse uniforms from a JS object, infers types and returns an array of objects with the
|
|
28
|
+
necessary information to set uniform values on a GL program. Each object in the returned
|
|
29
|
+
array has the form:
|
|
30
|
+
{ type, method, name, value }
|
|
31
|
+
|
|
32
|
+
type: the GL uniform type, such as 'vec3', 'float', etc.
|
|
33
|
+
method: the GL uniform setter method to use, such as '1f', '3fv', etc.
|
|
34
|
+
name: the fully qualified name of the GL uniform location, e.g. 'array[0].field', etc.
|
|
35
|
+
value: the value to be passed to the GL uniform setter for that type, e.g. [1, 2, 3] for a vec3
|
|
36
|
+
|
|
37
|
+
Textures have special behavior: uniforms with string values are treated as textures, and
|
|
38
|
+
the string is used as a unique texture 'key' to be interpreted by the caller (which is responsible
|
|
39
|
+
for actually setting the uniforms). For example, this could be used as a key into a dictionary of
|
|
40
|
+
known texture names, or it could simply be used as a URL to dynamically load the texture from.
|
|
41
|
+
*/
|
|
42
|
+
GLSL.parseUniforms = function (uniforms: Record<string, unknown> = {}): ParsedUniform[] {
|
|
43
|
+
const parsed: ParsedUniform[] = [];
|
|
44
|
+
|
|
45
|
+
for (const [name, uniform] of Object.entries(uniforms)) {
|
|
46
|
+
// Single float
|
|
47
|
+
if (typeof uniform === 'number') {
|
|
48
|
+
parsed.push({
|
|
49
|
+
type: 'float',
|
|
50
|
+
method: '1f',
|
|
51
|
+
name,
|
|
52
|
+
value: uniform,
|
|
53
|
+
path: [name]
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
// Array: vector, array of floats, array of textures
|
|
57
|
+
else if (Array.isArray(uniform)) {
|
|
58
|
+
// Numeric values
|
|
59
|
+
if (typeof uniform[0] === 'number') {
|
|
60
|
+
// float vectors (vec2, vec3, vec4)
|
|
61
|
+
if (uniform.length >= 2 && uniform.length <= 4) {
|
|
62
|
+
parsed.push({
|
|
63
|
+
type: 'vec' + uniform.length,
|
|
64
|
+
method: uniform.length + 'fv',
|
|
65
|
+
name,
|
|
66
|
+
value: uniform,
|
|
67
|
+
path: [name]
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
// float array
|
|
71
|
+
else if (uniform.length > 4) {
|
|
72
|
+
parsed.push({
|
|
73
|
+
type: 'float[]',
|
|
74
|
+
method: '1fv',
|
|
75
|
+
name: name + '[0]',
|
|
76
|
+
value: uniform,
|
|
77
|
+
path: [name]
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
// TODO: assume matrix for (typeof == Float32Array && length == 16)?
|
|
81
|
+
}
|
|
82
|
+
// Array of textures
|
|
83
|
+
else if (typeof uniform[0] === 'string') {
|
|
84
|
+
for (let u = 0; u < uniform.length; u++) {
|
|
85
|
+
parsed.push({
|
|
86
|
+
type: 'sampler2D',
|
|
87
|
+
method: '1i',
|
|
88
|
+
name: name + '[' + u + ']',
|
|
89
|
+
value: uniform[u],
|
|
90
|
+
path: [name, u]
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Array of arrays - but only arrays of vectors are allowed in this case
|
|
95
|
+
else if (Array.isArray(uniform[0]) && typeof uniform[0][0] === 'number') {
|
|
96
|
+
// float vectors (vec2, vec3, vec4)
|
|
97
|
+
if (uniform[0].length >= 2 && uniform[0].length <= 4) {
|
|
98
|
+
// Set each vector in the array
|
|
99
|
+
for (let u = 0; u < uniform.length; u++) {
|
|
100
|
+
parsed.push({
|
|
101
|
+
type: 'vec' + uniform[0].length,
|
|
102
|
+
method: uniform[0].length + 'fv',
|
|
103
|
+
name: name + '[' + u + ']',
|
|
104
|
+
value: uniform[u],
|
|
105
|
+
path: [name, u]
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// TODO: else warning
|
|
111
|
+
}
|
|
112
|
+
// Boolean
|
|
113
|
+
else if (typeof uniform === 'boolean') {
|
|
114
|
+
parsed.push({
|
|
115
|
+
type: 'bool',
|
|
116
|
+
method: '1i',
|
|
117
|
+
name,
|
|
118
|
+
value: uniform,
|
|
119
|
+
path: [name]
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
// Texture
|
|
123
|
+
else if (typeof uniform === 'string') {
|
|
124
|
+
parsed.push({
|
|
125
|
+
type: 'sampler2D',
|
|
126
|
+
method: '1i',
|
|
127
|
+
name,
|
|
128
|
+
value: uniform,
|
|
129
|
+
path: [name]
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return parsed;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
Generate a GLSL variable definition from a JS object
|
|
139
|
+
*/
|
|
140
|
+
GLSL.defineVariable = function (name: string, value: unknown): string | undefined {
|
|
141
|
+
let type: string | undefined;
|
|
142
|
+
let array: number | undefined;
|
|
143
|
+
|
|
144
|
+
// Single float
|
|
145
|
+
if (typeof value === 'number') {
|
|
146
|
+
type = 'float';
|
|
147
|
+
}
|
|
148
|
+
// Multiple floats - vector or array
|
|
149
|
+
else if (Array.isArray(value)) {
|
|
150
|
+
// Numeric values
|
|
151
|
+
if (typeof value[0] === 'number') {
|
|
152
|
+
// float vectors (vec2, vec3, vec4)
|
|
153
|
+
if (value.length >= 2 && value.length <= 4) {
|
|
154
|
+
type = 'vec' + value.length;
|
|
155
|
+
}
|
|
156
|
+
// float array
|
|
157
|
+
else { //if (value.length > 4) {
|
|
158
|
+
type = 'float';
|
|
159
|
+
array = value.length;
|
|
160
|
+
}
|
|
161
|
+
// TODO: assume matrix for (typeof == Float32Array && length == 16)?
|
|
162
|
+
}
|
|
163
|
+
// Array of textures
|
|
164
|
+
else if (typeof value[0] === 'string') {
|
|
165
|
+
type = 'sampler2D';
|
|
166
|
+
array = value.length;
|
|
167
|
+
}
|
|
168
|
+
// Array of arrays - but only arrays of vectors are allowed in this case
|
|
169
|
+
else if (Array.isArray(value[0]) && typeof value[0][0] === 'number') {
|
|
170
|
+
// float vectors (vec2, vec3, vec4)
|
|
171
|
+
if (value[0].length >= 2 && value[0].length <= 4) {
|
|
172
|
+
type = 'vec' + value[0].length;
|
|
173
|
+
array = value.length;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// Boolean
|
|
178
|
+
else if (typeof value === 'boolean') {
|
|
179
|
+
type = 'bool';
|
|
180
|
+
}
|
|
181
|
+
// Texture
|
|
182
|
+
else if (typeof value === 'string') {
|
|
183
|
+
type = 'sampler2D';
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
return; // no valid type found
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Construct variable definition
|
|
190
|
+
var variable = '';
|
|
191
|
+
variable += `${type} ${name}`;
|
|
192
|
+
if (array) {
|
|
193
|
+
variable += `[${array}]`;
|
|
194
|
+
}
|
|
195
|
+
variable += ';\n';
|
|
196
|
+
|
|
197
|
+
return variable;
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
Generate a GLSL uniform definition from a JS object
|
|
202
|
+
*/
|
|
203
|
+
GLSL.defineUniform = function (name: string, value: unknown): string | undefined {
|
|
204
|
+
var def = GLSL.defineVariable(name, value);
|
|
205
|
+
if (!def) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
return 'uniform ' + def;
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
Expand a single value or 2-element array into a 3-element array, with the last ( z )
|
|
213
|
+
coordinate defaulting to 1 (with option to specify). Also runs parseFloat to try to maintain
|
|
214
|
+
data integrity. Returns null if input couldn't be parsed.
|
|
215
|
+
*/
|
|
216
|
+
GLSL.expandVec3 = function (v: UniformValue, z = 1): number[] | undefined {
|
|
217
|
+
let x: number[];
|
|
218
|
+
if (Array.isArray(v)) {
|
|
219
|
+
if (v.length === 2) {
|
|
220
|
+
x = [...v, z].map(parseFloat as any);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
return v as number[];
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
x = [v, v, v].map(parseFloat as any);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (x && x.every(n => typeof n === 'number' && !isNaN(n))) {
|
|
231
|
+
return x;
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
Expand a single value or 3-element array into a 4-element array, with the last (e.g. w or a)
|
|
237
|
+
coordinate defaulting to 1 (with option to specify). Also runs parseFloat to try to maintain
|
|
238
|
+
data integrity. Returns null if input couldn't be parsed.
|
|
239
|
+
*/
|
|
240
|
+
GLSL.expandVec4 = function (v: UniformValue, w = 1): number[] | undefined {
|
|
241
|
+
let x: number[];
|
|
242
|
+
if (Array.isArray(v)) {
|
|
243
|
+
if (v.length === 3) {
|
|
244
|
+
x = [...v, w].map(parseFloat as any);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
return v as number[];
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
x = [v, v, v, w].map(parseFloat as any);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (x && x.every(n => typeof n === 'number' && !isNaN(n))) {
|
|
255
|
+
return x;
|
|
256
|
+
}
|
|
257
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// tangram-layers
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import type {Buffer, RenderPass, RenderPipelineParameters} from '@luma.gl/core';
|
|
6
|
+
import type {GlobeMeshOptions} from './globe_mesh';
|
|
7
|
+
import type {VertexArrayBinding, VertexArrayContext} from './vao';
|
|
8
|
+
import type {VertexAttribute, VertexAttributeProgram, VertexAttributeContext} from './vertex-types';
|
|
9
|
+
import type VBOMesh from './vbo_mesh';
|
|
10
|
+
import type {TangramDrawableProgram, TangramMeshBufferOptions, TangramMeshDrawOptions, TangramMeshDrawDescriptor} from '../gpu/tangram_gpu_backend';
|
|
11
|
+
|
|
12
|
+
/** Original packed vertex/index bytes retained only when CPU updates or refinement need them. */
|
|
13
|
+
export type MeshVertexData = Uint8Array | Int8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array;
|
|
14
|
+
/** Missing element data means the mesh uses a non-indexed draw. */
|
|
15
|
+
export type MeshElementData = Uint16Array | Uint32Array | false | null | undefined;
|
|
16
|
+
/** The classic mesh path uses raw GL; the portable path needs no GL context. */
|
|
17
|
+
export type MeshContext = Pick<WebGLRenderingContext, 'STATIC_DRAW' | 'ELEMENT_ARRAY_BUFFER' | 'ARRAY_BUFFER' |
|
|
18
|
+
'createBuffer' | 'bindBuffer' | 'bufferData' | 'drawElements' | 'drawArrays' | 'deleteBuffer'> & VertexArrayContext & VertexAttributeContext;
|
|
19
|
+
/** Layout capabilities shared by device meshes and their classic attribute bindings. */
|
|
20
|
+
export interface MeshVertexLayout {
|
|
21
|
+
stride: number;
|
|
22
|
+
/** Packed attribute offsets, absent only for minimal non-annotation layouts. */
|
|
23
|
+
offset?: Record<string, number>;
|
|
24
|
+
dynamic_attribs?: VertexAttribute[];
|
|
25
|
+
getBufferLayout(): TangramMeshDrawDescriptor['bufferLayout'];
|
|
26
|
+
getStaticAttributes(): {attribute: string; value: number[]}[];
|
|
27
|
+
enableDynamicAttributes?(context: VertexAttributeContext, program: VertexAttributeProgram): void;
|
|
28
|
+
enableStaticAttributes?(context: VertexAttributeContext, program: VertexAttributeProgram): void;
|
|
29
|
+
}
|
|
30
|
+
/** Legacy program operations added to the device submission contract. */
|
|
31
|
+
export interface MeshProgram extends TangramDrawableProgram, VertexAttributeProgram {
|
|
32
|
+
use(options?: {bindUniformBlocks: boolean}): void;
|
|
33
|
+
}
|
|
34
|
+
/** Caller-supplied allocation and owned texture/fade/refinement state. */
|
|
35
|
+
export interface MeshOptions {
|
|
36
|
+
id?: string | number;
|
|
37
|
+
bufferFactory?: (options: TangramMeshBufferOptions) => Buffer;
|
|
38
|
+
draw_mode?: number;
|
|
39
|
+
data_usage?: number;
|
|
40
|
+
uniforms?: Record<string, unknown>;
|
|
41
|
+
textures?: string[];
|
|
42
|
+
retain?: boolean;
|
|
43
|
+
fade_in_time?: number;
|
|
44
|
+
globeRefinement?: GlobeMeshOptions;
|
|
45
|
+
globeRefinementError?: string;
|
|
46
|
+
}
|
|
47
|
+
/** Per-draw host state; camera projection controls lazy geometry refinement only. */
|
|
48
|
+
export interface MeshRenderOptions {
|
|
49
|
+
projection?: string;
|
|
50
|
+
program?: MeshProgram;
|
|
51
|
+
meshRenderer?: {drawMesh(options: Omit<TangramMeshDrawOptions, 'mesh'> & {mesh: VBOMesh}): boolean | null};
|
|
52
|
+
renderPass?: RenderPass;
|
|
53
|
+
renderState?: RenderPipelineParameters;
|
|
54
|
+
}
|
|
55
|
+
/** Classic bindings are opaque to device renderers and keyed by program identity. */
|
|
56
|
+
export type MeshVertexArrays = Record<string | number, VertexArrayBinding>;
|