@sakuzu/maplibre-gl-draw 1.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/CHANGELOG.md +43 -0
- package/LICENSE +661 -0
- package/README.ja.md +248 -0
- package/README.md +255 -0
- package/THIRD_PARTY_NOTICES.md +275 -0
- package/dist/api/api.d.ts +1259 -0
- package/dist/api/api.js +86 -0
- package/dist/api/context.d.ts +173 -0
- package/dist/api/context.js +193 -0
- package/dist/api/display-api.d.ts +1 -0
- package/dist/api/display-api.js +23 -0
- package/dist/api/event-api.d.ts +13 -0
- package/dist/api/event-api.js +17 -0
- package/dist/api/extension-api.d.ts +46 -0
- package/dist/api/extension-api.js +85 -0
- package/dist/api/feature-api.d.ts +11 -0
- package/dist/api/feature-api.js +101 -0
- package/dist/api/geometry/apply.d.ts +51 -0
- package/dist/api/geometry/apply.js +114 -0
- package/dist/api/geometry/boolean.d.ts +28 -0
- package/dist/api/geometry/boolean.js +65 -0
- package/dist/api/geometry/buffer.d.ts +11 -0
- package/dist/api/geometry/buffer.js +105 -0
- package/dist/api/geometry/split.d.ts +16 -0
- package/dist/api/geometry/split.js +75 -0
- package/dist/api/geometry/targets.d.ts +76 -0
- package/dist/api/geometry/targets.js +158 -0
- package/dist/api/geometry/types.d.ts +31 -0
- package/dist/api/geometry/types.js +3 -0
- package/dist/api/geometry-operations.d.ts +162 -0
- package/dist/api/geometry-operations.js +94 -0
- package/dist/api/group-api.d.ts +10 -0
- package/dist/api/group-api.js +78 -0
- package/dist/api/import-export/constants.d.ts +29 -0
- package/dist/api/import-export/constants.js +40 -0
- package/dist/api/import-export/embedded-file.d.ts +13 -0
- package/dist/api/import-export/embedded-file.js +31 -0
- package/dist/api/import-export/file-name.d.ts +10 -0
- package/dist/api/import-export/file-name.js +20 -0
- package/dist/api/import-export/format-detection.d.ts +12 -0
- package/dist/api/import-export/format-detection.js +29 -0
- package/dist/api/import-export/geojson-export.d.ts +19 -0
- package/dist/api/import-export/geojson-export.js +262 -0
- package/dist/api/import-export/geojson-import.d.ts +34 -0
- package/dist/api/import-export/geojson-import.js +538 -0
- package/dist/api/import-export/geometry-validation.d.ts +20 -0
- package/dist/api/import-export/geometry-validation.js +107 -0
- package/dist/api/import-export/image-import.d.ts +12 -0
- package/dist/api/import-export/image-import.js +53 -0
- package/dist/api/import-export/index.d.ts +9 -0
- package/dist/api/import-export/index.js +107 -0
- package/dist/api/import-export/native-format.d.ts +15 -0
- package/dist/api/import-export/native-format.js +126 -0
- package/dist/api/import-export/native-validation.d.ts +28 -0
- package/dist/api/import-export/native-validation.js +212 -0
- package/dist/api/import-export/own-property.d.ts +10 -0
- package/dist/api/import-export/own-property.js +19 -0
- package/dist/api/import-export/style-validation.d.ts +27 -0
- package/dist/api/import-export/style-validation.js +49 -0
- package/dist/api/import-export/types.d.ts +26 -0
- package/dist/api/import-export/types.js +3 -0
- package/dist/api/index.d.ts +15 -0
- package/dist/api/index.js +3 -0
- package/dist/api/input-api.d.ts +158 -0
- package/dist/api/input-api.js +144 -0
- package/dist/api/instance-api.d.ts +38 -0
- package/dist/api/instance-api.js +136 -0
- package/dist/api/layer-api.d.ts +12 -0
- package/dist/api/layer-api.js +62 -0
- package/dist/api/selection-api.d.ts +7 -0
- package/dist/api/selection-api.js +78 -0
- package/dist/api/snapping-api.d.ts +125 -0
- package/dist/api/snapping-api.js +50 -0
- package/dist/api/topology-api.d.ts +30 -0
- package/dist/api/topology-api.js +16 -0
- package/dist/api/tracing-api.d.ts +31 -0
- package/dist/api/tracing-api.js +16 -0
- package/dist/dispatcher/hit-test/box-strategies.d.ts +19 -0
- package/dist/dispatcher/hit-test/box-strategies.js +275 -0
- package/dist/dispatcher/hit-test/box-strategy.d.ts +59 -0
- package/dist/dispatcher/hit-test/box-strategy.js +37 -0
- package/dist/dispatcher/hit-test/globe-shape.d.ts +46 -0
- package/dist/dispatcher/hit-test/globe-shape.js +70 -0
- package/dist/dispatcher/hit-test/index.d.ts +14 -0
- package/dist/dispatcher/hit-test/index.js +9 -0
- package/dist/dispatcher/hit-test/local-frame.d.ts +77 -0
- package/dist/dispatcher/hit-test/local-frame.js +112 -0
- package/dist/dispatcher/hit-test/segment-grid.d.ts +32 -0
- package/dist/dispatcher/hit-test/segment-grid.js +79 -0
- package/dist/dispatcher/hit-test/service.d.ts +120 -0
- package/dist/dispatcher/hit-test/service.js +333 -0
- package/dist/dispatcher/hit-test/strategies/base.d.ts +136 -0
- package/dist/dispatcher/hit-test/strategies/base.js +66 -0
- package/dist/dispatcher/hit-test/strategies/circle.d.ts +10 -0
- package/dist/dispatcher/hit-test/strategies/circle.js +56 -0
- package/dist/dispatcher/hit-test/strategies/image.d.ts +22 -0
- package/dist/dispatcher/hit-test/strategies/image.js +115 -0
- package/dist/dispatcher/hit-test/strategies/index.d.ts +11 -0
- package/dist/dispatcher/hit-test/strategies/index.js +10 -0
- package/dist/dispatcher/hit-test/strategies/line.d.ts +17 -0
- package/dist/dispatcher/hit-test/strategies/line.js +30 -0
- package/dist/dispatcher/hit-test/strategies/multi.d.ts +44 -0
- package/dist/dispatcher/hit-test/strategies/multi.js +141 -0
- package/dist/dispatcher/hit-test/strategies/point.d.ts +20 -0
- package/dist/dispatcher/hit-test/strategies/point.js +29 -0
- package/dist/dispatcher/hit-test/strategies/polygon.d.ts +52 -0
- package/dist/dispatcher/hit-test/strategies/polygon.js +138 -0
- package/dist/dispatcher/hit-test/topmost.d.ts +48 -0
- package/dist/dispatcher/hit-test/topmost.js +157 -0
- package/dist/dispatcher/hit-test/visibility-lookup.d.ts +23 -0
- package/dist/dispatcher/hit-test/visibility-lookup.js +40 -0
- package/dist/dispatcher/index.d.ts +15 -0
- package/dist/dispatcher/index.js +3 -0
- package/dist/dispatcher/input-router.d.ts +1 -0
- package/dist/dispatcher/input-router.js +288 -0
- package/dist/dispatcher/normalizer.d.ts +1 -0
- package/dist/dispatcher/normalizer.js +513 -0
- package/dist/dispatcher/types.d.ts +144 -0
- package/dist/dispatcher/types.js +15 -0
- package/dist/display/chunk-set.d.ts +24 -0
- package/dist/display/chunk-set.js +533 -0
- package/dist/display/chunk.d.ts +1 -0
- package/dist/display/chunk.js +104 -0
- package/dist/display/columnar/index.d.ts +12 -0
- package/dist/display/columnar/index.js +13 -0
- package/dist/display/columnar/prepare.d.ts +42 -0
- package/dist/display/columnar/prepare.js +116 -0
- package/dist/display/columnar/source.d.ts +1 -0
- package/dist/display/columnar/source.js +531 -0
- package/dist/display/columnar/table.d.ts +1 -0
- package/dist/display/columnar/table.js +471 -0
- package/dist/display/columnar/types.d.ts +223 -0
- package/dist/display/columnar/types.js +3 -0
- package/dist/display/dataset.d.ts +2 -0
- package/dist/display/dataset.js +891 -0
- package/dist/display/index.d.ts +13 -0
- package/dist/display/index.js +3 -0
- package/dist/display/interaction.d.ts +1 -0
- package/dist/display/interaction.js +90 -0
- package/dist/display/manager.d.ts +1 -0
- package/dist/display/manager.js +440 -0
- package/dist/display/packed-rtree.d.ts +1 -0
- package/dist/display/packed-rtree.js +244 -0
- package/dist/display/partition.d.ts +1 -0
- package/dist/display/partition.js +226 -0
- package/dist/display/provider.d.ts +1 -0
- package/dist/display/provider.js +342 -0
- package/dist/display/retained.d.ts +40 -0
- package/dist/display/retained.js +898 -0
- package/dist/display/selection.d.ts +13 -0
- package/dist/display/selection.js +226 -0
- package/dist/display/source.d.ts +1 -0
- package/dist/display/source.js +119 -0
- package/dist/display/spatial.d.ts +1 -0
- package/dist/display/spatial.js +71 -0
- package/dist/display/style.d.ts +1 -0
- package/dist/display/style.js +126 -0
- package/dist/display/thinning.d.ts +65 -0
- package/dist/display/thinning.js +910 -0
- package/dist/display/triangulation.d.ts +1 -0
- package/dist/display/triangulation.js +0 -0
- package/dist/display/types.d.ts +561 -0
- package/dist/display/types.js +43 -0
- package/dist/extension/feature-handler.d.ts +182 -0
- package/dist/extension/feature-handler.js +3 -0
- package/dist/extension/index.d.ts +9 -0
- package/dist/extension/index.js +3 -0
- package/dist/extension/renderers.d.ts +208 -0
- package/dist/extension/renderers.js +3 -0
- package/dist/geometry/angle.d.ts +47 -0
- package/dist/geometry/angle.js +44 -0
- package/dist/geometry/bbox.d.ts +48 -0
- package/dist/geometry/bbox.js +83 -0
- package/dist/geometry/boolean.d.ts +162 -0
- package/dist/geometry/boolean.js +331 -0
- package/dist/geometry/buffer.d.ts +72 -0
- package/dist/geometry/buffer.js +218 -0
- package/dist/geometry/circle.d.ts +55 -0
- package/dist/geometry/circle.js +107 -0
- package/dist/geometry/coords.d.ts +97 -0
- package/dist/geometry/coords.js +149 -0
- package/dist/geometry/distance.d.ts +79 -0
- package/dist/geometry/distance.js +111 -0
- package/dist/geometry/errors.d.ts +74 -0
- package/dist/geometry/errors.js +104 -0
- package/dist/geometry/index.d.ts +28 -0
- package/dist/geometry/index.js +38 -0
- package/dist/geometry/measure.d.ts +81 -0
- package/dist/geometry/measure.js +236 -0
- package/dist/geometry/predicates.d.ts +62 -0
- package/dist/geometry/predicates.js +132 -0
- package/dist/geometry/simplify.d.ts +74 -0
- package/dist/geometry/simplify.js +159 -0
- package/dist/geometry/split.d.ts +68 -0
- package/dist/geometry/split.js +430 -0
- package/dist/geometry/types.d.ts +95 -0
- package/dist/geometry/types.js +3 -0
- package/dist/geometry/units.d.ts +35 -0
- package/dist/geometry/units.js +41 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.js +20 -0
- package/dist/maplibre-gl-draw.d.ts +47 -0
- package/dist/maplibre-gl-draw.js +407 -0
- package/dist/messages.d.ts +64 -0
- package/dist/messages.js +36 -0
- package/dist/modes/cursor.d.ts +1 -0
- package/dist/modes/cursor.js +72 -0
- package/dist/modes/draw/circle.d.ts +1 -0
- package/dist/modes/draw/circle.js +222 -0
- package/dist/modes/draw/commit-layer.d.ts +26 -0
- package/dist/modes/draw/commit-layer.js +31 -0
- package/dist/modes/draw/freehand.d.ts +1 -0
- package/dist/modes/draw/freehand.js +264 -0
- package/dist/modes/draw/image.d.ts +1 -0
- package/dist/modes/draw/image.js +60 -0
- package/dist/modes/draw/index.d.ts +9 -0
- package/dist/modes/draw/index.js +11 -0
- package/dist/modes/draw/line.d.ts +1 -0
- package/dist/modes/draw/line.js +363 -0
- package/dist/modes/draw/point.d.ts +1 -0
- package/dist/modes/draw/point.js +87 -0
- package/dist/modes/draw/polygon.d.ts +1 -0
- package/dist/modes/draw/polygon.js +378 -0
- package/dist/modes/draw/trace-support.d.ts +79 -0
- package/dist/modes/draw/trace-support.js +161 -0
- package/dist/modes/handler.d.ts +285 -0
- package/dist/modes/handler.js +3 -0
- package/dist/modes/index.d.ts +7 -0
- package/dist/modes/index.js +3 -0
- package/dist/modes/manager.d.ts +15 -0
- package/dist/modes/manager.js +196 -0
- package/dist/modes/select/box-selection.d.ts +52 -0
- package/dist/modes/select/box-selection.js +140 -0
- package/dist/modes/select/click-handler.d.ts +32 -0
- package/dist/modes/select/click-handler.js +166 -0
- package/dist/modes/select/cursor-handler.d.ts +15 -0
- package/dist/modes/select/cursor-handler.js +59 -0
- package/dist/modes/select/drag/auxiliary.d.ts +26 -0
- package/dist/modes/select/drag/auxiliary.js +56 -0
- package/dist/modes/select/drag/intermediate-writes.d.ts +1 -0
- package/dist/modes/select/drag/intermediate-writes.js +171 -0
- package/dist/modes/select/drag/move.d.ts +24 -0
- package/dist/modes/select/drag/move.js +59 -0
- package/dist/modes/select/drag/operation.d.ts +30 -0
- package/dist/modes/select/drag/operation.js +18 -0
- package/dist/modes/select/drag/radius.d.ts +15 -0
- package/dist/modes/select/drag/radius.js +49 -0
- package/dist/modes/select/drag/transform.d.ts +17 -0
- package/dist/modes/select/drag/transform.js +155 -0
- package/dist/modes/select/drag/vertex.d.ts +17 -0
- package/dist/modes/select/drag/vertex.js +163 -0
- package/dist/modes/select/drag-handler.d.ts +1 -0
- package/dist/modes/select/drag-handler.js +254 -0
- package/dist/modes/select/hit-helpers.d.ts +40 -0
- package/dist/modes/select/hit-helpers.js +51 -0
- package/dist/modes/select/mode.d.ts +1 -0
- package/dist/modes/select/mode.js +397 -0
- package/dist/modes/select/shortcut-handler.d.ts +40 -0
- package/dist/modes/select/shortcut-handler.js +128 -0
- package/dist/operations/index.d.ts +9 -0
- package/dist/operations/index.js +3 -0
- package/dist/operations/layer-operations.d.ts +1 -0
- package/dist/operations/layer-operations.js +350 -0
- package/dist/operations/resize.d.ts +71 -0
- package/dist/operations/resize.js +252 -0
- package/dist/operations/rotate.d.ts +17 -0
- package/dist/operations/rotate.js +166 -0
- package/dist/operations/selection-operations.d.ts +20 -0
- package/dist/operations/selection-operations.js +159 -0
- package/dist/operations/shared-vertex.d.ts +1 -0
- package/dist/operations/shared-vertex.js +210 -0
- package/dist/operations/trace-graph.d.ts +96 -0
- package/dist/operations/trace-graph.js +283 -0
- package/dist/operations/vertex.d.ts +1 -0
- package/dist/operations/vertex.js +538 -0
- package/dist/plugins/index.d.ts +10 -0
- package/dist/plugins/index.js +3 -0
- package/dist/plugins/mutation-hooks.d.ts +28 -0
- package/dist/plugins/mutation-hooks.js +84 -0
- package/dist/plugins/plugin-context.d.ts +1 -0
- package/dist/plugins/plugin-context.js +367 -0
- package/dist/plugins/plugin-manager.d.ts +103 -0
- package/dist/plugins/plugin-manager.js +316 -0
- package/dist/plugins/plugin.d.ts +529 -0
- package/dist/plugins/plugin.js +3 -0
- package/dist/shared/config/constants.d.ts +66 -0
- package/dist/shared/config/constants.js +60 -0
- package/dist/shared/config/feature-style.d.ts +155 -0
- package/dist/shared/config/feature-style.js +154 -0
- package/dist/shared/config/index.d.ts +17 -0
- package/dist/shared/config/index.js +8 -0
- package/dist/shared/config/rendering.d.ts +107 -0
- package/dist/shared/config/rendering.js +33 -0
- package/dist/shared/config/selection-highlight.d.ts +29 -0
- package/dist/shared/config/selection-highlight.js +35 -0
- package/dist/shared/config/selection.d.ts +273 -0
- package/dist/shared/config/selection.js +266 -0
- package/dist/shared/config/topology.d.ts +33 -0
- package/dist/shared/config/topology.js +17 -0
- package/dist/shared/config/trace.d.ts +40 -0
- package/dist/shared/config/trace.js +17 -0
- package/dist/shared/math/angle.d.ts +21 -0
- package/dist/shared/math/angle.js +34 -0
- package/dist/shared/math/circle.d.ts +6 -0
- package/dist/shared/math/circle.js +10 -0
- package/dist/shared/math/constants.d.ts +48 -0
- package/dist/shared/math/constants.js +59 -0
- package/dist/shared/math/distance.d.ts +78 -0
- package/dist/shared/math/distance.js +147 -0
- package/dist/shared/math/globe-subdivision.d.ts +62 -0
- package/dist/shared/math/globe-subdivision.js +99 -0
- package/dist/shared/math/index.d.ts +17 -0
- package/dist/shared/math/index.js +21 -0
- package/dist/shared/math/intersection.d.ts +63 -0
- package/dist/shared/math/intersection.js +236 -0
- package/dist/shared/math/longitude.d.ts +20 -0
- package/dist/shared/math/longitude.js +31 -0
- package/dist/shared/math/mercator-plane.d.ts +27 -0
- package/dist/shared/math/mercator-plane.js +26 -0
- package/dist/shared/math/obb.d.ts +65 -0
- package/dist/shared/math/obb.js +107 -0
- package/dist/shared/math/rotation.d.ts +93 -0
- package/dist/shared/math/rotation.js +186 -0
- package/dist/shared/math/segment-grid.d.ts +69 -0
- package/dist/shared/math/segment-grid.js +159 -0
- package/dist/shared/math/transform.d.ts +140 -0
- package/dist/shared/math/transform.js +189 -0
- package/dist/shared/types/events.d.ts +128 -0
- package/dist/shared/types/events.js +3 -0
- package/dist/shared/types/model.d.ts +950 -0
- package/dist/shared/types/model.js +3 -0
- package/dist/shared/types/selection-box.d.ts +23 -0
- package/dist/shared/types/selection-box.js +3 -0
- package/dist/shared/types/style.d.ts +68 -0
- package/dist/shared/types/style.js +3 -0
- package/dist/shared/utils/color.d.ts +49 -0
- package/dist/shared/utils/color.js +180 -0
- package/dist/shared/utils/coordinates.d.ts +52 -0
- package/dist/shared/utils/coordinates.js +75 -0
- package/dist/shared/utils/embedded-image.d.ts +34 -0
- package/dist/shared/utils/embedded-image.js +161 -0
- package/dist/shared/utils/event-emitter.d.ts +262 -0
- package/dist/shared/utils/event-emitter.js +44 -0
- package/dist/shared/utils/feature-bbox.d.ts +8 -0
- package/dist/shared/utils/feature-bbox.js +207 -0
- package/dist/shared/utils/feature-segments.d.ts +23 -0
- package/dist/shared/utils/feature-segments.js +179 -0
- package/dist/shared/utils/id.d.ts +1 -0
- package/dist/shared/utils/id.js +35 -0
- package/dist/shared/utils/image.d.ts +34 -0
- package/dist/shared/utils/image.js +106 -0
- package/dist/shared/utils/index.d.ts +15 -0
- package/dist/shared/utils/index.js +24 -0
- package/dist/shared/utils/map.d.ts +26 -0
- package/dist/shared/utils/map.js +35 -0
- package/dist/shared/utils/name-generator.d.ts +197 -0
- package/dist/shared/utils/name-generator.js +337 -0
- package/dist/shared/utils/pixel-ratio.d.ts +111 -0
- package/dist/shared/utils/pixel-ratio.js +85 -0
- package/dist/shared/utils/property.d.ts +88 -0
- package/dist/shared/utils/property.js +140 -0
- package/dist/shared/utils/vertex-ref.d.ts +23 -0
- package/dist/shared/utils/vertex-ref.js +20 -0
- package/dist/snapping/custom-targets.d.ts +1 -0
- package/dist/snapping/custom-targets.js +21 -0
- package/dist/snapping/geometry.d.ts +1 -0
- package/dist/snapping/geometry.js +61 -0
- package/dist/snapping/index.d.ts +14 -0
- package/dist/snapping/index.js +4 -0
- package/dist/snapping/indicator.d.ts +19 -0
- package/dist/snapping/indicator.js +145 -0
- package/dist/snapping/providers/display.d.ts +72 -0
- package/dist/snapping/providers/display.js +268 -0
- package/dist/snapping/providers/guide.d.ts +69 -0
- package/dist/snapping/providers/guide.js +187 -0
- package/dist/snapping/providers/intersection.d.ts +1 -0
- package/dist/snapping/providers/intersection.js +92 -0
- package/dist/snapping/providers/shared.d.ts +39 -0
- package/dist/snapping/providers/shared.js +146 -0
- package/dist/snapping/providers/store.d.ts +1 -0
- package/dist/snapping/providers/store.js +132 -0
- package/dist/snapping/service.d.ts +1 -0
- package/dist/snapping/service.js +272 -0
- package/dist/snapping/types.d.ts +267 -0
- package/dist/snapping/types.js +66 -0
- package/dist/store/change-merger.d.ts +1 -0
- package/dist/store/change-merger.js +102 -0
- package/dist/store/draw-store.d.ts +1 -0
- package/dist/store/draw-store.js +396 -0
- package/dist/store/event-bridge.d.ts +1 -0
- package/dist/store/event-bridge.js +161 -0
- package/dist/store/index.d.ts +12 -0
- package/dist/store/index.js +4 -0
- package/dist/store/local-visibility.d.ts +21 -0
- package/dist/store/local-visibility.js +27 -0
- package/dist/store/lock.d.ts +67 -0
- package/dist/store/lock.js +54 -0
- package/dist/store/memory/change-bus.d.ts +60 -0
- package/dist/store/memory/change-bus.js +232 -0
- package/dist/store/memory/file-store.d.ts +15 -0
- package/dist/store/memory/file-store.js +33 -0
- package/dist/store/memory/frozen.d.ts +21 -0
- package/dist/store/memory/frozen.js +51 -0
- package/dist/store/memory/ui-state.d.ts +51 -0
- package/dist/store/memory/ui-state.js +223 -0
- package/dist/store/memory.d.ts +26 -0
- package/dist/store/memory.js +708 -0
- package/dist/store/spatial/index.d.ts +6 -0
- package/dist/store/spatial/index.js +4 -0
- package/dist/store/spatial/spatial-index.d.ts +90 -0
- package/dist/store/spatial/spatial-index.js +148 -0
- package/dist/store/spatial/store-spatial-index.d.ts +60 -0
- package/dist/store/spatial/store-spatial-index.js +125 -0
- package/dist/store/store.d.ts +417 -0
- package/dist/store/store.js +3 -0
- package/dist/store/types.d.ts +8 -0
- package/dist/store/types.js +3 -0
- package/dist/store/writable-layer.d.ts +35 -0
- package/dist/store/writable-layer.js +20 -0
- package/dist/view/cache/buffer.d.ts +28 -0
- package/dist/view/cache/buffer.js +176 -0
- package/dist/view/cache/earcut.d.ts +1 -0
- package/dist/view/cache/earcut.js +122 -0
- package/dist/view/cache/style-rule.d.ts +1 -0
- package/dist/view/cache/style-rule.js +97 -0
- package/dist/view/cache/terrain-fill.d.ts +30 -0
- package/dist/view/cache/terrain-fill.js +60 -0
- package/dist/view/cache/texture.d.ts +14 -0
- package/dist/view/cache/texture.js +292 -0
- package/dist/view/coordinator.d.ts +27 -0
- package/dist/view/coordinator.js +72 -0
- package/dist/view/feature-companion.d.ts +173 -0
- package/dist/view/feature-companion.js +108 -0
- package/dist/view/globe-subdivision.d.ts +78 -0
- package/dist/view/globe-subdivision.js +128 -0
- package/dist/view/index.d.ts +47 -0
- package/dist/view/index.js +20 -0
- package/dist/view/layer/attach.d.ts +20 -0
- package/dist/view/layer/attach.js +47 -0
- package/dist/view/layer/blend.d.ts +57 -0
- package/dist/view/layer/blend.js +14 -0
- package/dist/view/layer/custom-layer.d.ts +1 -0
- package/dist/view/layer/custom-layer.js +509 -0
- package/dist/view/layer/depth-state.d.ts +14 -0
- package/dist/view/layer/depth-state.js +44 -0
- package/dist/view/layer/display-list.d.ts +1 -0
- package/dist/view/layer/display-list.js +111 -0
- package/dist/view/layer/drape-planner.d.ts +139 -0
- package/dist/view/layer/drape-planner.js +726 -0
- package/dist/view/layer/frame-render.d.ts +57 -0
- package/dist/view/layer/frame-render.js +209 -0
- package/dist/view/layer/frame-state.d.ts +147 -0
- package/dist/view/layer/frame-state.js +484 -0
- package/dist/view/layer/gl-state.d.ts +77 -0
- package/dist/view/layer/gl-state.js +132 -0
- package/dist/view/layer/index.d.ts +6 -0
- package/dist/view/layer/index.js +5 -0
- package/dist/view/layer/render-scope.d.ts +30 -0
- package/dist/view/layer/render-scope.js +28 -0
- package/dist/view/layer/render.d.ts +87 -0
- package/dist/view/layer/render.js +187 -0
- package/dist/view/layer/renderers.d.ts +81 -0
- package/dist/view/layer/renderers.js +142 -0
- package/dist/view/layer/slot-manager.d.ts +26 -0
- package/dist/view/layer/slot-manager.js +133 -0
- package/dist/view/layer/slots.d.ts +33 -0
- package/dist/view/layer/slots.js +50 -0
- package/dist/view/layer/store-retained-bbox.d.ts +36 -0
- package/dist/view/layer/store-retained-bbox.js +188 -0
- package/dist/view/layer/store-retained-chunk.d.ts +97 -0
- package/dist/view/layer/store-retained-chunk.js +94 -0
- package/dist/view/layer/store-retained-classify.d.ts +34 -0
- package/dist/view/layer/store-retained-classify.js +88 -0
- package/dist/view/layer/store-retained-collect.d.ts +24 -0
- package/dist/view/layer/store-retained-collect.js +121 -0
- package/dist/view/layer/store-retained-coord-patch.d.ts +119 -0
- package/dist/view/layer/store-retained-coord-patch.js +168 -0
- package/dist/view/layer/store-retained-immediate.d.ts +63 -0
- package/dist/view/layer/store-retained-immediate.js +49 -0
- package/dist/view/layer/store-retained-invalidation.d.ts +96 -0
- package/dist/view/layer/store-retained-invalidation.js +192 -0
- package/dist/view/layer/store-retained.d.ts +198 -0
- package/dist/view/layer/store-retained.js +430 -0
- package/dist/view/layer/terrain-resolver.d.ts +1 -0
- package/dist/view/layer/terrain-resolver.js +174 -0
- package/dist/view/renderers/batch-manager.d.ts +61 -0
- package/dist/view/renderers/batch-manager.js +718 -0
- package/dist/view/renderers/draw-factors.d.ts +60 -0
- package/dist/view/renderers/draw-factors.js +35 -0
- package/dist/view/renderers/drawer.d.ts +1 -0
- package/dist/view/renderers/drawer.js +346 -0
- package/dist/view/renderers/image.d.ts +1 -0
- package/dist/view/renderers/image.js +255 -0
- package/dist/view/renderers/line/dash.d.ts +31 -0
- package/dist/view/renderers/line/dash.js +152 -0
- package/dist/view/renderers/line/line-geometry.d.ts +39 -0
- package/dist/view/renderers/line/line-geometry.js +460 -0
- package/dist/view/renderers/line/line-gl.d.ts +1 -0
- package/dist/view/renderers/line/line-gl.js +236 -0
- package/dist/view/renderers/line/line-shader.d.ts +1 -0
- package/dist/view/renderers/line/line-shader.js +364 -0
- package/dist/view/renderers/line/line-types.d.ts +43 -0
- package/dist/view/renderers/line/line-types.js +3 -0
- package/dist/view/renderers/line/line-uniforms.d.ts +1 -0
- package/dist/view/renderers/line/line-uniforms.js +390 -0
- package/dist/view/renderers/line/sdf-line.d.ts +92 -0
- package/dist/view/renderers/line/sdf-line.js +567 -0
- package/dist/view/renderers/point/billboard-depth.d.ts +10 -0
- package/dist/view/renderers/point/billboard-depth.js +56 -0
- package/dist/view/renderers/point/point-instance.d.ts +124 -0
- package/dist/view/renderers/point/point-instance.js +738 -0
- package/dist/view/renderers/point/point-sdf.d.ts +58 -0
- package/dist/view/renderers/point/point-sdf.js +170 -0
- package/dist/view/renderers/point/point-shape.d.ts +99 -0
- package/dist/view/renderers/point/point-shape.js +504 -0
- package/dist/view/renderers/point/point-style.d.ts +1 -0
- package/dist/view/renderers/point/point-style.js +46 -0
- package/dist/view/renderers/polygon/batch.d.ts +26 -0
- package/dist/view/renderers/polygon/batch.js +336 -0
- package/dist/view/renderers/polygon/earcut-input.d.ts +37 -0
- package/dist/view/renderers/polygon/earcut-input.js +55 -0
- package/dist/view/renderers/polygon/earcut-sliced.d.ts +69 -0
- package/dist/view/renderers/polygon/earcut-sliced.js +960 -0
- package/dist/view/renderers/polygon/fill.d.ts +74 -0
- package/dist/view/renderers/polygon/fill.js +251 -0
- package/dist/view/renderers/polygon/sdf-polygon.d.ts +62 -0
- package/dist/view/renderers/polygon/sdf-polygon.js +919 -0
- package/dist/view/renderers/polygon/terrain-cull.d.ts +3 -0
- package/dist/view/renderers/polygon/terrain-cull.js +14 -0
- package/dist/view/renderers/polygon/triangulator.d.ts +41 -0
- package/dist/view/renderers/polygon/triangulator.js +3 -0
- package/dist/view/renderers/retained.d.ts +43 -0
- package/dist/view/renderers/retained.js +3 -0
- package/dist/view/renderers/stroke.d.ts +121 -0
- package/dist/view/renderers/stroke.js +621 -0
- package/dist/view/shaders/frame.d.ts +8 -0
- package/dist/view/shaders/frame.js +37 -0
- package/dist/view/shaders/helpers.d.ts +238 -0
- package/dist/view/shaders/helpers.js +611 -0
- package/dist/view/shaders/initializer.d.ts +27 -0
- package/dist/view/shaders/initializer.js +125 -0
- package/dist/view/shaders/projection.d.ts +123 -0
- package/dist/view/shaders/projection.js +299 -0
- package/dist/view/shaders/quad-grid.d.ts +77 -0
- package/dist/view/shaders/quad-grid.js +128 -0
- package/dist/view/shaders/quad.d.ts +189 -0
- package/dist/view/shaders/quad.js +582 -0
- package/dist/view/shaders/retained-origin.d.ts +50 -0
- package/dist/view/shaders/retained-origin.js +67 -0
- package/dist/view/shaders/terrain-shade.d.ts +23 -0
- package/dist/view/shaders/terrain-shade.js +93 -0
- package/dist/view/style-rule.d.ts +166 -0
- package/dist/view/style-rule.js +300 -0
- package/dist/view/terrain/anchor.d.ts +135 -0
- package/dist/view/terrain/anchor.js +226 -0
- package/dist/view/terrain/context.d.ts +132 -0
- package/dist/view/terrain/context.js +437 -0
- package/dist/view/terrain/dem-atlas.d.ts +97 -0
- package/dist/view/terrain/dem-atlas.js +534 -0
- package/dist/view/terrain/detect.d.ts +126 -0
- package/dist/view/terrain/detect.js +198 -0
- package/dist/view/terrain/drape/bin-store.d.ts +179 -0
- package/dist/view/terrain/drape/bin-store.js +529 -0
- package/dist/view/terrain/drape/binning.d.ts +259 -0
- package/dist/view/terrain/drape/binning.js +604 -0
- package/dist/view/terrain/drape/edge-constrain.d.ts +37 -0
- package/dist/view/terrain/drape/edge-constrain.js +175 -0
- package/dist/view/terrain/drape/geometry.d.ts +95 -0
- package/dist/view/terrain/drape/geometry.js +260 -0
- package/dist/view/terrain/drape/mesh.d.ts +50 -0
- package/dist/view/terrain/drape/mesh.js +86 -0
- package/dist/view/terrain/drape/pass.d.ts +122 -0
- package/dist/view/terrain/drape/pass.js +379 -0
- package/dist/view/terrain/drape/quad-glyphs.d.ts +64 -0
- package/dist/view/terrain/drape/quad-glyphs.js +117 -0
- package/dist/view/terrain/drape/quad.d.ts +249 -0
- package/dist/view/terrain/drape/quad.js +835 -0
- package/dist/view/terrain/drape/renderer.d.ts +184 -0
- package/dist/view/terrain/drape/renderer.js +706 -0
- package/dist/view/terrain/drape/shared.d.ts +80 -0
- package/dist/view/terrain/drape/shared.js +173 -0
- package/dist/view/terrain/drape/stitch.d.ts +155 -0
- package/dist/view/terrain/drape/stitch.js +228 -0
- package/dist/view/terrain/ground.d.ts +72 -0
- package/dist/view/terrain/ground.js +151 -0
- package/dist/view/terrain/metrics.d.ts +180 -0
- package/dist/view/terrain/metrics.js +231 -0
- package/dist/view/terrain/occlusion.d.ts +11 -0
- package/dist/view/terrain/occlusion.js +129 -0
- package/dist/view/terrain/polygon.d.ts +86 -0
- package/dist/view/terrain/polygon.js +301 -0
- package/dist/view/terrain/shade.d.ts +48 -0
- package/dist/view/terrain/shade.js +45 -0
- package/dist/view/terrain/state.d.ts +99 -0
- package/dist/view/terrain/state.js +186 -0
- package/dist/view/terrain/tessellation.d.ts +265 -0
- package/dist/view/terrain/tessellation.js +924 -0
- package/dist/view/terrain/tiling.d.ts +56 -0
- package/dist/view/terrain/tiling.js +155 -0
- package/dist/view/terrain/upstream-terrain.d.ts +82 -0
- package/dist/view/terrain/upstream-terrain.js +116 -0
- package/dist/view/ui/auxiliary-handles.d.ts +151 -0
- package/dist/view/ui/auxiliary-handles.js +22 -0
- package/dist/view/ui/bounds.d.ts +53 -0
- package/dist/view/ui/bounds.js +149 -0
- package/dist/view/ui/box-selection.d.ts +1 -0
- package/dist/view/ui/box-selection.js +83 -0
- package/dist/view/ui/handle-test.d.ts +1 -0
- package/dist/view/ui/handle-test.js +437 -0
- package/dist/view/ui/handle-thinning.d.ts +122 -0
- package/dist/view/ui/handle-thinning.js +430 -0
- package/dist/view/ui/handles.d.ts +25 -0
- package/dist/view/ui/handles.js +673 -0
- package/dist/view/ui/helper.d.ts +19 -0
- package/dist/view/ui/helper.js +76 -0
- package/dist/view/ui/index.d.ts +15 -0
- package/dist/view/ui/index.js +15 -0
- package/dist/view/ui/selection-scope.d.ts +25 -0
- package/dist/view/ui/selection-scope.js +34 -0
- package/dist/view/ui/selection-ui/bounding-box.d.ts +44 -0
- package/dist/view/ui/selection-ui/bounding-box.js +240 -0
- package/dist/view/ui/selection-ui/extension-registry.d.ts +76 -0
- package/dist/view/ui/selection-ui/extension-registry.js +78 -0
- package/dist/view/ui/selection-ui/index.d.ts +12 -0
- package/dist/view/ui/selection-ui/index.js +12 -0
- package/dist/view/ui/selection-ui/renderer.d.ts +29 -0
- package/dist/view/ui/selection-ui/renderer.js +227 -0
- package/dist/view/ui/selection-ui/types.d.ts +55 -0
- package/dist/view/ui/selection-ui/types.js +3 -0
- package/dist/view/ui/selection-ui-drawer.d.ts +52 -0
- package/dist/view/ui/selection-ui-drawer.js +329 -0
- package/dist/view/ui/tentative.d.ts +1 -0
- package/dist/view/ui/tentative.js +320 -0
- package/dist/view/viewport.d.ts +119 -0
- package/dist/view/viewport.js +254 -0
- package/package.json +113 -0
|
@@ -0,0 +1,835 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
import { setDepthTestEnabled } from '../../layer/depth-state.js';
|
|
4
|
+
import { createProgram } from '../../shaders/helpers.js';
|
|
5
|
+
import { circumferenceAtLatitude, tileCenterLatitude } from '../metrics.js';
|
|
6
|
+
import { applyEdgeConstrainUniforms, EDGE_CONSTRAIN_GLSL, EDGE_CONSTRAIN_UNIFORMS, } from './edge-constrain.js';
|
|
7
|
+
import { createTerrainMeshBuffers, disposeTerrainMeshBuffers, TILE_EXTENT, } from './mesh.js';
|
|
8
|
+
import { binQuadGlyphs } from './quad-glyphs.js';
|
|
9
|
+
import { DRAPE_LIFT_RATIO } from './renderer.js';
|
|
10
|
+
import { applyDrapeProjectionUniforms, applyDrapeTerrainUniforms, DRAPE_PROJECTION_UNIFORMS, DRAPE_TERRAIN_UNIFORMS, TERRAIN_SAMPLE_GLSL, TERRAIN_SHADE_GLSL, } from './shared.js';
|
|
11
|
+
import { buildTileKeySet, resolveTileEdges, wrappedTileKey } from './stitch.js';
|
|
12
|
+
/** Texture units */
|
|
13
|
+
const UNIT_TERRAIN = 0;
|
|
14
|
+
const UNIT_TEXTURE = 1;
|
|
15
|
+
const UNIT_ATLAS = 2;
|
|
16
|
+
const UNIT_GLYPH = 3;
|
|
17
|
+
const UNIT_BIN = 4;
|
|
18
|
+
/** Width of the glyph data texture (texels). Even, because one glyph takes 2 texels */
|
|
19
|
+
const GLYPH_TEX_WIDTH = 256;
|
|
20
|
+
/** Number of glyph data textures kept (LRU) */
|
|
21
|
+
const GLYPH_CACHE_LIMIT = 64;
|
|
22
|
+
/**
|
|
23
|
+
* The (u, v) that represents "there is no solution"
|
|
24
|
+
*
|
|
25
|
+
* It is merely a value that tips the test to "outside the range". Because fwidth
|
|
26
|
+
* must be taken under uniform control flow, failure is expressed as a value rather
|
|
27
|
+
* than by discard. An extremely large value would make the derivatives of
|
|
28
|
+
* neighboring pixels blow up, so it is kept just large enough to be recognized as
|
|
29
|
+
* outside the range.
|
|
30
|
+
*/
|
|
31
|
+
const OUTSIDE_UV = -8;
|
|
32
|
+
const VERTEX_SOURCE = (prelude, define) => `#version 300 es
|
|
33
|
+
${prelude}
|
|
34
|
+
${define}
|
|
35
|
+
layout(location = 0) in vec2 a_pos;
|
|
36
|
+
// A very slight lift from the ground surface (meters), so that boundary vertices
|
|
37
|
+
// lowered by edge constraining do not lose to the terrain mesh in depth (the same
|
|
38
|
+
// amount as the polygon and line drape)
|
|
39
|
+
uniform float u_drape_lift_m;
|
|
40
|
+
out vec2 v_tile;
|
|
41
|
+
${TERRAIN_SAMPLE_GLSL}
|
|
42
|
+
${EDGE_CONSTRAIN_GLSL}
|
|
43
|
+
void main() {
|
|
44
|
+
// A boundary vertex is constrained to the coarser side's polyline only when the
|
|
45
|
+
// neighbor is coarser (edge-constrain.ts). Without the constraint it sits at a
|
|
46
|
+
// height different from the neighboring tile at an LOD boundary and a crack
|
|
47
|
+
// opens (skirts are not used, so the crack shows on screen as it is)
|
|
48
|
+
float ele = drape_edge_constrained(a_pos, drape_get_elevation(a_pos));
|
|
49
|
+
gl_Position = projectTileWithElevation(a_pos, ele + u_drape_lift_m);
|
|
50
|
+
v_tile = a_pos / ${TILE_EXTENT}.0;
|
|
51
|
+
}`;
|
|
52
|
+
/** Inverse bilinear interpolation and other parts used by both fragment shaders */
|
|
53
|
+
const QUAD_UV_GLSL = `
|
|
54
|
+
float cross2(vec2 a, vec2 b) {
|
|
55
|
+
return a.x * b.y - a.y * b.x;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Inverse bilinear interpolation (a point -> the (u, v) inside the quad)
|
|
60
|
+
*
|
|
61
|
+
* Solves the bilinear map P(u, v) = a + u(b - a) + v(d - a) + uv(a - b + c - d)
|
|
62
|
+
* for (u, v). v is a root of a quadratic equation, and to avoid loss of
|
|
63
|
+
* significance it is solved in the sign-aligned form
|
|
64
|
+
* (q = -(k1 + sign(k1)*sqrt(D))/2, with the roots k0/q and q/k2).
|
|
65
|
+
* Even when it degenerates into a parallelogram (k2 = 0), k0/q is directly the
|
|
66
|
+
* linear solution.
|
|
67
|
+
*
|
|
68
|
+
* Because a quad is a "rotated rectangle normalized by the latitude scale", on the
|
|
69
|
+
* Mercator plane it becomes nearly a parallelogram, so in practice the linear
|
|
70
|
+
* branch is taken.
|
|
71
|
+
*/
|
|
72
|
+
vec2 quadUV(vec2 p) {
|
|
73
|
+
vec2 e = u_quad_b - u_quad_a;
|
|
74
|
+
vec2 f = u_quad_d - u_quad_a;
|
|
75
|
+
vec2 g = u_quad_a - u_quad_b + u_quad_c - u_quad_d;
|
|
76
|
+
vec2 h = p - u_quad_a;
|
|
77
|
+
|
|
78
|
+
float k2 = cross2(g, f);
|
|
79
|
+
float k1 = cross2(h, g) + cross2(e, f);
|
|
80
|
+
float k0 = cross2(h, e);
|
|
81
|
+
|
|
82
|
+
if (abs(k1) < 1e-30 && abs(k2) < 1e-30) return vec2(${OUTSIDE_UV}.0);
|
|
83
|
+
|
|
84
|
+
float disc = k1 * k1 - 4.0 * k0 * k2;
|
|
85
|
+
if (disc < 0.0) return vec2(${OUTSIDE_UV}.0);
|
|
86
|
+
float root = sqrt(disc);
|
|
87
|
+
float q = -0.5 * (k1 + (k1 >= 0.0 ? root : -root));
|
|
88
|
+
|
|
89
|
+
float v1 = (q != 0.0) ? (k0 / q) : ${OUTSIDE_UV}.0;
|
|
90
|
+
float v2 = (k2 != 0.0) ? (q / k2) : ${OUTSIDE_UV}.0;
|
|
91
|
+
float v = (abs(v1 - 0.5) <= abs(v2 - 0.5)) ? v1 : v2;
|
|
92
|
+
|
|
93
|
+
vec2 den = e + g * v;
|
|
94
|
+
vec2 num = h - f * v;
|
|
95
|
+
if (abs(den.x) < 1e-30 && abs(den.y) < 1e-30) return vec2(${OUTSIDE_UV}.0);
|
|
96
|
+
float u = (abs(den.x) >= abs(den.y)) ? (num.x / den.x) : (num.y / den.y);
|
|
97
|
+
return vec2(u, v);
|
|
98
|
+
}
|
|
99
|
+
`;
|
|
100
|
+
/** Uniform declarations for the quad's four corners and for the shading */
|
|
101
|
+
const QUAD_COMMON_UNIFORMS_GLSL = `
|
|
102
|
+
// The four corners of the quad (in this tile's 0..1 coordinates. They may lie
|
|
103
|
+
// outside the tile)
|
|
104
|
+
uniform vec2 u_quad_a; // top left
|
|
105
|
+
uniform vec2 u_quad_b; // top right
|
|
106
|
+
uniform vec2 u_quad_c; // bottom right
|
|
107
|
+
uniform vec2 u_quad_d; // bottom left
|
|
108
|
+
uniform float u_opacity;
|
|
109
|
+
// Shading (an aid to reading the terrain). The same light source and the same
|
|
110
|
+
// formula as the polygon fill.
|
|
111
|
+
uniform vec3 u_light_dir;
|
|
112
|
+
uniform float u_shade_strength;
|
|
113
|
+
uniform float u_tile_meters;
|
|
114
|
+
`;
|
|
115
|
+
/** The fragment shader that pastes an image */
|
|
116
|
+
const IMAGE_FRAGMENT_SOURCE = `#version 300 es
|
|
117
|
+
precision highp float;
|
|
118
|
+
precision highp sampler2D;
|
|
119
|
+
|
|
120
|
+
in vec2 v_tile;
|
|
121
|
+
|
|
122
|
+
${QUAD_COMMON_UNIFORMS_GLSL}
|
|
123
|
+
uniform sampler2D u_texture;
|
|
124
|
+
|
|
125
|
+
out vec4 fragColor;
|
|
126
|
+
|
|
127
|
+
` +
|
|
128
|
+
TERRAIN_SAMPLE_GLSL +
|
|
129
|
+
TERRAIN_SHADE_GLSL +
|
|
130
|
+
QUAD_UV_GLSL +
|
|
131
|
+
`
|
|
132
|
+
void main() {
|
|
133
|
+
// Take the derivatives before entering a branch (under uniform control flow)
|
|
134
|
+
vec2 uv = quadUV(v_tile);
|
|
135
|
+
vec2 w = max(fwidth(uv), vec2(1e-8));
|
|
136
|
+
|
|
137
|
+
// The edge is smoothed with one pixel of coverage (the billboard's edge does
|
|
138
|
+
// not turn jagged)
|
|
139
|
+
vec2 cover = clamp((0.5 - abs(uv - 0.5)) / w + 0.5, 0.0, 1.0);
|
|
140
|
+
float coverage = cover.x * cover.y;
|
|
141
|
+
if (coverage <= 0.0) discard;
|
|
142
|
+
|
|
143
|
+
vec4 color = texture(u_texture, clamp(uv, 0.0, 1.0));
|
|
144
|
+
float alpha = color.a * u_opacity * coverage;
|
|
145
|
+
if (alpha <= 0.0) discard;
|
|
146
|
+
|
|
147
|
+
fragColor = vec4(color.rgb * terrainShade(v_tile), alpha);
|
|
148
|
+
}`;
|
|
149
|
+
/**
|
|
150
|
+
* The fragment shader that paints fill + text
|
|
151
|
+
*
|
|
152
|
+
* The fill is a rectangular fill, and the text references the SDF atlas at the
|
|
153
|
+
* same pixel. Compositing is accumulated premultiplied and converted back to
|
|
154
|
+
* straight at the end (because the frame's blend state is `applyDrawBlendState`
|
|
155
|
+
* = RGB straight, A additive).
|
|
156
|
+
*
|
|
157
|
+
* Shading is applied only to the fill. The text gives priority to legibility and
|
|
158
|
+
* is unshaded, just like labels, lines and points.
|
|
159
|
+
*/
|
|
160
|
+
const SURFACE_FRAGMENT_SOURCE = `#version 300 es
|
|
161
|
+
precision highp float;
|
|
162
|
+
precision highp int;
|
|
163
|
+
precision highp sampler2D;
|
|
164
|
+
|
|
165
|
+
in vec2 v_tile;
|
|
166
|
+
|
|
167
|
+
${QUAD_COMMON_UNIFORMS_GLSL}
|
|
168
|
+
|
|
169
|
+
// Fill
|
|
170
|
+
uniform vec4 u_fill_color;
|
|
171
|
+
uniform vec4 u_border_color;
|
|
172
|
+
uniform vec2 u_border;
|
|
173
|
+
|
|
174
|
+
// Text (u_grid = 0 means there is no text)
|
|
175
|
+
uniform sampler2D u_atlas;
|
|
176
|
+
uniform sampler2D u_glyph_tex;
|
|
177
|
+
uniform sampler2D u_bin_tex;
|
|
178
|
+
uniform int u_glyph_tex_width;
|
|
179
|
+
uniform int u_grid;
|
|
180
|
+
uniform vec2 u_atlas_size;
|
|
181
|
+
uniform vec2 u_atlas_texels;
|
|
182
|
+
uniform vec4 u_text_color;
|
|
183
|
+
uniform vec4 u_halo_color;
|
|
184
|
+
uniform float u_halo_width;
|
|
185
|
+
uniform float u_sdf_edge;
|
|
186
|
+
uniform float u_sdf_value_per_texel;
|
|
187
|
+
uniform float u_lod_scale;
|
|
188
|
+
|
|
189
|
+
out vec4 fragColor;
|
|
190
|
+
|
|
191
|
+
` +
|
|
192
|
+
TERRAIN_SAMPLE_GLSL +
|
|
193
|
+
TERRAIN_SHADE_GLSL +
|
|
194
|
+
QUAD_UV_GLSL +
|
|
195
|
+
`
|
|
196
|
+
vec4 fetchGlyph(int i) {
|
|
197
|
+
return texelFetch(u_glyph_tex, ivec2(i % u_glyph_tex_width, i / u_glyph_tex_width), 0);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Compose on top (premultiplied alpha)
|
|
201
|
+
vec4 over(vec4 below, vec3 rgb, float a) {
|
|
202
|
+
return vec4(rgb * a + below.rgb * (1.0 - a), a + below.a * (1.0 - a));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
void main() {
|
|
206
|
+
// Take the derivatives before entering a branch (under uniform control flow)
|
|
207
|
+
vec2 uv = quadUV(v_tile);
|
|
208
|
+
vec2 dux = dFdx(uv);
|
|
209
|
+
vec2 duy = dFdy(uv);
|
|
210
|
+
vec2 w = max(abs(dux) + abs(duy), vec2(1e-8));
|
|
211
|
+
|
|
212
|
+
vec2 cover = clamp((0.5 - abs(uv - 0.5)) / w + 0.5, 0.0, 1.0);
|
|
213
|
+
float coverage = cover.x * cover.y;
|
|
214
|
+
if (coverage <= 0.0) discard;
|
|
215
|
+
|
|
216
|
+
// --- Fill (background + border) ---
|
|
217
|
+
bool onBorder = uv.x < u_border.x || uv.x > 1.0 - u_border.x
|
|
218
|
+
|| uv.y < u_border.y || uv.y > 1.0 - u_border.y;
|
|
219
|
+
vec4 fill = onBorder ? u_border_color : u_fill_color;
|
|
220
|
+
float shade = terrainShade(v_tile);
|
|
221
|
+
vec4 acc = vec4(fill.rgb * shade * fill.a, fill.a);
|
|
222
|
+
|
|
223
|
+
// --- Text (references the SDF atlas) ---
|
|
224
|
+
if (u_grid > 0) {
|
|
225
|
+
// The gradient in atlas space. It is constant regardless of the glyph, so
|
|
226
|
+
// it is taken only once outside the branch. Derivatives cannot be used
|
|
227
|
+
// inside a branch, so texture lookups pass this gradient explicitly with
|
|
228
|
+
// textureGrad (the mip bias is expressed by shrinking the gradient).
|
|
229
|
+
vec2 tx = dux * u_atlas_texels;
|
|
230
|
+
vec2 ty = duy * u_atlas_texels;
|
|
231
|
+
vec2 gx = tx / u_atlas_size * u_lod_scale;
|
|
232
|
+
vec2 gy = ty / u_atlas_size * u_lod_scale;
|
|
233
|
+
float texelsPerPixel = sqrt(dot(tx, tx) + dot(ty, ty));
|
|
234
|
+
float gamma = max(0.5 * texelsPerPixel * u_sdf_value_per_texel, 0.001);
|
|
235
|
+
|
|
236
|
+
float gridF = float(u_grid);
|
|
237
|
+
ivec2 cell = ivec2(clamp(floor(uv * gridF), 0.0, gridF - 1.0));
|
|
238
|
+
vec4 bin = texelFetch(u_bin_tex, cell, 0);
|
|
239
|
+
int start = int(bin.x);
|
|
240
|
+
int count = int(bin.y);
|
|
241
|
+
|
|
242
|
+
// For overlapping glyphs the maximum of the distance field is taken (this
|
|
243
|
+
// combines them in the same way as drawing all halos and then all
|
|
244
|
+
// letterforms in two passes)
|
|
245
|
+
float dist = 0.0;
|
|
246
|
+
for (int i = 0; i < count; i++) {
|
|
247
|
+
int slot = (start + i) * 2;
|
|
248
|
+
vec4 rect = fetchGlyph(slot);
|
|
249
|
+
if (uv.x < rect.x || uv.x > rect.z || uv.y < rect.y || uv.y > rect.w) continue;
|
|
250
|
+
vec4 auv = fetchGlyph(slot + 1);
|
|
251
|
+
vec2 t = (uv - rect.xy) / max(rect.zw - rect.xy, vec2(1e-9));
|
|
252
|
+
dist = max(dist, textureGrad(u_atlas, mix(auv.xy, auv.zw, t), gx, gy).r);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (dist > 0.0) {
|
|
256
|
+
if (u_halo_width > 0.0) {
|
|
257
|
+
float haloEdge = u_sdf_edge - u_halo_width;
|
|
258
|
+
float haloAlpha = smoothstep(haloEdge - gamma, haloEdge + gamma, dist);
|
|
259
|
+
acc = over(acc, u_halo_color.rgb, u_halo_color.a * haloAlpha);
|
|
260
|
+
}
|
|
261
|
+
float textAlpha = smoothstep(u_sdf_edge - gamma, u_sdf_edge + gamma, dist);
|
|
262
|
+
acc = over(acc, u_text_color.rgb, u_text_color.a * textAlpha);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
float alpha = acc.a * u_opacity * coverage;
|
|
267
|
+
if (alpha <= 0.0) discard;
|
|
268
|
+
fragColor = vec4(acc.rgb / max(acc.a, 1e-4), alpha);
|
|
269
|
+
}`;
|
|
270
|
+
/** Longitude -> Mercator x */
|
|
271
|
+
function mercatorX(lng) {
|
|
272
|
+
return (lng + 180) / 360;
|
|
273
|
+
}
|
|
274
|
+
/** Latitude -> Mercator y */
|
|
275
|
+
function mercatorY(lat) {
|
|
276
|
+
const latRad = (lat * Math.PI) / 180;
|
|
277
|
+
return (1 - Math.log(Math.tan(latRad) + 1 / Math.cos(latRad)) / Math.PI) / 2;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Converts the four corners into Mercator coordinates (in the order top left,
|
|
281
|
+
* top right, bottom right, bottom left)
|
|
282
|
+
*
|
|
283
|
+
* This order corresponds to (u, v) = (0,0), (1,0), (1,1), (0,1) of the inverse
|
|
284
|
+
* bilinear interpolation.
|
|
285
|
+
*/
|
|
286
|
+
export function quadMercatorCorners(corners) {
|
|
287
|
+
const out = new Float64Array(8);
|
|
288
|
+
const order = [corners.topLeft, corners.topRight, corners.bottomRight, corners.bottomLeft];
|
|
289
|
+
for (let i = 0; i < 4; i++) {
|
|
290
|
+
out[i * 2] = mercatorX(order[i][0]);
|
|
291
|
+
out[i * 2 + 1] = mercatorY(order[i][1]);
|
|
292
|
+
}
|
|
293
|
+
return out;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* A y range within a tile -> a range of terrain mesh rows
|
|
297
|
+
*
|
|
298
|
+
* The mesh indices are in row-major order, with the 6 * meshSize indices of row k
|
|
299
|
+
* laid out contiguously (the generation rule of `mesh.ts`). Simply dropping the
|
|
300
|
+
* rows the quad does not cover narrows the range while keeping a single
|
|
301
|
+
* drawElements call.
|
|
302
|
+
*/
|
|
303
|
+
export function meshRowRange(y0, y1, meshSize) {
|
|
304
|
+
if (!(y1 >= y0))
|
|
305
|
+
return null;
|
|
306
|
+
if (y1 < 0 || y0 > 1)
|
|
307
|
+
return null;
|
|
308
|
+
const start = Math.max(0, Math.floor(y0 * meshSize));
|
|
309
|
+
const end = Math.min(meshSize - 1, Math.ceil(y1 * meshSize) - 1);
|
|
310
|
+
if (end < start)
|
|
311
|
+
return null;
|
|
312
|
+
return { start, count: end - start + 1 };
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Inverse bilinear interpolation on the CPU side (a mirror of the shader. For
|
|
316
|
+
* tests and diagnostics)
|
|
317
|
+
*
|
|
318
|
+
* @param quad The four corners (x, y in the order top left, top right, bottom
|
|
319
|
+
* right, bottom left)
|
|
320
|
+
* @returns The (u, v) inside the quad. null if there is no solution
|
|
321
|
+
*/
|
|
322
|
+
export function solveQuadUV(px, py, quad) {
|
|
323
|
+
const ax = quad[0];
|
|
324
|
+
const ay = quad[1];
|
|
325
|
+
const ex = quad[2] - ax;
|
|
326
|
+
const ey = quad[3] - ay;
|
|
327
|
+
const fx = quad[6] - ax;
|
|
328
|
+
const fy = quad[7] - ay;
|
|
329
|
+
const gx = ax - quad[2] + quad[4] - quad[6];
|
|
330
|
+
const gy = ay - quad[3] + quad[5] - quad[7];
|
|
331
|
+
const hx = px - ax;
|
|
332
|
+
const hy = py - ay;
|
|
333
|
+
const cross = (x0, y0, x1, y1) => x0 * y1 - y0 * x1;
|
|
334
|
+
const k2 = cross(gx, gy, fx, fy);
|
|
335
|
+
const k1 = cross(hx, hy, gx, gy) + cross(ex, ey, fx, fy);
|
|
336
|
+
const k0 = cross(hx, hy, ex, ey);
|
|
337
|
+
if (Math.abs(k1) < 1e-30 && Math.abs(k2) < 1e-30)
|
|
338
|
+
return null;
|
|
339
|
+
const disc = k1 * k1 - 4 * k0 * k2;
|
|
340
|
+
if (disc < 0)
|
|
341
|
+
return null;
|
|
342
|
+
const root = Math.sqrt(disc);
|
|
343
|
+
const q = -0.5 * (k1 + (k1 >= 0 ? root : -root));
|
|
344
|
+
const v1 = q !== 0 ? k0 / q : OUTSIDE_UV;
|
|
345
|
+
const v2 = k2 !== 0 ? q / k2 : OUTSIDE_UV;
|
|
346
|
+
const v = Math.abs(v1 - 0.5) <= Math.abs(v2 - 0.5) ? v1 : v2;
|
|
347
|
+
const denX = ex + gx * v;
|
|
348
|
+
const denY = ey + gy * v;
|
|
349
|
+
if (Math.abs(denX) < 1e-30 && Math.abs(denY) < 1e-30)
|
|
350
|
+
return null;
|
|
351
|
+
const u = Math.abs(denX) >= Math.abs(denY) ? (hx - fx * v) / denX : (hy - fy * v) / denY;
|
|
352
|
+
return [u, v];
|
|
353
|
+
}
|
|
354
|
+
/** The uniforms specific to pasting an image */
|
|
355
|
+
const IMAGE_UNIFORMS = ['u_texture'];
|
|
356
|
+
/** The uniforms specific to fill + text */
|
|
357
|
+
const SURFACE_UNIFORMS = [
|
|
358
|
+
'u_fill_color',
|
|
359
|
+
'u_border_color',
|
|
360
|
+
'u_border',
|
|
361
|
+
'u_atlas',
|
|
362
|
+
'u_glyph_tex',
|
|
363
|
+
'u_bin_tex',
|
|
364
|
+
'u_glyph_tex_width',
|
|
365
|
+
'u_grid',
|
|
366
|
+
'u_atlas_size',
|
|
367
|
+
'u_atlas_texels',
|
|
368
|
+
'u_text_color',
|
|
369
|
+
'u_halo_color',
|
|
370
|
+
'u_halo_width',
|
|
371
|
+
'u_sdf_edge',
|
|
372
|
+
'u_sdf_value_per_texel',
|
|
373
|
+
'u_lod_scale',
|
|
374
|
+
];
|
|
375
|
+
/** The uniforms that both fragment shaders have */
|
|
376
|
+
const QUAD_COMMON_UNIFORMS = [
|
|
377
|
+
...DRAPE_PROJECTION_UNIFORMS,
|
|
378
|
+
...DRAPE_TERRAIN_UNIFORMS,
|
|
379
|
+
'u_quad_a',
|
|
380
|
+
'u_quad_b',
|
|
381
|
+
'u_quad_c',
|
|
382
|
+
'u_quad_d',
|
|
383
|
+
'u_opacity',
|
|
384
|
+
'u_light_dir',
|
|
385
|
+
'u_shade_strength',
|
|
386
|
+
'u_tile_meters',
|
|
387
|
+
'u_drape_lift_m',
|
|
388
|
+
...EDGE_CONSTRAIN_UNIFORMS,
|
|
389
|
+
];
|
|
390
|
+
/**
|
|
391
|
+
* The renderer that pastes textured quads onto the ground surface
|
|
392
|
+
*/
|
|
393
|
+
export class QuadDrapeRenderer {
|
|
394
|
+
constructor(gl) {
|
|
395
|
+
Object.defineProperty(this, "gl", {
|
|
396
|
+
enumerable: true,
|
|
397
|
+
configurable: true,
|
|
398
|
+
writable: true,
|
|
399
|
+
value: void 0
|
|
400
|
+
});
|
|
401
|
+
Object.defineProperty(this, "imageSlot", {
|
|
402
|
+
enumerable: true,
|
|
403
|
+
configurable: true,
|
|
404
|
+
writable: true,
|
|
405
|
+
value: null
|
|
406
|
+
});
|
|
407
|
+
Object.defineProperty(this, "surfaceSlot", {
|
|
408
|
+
enumerable: true,
|
|
409
|
+
configurable: true,
|
|
410
|
+
writable: true,
|
|
411
|
+
value: null
|
|
412
|
+
});
|
|
413
|
+
Object.defineProperty(this, "mesh", {
|
|
414
|
+
enumerable: true,
|
|
415
|
+
configurable: true,
|
|
416
|
+
writable: true,
|
|
417
|
+
value: null
|
|
418
|
+
});
|
|
419
|
+
Object.defineProperty(this, "glyphCache", {
|
|
420
|
+
enumerable: true,
|
|
421
|
+
configurable: true,
|
|
422
|
+
writable: true,
|
|
423
|
+
value: new Map()
|
|
424
|
+
});
|
|
425
|
+
/** A 1x1 texture bound to the samplers in frames that have no text */
|
|
426
|
+
Object.defineProperty(this, "placeholderTex", {
|
|
427
|
+
enumerable: true,
|
|
428
|
+
configurable: true,
|
|
429
|
+
writable: true,
|
|
430
|
+
value: null
|
|
431
|
+
});
|
|
432
|
+
Object.defineProperty(this, "useCounter", {
|
|
433
|
+
enumerable: true,
|
|
434
|
+
configurable: true,
|
|
435
|
+
writable: true,
|
|
436
|
+
value: 0
|
|
437
|
+
});
|
|
438
|
+
/** The most recent failure reason (for diagnostics) */
|
|
439
|
+
Object.defineProperty(this, "lastError", {
|
|
440
|
+
enumerable: true,
|
|
441
|
+
configurable: true,
|
|
442
|
+
writable: true,
|
|
443
|
+
value: ''
|
|
444
|
+
});
|
|
445
|
+
this.gl = gl;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Allocates the terrain mesh
|
|
449
|
+
*/
|
|
450
|
+
ensureMesh(meshSize) {
|
|
451
|
+
const gl = this.gl;
|
|
452
|
+
if (this.mesh && this.mesh.meshSize === meshSize)
|
|
453
|
+
return true;
|
|
454
|
+
if (this.mesh)
|
|
455
|
+
disposeTerrainMeshBuffers(gl, this.mesh);
|
|
456
|
+
this.mesh = createTerrainMeshBuffers(gl, meshSize);
|
|
457
|
+
if (!this.mesh) {
|
|
458
|
+
this.lastError = 'mesh-alloc-failed';
|
|
459
|
+
return false;
|
|
460
|
+
}
|
|
461
|
+
return true;
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Allocates a shader (one per fragment shader body)
|
|
465
|
+
*/
|
|
466
|
+
ensureProgram(slot, fragmentSource, extraUniforms, shaderData) {
|
|
467
|
+
const gl = this.gl;
|
|
468
|
+
if (slot && slot.variantName === shaderData.variantName)
|
|
469
|
+
return slot;
|
|
470
|
+
if (slot)
|
|
471
|
+
gl.deleteProgram(slot.program);
|
|
472
|
+
let program;
|
|
473
|
+
try {
|
|
474
|
+
program = createProgram(gl, VERTEX_SOURCE(shaderData.vertexShaderPrelude, shaderData.define), fragmentSource);
|
|
475
|
+
}
|
|
476
|
+
catch (error) {
|
|
477
|
+
this.lastError = `shader: ${String(error)}`;
|
|
478
|
+
return null;
|
|
479
|
+
}
|
|
480
|
+
const locations = {};
|
|
481
|
+
for (const name of [...QUAD_COMMON_UNIFORMS, ...extraUniforms]) {
|
|
482
|
+
locations[name] = gl.getUniformLocation(program, name);
|
|
483
|
+
}
|
|
484
|
+
return { program, variantName: shaderData.variantName, locations };
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Allocates the shader and the mesh (the image path. Kept for existing callers)
|
|
488
|
+
*/
|
|
489
|
+
ensure(shaderData, meshSize) {
|
|
490
|
+
if (!this.ensureMesh(meshSize))
|
|
491
|
+
return false;
|
|
492
|
+
this.imageSlot = this.ensureProgram(this.imageSlot, IMAGE_FRAGMENT_SOURCE, IMAGE_UNIFORMS, shaderData);
|
|
493
|
+
return this.imageSlot !== null;
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Allocates the shader and the mesh of the fill and text path
|
|
497
|
+
*/
|
|
498
|
+
ensureSurface(shaderData, meshSize) {
|
|
499
|
+
if (!this.ensureMesh(meshSize))
|
|
500
|
+
return false;
|
|
501
|
+
this.surfaceSlot = this.ensureProgram(this.surfaceSlot, SURFACE_FRAGMENT_SOURCE, SURFACE_UNIFORMS, shaderData);
|
|
502
|
+
return this.surfaceSlot !== null;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Pastes an image onto a single quad
|
|
506
|
+
*
|
|
507
|
+
* @returns true if it could be pasted (the caller then does not perform the
|
|
508
|
+
* conventional flat drawing). false is returned only when the resources
|
|
509
|
+
* cannot be prepared, in which case the caller falls back to the degraded
|
|
510
|
+
* path.
|
|
511
|
+
*/
|
|
512
|
+
drawQuad(corners, texture, opacity, frame) {
|
|
513
|
+
if (!this.ensure(frame.shaderData, frame.meshSize))
|
|
514
|
+
return false;
|
|
515
|
+
const slot = this.imageSlot;
|
|
516
|
+
if (!slot)
|
|
517
|
+
return false;
|
|
518
|
+
return this.drawTiles(corners, opacity, frame, slot, (set) => {
|
|
519
|
+
const gl = this.gl;
|
|
520
|
+
gl.activeTexture(gl.TEXTURE0 + UNIT_TEXTURE);
|
|
521
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
522
|
+
if (set.u_texture)
|
|
523
|
+
gl.uniform1i(set.u_texture, UNIT_TEXTURE);
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Paints fill and text onto a single quad
|
|
528
|
+
*
|
|
529
|
+
* The fill is a rectangular fill, and the text looks up the SDF atlas within
|
|
530
|
+
* the same per-pixel evaluation.
|
|
531
|
+
*
|
|
532
|
+
* @returns true if it could be painted. false is returned only when the
|
|
533
|
+
* resources cannot be prepared.
|
|
534
|
+
*/
|
|
535
|
+
drawSurface(corners, surface, opacity, frame) {
|
|
536
|
+
const gl = this.gl;
|
|
537
|
+
if (!this.ensureSurface(frame.shaderData, frame.meshSize))
|
|
538
|
+
return false;
|
|
539
|
+
const slot = this.surfaceSlot;
|
|
540
|
+
if (!slot)
|
|
541
|
+
return false;
|
|
542
|
+
const text = surface.text && surface.text.glyphCount > 0 ? surface.text : null;
|
|
543
|
+
const glyphs = text ? this.ensureGlyphBuffers(text) : null;
|
|
544
|
+
return this.drawTiles(corners, opacity, frame, slot, (set) => {
|
|
545
|
+
const fill = surface.fill;
|
|
546
|
+
setColorUniform(gl, set.u_fill_color, fill.color);
|
|
547
|
+
setColorUniform(gl, set.u_border_color, fill.borderColor);
|
|
548
|
+
if (set.u_border)
|
|
549
|
+
gl.uniform2f(set.u_border, fill.border[0], fill.border[1]);
|
|
550
|
+
if (!text || !glyphs) {
|
|
551
|
+
if (set.u_grid)
|
|
552
|
+
gl.uniform1i(set.u_grid, 0);
|
|
553
|
+
// A sampler that is not bound leads to undefined behavior, so something is
|
|
554
|
+
// bound even when there is no text (there is no fill texture, so the bin
|
|
555
|
+
// stands in for it)
|
|
556
|
+
this.bindPlaceholderSamplers(set);
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
gl.activeTexture(gl.TEXTURE0 + UNIT_ATLAS);
|
|
560
|
+
gl.bindTexture(gl.TEXTURE_2D, text.atlas);
|
|
561
|
+
if (set.u_atlas)
|
|
562
|
+
gl.uniform1i(set.u_atlas, UNIT_ATLAS);
|
|
563
|
+
gl.activeTexture(gl.TEXTURE0 + UNIT_GLYPH);
|
|
564
|
+
gl.bindTexture(gl.TEXTURE_2D, glyphs.glyphTex);
|
|
565
|
+
if (set.u_glyph_tex)
|
|
566
|
+
gl.uniform1i(set.u_glyph_tex, UNIT_GLYPH);
|
|
567
|
+
gl.activeTexture(gl.TEXTURE0 + UNIT_BIN);
|
|
568
|
+
gl.bindTexture(gl.TEXTURE_2D, glyphs.binTex);
|
|
569
|
+
if (set.u_bin_tex)
|
|
570
|
+
gl.uniform1i(set.u_bin_tex, UNIT_BIN);
|
|
571
|
+
if (set.u_glyph_tex_width)
|
|
572
|
+
gl.uniform1i(set.u_glyph_tex_width, GLYPH_TEX_WIDTH);
|
|
573
|
+
if (set.u_grid)
|
|
574
|
+
gl.uniform1i(set.u_grid, glyphs.grid);
|
|
575
|
+
if (set.u_atlas_size)
|
|
576
|
+
gl.uniform2f(set.u_atlas_size, text.atlasWidth, text.atlasHeight);
|
|
577
|
+
if (set.u_atlas_texels) {
|
|
578
|
+
gl.uniform2f(set.u_atlas_texels, text.atlasTexelsPerUnit[0], text.atlasTexelsPerUnit[1]);
|
|
579
|
+
}
|
|
580
|
+
setColorUniform(gl, set.u_text_color, text.color);
|
|
581
|
+
setColorUniform(gl, set.u_halo_color, text.haloColor);
|
|
582
|
+
if (set.u_halo_width)
|
|
583
|
+
gl.uniform1f(set.u_halo_width, text.haloWidth);
|
|
584
|
+
if (set.u_sdf_edge)
|
|
585
|
+
gl.uniform1f(set.u_sdf_edge, text.edge);
|
|
586
|
+
if (set.u_sdf_value_per_texel)
|
|
587
|
+
gl.uniform1f(set.u_sdf_value_per_texel, text.valuePerTexel);
|
|
588
|
+
if (set.u_lod_scale)
|
|
589
|
+
gl.uniform1f(set.u_lod_scale, 2 ** text.lodBias);
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Binds a 1x1 texture to the samplers when there is no text
|
|
594
|
+
*
|
|
595
|
+
* If drawing happens with a sampler left unbound and a texture of a different
|
|
596
|
+
* type remains on that unit, it is regarded as incomplete and the whole draw
|
|
597
|
+
* call is dropped. Even for pixels that do not read text, having something
|
|
598
|
+
* bound is safer.
|
|
599
|
+
*/
|
|
600
|
+
bindPlaceholderSamplers(set) {
|
|
601
|
+
const gl = this.gl;
|
|
602
|
+
if (!this.placeholderTex) {
|
|
603
|
+
this.placeholderTex = createDataTexture(gl, 1, 1);
|
|
604
|
+
if (this.placeholderTex) {
|
|
605
|
+
gl.bindTexture(gl.TEXTURE_2D, this.placeholderTex);
|
|
606
|
+
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, gl.RGBA, gl.FLOAT, new Float32Array(4));
|
|
607
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
for (const [name, unit] of [
|
|
611
|
+
['u_atlas', UNIT_ATLAS],
|
|
612
|
+
['u_glyph_tex', UNIT_GLYPH],
|
|
613
|
+
['u_bin_tex', UNIT_BIN],
|
|
614
|
+
]) {
|
|
615
|
+
gl.activeTexture(gl.TEXTURE0 + unit);
|
|
616
|
+
gl.bindTexture(gl.TEXTURE_2D, this.placeholderTex);
|
|
617
|
+
if (set[name])
|
|
618
|
+
gl.uniform1i(set[name], unit);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Draws the tiles the quad covers (the skeleton shared by image and fill)
|
|
623
|
+
*/
|
|
624
|
+
drawTiles(corners, opacity, frame, slot, bindContent) {
|
|
625
|
+
const gl = this.gl;
|
|
626
|
+
if (frame.tiles.length === 0)
|
|
627
|
+
return false;
|
|
628
|
+
const mesh = this.mesh;
|
|
629
|
+
if (!mesh)
|
|
630
|
+
return false;
|
|
631
|
+
const quad = quadMercatorCorners(corners);
|
|
632
|
+
let minX = quad[0];
|
|
633
|
+
let maxX = quad[0];
|
|
634
|
+
let minY = quad[1];
|
|
635
|
+
let maxY = quad[1];
|
|
636
|
+
for (let i = 2; i < 8; i += 2) {
|
|
637
|
+
minX = Math.min(minX, quad[i]);
|
|
638
|
+
maxX = Math.max(maxX, quad[i]);
|
|
639
|
+
minY = Math.min(minY, quad[i + 1]);
|
|
640
|
+
maxY = Math.max(maxY, quad[i + 1]);
|
|
641
|
+
}
|
|
642
|
+
// A quad with zero area is not drawn (the inverse bilinear cannot be solved)
|
|
643
|
+
if (!(maxX > minX) || !(maxY > minY))
|
|
644
|
+
return true;
|
|
645
|
+
gl.useProgram(slot.program);
|
|
646
|
+
const set = slot.locations;
|
|
647
|
+
bindContent(set);
|
|
648
|
+
if (set.u_opacity)
|
|
649
|
+
gl.uniform1f(set.u_opacity, opacity);
|
|
650
|
+
if (set.u_light_dir) {
|
|
651
|
+
const d = frame.light.direction;
|
|
652
|
+
gl.uniform3f(set.u_light_dir, d[0], d[1], d[2]);
|
|
653
|
+
}
|
|
654
|
+
if (set.u_shade_strength)
|
|
655
|
+
gl.uniform1f(set.u_shade_strength, frame.light.strength);
|
|
656
|
+
// The depth of the terrain mesh hides what lies behind a ridge (depth works
|
|
657
|
+
// because this is the ground surface, not a billboard). polygonOffset is
|
|
658
|
+
// applied to the whole frame by CustomLayer.
|
|
659
|
+
setDepthTestEnabled(gl, true);
|
|
660
|
+
// The "neighbor" for edge constraining is looked up from the set of terrain
|
|
661
|
+
// tiles drawn in this frame. A tile the quad does not cover is still valid as
|
|
662
|
+
// a neighbor (maplibre draws that tile, so the boundary polyline really does
|
|
663
|
+
// exist there)
|
|
664
|
+
const drawnKeys = buildTileKeySet(frame.tiles);
|
|
665
|
+
const tileByKey = new Map();
|
|
666
|
+
for (const t of frame.tiles)
|
|
667
|
+
tileByKey.set(wrappedTileKey(t), t);
|
|
668
|
+
const indicesPerRow = mesh.meshSize * 6;
|
|
669
|
+
for (const tile of frame.tiles) {
|
|
670
|
+
const scale = 2 ** tile.z;
|
|
671
|
+
const tileX0 = tile.x / scale;
|
|
672
|
+
const tileY0 = tile.y / scale;
|
|
673
|
+
const tileSpan = 1 / scale;
|
|
674
|
+
if (maxX <= tileX0 || minX >= tileX0 + tileSpan)
|
|
675
|
+
continue;
|
|
676
|
+
if (maxY <= tileY0 || minY >= tileY0 + tileSpan)
|
|
677
|
+
continue;
|
|
678
|
+
const rows = meshRowRange((minY - tileY0) * scale, (maxY - tileY0) * scale, mesh.meshSize);
|
|
679
|
+
if (!rows)
|
|
680
|
+
continue;
|
|
681
|
+
const data = frame.getTerrainData(tile);
|
|
682
|
+
if (!data)
|
|
683
|
+
continue;
|
|
684
|
+
const projection = frame.getProjectionData(tile);
|
|
685
|
+
if (!projection)
|
|
686
|
+
continue;
|
|
687
|
+
applyDrapeProjectionUniforms(gl, set, projection);
|
|
688
|
+
applyDrapeTerrainUniforms(gl, set, data, UNIT_TERRAIN);
|
|
689
|
+
// Constrain the boundary vertices to the coarser side's polyline (the same
|
|
690
|
+
// mechanism as the polygon and line drape)
|
|
691
|
+
const edges = resolveTileEdges(drawnKeys, tile, mesh.meshSize, (n) => {
|
|
692
|
+
const neighbor = tileByKey.get(wrappedTileKey(n));
|
|
693
|
+
return neighbor ? frame.getTerrainData(neighbor) : null;
|
|
694
|
+
});
|
|
695
|
+
applyEdgeConstrainUniforms(gl, set, edges, data);
|
|
696
|
+
const groundMeters = circumferenceAtLatitude(tileCenterLatitude(tile.y, tile.z)) / scale;
|
|
697
|
+
if (set.u_tile_meters)
|
|
698
|
+
gl.uniform1f(set.u_tile_meters, groundMeters);
|
|
699
|
+
// Lift by the same amount as the polygon and line drape so that boundary
|
|
700
|
+
// vertices lowered by the constraint do not lose to the terrain mesh in
|
|
701
|
+
// depth (on screen this is less than 0.1 pixel)
|
|
702
|
+
if (set.u_drape_lift_m)
|
|
703
|
+
gl.uniform1f(set.u_drape_lift_m, groundMeters * DRAPE_LIFT_RATIO);
|
|
704
|
+
// The four corners into this tile's 0..1 coordinates (values that fall
|
|
705
|
+
// outside the tile may stay as they are)
|
|
706
|
+
setQuadUniform(gl, set.u_quad_a, quad[0], quad[1], tileX0, tileY0, scale);
|
|
707
|
+
setQuadUniform(gl, set.u_quad_b, quad[2], quad[3], tileX0, tileY0, scale);
|
|
708
|
+
setQuadUniform(gl, set.u_quad_c, quad[4], quad[5], tileX0, tileY0, scale);
|
|
709
|
+
setQuadUniform(gl, set.u_quad_d, quad[6], quad[7], tileX0, tileY0, scale);
|
|
710
|
+
gl.bindVertexArray(mesh.vao);
|
|
711
|
+
gl.drawElements(gl.TRIANGLES, rows.count * indicesPerRow, gl.UNSIGNED_INT, rows.start * indicesPerRow * 4);
|
|
712
|
+
gl.bindVertexArray(null);
|
|
713
|
+
}
|
|
714
|
+
if (!frame.keepDepthTest)
|
|
715
|
+
setDepthTestEnabled(gl, false);
|
|
716
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
717
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
718
|
+
return true;
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Allocates the glyph data textures (no repacking if the key is the same)
|
|
722
|
+
*/
|
|
723
|
+
ensureGlyphBuffers(text) {
|
|
724
|
+
const gl = this.gl;
|
|
725
|
+
this.useCounter++;
|
|
726
|
+
const cached = this.glyphCache.get(text.key);
|
|
727
|
+
if (cached) {
|
|
728
|
+
cached.usedAt = this.useCounter;
|
|
729
|
+
return cached;
|
|
730
|
+
}
|
|
731
|
+
const bins = binQuadGlyphs(text.glyphs, text.glyphCount);
|
|
732
|
+
if (bins.grid === 0 || bins.entryCount === 0)
|
|
733
|
+
return null;
|
|
734
|
+
// 2 texels per glyph. The width is even, so a glyph never straddles two rows
|
|
735
|
+
const texels = bins.entryCount * 2;
|
|
736
|
+
const glyphRows = Math.max(1, Math.ceil(texels / GLYPH_TEX_WIDTH));
|
|
737
|
+
const glyphTex = createDataTexture(gl, GLYPH_TEX_WIDTH, glyphRows);
|
|
738
|
+
const binTex = createDataTexture(gl, bins.grid, bins.grid);
|
|
739
|
+
if (!glyphTex || !binTex) {
|
|
740
|
+
if (glyphTex)
|
|
741
|
+
gl.deleteTexture(glyphTex);
|
|
742
|
+
if (binTex)
|
|
743
|
+
gl.deleteTexture(binTex);
|
|
744
|
+
this.lastError = 'glyph-texture-alloc-failed';
|
|
745
|
+
return null;
|
|
746
|
+
}
|
|
747
|
+
const payload = new Float32Array(GLYPH_TEX_WIDTH * glyphRows * 4);
|
|
748
|
+
payload.set(bins.entries.subarray(0, Math.min(bins.entries.length, payload.length)));
|
|
749
|
+
gl.bindTexture(gl.TEXTURE_2D, glyphTex);
|
|
750
|
+
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, GLYPH_TEX_WIDTH, glyphRows, gl.RGBA, gl.FLOAT, payload);
|
|
751
|
+
gl.bindTexture(gl.TEXTURE_2D, binTex);
|
|
752
|
+
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, bins.grid, bins.grid, gl.RGBA, gl.FLOAT, bins.cells);
|
|
753
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
754
|
+
const entry = {
|
|
755
|
+
glyphTex,
|
|
756
|
+
binTex,
|
|
757
|
+
glyphRows,
|
|
758
|
+
grid: bins.grid,
|
|
759
|
+
key: text.key,
|
|
760
|
+
usedAt: this.useCounter,
|
|
761
|
+
};
|
|
762
|
+
this.glyphCache.set(text.key, entry);
|
|
763
|
+
this.evictGlyphBuffers();
|
|
764
|
+
return entry;
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Discards glyph data textures that are not in use (LRU)
|
|
768
|
+
*/
|
|
769
|
+
evictGlyphBuffers() {
|
|
770
|
+
if (this.glyphCache.size <= GLYPH_CACHE_LIMIT)
|
|
771
|
+
return;
|
|
772
|
+
const gl = this.gl;
|
|
773
|
+
const sorted = [...this.glyphCache.entries()].sort((a, b) => a[1].usedAt - b[1].usedAt);
|
|
774
|
+
for (const [key, entry] of sorted) {
|
|
775
|
+
if (this.glyphCache.size <= GLYPH_CACHE_LIMIT)
|
|
776
|
+
break;
|
|
777
|
+
gl.deleteTexture(entry.glyphTex);
|
|
778
|
+
gl.deleteTexture(entry.binTex);
|
|
779
|
+
this.glyphCache.delete(key);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* Releases the resources
|
|
784
|
+
*/
|
|
785
|
+
dispose() {
|
|
786
|
+
const gl = this.gl;
|
|
787
|
+
for (const slot of [this.imageSlot, this.surfaceSlot]) {
|
|
788
|
+
if (slot)
|
|
789
|
+
gl.deleteProgram(slot.program);
|
|
790
|
+
}
|
|
791
|
+
this.imageSlot = null;
|
|
792
|
+
this.surfaceSlot = null;
|
|
793
|
+
if (this.mesh) {
|
|
794
|
+
disposeTerrainMeshBuffers(gl, this.mesh);
|
|
795
|
+
this.mesh = null;
|
|
796
|
+
}
|
|
797
|
+
for (const entry of this.glyphCache.values()) {
|
|
798
|
+
gl.deleteTexture(entry.glyphTex);
|
|
799
|
+
gl.deleteTexture(entry.binTex);
|
|
800
|
+
}
|
|
801
|
+
this.glyphCache.clear();
|
|
802
|
+
if (this.placeholderTex) {
|
|
803
|
+
gl.deleteTexture(this.placeholderTex);
|
|
804
|
+
this.placeholderTex = null;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
/** Writes a color uniform (shaped so that a readonly tuple can be passed as is) */
|
|
809
|
+
function setColorUniform(gl, location, color) {
|
|
810
|
+
if (!location)
|
|
811
|
+
return;
|
|
812
|
+
gl.uniform4f(location, color[0], color[1], color[2], color[3]);
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Creates a float texture used only for indexed lookups (the same manner as the
|
|
816
|
+
* polygon and line drape)
|
|
817
|
+
*/
|
|
818
|
+
function createDataTexture(gl, width, height) {
|
|
819
|
+
const texture = gl.createTexture();
|
|
820
|
+
if (!texture)
|
|
821
|
+
return null;
|
|
822
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
823
|
+
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA32F, width, height);
|
|
824
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
825
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
826
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
827
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
828
|
+
return texture;
|
|
829
|
+
}
|
|
830
|
+
/** Maps a Mercator coordinate into the tile's 0..1 space and writes it to a uniform */
|
|
831
|
+
function setQuadUniform(gl, location, x, y, tileX0, tileY0, scale) {
|
|
832
|
+
if (!location)
|
|
833
|
+
return;
|
|
834
|
+
gl.uniform2f(location, (x - tileX0) * scale, (y - tileY0) * scale);
|
|
835
|
+
}
|