UNPKG

@deck.gl/core

Version:

deck.gl core library

4 lines 850 kB
{ "version": 3, "sources": ["../src/index.ts", "../src/lib/init.ts", "../src/utils/log.ts", "../src/debug/loggers.ts", "../src/debug/index.ts", "../src/utils/json-loader.ts", "../src/shaderlib/index.ts", "../src/shaderlib/misc/layer-uniforms.ts", "../src/shaderlib/misc/geometry.ts", "../src/shaderlib/project/project.ts", "../src/shaderlib/project/viewport-uniforms.ts", "../src/lib/constants.ts", "../src/utils/memoize.ts", "../src/shaderlib/project/project.wgsl.ts", "../src/shaderlib/project/project.glsl.ts", "../src/shaderlib/project32/project32.ts", "../src/shaderlib/shadow/shadow.ts", "../src/shaderlib/picking/picking.ts", "../src/effects/lighting/ambient-light.ts", "../src/effects/lighting/directional-light.ts", "../src/effects/lighting/lighting-effect.ts", "../src/passes/pass.ts", "../src/passes/layers-pass.ts", "../src/passes/shadow-pass.ts", "../src/utils/typed-array-manager.ts", "../src/utils/math-utils.ts", "../src/viewports/viewport.ts", "../src/viewports/web-mercator-viewport.ts", "../src/shaderlib/project/project-functions.ts", "../src/effects/lighting/point-light.ts", "../src/effects/lighting/camera-light.ts", "../src/effects/lighting/sun-light.ts", "../src/effects/post-process-effect.ts", "../src/passes/screen-pass.ts", "../src/passes/screen-pass-uniforms.ts", "../src/passes/pick-layers-pass.ts", "../src/lib/layer-manager.ts", "../src/lifecycle/constants.ts", "../src/utils/flatten.ts", "../src/lib/resource/resource.ts", "../src/lib/resource/resource-manager.ts", "../src/utils/deep-equal.ts", "../src/lib/view-manager.ts", "../src/utils/positions.ts", "../src/views/view.ts", "../src/controllers/map-controller.ts", "../src/transitions/transition.ts", "../src/controllers/transition-manager.ts", "../src/transitions/transition-interpolator.ts", "../src/utils/assert.ts", "../src/transitions/linear-interpolator.ts", "../src/controllers/controller.ts", "../src/controllers/view-state.ts", "../src/views/map-view.ts", "../src/lib/effect-manager.ts", "../src/passes/draw-layers-pass.ts", "../src/lib/deck-renderer.ts", "../src/lib/picking/query-object.ts", "../src/lib/picking/pick-info.ts", "../src/lib/deck-picker.ts", "../src/lib/widget-manager.ts", "../src/lib/tooltip.ts", "../src/lib/deck.ts", "../src/lib/attribute/data-column.ts", "../src/lib/attribute/gl-utils.ts", "../src/utils/iterable-utils.ts", "../src/utils/range.ts", "../src/lib/attribute/transition-settings.ts", "../src/lib/attribute/attribute.ts", "../src/transitions/gpu-interpolation-transition.ts", "../src/utils/array-utils.ts", "../src/transitions/gpu-transition-utils.ts", "../src/transitions/gpu-transition.ts", "../src/transitions/gpu-spring-transition.ts", "../src/lib/attribute/attribute-transition-manager.ts", "../src/lib/attribute/attribute-manager.ts", "../src/lib/layer.ts", "../src/transitions/cpu-interpolation-transition.ts", "../src/transitions/cpu-spring-transition.ts", "../src/lib/uniform-transition-manager.ts", "../src/lifecycle/props.ts", "../src/utils/count.ts", "../src/utils/shader.ts", "../src/utils/texture.ts", "../src/lifecycle/prop-types.ts", "../src/lifecycle/create-props.ts", "../src/lifecycle/component.ts", "../src/lifecycle/component-state.ts", "../src/lib/layer-state.ts", "../src/lib/composite-layer.ts", "../src/viewports/globe-viewport.ts", "../src/viewports/orbit-viewport.ts", "../src/viewports/orthographic-viewport.ts", "../src/viewports/first-person-viewport.ts", "../src/controllers/first-person-controller.ts", "../src/views/first-person-view.ts", "../src/controllers/orbit-controller.ts", "../src/views/orbit-view.ts", "../src/controllers/orthographic-controller.ts", "../src/views/orthographic-view.ts", "../src/controllers/globe-controller.ts", "../src/views/globe-view.ts", "../src/lib/layer-extension.ts", "../src/transitions/fly-to-interpolator.ts", "../src/utils/tesselator.ts", "../src/utils/apply-styles.ts"], "sourcesContent": ["// deck.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\n/* eslint-disable max-len */\n\n// Intialize globals, extract version\nexport {VERSION} from './lib/init';\n\n// Import shaderlib to make sure shader modules are initialized\nexport {getShaderAssembler} from './shaderlib/index';\n\n// Core Library\nexport {COORDINATE_SYSTEM, OPERATION, UNIT} from './lib/constants';\n\n// Effects\nexport {default as LightingEffect} from './effects/lighting/lighting-effect';\nexport {AmbientLight} from './effects/lighting/ambient-light';\nexport {DirectionalLight} from './effects/lighting/directional-light';\nexport {PointLight} from './effects/lighting/point-light';\nexport {default as _CameraLight} from './effects/lighting/camera-light';\nexport {default as _SunLight} from './effects/lighting/sun-light';\nexport {default as PostProcessEffect} from './effects/post-process-effect';\n\n// Passes\nexport {default as _LayersPass} from './passes/layers-pass';\nexport {default as _PickLayersPass} from './passes/pick-layers-pass';\n\n// Experimental Pure JS (non-React) bindings\nexport {default as Deck} from './lib/deck';\n\nexport {default as LayerManager} from './lib/layer-manager';\nexport {default as Attribute} from './lib/attribute/attribute';\nexport {default as AttributeManager} from './lib/attribute/attribute-manager';\nexport {default as Layer} from './lib/layer';\nexport {default as CompositeLayer} from './lib/composite-layer';\nexport {default as DeckRenderer} from './lib/deck-renderer';\n\n// Viewports\nexport {default as Viewport} from './viewports/viewport';\nexport {default as WebMercatorViewport} from './viewports/web-mercator-viewport';\nexport {default as _GlobeViewport} from './viewports/globe-viewport';\nexport {default as OrbitViewport} from './viewports/orbit-viewport';\nexport {default as OrthographicViewport} from './viewports/orthographic-viewport';\nexport {default as FirstPersonViewport} from './viewports/first-person-viewport';\n\n// Shader modules\nexport {\n picking,\n project,\n project32,\n gouraudLighting,\n phongLighting,\n shadow\n} from './shaderlib/index';\n\nexport {default as View} from './views/view';\nexport {default as MapView} from './views/map-view';\nexport {default as FirstPersonView} from './views/first-person-view';\nexport {default as OrbitView} from './views/orbit-view';\nexport {default as OrthographicView} from './views/orthographic-view';\nexport {default as _GlobeView} from './views/globe-view';\n\n// Controllers\nexport {default as Controller} from './controllers/controller';\nexport {default as MapController} from './controllers/map-controller';\nexport {default as _GlobeController} from './controllers/globe-controller';\nexport {default as FirstPersonController} from './controllers/first-person-controller';\nexport {default as OrbitController} from './controllers/orbit-controller';\nexport {default as OrthographicController} from './controllers/orthographic-controller';\n\n// Extensions interface\nexport {default as LayerExtension} from './lib/layer-extension';\n\n// Transitions\nexport {TRANSITION_EVENTS} from './controllers/transition-manager';\nexport {default as TransitionInterpolator} from './transitions/transition-interpolator';\nexport {default as LinearInterpolator} from './transitions/linear-interpolator';\nexport {default as FlyToInterpolator} from './transitions/fly-to-interpolator';\n\n// Layer utilities\nexport {default as log} from './utils/log';\nexport {default as assert} from './utils/assert';\nexport {createIterable} from './utils/iterable-utils';\nexport {fp64LowPart} from './utils/math-utils';\nexport {default as Tesselator} from './utils/tesselator'; // Export? move to luma.gl or math.gl?\n\n// Experimental utilities\nexport {fillArray as _fillArray, flatten as _flatten} from './utils/flatten'; // Export? move to luma.gl or math.gl?\nexport {count as _count} from './utils/count';\nexport {deepEqual as _deepEqual} from './utils/deep-equal';\nexport {default as _memoize} from './utils/memoize';\nexport {mergeShaders as _mergeShaders} from './utils/shader';\nexport {compareProps as _compareProps} from './lifecycle/props';\nexport {applyStyles as _applyStyles, removeStyles as _removeStyles} from './utils/apply-styles';\n\n// Types\nexport type {CoordinateSystem} from './lib/constants';\nexport type {MapViewState, MapViewProps} from './views/map-view';\nexport type {FirstPersonViewState, FirstPersonViewProps} from './views/first-person-view';\nexport type {OrbitViewState, OrbitViewProps} from './views/orbit-view';\nexport type {OrthographicViewState, OrthographicViewProps} from './views/orthographic-view';\nexport type {GlobeViewState, GlobeViewProps} from './views/globe-view';\nexport type {ChangeFlags} from './lib/layer-state';\nexport type {LayersList, LayerContext} from './lib/layer-manager';\nexport type {ViewStateMap} from './lib/view-manager';\nexport type {UpdateParameters} from './lib/layer';\nexport type {DeckProps} from './lib/deck';\nexport type {\n LayerProps,\n CompositeLayerProps,\n Accessor,\n AccessorContext,\n AccessorFunction,\n LayerData,\n LayerDataSource,\n Unit,\n Operation,\n Position,\n Color,\n TextureSource,\n Material\n} from './types/layer-props';\nexport type {DrawLayerParameters, FilterContext} from './passes/layers-pass';\nexport type {PickingInfo, GetPickingInfoParams} from './lib/picking/pick-info';\nexport type {ConstructorOf as _ConstructorOf} from './types/types';\nexport type {BinaryAttribute} from './lib/attribute/attribute';\nexport type {Effect, EffectContext, PreRenderOptions, PostRenderOptions} from './lib/effect';\nexport type {PickingUniforms, ProjectProps, ProjectUniforms} from './shaderlib/index';\nexport type {DefaultProps} from './lifecycle/prop-types';\nexport type {LayersPassRenderOptions} from './passes/layers-pass';\nexport type {Widget, WidgetPlacement} from './lib/widget-manager';\nexport type {LightingEffectProps} from './effects/lighting/lighting-effect';\nexport type {AmbientLightOptions} from './effects/lighting/ambient-light';\nexport type {DirectionalLightOptions} from './effects/lighting/directional-light';\nexport type {PointLightOptions} from './effects/lighting/point-light';\nexport type {SunLightOptions} from './effects/lighting/sun-light';\nexport type {\n ControllerProps,\n ViewStateChangeParameters,\n InteractionState\n} from './controllers/controller';\n\n// INTERNAL, DO NOT USE\n// @deprecated internal do not use\nexport {default as _Component} from './lifecycle/component';\n// @deprecated internal do not use\nexport {default as _ComponentState} from './lifecycle/component-state';\n", "// deck.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {registerLoaders} from '@loaders.gl/core';\nimport {ImageLoader} from '@loaders.gl/images';\n\nimport log from '../utils/log';\nimport {register} from '../debug/index';\nimport jsonLoader from '../utils/json-loader';\n\ndeclare global {\n const __VERSION__: string;\n}\n\nfunction checkVersion() {\n // Version detection using typescript plugin.\n // Fallback for tests and SSR since global variable is defined by esbuild.\n const version =\n typeof __VERSION__ !== 'undefined'\n ? __VERSION__\n : globalThis.DECK_VERSION || 'untranspiled source';\n\n // Note: a `deck` object not created by deck.gl may exist in the global scope\n const existingVersion = globalThis.deck && globalThis.deck.VERSION;\n\n if (existingVersion && existingVersion !== version) {\n throw new Error(`deck.gl - multiple versions detected: ${existingVersion} vs ${version}`);\n }\n\n if (!existingVersion) {\n log.log(1, `deck.gl ${version}`)();\n\n globalThis.deck = {\n ...globalThis.deck,\n VERSION: version,\n version,\n log,\n // experimental\n _registerLoggers: register\n };\n\n registerLoaders([\n jsonLoader,\n // @ts-expect-error non-standard Loader format\n [ImageLoader, {imagebitmap: {premultiplyAlpha: 'none'}}]\n ]);\n }\n\n return version;\n}\n\nexport const VERSION = checkVersion();\n", "// deck.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {Log} from '@probe.gl/log';\n\nconst defaultLogger: Log = new Log({id: 'deck'});\n\nexport default defaultLogger;\n", "// deck.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport type {Log} from '@probe.gl/log';\n\nconst logState: {\n attributeUpdateStart: number;\n attributeManagerUpdateStart: number;\n attributeUpdateMessages: string[];\n} = {\n attributeUpdateStart: -1,\n attributeManagerUpdateStart: -1,\n attributeUpdateMessages: []\n};\n\nconst LOG_LEVEL_MAJOR_UPDATE = 1; // Events with direct perf impact\nconst LOG_LEVEL_MINOR_UPDATE = 2; // Events that may affect perf\nconst LOG_LEVEL_UPDATE_DETAIL = 3;\nconst LOG_LEVEL_INFO = 4;\nconst LOG_LEVEL_DRAW = 2;\n\nexport const getLoggers = (log: Log): Record<string, Function> => ({\n /* Layer events */\n\n 'layer.changeFlag': (layer, key, flags) => {\n log.log(LOG_LEVEL_UPDATE_DETAIL, `${layer.id} ${key}: `, flags[key])();\n },\n\n 'layer.initialize': layer => {\n log.log(LOG_LEVEL_MAJOR_UPDATE, `Initializing ${layer}`)();\n },\n 'layer.update': (layer, needsUpdate) => {\n if (needsUpdate) {\n const flags = layer.getChangeFlags();\n log.log(\n LOG_LEVEL_MINOR_UPDATE,\n `Updating ${layer} because: ${Object.keys(flags)\n .filter(key => flags[key])\n .join(', ')}`\n )();\n } else {\n log.log(LOG_LEVEL_INFO, `${layer} does not need update`)();\n }\n },\n 'layer.matched': (layer, changed) => {\n if (changed) {\n log.log(LOG_LEVEL_INFO, `Matched ${layer}, state transfered`)();\n }\n },\n 'layer.finalize': layer => {\n log.log(LOG_LEVEL_MAJOR_UPDATE, `Finalizing ${layer}`)();\n },\n\n /* CompositeLayer events */\n\n 'compositeLayer.renderLayers': (layer, updated, subLayers) => {\n if (updated) {\n log.log(\n LOG_LEVEL_MINOR_UPDATE,\n `Composite layer rendered new subLayers ${layer}`,\n subLayers\n )();\n } else {\n log.log(LOG_LEVEL_INFO, `Composite layer reused subLayers ${layer}`, subLayers)();\n }\n },\n\n /* LayerManager events */\n\n 'layerManager.setLayers': (layerManager, updated, layers) => {\n if (updated) {\n log.log(LOG_LEVEL_MINOR_UPDATE, `Updating ${layers.length} deck layers`)();\n }\n },\n\n 'layerManager.activateViewport': (layerManager, viewport) => {\n log.log(LOG_LEVEL_UPDATE_DETAIL, 'Viewport changed', viewport)();\n },\n\n /* AttributeManager events */\n\n 'attributeManager.invalidate': (attributeManager, trigger, attributeNames) => {\n log.log(\n LOG_LEVEL_MAJOR_UPDATE,\n attributeNames\n ? `invalidated attributes ${attributeNames} (${trigger}) for ${attributeManager.id}`\n : `invalidated all attributes for ${attributeManager.id}`\n )();\n },\n\n 'attributeManager.updateStart': attributeManager => {\n logState.attributeUpdateMessages.length = 0;\n logState.attributeManagerUpdateStart = Date.now();\n },\n 'attributeManager.updateEnd': (attributeManager, numInstances) => {\n const timeMs = Math.round(Date.now() - logState.attributeManagerUpdateStart);\n log.groupCollapsed(\n LOG_LEVEL_MINOR_UPDATE,\n `Updated attributes for ${numInstances} instances in ${attributeManager.id} in ${timeMs}ms`\n )();\n for (const updateMessage of logState.attributeUpdateMessages) {\n log.log(LOG_LEVEL_UPDATE_DETAIL, updateMessage)();\n }\n log.groupEnd(LOG_LEVEL_MINOR_UPDATE)();\n },\n\n /* Attribute events */\n\n 'attribute.updateStart': attribute => {\n logState.attributeUpdateStart = Date.now();\n },\n 'attribute.allocate': (attribute, numInstances) => {\n const message = `${attribute.id} allocated ${numInstances}`;\n logState.attributeUpdateMessages.push(message);\n },\n 'attribute.updateEnd': (attribute, numInstances) => {\n const timeMs = Math.round(Date.now() - logState.attributeUpdateStart);\n const message = `${attribute.id} updated ${numInstances} in ${timeMs}ms`;\n logState.attributeUpdateMessages.push(message);\n },\n\n /* Render events */\n\n 'deckRenderer.renderLayers': (deckRenderer, renderStats, opts) => {\n const {pass, redrawReason, stats} = opts;\n for (const status of renderStats) {\n const {totalCount, visibleCount, compositeCount, pickableCount} = status;\n const primitiveCount = totalCount - compositeCount;\n const hiddenCount = primitiveCount - visibleCount;\n\n log.log(\n LOG_LEVEL_DRAW,\n `RENDER #${deckRenderer.renderCount} \\\n ${visibleCount} (of ${totalCount} layers) to ${pass} because ${redrawReason} \\\n (${hiddenCount} hidden, ${compositeCount} composite ${pickableCount} pickable)`\n )();\n\n if (stats) {\n stats.get('Redraw Layers').add(visibleCount);\n }\n }\n }\n});\n", "// deck.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport deckLog from '../utils/log';\nimport {getLoggers} from './loggers';\n\n/* debug utility */\n\nlet loggers: Record<string, Function> = {};\n\n// Conditionally load default loggers in development mode\n// eslint-disable-next-line\nif (process.env.NODE_ENV !== 'production') {\n loggers = getLoggers(deckLog);\n}\n\nexport function register(handlers: Record<string, Function>): void {\n loggers = handlers;\n}\n\nexport default function debug(eventType: string, arg1?: any, arg2?: any, arg3?: any): void {\n if (deckLog.level > 0 && loggers[eventType]) {\n // Not using rest parameters to defeat perf hit from array construction\n loggers[eventType].call(null, arg1, arg2, arg3);\n }\n}\n", "// deck.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport type {Loader} from '@loaders.gl/loader-utils';\n\nfunction isJSON(text: string): boolean {\n const firstChar = text[0];\n const lastChar = text[text.length - 1];\n return (firstChar === '{' && lastChar === '}') || (firstChar === '[' && lastChar === ']');\n}\n\n// A light weight version instead of @loaders.gl/json (stream processing etc.)\nexport default {\n dataType: null as any,\n batchType: null as never,\n id: 'JSON',\n name: 'JSON',\n module: '',\n version: '',\n options: {},\n extensions: ['json', 'geojson'],\n mimeTypes: ['application/json', 'application/geo+json'],\n testText: isJSON,\n parseTextSync: JSON.parse\n} as Loader;\n", "// deck.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {ShaderAssembler} from '@luma.gl/shadertools';\n\nimport {gouraudLighting, phongLighting} from '@luma.gl/shadertools';\nimport {layerUniforms} from './misc/layer-uniforms';\nimport geometry from './misc/geometry';\nimport project from './project/project';\nimport project32 from './project32/project32';\nimport shadow from './shadow/shadow';\nimport picking from './picking/picking';\n\nconst DEFAULT_MODULES = [geometry];\n\nconst SHADER_HOOKS_GLSL = [\n 'vs:DECKGL_FILTER_SIZE(inout vec3 size, VertexGeometry geometry)',\n 'vs:DECKGL_FILTER_GL_POSITION(inout vec4 position, VertexGeometry geometry)',\n 'vs:DECKGL_FILTER_COLOR(inout vec4 color, VertexGeometry geometry)',\n 'fs:DECKGL_FILTER_COLOR(inout vec4 color, FragmentGeometry geometry)'\n];\n\nconst SHADER_HOOKS_WGSL = [\n // Not yet supported\n];\n\nexport function getShaderAssembler(language: 'glsl' | 'wgsl'): ShaderAssembler {\n const shaderAssembler = ShaderAssembler.getDefaultShaderAssembler();\n\n for (const shaderModule of DEFAULT_MODULES) {\n shaderAssembler.addDefaultModule(shaderModule);\n }\n\n // Add shader hooks based on language\n // TODO(ibgreen) - should the luma shader assembler support both sets of hooks?\n const shaderHooks = language === 'glsl' ? SHADER_HOOKS_GLSL : SHADER_HOOKS_WGSL;\n for (const shaderHook of shaderHooks) {\n shaderAssembler.addShaderHook(shaderHook);\n }\n\n return shaderAssembler;\n}\n\nexport {layerUniforms, picking, project, project32, gouraudLighting, phongLighting, shadow};\n\n// Useful for custom shader modules\nexport type {ProjectProps, ProjectUniforms} from './project/viewport-uniforms';\n\n// TODO - these should be imported from luma.gl\n/* eslint-disable camelcase */\nexport type PickingUniforms = {\n picking_uActive: boolean;\n picking_uAttribute: boolean;\n picking_uSelectedColor: [number, number, number];\n picking_uSelectedColorValid: boolean;\n picking_uHighlightColor: [number, number, number, number];\n};\n\nexport type LightingModuleSettings = {\n material:\n | boolean\n | {\n ambient?: number;\n diffuse?: number;\n shininess?: number;\n specularColor?: [number, number, number];\n };\n};\n", "// deck.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport type {ShaderModule} from '@luma.gl/shadertools';\nimport type {LayerProps} from '../../types/layer-props';\n\nconst uniformBlock = `\\\nuniform layerUniforms {\n uniform float opacity;\n} layer;\n`;\n\nexport type LayerUniforms = {\n opacity?: number;\n};\n\nexport const layerUniforms = {\n name: 'layer',\n vs: uniformBlock,\n fs: uniformBlock,\n getUniforms: (props: Partial<LayerProps>) => {\n return {\n // apply gamma to opacity to make it visually \"linear\"\n // TODO - v10: use raw opacity?\n opacity: Math.pow(props.opacity!, 1 / 2.2)\n };\n },\n uniformTypes: {\n opacity: 'f32'\n }\n} as const satisfies ShaderModule<LayerProps, LayerUniforms>;\n", "// deck.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport type {ShaderModule} from '@luma.gl/shadertools';\n\nconst source = /* wgsl */ `\\\nconst SMOOTH_EDGE_RADIUS: f32 = 0.5;\n\nstruct VertexGeometry {\n position: vec4<f32>,\n worldPosition: vec3<f32>,\n worldPositionAlt: vec3<f32>,\n normal: vec3<f32>,\n uv: vec2<f32>,\n pickingColor: vec3<f32>,\n};\n\nvar<private> geometry_: VertexGeometry = VertexGeometry(\n vec4<f32>(0.0, 0.0, 1.0, 0.0),\n vec3<f32>(0.0, 0.0, 0.0),\n vec3<f32>(0.0, 0.0, 0.0),\n vec3<f32>(0.0, 0.0, 0.0),\n vec2<f32>(0.0, 0.0),\n vec3<f32>(0.0, 0.0, 0.0)\n);\n\nstruct FragmentGeometry {\n uv: vec2<f32>,\n};\n\nvar<private> fragmentGeometry: FragmentGeometry;\n\nfn smoothedge(edge: f32, x: f32) -> f32 {\n return smoothstep(edge - SMOOTH_EDGE_RADIUS, edge + SMOOTH_EDGE_RADIUS, x);\n}\n`;\n\nconst defines = '#define SMOOTH_EDGE_RADIUS 0.5';\n\nconst vs = /* glsl */ `\\\n${defines}\n\nstruct VertexGeometry {\n vec4 position;\n vec3 worldPosition;\n vec3 worldPositionAlt;\n vec3 normal;\n vec2 uv;\n vec3 pickingColor;\n} geometry = VertexGeometry(\n vec4(0.0, 0.0, 1.0, 0.0),\n vec3(0.0),\n vec3(0.0),\n vec3(0.0),\n vec2(0.0),\n vec3(0.0)\n);\n`;\n\nconst fs = /* glsl */ `\\\n${defines}\n\nstruct FragmentGeometry {\n vec2 uv;\n} geometry;\n\nfloat smoothedge(float edge, float x) {\n return smoothstep(edge - SMOOTH_EDGE_RADIUS, edge + SMOOTH_EDGE_RADIUS, x);\n}\n`;\n\nexport default {\n name: 'geometry',\n source,\n vs,\n fs\n} as const satisfies ShaderModule;\n", "// deck.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {fp32, ShaderModule} from '@luma.gl/shadertools';\nimport geometry from '../misc/geometry';\nimport {getUniformsFromViewport} from './viewport-uniforms';\nimport {projectWGSL} from './project.wgsl';\nimport {projectGLSL} from './project.glsl';\n\nimport type {ProjectProps, ProjectUniforms} from './viewport-uniforms';\n\nconst INITIAL_MODULE_OPTIONS = {};\n\nfunction getUniforms(opts: ProjectProps | {} = INITIAL_MODULE_OPTIONS) {\n if ('viewport' in opts) {\n return getUniformsFromViewport(opts);\n }\n return {};\n}\n\nexport default {\n name: 'project',\n dependencies: [fp32, geometry],\n source: projectWGSL,\n vs: projectGLSL,\n getUniforms,\n uniformTypes: {\n wrapLongitude: 'f32',\n coordinateSystem: 'i32',\n commonUnitsPerMeter: 'vec3<f32>',\n projectionMode: 'i32',\n scale: 'f32',\n commonUnitsPerWorldUnit: 'vec3<f32>',\n commonUnitsPerWorldUnit2: 'vec3<f32>',\n center: 'vec4<f32>',\n modelMatrix: 'mat4x4<f32>',\n viewProjectionMatrix: 'mat4x4<f32>',\n viewportSize: 'vec2<f32>',\n devicePixelRatio: 'f32',\n focalDistance: 'f32',\n cameraPosition: 'vec3<f32>',\n coordinateOrigin: 'vec3<f32>',\n commonOrigin: 'vec3<f32>',\n pseudoMeters: 'f32'\n }\n // @ts-ignore TODO v9.1\n} as const satisfies ShaderModule<ProjectProps, ProjectUniforms, {}>;\n", "// deck.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\n/* eslint-disable complexity, camelcase */\n\nimport {mat4, Matrix4Like, vec4} from '@math.gl/core';\n\nimport {COORDINATE_SYSTEM, PROJECTION_MODE} from '../../lib/constants';\n\nimport memoize from '../../utils/memoize';\n\nimport type Viewport from '../../viewports/viewport';\nimport type {CoordinateSystem} from '../../lib/constants';\n\ntype Vec3 = [number, number, number];\ntype Vec4 = [number, number, number, number];\n\n// To quickly set a vector to zero\nconst ZERO_VECTOR: Vec4 = [0, 0, 0, 0];\n// 4x4 matrix that drops 4th component of vector\nconst VECTOR_TO_POINT_MATRIX: Matrix4Like = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0];\nconst IDENTITY_MATRIX: Matrix4Like = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];\nconst DEFAULT_PIXELS_PER_UNIT2: Vec3 = [0, 0, 0];\nconst DEFAULT_COORDINATE_ORIGIN: Vec3 = [0, 0, 0];\n\nconst getMemoizedViewportUniforms = memoize(calculateViewportUniforms);\n\nexport function getOffsetOrigin(\n viewport: Viewport,\n coordinateSystem: CoordinateSystem,\n coordinateOrigin: Vec3 = DEFAULT_COORDINATE_ORIGIN\n): {\n geospatialOrigin: Vec3 | null;\n shaderCoordinateOrigin: Vec3;\n offsetMode: boolean;\n} {\n if (coordinateOrigin.length < 3) {\n coordinateOrigin = [coordinateOrigin[0], coordinateOrigin[1], 0];\n }\n\n let shaderCoordinateOrigin = coordinateOrigin;\n let geospatialOrigin: Vec3 | null;\n let offsetMode = true;\n\n if (\n coordinateSystem === COORDINATE_SYSTEM.LNGLAT_OFFSETS ||\n coordinateSystem === COORDINATE_SYSTEM.METER_OFFSETS\n ) {\n geospatialOrigin = coordinateOrigin;\n } else {\n geospatialOrigin = viewport.isGeospatial\n ? // @ts-expect-error longitude and latitude are not defined on the base Viewport, but is expected on geospatial viewports\n [Math.fround(viewport.longitude), Math.fround(viewport.latitude), 0]\n : null;\n }\n\n switch (viewport.projectionMode) {\n case PROJECTION_MODE.WEB_MERCATOR:\n if (\n coordinateSystem === COORDINATE_SYSTEM.LNGLAT ||\n coordinateSystem === COORDINATE_SYSTEM.CARTESIAN\n ) {\n geospatialOrigin = [0, 0, 0];\n offsetMode = false;\n }\n break;\n\n case PROJECTION_MODE.WEB_MERCATOR_AUTO_OFFSET:\n if (coordinateSystem === COORDINATE_SYSTEM.LNGLAT) {\n // viewport center in world space\n // @ts-expect-error when using LNGLAT coordinates, we expect the viewport to be geospatial, in which case geospatialOrigin is defined\n shaderCoordinateOrigin = geospatialOrigin;\n } else if (coordinateSystem === COORDINATE_SYSTEM.CARTESIAN) {\n // viewport center in common space\n shaderCoordinateOrigin = [\n Math.fround(viewport.center[0]),\n Math.fround(viewport.center[1]),\n 0\n ];\n // Geospatial origin (wgs84) must match shaderCoordinateOrigin (common)\n geospatialOrigin = viewport.unprojectPosition(shaderCoordinateOrigin);\n shaderCoordinateOrigin[0] -= coordinateOrigin[0];\n shaderCoordinateOrigin[1] -= coordinateOrigin[1];\n shaderCoordinateOrigin[2] -= coordinateOrigin[2];\n }\n break;\n\n case PROJECTION_MODE.IDENTITY:\n shaderCoordinateOrigin = viewport.position.map(Math.fround) as Vec3;\n shaderCoordinateOrigin[2] = shaderCoordinateOrigin[2] || 0;\n break;\n\n case PROJECTION_MODE.GLOBE:\n offsetMode = false;\n geospatialOrigin = null;\n break;\n\n default:\n // Unknown projection mode\n offsetMode = false;\n }\n\n return {geospatialOrigin, shaderCoordinateOrigin, offsetMode};\n}\n\n// The code that utilizes Matrix4 does the same calculation as their mat4 counterparts,\n// has lower performance but provides error checking.\nfunction calculateMatrixAndOffset(\n viewport: Viewport,\n coordinateSystem: CoordinateSystem,\n coordinateOrigin: Vec3\n): {\n viewMatrix: Matrix4Like;\n viewProjectionMatrix: Matrix4Like;\n projectionCenter: Vec4;\n originCommon: Vec4;\n cameraPosCommon: Vec3;\n shaderCoordinateOrigin: Vec3;\n geospatialOrigin: Vec3 | null;\n} {\n const {viewMatrixUncentered, projectionMatrix} = viewport;\n let {viewMatrix, viewProjectionMatrix} = viewport;\n\n let projectionCenter = ZERO_VECTOR;\n let originCommon: Vec4 = ZERO_VECTOR;\n let cameraPosCommon: Vec3 = viewport.cameraPosition as Vec3;\n const {geospatialOrigin, shaderCoordinateOrigin, offsetMode} = getOffsetOrigin(\n viewport,\n coordinateSystem,\n coordinateOrigin\n );\n\n if (offsetMode) {\n // Calculate transformed projectionCenter (using 64 bit precision JS)\n // This is the key to offset mode precision\n // (avoids doing this addition in 32 bit precision in GLSL)\n // @ts-expect-error the 4th component is assigned below\n originCommon = viewport.projectPosition(geospatialOrigin || shaderCoordinateOrigin);\n\n cameraPosCommon = [\n cameraPosCommon[0] - originCommon[0],\n cameraPosCommon[1] - originCommon[1],\n cameraPosCommon[2] - originCommon[2]\n ];\n\n originCommon[3] = 1;\n\n // projectionCenter = new Matrix4(viewProjectionMatrix)\n // .transformVector([positionPixels[0], positionPixels[1], 0.0, 1.0]);\n projectionCenter = vec4.transformMat4([], originCommon, viewProjectionMatrix);\n\n // Always apply uncentered projection matrix if available (shader adds center)\n viewMatrix = viewMatrixUncentered || viewMatrix;\n\n // Zero out 4th coordinate (\"after\" model matrix) - avoids further translations\n // viewMatrix = new Matrix4(viewMatrixUncentered || viewMatrix)\n // .multiplyRight(VECTOR_TO_POINT_MATRIX);\n viewProjectionMatrix = mat4.multiply([], projectionMatrix, viewMatrix);\n viewProjectionMatrix = mat4.multiply([], viewProjectionMatrix, VECTOR_TO_POINT_MATRIX);\n }\n\n return {\n viewMatrix: viewMatrix as Matrix4Like,\n viewProjectionMatrix: viewProjectionMatrix as Matrix4Like,\n projectionCenter,\n originCommon,\n cameraPosCommon,\n shaderCoordinateOrigin,\n geospatialOrigin\n };\n}\n\nexport type ProjectUniforms = {\n coordinateSystem: number;\n projectionMode: number;\n coordinateOrigin: Vec3;\n commonOrigin: Vec3;\n center: Vec4;\n // Backward compatibility\n // TODO: remove in v9\n pseudoMeters: boolean;\n\n // Screen size\n viewportSize: [number, number];\n devicePixelRatio: number;\n\n focalDistance: number;\n commonUnitsPerMeter: Vec3;\n commonUnitsPerWorldUnit: Vec3;\n commonUnitsPerWorldUnit2: Vec3;\n /** 2^zoom */\n scale: number;\n wrapLongitude: boolean;\n\n viewProjectionMatrix: Matrix4Like;\n modelMatrix: Matrix4Like;\n\n // This is for lighting calculations\n cameraPosition: Vec3;\n};\n\nexport type ProjectProps = {\n viewport: Viewport;\n devicePixelRatio?: number;\n modelMatrix?: Matrix4Like | null;\n coordinateSystem?: CoordinateSystem;\n coordinateOrigin?: Vec3;\n autoWrapLongitude?: boolean;\n};\n\n/**\n * Returns uniforms for shaders based on current projection\n * includes: projection matrix suitable for shaders\n *\n * TODO - Ensure this works with any viewport, not just WebMercatorViewports\n *\n * @param {WebMercatorViewport} viewport -\n * @return {Float32Array} - 4x4 projection matrix that can be used in shaders\n */\nexport function getUniformsFromViewport({\n viewport,\n devicePixelRatio = 1,\n modelMatrix = null,\n // Match Layer.defaultProps\n coordinateSystem = COORDINATE_SYSTEM.DEFAULT,\n coordinateOrigin = DEFAULT_COORDINATE_ORIGIN,\n autoWrapLongitude = false\n}: ProjectProps): ProjectUniforms {\n if (coordinateSystem === COORDINATE_SYSTEM.DEFAULT) {\n coordinateSystem = viewport.isGeospatial\n ? COORDINATE_SYSTEM.LNGLAT\n : COORDINATE_SYSTEM.CARTESIAN;\n }\n\n const uniforms = getMemoizedViewportUniforms({\n viewport,\n devicePixelRatio,\n coordinateSystem,\n coordinateOrigin\n });\n\n uniforms.wrapLongitude = autoWrapLongitude;\n uniforms.modelMatrix = modelMatrix || IDENTITY_MATRIX;\n\n return uniforms;\n}\n\nfunction calculateViewportUniforms({\n viewport,\n devicePixelRatio,\n coordinateSystem,\n coordinateOrigin\n}: {\n viewport: Viewport;\n devicePixelRatio: number;\n coordinateSystem: CoordinateSystem;\n coordinateOrigin: Vec3;\n}): ProjectUniforms {\n const {\n projectionCenter,\n viewProjectionMatrix,\n originCommon,\n cameraPosCommon,\n shaderCoordinateOrigin,\n geospatialOrigin\n } = calculateMatrixAndOffset(viewport, coordinateSystem, coordinateOrigin);\n\n // Calculate projection pixels per unit\n const distanceScales = viewport.getDistanceScales();\n\n const viewportSize: [number, number] = [\n viewport.width * devicePixelRatio,\n viewport.height * devicePixelRatio\n ];\n\n // Distance at which screen pixels are projected.\n // Used to scale sizes in clipspace to match screen pixels.\n // When using Viewport class's default projection matrix, this yields 1 for orthographic\n // and `viewport.focalDistance` for perspective views\n const focalDistance =\n vec4.transformMat4([], [0, 0, -viewport.focalDistance, 1], viewport.projectionMatrix)[3] || 1;\n\n const uniforms: ProjectUniforms = {\n // Projection mode values\n coordinateSystem,\n projectionMode: viewport.projectionMode,\n coordinateOrigin: shaderCoordinateOrigin,\n commonOrigin: originCommon.slice(0, 3) as Vec3,\n center: projectionCenter,\n\n // Backward compatibility\n // TODO: remove in v9\n // @ts-expect-error _pseudoMeters is only defined on WebMercator viewport\n pseudoMeters: Boolean(viewport._pseudoMeters),\n\n // Screen size\n viewportSize,\n devicePixelRatio,\n\n focalDistance,\n commonUnitsPerMeter: distanceScales.unitsPerMeter as Vec3,\n commonUnitsPerWorldUnit: distanceScales.unitsPerMeter as Vec3,\n commonUnitsPerWorldUnit2: DEFAULT_PIXELS_PER_UNIT2,\n scale: viewport.scale, // This is the mercator scale (2 ** zoom)\n wrapLongitude: false,\n\n viewProjectionMatrix,\n modelMatrix: IDENTITY_MATRIX,\n\n // This is for lighting calculations\n cameraPosition: cameraPosCommon\n };\n\n if (geospatialOrigin) {\n // Get high-precision DistanceScales from geospatial viewport\n // TODO: stricter types in Viewport classes\n const distanceScalesAtOrigin = viewport.getDistanceScales(geospatialOrigin) as {\n unitsPerMeter: Vec3;\n metersPerUnit: Vec3;\n unitsPerMeter2: Vec3;\n unitsPerDegree: Vec3;\n degreesPerUnit: Vec3;\n unitsPerDegree2: Vec3;\n };\n switch (coordinateSystem) {\n case COORDINATE_SYSTEM.METER_OFFSETS:\n uniforms.commonUnitsPerWorldUnit = distanceScalesAtOrigin.unitsPerMeter;\n uniforms.commonUnitsPerWorldUnit2 = distanceScalesAtOrigin.unitsPerMeter2;\n break;\n\n case COORDINATE_SYSTEM.LNGLAT:\n case COORDINATE_SYSTEM.LNGLAT_OFFSETS:\n // @ts-expect-error _pseudoMeters only exists on WebMercatorView\n if (!viewport._pseudoMeters) {\n uniforms.commonUnitsPerMeter = distanceScalesAtOrigin.unitsPerMeter;\n }\n uniforms.commonUnitsPerWorldUnit = distanceScalesAtOrigin.unitsPerDegree;\n uniforms.commonUnitsPerWorldUnit2 = distanceScalesAtOrigin.unitsPerDegree2;\n break;\n\n // a.k.a \"preprojected\" positions\n case COORDINATE_SYSTEM.CARTESIAN:\n uniforms.commonUnitsPerWorldUnit = [1, 1, distanceScalesAtOrigin.unitsPerMeter[2]];\n uniforms.commonUnitsPerWorldUnit2 = [0, 0, distanceScalesAtOrigin.unitsPerMeter2[2]];\n break;\n\n default:\n break;\n }\n }\n\n return uniforms;\n}\n", "// deck.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\n// Note: The numeric values here are matched by shader code in the\n// \"project\" and \"project64\" shader modules. Both places need to be\n// updated.\nimport log from '../utils/log';\nimport {Pan, InputDirection, Pinch, Tap} from 'mjolnir.js';\nimport type {PanRecognizerOptions, PinchRecognizerOptions, TapRecognizerOptions} from 'mjolnir.js';\n\n/**\n * The coordinate system that positions/dimensions are defined in.\n */\nexport const COORDINATE_SYSTEM = {\n /**\n * `LNGLAT` if rendering into a geospatial viewport, `CARTESIAN` otherwise\n */\n DEFAULT: -1,\n /**\n * Positions are interpreted as [longitude, latitude, elevation]\n * longitude/latitude are in degrees, elevation is in meters.\n * Dimensions are in meters.\n */\n LNGLAT: 1,\n\n /**\n * Positions are interpreted as [x, y, z] in meter offsets from the coordinate origin.\n * Dimensions are in meters.\n */\n METER_OFFSETS: 2,\n\n /**\n * Positions are interpreted as [deltaLng, deltaLat, elevation] from the coordinate origin.\n * deltaLng/deltaLat are in degrees, elevation is in meters.\n * Dimensions are in meters.\n */\n LNGLAT_OFFSETS: 3,\n\n /**\n * Positions and dimensions are in the common units of the viewport.\n */\n CARTESIAN: 0\n} as const;\n\n// Enums cannot be directly exported as they are not transpiled correctly into ES5, see https://github.com/visgl/deck.gl/issues/7130\nexport type CoordinateSystem = -1 | 0 | 1 | 2 | 3;\n\n// Deprecated\n/* eslint-disable accessor-pairs */\nObject.defineProperty(COORDINATE_SYSTEM, 'IDENTITY', {\n get: () => {\n log.deprecated('COORDINATE_SYSTEM.IDENTITY', 'COORDINATE_SYSTEM.CARTESIAN')();\n return 0;\n }\n});\n/* eslint-enable accessor-pairs */\n\n/**\n * How coordinates are transformed from the world space into the common space.\n */\nexport const PROJECTION_MODE = {\n /**\n * Render geospatial data in Web Mercator projection\n */\n WEB_MERCATOR: 1,\n /**\n * Render geospatial data as a 3D globe\n */\n GLOBE: 2,\n\n /**\n * (Internal use only) Web Mercator projection at high zoom\n */\n WEB_MERCATOR_AUTO_OFFSET: 4,\n\n /**\n * No transformation\n */\n IDENTITY: 0\n} as const;\n\nexport const UNIT = {\n common: 0,\n meters: 1,\n pixels: 2\n} as const;\n\nexport const EVENT_HANDLERS: {[eventName: string]: string} = {\n click: 'onClick',\n panstart: 'onDragStart',\n panmove: 'onDrag',\n panend: 'onDragEnd'\n} as const;\n\nexport const RECOGNIZERS = {\n multipan: [Pan, {threshold: 10, direction: InputDirection.Vertical, pointers: 2}],\n pinch: [Pinch, {}, null, ['multipan']],\n pan: [Pan, {threshold: 1}, ['pinch'], ['multipan']],\n dblclick: [Tap, {event: 'dblclick', taps: 2}],\n click: [Tap, {event: 'click'}, null, ['dblclick']]\n} as const;\nexport type RecognizerOptions = {\n pinch?: Omit<PinchRecognizerOptions, 'event' | 'enable'>;\n multipan?: Omit<PanRecognizerOptions, 'event' | 'enable'>;\n pan?: Omit<PanRecognizerOptions, 'event' | 'enable'>;\n dblclick?: Omit<TapRecognizerOptions, 'event' | 'enable'>;\n click?: Omit<TapRecognizerOptions, 'event' | 'enable'>;\n};\n\n/**\n * @deprecated Use string constants directly\n */\nexport const OPERATION = {\n DRAW: 'draw',\n MASK: 'mask',\n TERRAIN: 'terrain'\n} as const;\n", "// deck.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nfunction isEqual(a, b) {\n if (a === b) {\n return true;\n }\n if (Array.isArray(a)) {\n // Special treatment for arrays: compare 1-level deep\n // This is to support equality of matrix/coordinate props\n const len = a.length;\n if (!b || b.length !== len) {\n return false;\n }\n\n for (let i = 0; i < len; i++) {\n if (a[i] !== b[i]) {\n return false;\n }\n }\n return true;\n }\n return false;\n}\n\n/**\n * Speed up consecutive function calls by caching the result of calls with identical input\n * https://en.wikipedia.org/wiki/Memoization\n * @param {function} compute - the function to be memoized\n */\nexport default function memoize<In, Out>(compute: (args: In) => Out): (args: In) => Out {\n let cachedArgs: any = {};\n let cachedResult: Out;\n\n return (args: In) => {\n for (const key in args) {\n if (!isEqual(args[key], cachedArgs[key])) {\n cachedResult = compute(args);\n cachedArgs = args;\n break;\n }\n }\n return cachedResult;\n };\n}\n", "// deck.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {COORDINATE_SYSTEM, PROJECTION_MODE, UNIT} from '../../lib/constants';\n\n// We are generating these from the js code in constants.js\nconst COORDINATE_SYSTEM_WGSL_CONSTANTS = Object.keys(COORDINATE_SYSTEM)\n .map(key => `const COORDINATE_SYSTEM_${key}: i32 = ${COORDINATE_SYSTEM[key]};`)\n .join('');\nconst PROJECTION_MODE_WGSL_CONSTANTS = Object.keys(PROJECTION_MODE)\n .map(key => `const PROJECTION_MODE_${key}: i32 = ${PROJECTION_MODE[key]};`)\n .join('');\nconst UNIT_WGSL_CONSTANTS = Object.keys(UNIT)\n .map(key => `const UNIT_${key.toUpperCase()}: i32 = ${UNIT[key]};`)\n .join('');\n\nexport const projectWGSLHeader = /* wgsl */ `\\\n${COORDINATE_SYSTEM_WGSL_CONSTANTS}\n${PROJECTION_MODE_WGSL_CONSTANTS}\n${UNIT_WGSL_CONSTANTS}\n\nconst TILE_SIZE: f32 = 512.0;\nconst PI: f32 = 3.1415926536;\nconst WORLD_SCALE: f32 = TILE_SIZE / (PI * 2.0);\nconst ZERO_64_LOW: vec3<f32> = vec3<f32>(0.0, 0.0, 0.0);\nconst EARTH_RADIUS: f32 = 6370972.0; // meters\nconst GLOBE_RADIUS: f32 = 256.0;\n\n// -----------------------------------------------------------------------------\n// Uniform block (converted from GLSL uniform block)\n// -----------------------------------------------------------------------------\nstruct ProjectUniforms {\n wrapLongitude: i32,\n coordinateSystem: i32,\n commonUnitsPerMeter: vec3<f32>,\n projectionMode: i32,\n scale: f32,\n commonUnitsPerWorldUnit: vec3<f32>,\n commonUnitsPerWorldUnit2: vec3<f32>,\n center: vec4<f32>,\n modelMatrix: mat4x4<f32>,\n viewProjectionMatrix: mat4x4<f32>,\n viewportSize: vec2<f32>,\n devicePixelRatio: f32,\n focalDistance: f32,\n cameraPosition: vec3<f32>,\n coordinateOrigin: vec3<f32>,\n commonOrigin: vec3<f32>,\n pseudoMeters: i32,\n};\n\n@group(0) @binding(0)\nvar<uniform> project: ProjectUniforms;\n\n// -----------------------------------------------------------------------------\n// Geometry data\n// (In your GLSL code, \"geometry\" was assumed to be available globally. In WGSL,\n// you might supply this via vertex attributes or a uniform. Here we define a\n// uniform struct for demonstration.)\n// -----------------------------------------------------------------------------\n\n// Structure to carry additional geometry data used by deck.gl filters.\nstruct Geometry {\n worldPosition: vec3<f32>,\n worldPositionAlt: vec3<f32>,\n position: vec4<f32>,\n uv: vec2<f32>,\n pickingColor: vec3<f32>,\n};\n\n// @group(0) @binding(1)\nvar<private> geometry: Geometry;\n`;\n\nexport const projectWGSL = /* wgsl */ `\\\n${projectWGSLHeader}\n\n// -----------------------------------------------------------------------------\n// Functions\n// -----------------------------------------------------------------------------\n\n// Returns an adjustment factor for commonUnitsPerMeter\nfn _project_size_at_latitude(lat: f32) -> f32 {\n let y = clamp(lat, -89.9, 89.9);\n return 1.0 / cos(radians(y));\n}\n\n// Overloaded version: scales a value in meters at a given latitude.\nfn _project_size_at_latitude_m(meters: f32, lat: f32) -> f32 {\n return meters * project.commonUnitsPerMeter.z * _project_size_at_latitude(lat);\n}\n\n// Computes a non-linear scale factor based on geometry.\n// (Note: This function relies on \"geometry\" being provided.)\nfn project_size() -> f32 {\n if (project.projectionMode == PROJECTION_MODE_WEB_MERCATOR &&\n project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT &&\n project.pseudoMeters == 0) {\n if (geometry.position.w == 0.0) {\n return _project_size_at_latitude(geometry.worldPosition.y);\n }\n let y: f32 = geometry.position.y / TILE_SIZE * 2.0 - 1.0;\n let y2 = y * y;\n let y4 = y2 * y2;\n let y6 = y4 * y2;\n return 1.0 + 4.9348 * y2 + 4.0587 * y4 + 1.5642 * y6;\n }\n return 1.0;\n}\n\n// Overloads to scale offsets (meters to world units)\nfn project_size_float(meters: f32) -> f32 {\n return meters * project.commonUnitsPerMeter.z * project_size();\n}\n\nfn project_size_vec2(meters: vec2<f32>) -> vec2<f32> {\n return meters * project.commonUnitsPerMeter.xy * project_size();\n}\n\nfn project_size_vec3(meters: vec3<f32>) -> vec3<f32> {\n return meters * project.commonUnitsPerMeter * project_size();\n}\n\nfn project_size_vec4(meters: vec4<f32>) -> vec4<f32> {\n return vec4<f32>(meters.xyz * project.commonUnitsPerMeter, meters.w);\n}\n\n// Returns a rotation matrix aligning the z\u2011axis with the given up vector.\nfn project_get_orientation_matrix(up: vec3<f32>) -> mat3x3<f32> {\n let uz = normalize(up);\n let ux = select(\n vec3<f32>(1.0, 0.0, 0.0),\n normalize(vec3<f32>(uz.y, -uz.x, 0.0)),\n abs(uz.z) == 1.0\n );\n let uy = cross(uz, ux);\n return mat3x3<f32>(ux, uy, uz);\n}\n\n// Since WGSL does not support \"out\" parameters, we return a struct.\nstruct RotationResult {\n needsRotation: bool,\n transform: mat3x3<f32>,\n};\n\nfn project_needs_rotation(commonPosition: vec3<f32>) -> RotationResult {\n if (project.projectionMode == PROJECTION_MODE_GLOBE) {\n return RotationResult(true, project_get_orientation_matrix(commonPosition));\n } else {\n return RotationResult(false, mat3x3<f32>()); // identity alternative if needed\n };\n}\n\n// Projects a normal vector from the current coordinate system to world space.\nfn project_normal(vector: vec3<f32>) -> vec3<f32> {\n let normal_modelspace = project.modelMatrix * vec4<f32>(vector, 0.0);\n var n = normalize(normal_modelspace.xyz * project.commonUnitsPerMeter);\n let rotResult = project_needs_rotation(geometry.position.xyz);\n if (rotResult.needsRotation) {\n n = rotResult.transform * n;\n }\n return n;\n}\n\n// Applies a scale offset based on y-offset (dy)\nfn project_offset_(offset: vec4<f32>) -> vec4<f32> {\n let dy: f32 = offset.y;\n let commonUnitsPerWorldUnit = project.commonUnitsPerWorldUnit + project.commonUnitsPerWorldUnit2 * dy;\n return vec4<f32>(offset.xyz * commonUnitsPerWorldUnit, offset.w);\n}\n\n// Projects lng/lat coordinates to a unit tile [0,1]\nfn project_mercator_(lnglat: vec2<f32>) -> vec2<f32> {\n var x = lnglat.x;\n if (project.wrapLongitude != 0) {\n x = ((x + 180.0) % 360.0) - 180.0;\n }\n let y = clamp(lnglat.y, -89.9, 89.9);\n return vec2<f32>(\n radians(x) + PI,\n PI + log(tan(PI * 0.25 + radians(y) * 0.5))\n ) * WORLD_SCALE;\n}\n\n// Projects lng/lat/z coordinates for a globe projection.\nfn project_globe_(lnglatz: vec3<f32>) -> vec3<f32> {\n let lambda = radians(lnglatz.x);\n let phi = radians(lnglatz.y);\n let cosPhi = cos(phi);\n let D = (lnglatz.z / EARTH_RADIUS + 1.0) * GLOBE_RADIUS;\n return vec3<f32>(\n sin(lambda) * cosPhi,\n -cos(lambda) * cosPhi,\n sin(phi)\n ) * D;\n}\n\n// Projects positions (with an optional 64-bit low part) from the input\n// coordinate system to the common space.\nfn project_position_vec4_f64(position: vec4<f32>, position64Low: vec3<f32>) -> vec4<f32> {\n var position_world = project.modelMatrix * position;\n\n // Work around for a Mac+NVIDIA bug:\n if (project.projectionMode == PROJECTION_MODE_WEB_MERCATOR) {\n if (project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT) {\n return vec4<f32>(\n project_mercator_(position_world.xy),\n _project_size_at_latitude_m(position_world.z, position_world.y),\n position_world.w\n );\n }\n if (project.coordinateSystem == COORDINATE_SYSTEM_CARTESIAN) {\n position_world = vec4f(position_world.xyz + project.coordinateOrigin, position_world.w);\n }\n }\n if (project.projectionMode == PROJECTION_MODE_GLOBE) {\n if (project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT) {\n return vec4<f32>(\n project_globe_(position_world.xyz),\n position_world.w\n );\n }\n }\n if (project.projectionMode == PROJECTION_MODE_WEB_MERCATOR_AUTO_OFFSET) {\n if (project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT) {\n if (abs(position_world.y - project.coordinateOrigin.y) > 0.25) {\n return vec4<f32>(\n project_mercator_(position_world.xy) - project.commonOrigin.xy,\n project_size_float(position_world.z),\n position_world.w\n );\n }\n }\n }\n if (project.projectionMode == PROJECTION_MODE_IDENTITY ||\n (project.projectionMode == PROJECTION_MODE_WEB_MERCATOR_AUTO_OFFSET &&\n (project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT ||\n project.coordinateSystem == COORDINATE_SYSTEM_CARTESIAN))) {\n position_world = vec4f(position_world.xyz - project.coordinateOrigin, position_world.w);\n }\n\n return project_offset_(position_world) +\n project_offset_(project.modelMatrix * vec4<f32>(position64Low, 0.0));\n}\n\n// Overloaded versions for different input types.\nfn project_position_vec4_f32(position: vec4<f32>) -> vec4<f32> {\n return project_position_vec4_f64(position, ZERO_64_LOW);\n}\n\nfn project_position_vec3_f64(position: vec3<f32>, position64Low: vec3<f32>) -> vec3<f32> {\n let projected_position = project_position_vec4_f64(vec4<f32>(position, 1.0), position64Low);\n return projected_position.xyz;\n}\n\nfn project_position_vec3_f32(position: vec3<f32>) -> vec3<f32>