UNPKG

@deck.gl/core

Version:

deck.gl core library

1,504 lines (1,418 loc) 422 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", { value: true }), mod2); // dist/index.js var dist_exports = {}; __export(dist_exports, { AmbientLight: () => AmbientLight, Attribute: () => Attribute, AttributeManager: () => AttributeManager, COORDINATE_SYSTEM: () => COORDINATE_SYSTEM, CompositeLayer: () => composite_layer_default, Controller: () => Controller, Deck: () => deck_default, DeckRenderer: () => DeckRenderer, DirectionalLight: () => DirectionalLight, FirstPersonController: () => FirstPersonController, FirstPersonView: () => first_person_view_default, FirstPersonViewport: () => FirstPersonViewport, FlyToInterpolator: () => FlyToInterpolator, Layer: () => layer_default, LayerExtension: () => layer_extension_default, LayerManager: () => LayerManager, LightingEffect: () => LightingEffect, LinearInterpolator: () => LinearInterpolator, MapController: () => MapController, MapView: () => map_view_default, OPERATION: () => OPERATION, OrbitController: () => OrbitController, OrbitView: () => orbit_view_default, OrbitViewport: () => OrbitViewport, OrthographicController: () => OrthographicController, OrthographicView: () => orthographic_view_default, OrthographicViewport: () => OrthographicViewport, PointLight: () => PointLight, PostProcessEffect: () => PostProcessEffect, TRANSITION_EVENTS: () => TRANSITION_EVENTS, Tesselator: () => Tesselator, TransitionInterpolator: () => TransitionInterpolator, UNIT: () => UNIT, VERSION: () => VERSION, View: () => View, Viewport: () => viewport_default, WebMercatorViewport: () => web_mercator_viewport_default, Widget: () => Widget, _CameraLight: () => CameraLight, _Component: () => component_default, _ComponentState: () => ComponentState, _GlobeController: () => GlobeController, _GlobeView: () => globe_view_default, _GlobeViewport: () => GlobeViewport, _LayersPass: () => LayersPass, _PickLayersPass: () => PickLayersPass, _SunLight: () => SunLight, _applyStyles: () => applyStyles, _compareProps: () => compareProps, _count: () => count, _deepEqual: () => deepEqual, _fillArray: () => fillArray, _flatten: () => flatten, _memoize: () => memoize, _mergeShaders: () => mergeShaders, _removeStyles: () => removeStyles, assert: () => assert, color: () => color_default, createIterable: () => createIterable, fp64LowPart: () => fp64LowPart, getShaderAssembler: () => getShaderAssembler, gouraudMaterial: () => import_shadertools4.gouraudMaterial, log: () => log_default, phongMaterial: () => import_shadertools4.phongMaterial, picking: () => picking_default, project: () => project_default, project32: () => project32_default, shadow: () => shadow_default }); module.exports = __toCommonJS(dist_exports); // dist/lib/init.js var import_core = require("@loaders.gl/core"); var import_images = require("@loaders.gl/images"); // dist/utils/log.js var import_log = require("@probe.gl/log"); var defaultLogger = new import_log.Log({ id: "deck" }); var log_default = defaultLogger; // dist/debug/loggers.js var logState = { attributeUpdateStart: -1, attributeManagerUpdateStart: -1, attributeUpdateMessages: [] }; var LOG_LEVEL_MAJOR_UPDATE = 1; var LOG_LEVEL_MINOR_UPDATE = 2; var LOG_LEVEL_UPDATE_DETAIL = 3; var LOG_LEVEL_INFO = 4; var LOG_LEVEL_DRAW = 2; var getLoggers = (log) => ({ /* Layer events */ "layer.changeFlag": (layer, key, flags) => { log.log(LOG_LEVEL_UPDATE_DETAIL, `${layer.id} ${key}: `, flags[key])(); }, "layer.initialize": (layer) => { log.log(LOG_LEVEL_MAJOR_UPDATE, `Initializing ${layer}`)(); }, "layer.update": (layer, needsUpdate) => { if (needsUpdate) { const flags = layer.getChangeFlags(); log.log(LOG_LEVEL_MINOR_UPDATE, `Updating ${layer} because: ${Object.keys(flags).filter((key) => flags[key]).join(", ")}`)(); } else { log.log(LOG_LEVEL_INFO, `${layer} does not need update`)(); } }, "layer.matched": (layer, changed) => { if (changed) { log.log(LOG_LEVEL_INFO, `Matched ${layer}, state transfered`)(); } }, "layer.finalize": (layer) => { log.log(LOG_LEVEL_MAJOR_UPDATE, `Finalizing ${layer}`)(); }, /* CompositeLayer events */ "compositeLayer.renderLayers": (layer, updated, subLayers) => { if (updated) { log.log(LOG_LEVEL_MINOR_UPDATE, `Composite layer rendered new subLayers ${layer}`, subLayers)(); } else { log.log(LOG_LEVEL_INFO, `Composite layer reused subLayers ${layer}`, subLayers)(); } }, /* LayerManager events */ "layerManager.setLayers": (layerManager, updated, layers) => { if (updated) { log.log(LOG_LEVEL_MINOR_UPDATE, `Updating ${layers.length} deck layers`)(); } }, "layerManager.activateViewport": (layerManager, viewport) => { log.log(LOG_LEVEL_UPDATE_DETAIL, "Viewport changed", viewport)(); }, /* AttributeManager events */ "attributeManager.invalidate": (attributeManager, trigger, attributeNames) => { log.log(LOG_LEVEL_MAJOR_UPDATE, attributeNames ? `invalidated attributes ${attributeNames} (${trigger}) for ${attributeManager.id}` : `invalidated all attributes for ${attributeManager.id}`)(); }, "attributeManager.updateStart": (attributeManager) => { logState.attributeUpdateMessages.length = 0; logState.attributeManagerUpdateStart = Date.now(); }, "attributeManager.updateEnd": (attributeManager, numInstances) => { const timeMs = Math.round(Date.now() - logState.attributeManagerUpdateStart); log.groupCollapsed(LOG_LEVEL_MINOR_UPDATE, `Updated attributes for ${numInstances} instances in ${attributeManager.id} in ${timeMs}ms`)(); for (const updateMessage of logState.attributeUpdateMessages) { log.log(LOG_LEVEL_UPDATE_DETAIL, updateMessage)(); } log.groupEnd(LOG_LEVEL_MINOR_UPDATE)(); }, /* Attribute events */ "attribute.updateStart": (attribute) => { logState.attributeUpdateStart = Date.now(); }, "attribute.allocate": (attribute, numInstances) => { const message = `${attribute.id} allocated ${numInstances}`; logState.attributeUpdateMessages.push(message); }, "attribute.updateEnd": (attribute, numInstances) => { const timeMs = Math.round(Date.now() - logState.attributeUpdateStart); const message = `${attribute.id} updated ${numInstances} in ${timeMs}ms`; logState.attributeUpdateMessages.push(message); }, /* Render events */ "deckRenderer.renderLayers": (deckRenderer, renderStats, opts) => { const { pass, redrawReason, stats } = opts; for (const status of renderStats) { const { totalCount, visibleCount, compositeCount, pickableCount } = status; const primitiveCount = totalCount - compositeCount; const hiddenCount = primitiveCount - visibleCount; log.log(LOG_LEVEL_DRAW, `RENDER #${deckRenderer.renderCount} ${visibleCount} (of ${totalCount} layers) to ${pass} because ${redrawReason} (${hiddenCount} hidden, ${compositeCount} composite ${pickableCount} pickable)`)(); if (stats) { stats.get("Redraw Layers").add(visibleCount); } } } }); // dist/debug/index.js var loggers = {}; if (true) { loggers = getLoggers(log_default); } function register(handlers) { loggers = handlers; } function debug(eventType, arg1, arg2, arg3) { if (log_default.level > 0 && loggers[eventType]) { loggers[eventType].call(null, arg1, arg2, arg3); } } // dist/utils/json-loader.js function isJSON(text) { const firstChar = text[0]; const lastChar = text[text.length - 1]; return firstChar === "{" && lastChar === "}" || firstChar === "[" && lastChar === "]"; } var json_loader_default = { dataType: null, batchType: null, id: "JSON", name: "JSON", module: "", version: "", options: {}, extensions: ["json", "geojson"], mimeTypes: ["application/json", "application/geo+json"], testText: isJSON, parseTextSync: JSON.parse }; // dist/lib/init.js function checkVersion() { const version = true ? "9.2.2" : globalThis.DECK_VERSION || "untranspiled source"; const existingVersion = globalThis.deck && globalThis.deck.VERSION; if (existingVersion && existingVersion !== version) { throw new Error(`deck.gl - multiple versions detected: ${existingVersion} vs ${version}`); } if (!existingVersion) { log_default.log(1, `deck.gl ${version}`)(); globalThis.deck = { ...globalThis.deck, VERSION: version, version, log: log_default, // experimental _registerLoggers: register }; (0, import_core.registerLoaders)([ json_loader_default, // @ts-expect-error non-standard Loader format [import_images.ImageLoader, { imagebitmap: { premultiplyAlpha: "none" } }] ]); } return version; } var VERSION = checkVersion(); // dist/shaderlib/index.js var import_shadertools3 = require("@luma.gl/shadertools"); var import_shadertools4 = require("@luma.gl/shadertools"); // dist/shaderlib/misc/layer-uniforms.js var uniformBlock = `uniform layerUniforms { uniform float opacity; } layer; `; var layerUniforms = { name: "layer", vs: uniformBlock, fs: uniformBlock, getUniforms: (props) => { return { // apply gamma to opacity to make it visually "linear" // TODO - v10: use raw opacity? opacity: Math.pow(props.opacity, 1 / 2.2) }; }, uniformTypes: { opacity: "f32" } }; // dist/shaderlib/color/color.js var colorWGSL = ( /* WGSL */ ` struct ColorUniforms { opacity: f32, }; var<private> color: ColorUniforms = ColorUniforms(1.0); // TODO (kaapp) avoiding binding index collisions to handle layer opacity // requires some thought. // @group(0) @binding(0) var<uniform> color: ColorUniforms; @must_use fn deckgl_premultiplied_alpha(fragColor: vec4<f32>) -> vec4<f32> { return vec4(fragColor.rgb * fragColor.a, fragColor.a); }; ` ); var color_default = { name: "color", dependencies: [], source: colorWGSL, getUniforms: (_props) => { return {}; }, uniformTypes: { opacity: "f32" } // @ts-ignore TODO v9.1 }; // dist/shaderlib/misc/geometry.js var source = ( /* wgsl */ `const SMOOTH_EDGE_RADIUS: f32 = 0.5; struct VertexGeometry { position: vec4<f32>, worldPosition: vec3<f32>, worldPositionAlt: vec3<f32>, normal: vec3<f32>, uv: vec2<f32>, pickingColor: vec3<f32>, }; var<private> geometry_: VertexGeometry = VertexGeometry( vec4<f32>(0.0, 0.0, 1.0, 0.0), vec3<f32>(0.0, 0.0, 0.0), vec3<f32>(0.0, 0.0, 0.0), vec3<f32>(0.0, 0.0, 0.0), vec2<f32>(0.0, 0.0), vec3<f32>(0.0, 0.0, 0.0) ); struct FragmentGeometry { uv: vec2<f32>, }; var<private> fragmentGeometry: FragmentGeometry; fn smoothedge(edge: f32, x: f32) -> f32 { return smoothstep(edge - SMOOTH_EDGE_RADIUS, edge + SMOOTH_EDGE_RADIUS, x); } ` ); var defines = "#define SMOOTH_EDGE_RADIUS 0.5"; var vs = ( /* glsl */ `${defines} struct VertexGeometry { vec4 position; vec3 worldPosition; vec3 worldPositionAlt; vec3 normal; vec2 uv; vec3 pickingColor; } geometry = VertexGeometry( vec4(0.0, 0.0, 1.0, 0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec2(0.0), vec3(0.0) ); ` ); var fs = ( /* glsl */ `${defines} struct FragmentGeometry { vec2 uv; } geometry; float smoothedge(float edge, float x) { return smoothstep(edge - SMOOTH_EDGE_RADIUS, edge + SMOOTH_EDGE_RADIUS, x); } ` ); var geometry_default = { name: "geometry", source, vs, fs }; // dist/shaderlib/project/project.js var import_shadertools = require("@luma.gl/shadertools"); // dist/shaderlib/project/viewport-uniforms.js var import_core2 = require("@math.gl/core"); // dist/lib/constants.js var import_mjolnir = require("mjolnir.js"); var COORDINATE_SYSTEM = { /** * `LNGLAT` if rendering into a geospatial viewport, `CARTESIAN` otherwise */ DEFAULT: -1, /** * Positions are interpreted as [longitude, latitude, elevation] * longitude/latitude are in degrees, elevation is in meters. * Dimensions are in meters. */ LNGLAT: 1, /** * Positions are interpreted as [x, y, z] in meter offsets from the coordinate origin. * Dimensions are in meters. */ METER_OFFSETS: 2, /** * Positions are interpreted as [deltaLng, deltaLat, elevation] from the coordinate origin. * deltaLng/deltaLat are in degrees, elevation is in meters. * Dimensions are in meters. */ LNGLAT_OFFSETS: 3, /** * Positions and dimensions are in the common units of the viewport. */ CARTESIAN: 0 }; Object.defineProperty(COORDINATE_SYSTEM, "IDENTITY", { get: () => { log_default.deprecated("COORDINATE_SYSTEM.IDENTITY", "COORDINATE_SYSTEM.CARTESIAN")(); return 0; } }); var PROJECTION_MODE = { /** * Render geospatial data in Web Mercator projection */ WEB_MERCATOR: 1, /** * Render geospatial data as a 3D globe */ GLOBE: 2, /** * (Internal use only) Web Mercator projection at high zoom */ WEB_MERCATOR_AUTO_OFFSET: 4, /** * No transformation */ IDENTITY: 0 }; var UNIT = { common: 0, meters: 1, pixels: 2 }; var EVENT_HANDLERS = { click: "onClick", dblclick: "onClick", panstart: "onDragStart", panmove: "onDrag", panend: "onDragEnd" }; var RECOGNIZERS = { multipan: [import_mjolnir.Pan, { threshold: 10, direction: import_mjolnir.InputDirection.Vertical, pointers: 2 }], pinch: [import_mjolnir.Pinch, {}, null, ["multipan"]], pan: [import_mjolnir.Pan, { threshold: 1 }, ["pinch"], ["multipan"]], dblclick: [import_mjolnir.Tap, { event: "dblclick", taps: 2 }], click: [import_mjolnir.Tap, { event: "click" }, null, ["dblclick"]] }; var OPERATION = { DRAW: "draw", MASK: "mask", TERRAIN: "terrain" }; // dist/utils/memoize.js function isEqual(a, b) { if (a === b) { return true; } if (Array.isArray(a)) { const len = a.length; if (!b || b.length !== len) { return false; } for (let i = 0; i < len; i++) { if (a[i] !== b[i]) { return false; } } return true; } return false; } function memoize(compute) { let cachedArgs = {}; let cachedResult; return (args) => { for (const key in args) { if (!isEqual(args[key], cachedArgs[key])) { cachedResult = compute(args); cachedArgs = args; break; } } return cachedResult; }; } // dist/shaderlib/project/viewport-uniforms.js var ZERO_VECTOR = [0, 0, 0, 0]; var VECTOR_TO_POINT_MATRIX = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]; var IDENTITY_MATRIX = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; var DEFAULT_PIXELS_PER_UNIT2 = [0, 0, 0]; var DEFAULT_COORDINATE_ORIGIN = [0, 0, 0]; var getMemoizedViewportUniforms = memoize(calculateViewportUniforms); function getOffsetOrigin(viewport, coordinateSystem, coordinateOrigin = DEFAULT_COORDINATE_ORIGIN) { if (coordinateOrigin.length < 3) { coordinateOrigin = [coordinateOrigin[0], coordinateOrigin[1], 0]; } let shaderCoordinateOrigin = coordinateOrigin; let geospatialOrigin; let offsetMode = true; if (coordinateSystem === COORDINATE_SYSTEM.LNGLAT_OFFSETS || coordinateSystem === COORDINATE_SYSTEM.METER_OFFSETS) { geospatialOrigin = coordinateOrigin; } else { geospatialOrigin = viewport.isGeospatial ? ( // @ts-expect-error longitude and latitude are not defined on the base Viewport, but is expected on geospatial viewports [Math.fround(viewport.longitude), Math.fround(viewport.latitude), 0] ) : null; } switch (viewport.projectionMode) { case PROJECTION_MODE.WEB_MERCATOR: if (coordinateSystem === COORDINATE_SYSTEM.LNGLAT || coordinateSystem === COORDINATE_SYSTEM.CARTESIAN) { geospatialOrigin = [0, 0, 0]; offsetMode = false; } break; case PROJECTION_MODE.WEB_MERCATOR_AUTO_OFFSET: if (coordinateSystem === COORDINATE_SYSTEM.LNGLAT) { shaderCoordinateOrigin = geospatialOrigin; } else if (coordinateSystem === COORDINATE_SYSTEM.CARTESIAN) { shaderCoordinateOrigin = [ Math.fround(viewport.center[0]), Math.fround(viewport.center[1]), 0 ]; geospatialOrigin = viewport.unprojectPosition(shaderCoordinateOrigin); shaderCoordinateOrigin[0] -= coordinateOrigin[0]; shaderCoordinateOrigin[1] -= coordinateOrigin[1]; shaderCoordinateOrigin[2] -= coordinateOrigin[2]; } break; case PROJECTION_MODE.IDENTITY: shaderCoordinateOrigin = viewport.position.map(Math.fround); shaderCoordinateOrigin[2] = shaderCoordinateOrigin[2] || 0; break; case PROJECTION_MODE.GLOBE: offsetMode = false; geospatialOrigin = null; break; default: offsetMode = false; } return { geospatialOrigin, shaderCoordinateOrigin, offsetMode }; } function calculateMatrixAndOffset(viewport, coordinateSystem, coordinateOrigin) { const { viewMatrixUncentered, projectionMatrix } = viewport; let { viewMatrix: viewMatrix2, viewProjectionMatrix } = viewport; let projectionCenter = ZERO_VECTOR; let originCommon = ZERO_VECTOR; let cameraPosCommon = viewport.cameraPosition; const { geospatialOrigin, shaderCoordinateOrigin, offsetMode } = getOffsetOrigin(viewport, coordinateSystem, coordinateOrigin); if (offsetMode) { originCommon = viewport.projectPosition(geospatialOrigin || shaderCoordinateOrigin); cameraPosCommon = [ cameraPosCommon[0] - originCommon[0], cameraPosCommon[1] - originCommon[1], cameraPosCommon[2] - originCommon[2] ]; originCommon[3] = 1; projectionCenter = import_core2.vec4.transformMat4([], originCommon, viewProjectionMatrix); viewMatrix2 = viewMatrixUncentered || viewMatrix2; viewProjectionMatrix = import_core2.mat4.multiply([], projectionMatrix, viewMatrix2); viewProjectionMatrix = import_core2.mat4.multiply([], viewProjectionMatrix, VECTOR_TO_POINT_MATRIX); } return { viewMatrix: viewMatrix2, viewProjectionMatrix, projectionCenter, originCommon, cameraPosCommon, shaderCoordinateOrigin, geospatialOrigin }; } function getUniformsFromViewport({ viewport, devicePixelRatio = 1, modelMatrix = null, // Match Layer.defaultProps coordinateSystem = COORDINATE_SYSTEM.DEFAULT, coordinateOrigin = DEFAULT_COORDINATE_ORIGIN, autoWrapLongitude = false }) { if (coordinateSystem === COORDINATE_SYSTEM.DEFAULT) { coordinateSystem = viewport.isGeospatial ? COORDINATE_SYSTEM.LNGLAT : COORDINATE_SYSTEM.CARTESIAN; } const uniforms = getMemoizedViewportUniforms({ viewport, devicePixelRatio, coordinateSystem, coordinateOrigin }); uniforms.wrapLongitude = autoWrapLongitude; uniforms.modelMatrix = modelMatrix || IDENTITY_MATRIX; return uniforms; } function calculateViewportUniforms({ viewport, devicePixelRatio, coordinateSystem, coordinateOrigin }) { const { projectionCenter, viewProjectionMatrix, originCommon, cameraPosCommon, shaderCoordinateOrigin, geospatialOrigin } = calculateMatrixAndOffset(viewport, coordinateSystem, coordinateOrigin); const distanceScales = viewport.getDistanceScales(); const viewportSize = [ viewport.width * devicePixelRatio, viewport.height * devicePixelRatio ]; const focalDistance = import_core2.vec4.transformMat4([], [0, 0, -viewport.focalDistance, 1], viewport.projectionMatrix)[3] || 1; const uniforms = { // Projection mode values coordinateSystem, projectionMode: viewport.projectionMode, coordinateOrigin: shaderCoordinateOrigin, commonOrigin: originCommon.slice(0, 3), center: projectionCenter, // Backward compatibility // TODO: remove in v9 // @ts-expect-error _pseudoMeters is only defined on WebMercator viewport pseudoMeters: Boolean(viewport._pseudoMeters), // Screen size viewportSize, devicePixelRatio, focalDistance, commonUnitsPerMeter: distanceScales.unitsPerMeter, commonUnitsPerWorldUnit: distanceScales.unitsPerMeter, commonUnitsPerWorldUnit2: DEFAULT_PIXELS_PER_UNIT2, scale: viewport.scale, // This is the mercator scale (2 ** zoom) wrapLongitude: false, viewProjectionMatrix, modelMatrix: IDENTITY_MATRIX, // This is for lighting calculations cameraPosition: cameraPosCommon }; if (geospatialOrigin) { const distanceScalesAtOrigin = viewport.getDistanceScales(geospatialOrigin); switch (coordinateSystem) { case COORDINATE_SYSTEM.METER_OFFSETS: uniforms.commonUnitsPerWorldUnit = distanceScalesAtOrigin.unitsPerMeter; uniforms.commonUnitsPerWorldUnit2 = distanceScalesAtOrigin.unitsPerMeter2; break; case COORDINATE_SYSTEM.LNGLAT: case COORDINATE_SYSTEM.LNGLAT_OFFSETS: if (!viewport._pseudoMeters) { uniforms.commonUnitsPerMeter = distanceScalesAtOrigin.unitsPerMeter; } uniforms.commonUnitsPerWorldUnit = distanceScalesAtOrigin.unitsPerDegree; uniforms.commonUnitsPerWorldUnit2 = distanceScalesAtOrigin.unitsPerDegree2; break; case COORDINATE_SYSTEM.CARTESIAN: uniforms.commonUnitsPerWorldUnit = [1, 1, distanceScalesAtOrigin.unitsPerMeter[2]]; uniforms.commonUnitsPerWorldUnit2 = [0, 0, distanceScalesAtOrigin.unitsPerMeter2[2]]; break; default: break; } } return uniforms; } // dist/shaderlib/project/project.wgsl.js var COORDINATE_SYSTEM_WGSL_CONSTANTS = Object.keys(COORDINATE_SYSTEM).map((key) => `const COORDINATE_SYSTEM_${key}: i32 = ${COORDINATE_SYSTEM[key]};`).join(""); var PROJECTION_MODE_WGSL_CONSTANTS = Object.keys(PROJECTION_MODE).map((key) => `const PROJECTION_MODE_${key}: i32 = ${PROJECTION_MODE[key]};`).join(""); var UNIT_WGSL_CONSTANTS = Object.keys(UNIT).map((key) => `const UNIT_${key.toUpperCase()}: i32 = ${UNIT[key]};`).join(""); var projectWGSLHeader = ( /* wgsl */ `${COORDINATE_SYSTEM_WGSL_CONSTANTS} ${PROJECTION_MODE_WGSL_CONSTANTS} ${UNIT_WGSL_CONSTANTS} const TILE_SIZE: f32 = 512.0; const PI: f32 = 3.1415926536; const WORLD_SCALE: f32 = TILE_SIZE / (PI * 2.0); const ZERO_64_LOW: vec3<f32> = vec3<f32>(0.0, 0.0, 0.0); const EARTH_RADIUS: f32 = 6370972.0; // meters const GLOBE_RADIUS: f32 = 256.0; // ----------------------------------------------------------------------------- // Uniform block (converted from GLSL uniform block) // ----------------------------------------------------------------------------- struct ProjectUniforms { wrapLongitude: i32, coordinateSystem: i32, commonUnitsPerMeter: vec3<f32>, projectionMode: i32, scale: f32, commonUnitsPerWorldUnit: vec3<f32>, commonUnitsPerWorldUnit2: vec3<f32>, center: vec4<f32>, modelMatrix: mat4x4<f32>, viewProjectionMatrix: mat4x4<f32>, viewportSize: vec2<f32>, devicePixelRatio: f32, focalDistance: f32, cameraPosition: vec3<f32>, coordinateOrigin: vec3<f32>, commonOrigin: vec3<f32>, pseudoMeters: i32, }; @group(0) @binding(0) var<uniform> project: ProjectUniforms; // ----------------------------------------------------------------------------- // Geometry data // (In your GLSL code, "geometry" was assumed to be available globally. In WGSL, // you might supply this via vertex attributes or a uniform. Here we define a // uniform struct for demonstration.) // ----------------------------------------------------------------------------- // Structure to carry additional geometry data used by deck.gl filters. struct Geometry { worldPosition: vec3<f32>, worldPositionAlt: vec3<f32>, position: vec4<f32>, normal: vec3<f32>, uv: vec2<f32>, pickingColor: vec3<f32>, }; // @group(0) @binding(1) var<private> geometry: Geometry; ` ); var projectWGSL = ( /* wgsl */ `${projectWGSLHeader} // ----------------------------------------------------------------------------- // Functions // ----------------------------------------------------------------------------- // Returns an adjustment factor for commonUnitsPerMeter fn _project_size_at_latitude(lat: f32) -> f32 { let y = clamp(lat, -89.9, 89.9); return 1.0 / cos(radians(y)); } // Overloaded version: scales a value in meters at a given latitude. fn _project_size_at_latitude_m(meters: f32, lat: f32) -> f32 { return meters * project.commonUnitsPerMeter.z * _project_size_at_latitude(lat); } // Computes a non-linear scale factor based on geometry. // (Note: This function relies on "geometry" being provided.) fn project_size() -> f32 { if (project.projectionMode == PROJECTION_MODE_WEB_MERCATOR && project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT && project.pseudoMeters == 0) { if (geometry.position.w == 0.0) { return _project_size_at_latitude(geometry.worldPosition.y); } let y: f32 = geometry.position.y / TILE_SIZE * 2.0 - 1.0; let y2 = y * y; let y4 = y2 * y2; let y6 = y4 * y2; return 1.0 + 4.9348 * y2 + 4.0587 * y4 + 1.5642 * y6; } return 1.0; } // Overloads to scale offsets (meters to world units) fn project_size_float(meters: f32) -> f32 { return meters * project.commonUnitsPerMeter.z * project_size(); } fn project_size_vec2(meters: vec2<f32>) -> vec2<f32> { return meters * project.commonUnitsPerMeter.xy * project_size(); } fn project_size_vec3(meters: vec3<f32>) -> vec3<f32> { return meters * project.commonUnitsPerMeter * project_size(); } fn project_size_vec4(meters: vec4<f32>) -> vec4<f32> { return vec4<f32>(meters.xyz * project.commonUnitsPerMeter, meters.w); } // Returns a rotation matrix aligning the z\u2011axis with the given up vector. fn project_get_orientation_matrix(up: vec3<f32>) -> mat3x3<f32> { let uz = normalize(up); let ux = select( vec3<f32>(1.0, 0.0, 0.0), normalize(vec3<f32>(uz.y, -uz.x, 0.0)), abs(uz.z) == 1.0 ); let uy = cross(uz, ux); return mat3x3<f32>(ux, uy, uz); } // Since WGSL does not support "out" parameters, we return a struct. struct RotationResult { needsRotation: bool, transform: mat3x3<f32>, }; fn project_needs_rotation(commonPosition: vec3<f32>) -> RotationResult { if (project.projectionMode == PROJECTION_MODE_GLOBE) { return RotationResult(true, project_get_orientation_matrix(commonPosition)); } else { return RotationResult(false, mat3x3<f32>()); // identity alternative if needed }; } // Projects a normal vector from the current coordinate system to world space. fn project_normal(vector: vec3<f32>) -> vec3<f32> { let normal_modelspace = project.modelMatrix * vec4<f32>(vector, 0.0); var n = normalize(normal_modelspace.xyz * project.commonUnitsPerMeter); let rotResult = project_needs_rotation(geometry.position.xyz); if (rotResult.needsRotation) { n = rotResult.transform * n; } return n; } // Applies a scale offset based on y-offset (dy) fn project_offset_(offset: vec4<f32>) -> vec4<f32> { let dy: f32 = offset.y; let commonUnitsPerWorldUnit = project.commonUnitsPerWorldUnit + project.commonUnitsPerWorldUnit2 * dy; return vec4<f32>(offset.xyz * commonUnitsPerWorldUnit, offset.w); } // Projects lng/lat coordinates to a unit tile [0,1] fn project_mercator_(lnglat: vec2<f32>) -> vec2<f32> { var x = lnglat.x; if (project.wrapLongitude != 0) { x = ((x + 180.0) % 360.0) - 180.0; } let y = clamp(lnglat.y, -89.9, 89.9); return vec2<f32>( radians(x) + PI, PI + log(tan(PI * 0.25 + radians(y) * 0.5)) ) * WORLD_SCALE; } // Projects lng/lat/z coordinates for a globe projection. fn project_globe_(lnglatz: vec3<f32>) -> vec3<f32> { let lambda = radians(lnglatz.x); let phi = radians(lnglatz.y); let cosPhi = cos(phi); let D = (lnglatz.z / EARTH_RADIUS + 1.0) * GLOBE_RADIUS; return vec3<f32>( sin(lambda) * cosPhi, -cos(lambda) * cosPhi, sin(phi) ) * D; } // Projects positions (with an optional 64-bit low part) from the input // coordinate system to the common space. fn project_position_vec4_f64(position: vec4<f32>, position64Low: vec3<f32>) -> vec4<f32> { var position_world = project.modelMatrix * position; // Work around for a Mac+NVIDIA bug: if (project.projectionMode == PROJECTION_MODE_WEB_MERCATOR) { if (project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT) { return vec4<f32>( project_mercator_(position_world.xy), _project_size_at_latitude_m(position_world.z, position_world.y), position_world.w ); } if (project.coordinateSystem == COORDINATE_SYSTEM_CARTESIAN) { position_world = vec4f(position_world.xyz + project.coordinateOrigin, position_world.w); } } if (project.projectionMode == PROJECTION_MODE_GLOBE) { if (project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT) { return vec4<f32>( project_globe_(position_world.xyz), position_world.w ); } } if (project.projectionMode == PROJECTION_MODE_WEB_MERCATOR_AUTO_OFFSET) { if (project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT) { if (abs(position_world.y - project.coordinateOrigin.y) > 0.25) { return vec4<f32>( project_mercator_(position_world.xy) - project.commonOrigin.xy, project_size_float(position_world.z), position_world.w ); } } } if (project.projectionMode == PROJECTION_MODE_IDENTITY || (project.projectionMode == PROJECTION_MODE_WEB_MERCATOR_AUTO_OFFSET && (project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT || project.coordinateSystem == COORDINATE_SYSTEM_CARTESIAN))) { position_world = vec4f(position_world.xyz - project.coordinateOrigin, position_world.w); } return project_offset_(position_world) + project_offset_(project.modelMatrix * vec4<f32>(position64Low, 0.0)); } // Overloaded versions for different input types. fn project_position_vec4_f32(position: vec4<f32>) -> vec4<f32> { return project_position_vec4_f64(position, ZERO_64_LOW); } fn project_position_vec3_f64(position: vec3<f32>, position64Low: vec3<f32>) -> vec3<f32> { let projected_position = project_position_vec4_f64(vec4<f32>(position, 1.0), position64Low); return projected_position.xyz; } fn project_position_vec3_f32(position: vec3<f32>) -> vec3<f32> { let projected_position = project_position_vec4_f64(vec4<f32>(position, 1.0), ZERO_64_LOW); return projected_position.xyz; } fn project_position_vec2_f32(position: vec2<f32>) -> vec2<f32> { let projected_position = project_position_vec4_f64(vec4<f32>(position, 0.0, 1.0), ZERO_64_LOW); return projected_position.xy; } // Transforms a common space position to clip space. fn project_common_position_to_clipspace_with_projection(position: vec4<f32>, viewProjectionMatrix: mat4x4<f32>, center: vec4<f32>) -> vec4<f32> { return viewProjectionMatrix * position + center; } // Uses the project viewProjectionMatrix and center. fn project_common_position_to_clipspace(position: vec4<f32>) -> vec4<f32> { return project_common_position_to_clipspace_with_projection(position, project.viewProjectionMatrix, project.center); } // Returns a clip space offset corresponding to a given number of screen pixels. fn project_pixel_size_to_clipspace(pixels: vec2<f32>) -> vec2<f32> { let offset = pixels / project.viewportSize * project.devicePixelRatio * 2.0; return offset * project.focalDistance; } fn project_meter_size_to_pixel(meters: f32) -> f32 { return project_size_float(meters) * project.scale; } fn project_unit_size_to_pixel(size: f32, unit: i32) -> f32 { if (unit == UNIT_METERS) { return project_meter_size_to_pixel(size); } else if (unit == UNIT_COMMON) { return size * project.scale; } // UNIT_PIXELS: no scaling applied. return size; } fn project_pixel_size_float(pixels: f32) -> f32 { return pixels / project.scale; } fn project_pixel_size_vec2(pixels: vec2<f32>) -> vec2<f32> { return pixels / project.scale; } ` ); // dist/shaderlib/project/project.glsl.js var COORDINATE_SYSTEM_GLSL_CONSTANTS = Object.keys(COORDINATE_SYSTEM).map((key) => `const int COORDINATE_SYSTEM_${key} = ${COORDINATE_SYSTEM[key]};`).join(""); var PROJECTION_MODE_GLSL_CONSTANTS = Object.keys(PROJECTION_MODE).map((key) => `const int PROJECTION_MODE_${key} = ${PROJECTION_MODE[key]};`).join(""); var UNIT_GLSL_CONSTANTS = Object.keys(UNIT).map((key) => `const int UNIT_${key.toUpperCase()} = ${UNIT[key]};`).join(""); var projectGLSL = ( /* glsl */ `${COORDINATE_SYSTEM_GLSL_CONSTANTS} ${PROJECTION_MODE_GLSL_CONSTANTS} ${UNIT_GLSL_CONSTANTS} uniform projectUniforms { bool wrapLongitude; int coordinateSystem; vec3 commonUnitsPerMeter; int projectionMode; float scale; vec3 commonUnitsPerWorldUnit; vec3 commonUnitsPerWorldUnit2; vec4 center; mat4 modelMatrix; mat4 viewProjectionMatrix; vec2 viewportSize; float devicePixelRatio; float focalDistance; vec3 cameraPosition; vec3 coordinateOrigin; vec3 commonOrigin; bool pseudoMeters; } project; const float TILE_SIZE = 512.0; const float PI = 3.1415926536; const float WORLD_SCALE = TILE_SIZE / (PI * 2.0); const vec3 ZERO_64_LOW = vec3(0.0); const float EARTH_RADIUS = 6370972.0; const float GLOBE_RADIUS = 256.0; float project_size_at_latitude(float lat) { float y = clamp(lat, -89.9, 89.9); return 1.0 / cos(radians(y)); } float project_size() { if (project.projectionMode == PROJECTION_MODE_WEB_MERCATOR && project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT && project.pseudoMeters == false) { if (geometry.position.w == 0.0) { return project_size_at_latitude(geometry.worldPosition.y); } float y = geometry.position.y / TILE_SIZE * 2.0 - 1.0; float y2 = y * y; float y4 = y2 * y2; float y6 = y4 * y2; return 1.0 + 4.9348 * y2 + 4.0587 * y4 + 1.5642 * y6; } return 1.0; } float project_size_at_latitude(float meters, float lat) { return meters * project.commonUnitsPerMeter.z * project_size_at_latitude(lat); } float project_size(float meters) { return meters * project.commonUnitsPerMeter.z * project_size(); } vec2 project_size(vec2 meters) { return meters * project.commonUnitsPerMeter.xy * project_size(); } vec3 project_size(vec3 meters) { return meters * project.commonUnitsPerMeter * project_size(); } vec4 project_size(vec4 meters) { return vec4(meters.xyz * project.commonUnitsPerMeter, meters.w); } mat3 project_get_orientation_matrix(vec3 up) { vec3 uz = normalize(up); vec3 ux = abs(uz.z) == 1.0 ? vec3(1.0, 0.0, 0.0) : normalize(vec3(uz.y, -uz.x, 0)); vec3 uy = cross(uz, ux); return mat3(ux, uy, uz); } bool project_needs_rotation(vec3 commonPosition, out mat3 transform) { if (project.projectionMode == PROJECTION_MODE_GLOBE) { transform = project_get_orientation_matrix(commonPosition); return true; } return false; } vec3 project_normal(vec3 vector) { vec4 normal_modelspace = project.modelMatrix * vec4(vector, 0.0); vec3 n = normalize(normal_modelspace.xyz * project.commonUnitsPerMeter); mat3 rotation; if (project_needs_rotation(geometry.position.xyz, rotation)) { n = rotation * n; } return n; } vec4 project_offset_(vec4 offset) { float dy = offset.y; vec3 commonUnitsPerWorldUnit = project.commonUnitsPerWorldUnit + project.commonUnitsPerWorldUnit2 * dy; return vec4(offset.xyz * commonUnitsPerWorldUnit, offset.w); } vec2 project_mercator_(vec2 lnglat) { float x = lnglat.x; if (project.wrapLongitude) { x = mod(x + 180., 360.0) - 180.; } float y = clamp(lnglat.y, -89.9, 89.9); return vec2( radians(x) + PI, PI + log(tan_fp32(PI * 0.25 + radians(y) * 0.5)) ) * WORLD_SCALE; } vec3 project_globe_(vec3 lnglatz) { float lambda = radians(lnglatz.x); float phi = radians(lnglatz.y); float cosPhi = cos(phi); float D = (lnglatz.z / EARTH_RADIUS + 1.0) * GLOBE_RADIUS; return vec3( sin(lambda) * cosPhi, -cos(lambda) * cosPhi, sin(phi) ) * D; } vec4 project_position(vec4 position, vec3 position64Low) { vec4 position_world = project.modelMatrix * position; if (project.projectionMode == PROJECTION_MODE_WEB_MERCATOR) { if (project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT) { return vec4( project_mercator_(position_world.xy), project_size_at_latitude(position_world.z, position_world.y), position_world.w ); } if (project.coordinateSystem == COORDINATE_SYSTEM_CARTESIAN) { position_world.xyz += project.coordinateOrigin; } } if (project.projectionMode == PROJECTION_MODE_GLOBE) { if (project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT) { return vec4( project_globe_(position_world.xyz), position_world.w ); } } if (project.projectionMode == PROJECTION_MODE_WEB_MERCATOR_AUTO_OFFSET) { if (project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT) { if (abs(position_world.y - project.coordinateOrigin.y) > 0.25) { return vec4( project_mercator_(position_world.xy) - project.commonOrigin.xy, project_size(position_world.z), position_world.w ); } } } if (project.projectionMode == PROJECTION_MODE_IDENTITY || (project.projectionMode == PROJECTION_MODE_WEB_MERCATOR_AUTO_OFFSET && (project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT || project.coordinateSystem == COORDINATE_SYSTEM_CARTESIAN))) { position_world.xyz -= project.coordinateOrigin; } return project_offset_(position_world) + project_offset_(project.modelMatrix * vec4(position64Low, 0.0)); } vec4 project_position(vec4 position) { return project_position(position, ZERO_64_LOW); } vec3 project_position(vec3 position, vec3 position64Low) { vec4 projected_position = project_position(vec4(position, 1.0), position64Low); return projected_position.xyz; } vec3 project_position(vec3 position) { vec4 projected_position = project_position(vec4(position, 1.0), ZERO_64_LOW); return projected_position.xyz; } vec2 project_position(vec2 position) { vec4 projected_position = project_position(vec4(position, 0.0, 1.0), ZERO_64_LOW); return projected_position.xy; } vec4 project_common_position_to_clipspace(vec4 position, mat4 viewProjectionMatrix, vec4 center) { return viewProjectionMatrix * position + center; } vec4 project_common_position_to_clipspace(vec4 position) { return project_common_position_to_clipspace(position, project.viewProjectionMatrix, project.center); } vec2 project_pixel_size_to_clipspace(vec2 pixels) { vec2 offset = pixels / project.viewportSize * project.devicePixelRatio * 2.0; return offset * project.focalDistance; } float project_size_to_pixel(float meters) { return project_size(meters) * project.scale; } float project_size_to_pixel(float size, int unit) { if (unit == UNIT_METERS) return project_size_to_pixel(size); if (unit == UNIT_COMMON) return size * project.scale; return size; } float project_pixel_size(float pixels) { return pixels / project.scale; } vec2 project_pixel_size(vec2 pixels) { return pixels / project.scale; } ` ); // dist/shaderlib/project/project.js var INITIAL_MODULE_OPTIONS = {}; function getUniforms(opts = INITIAL_MODULE_OPTIONS) { if ("viewport" in opts) { return getUniformsFromViewport(opts); } return {}; } var project_default = { name: "project", dependencies: [import_shadertools.fp32, geometry_default], source: projectWGSL, vs: projectGLSL, getUniforms, uniformTypes: { wrapLongitude: "f32", coordinateSystem: "i32", commonUnitsPerMeter: "vec3<f32>", projectionMode: "i32", scale: "f32", commonUnitsPerWorldUnit: "vec3<f32>", commonUnitsPerWorldUnit2: "vec3<f32>", center: "vec4<f32>", modelMatrix: "mat4x4<f32>", viewProjectionMatrix: "mat4x4<f32>", viewportSize: "vec2<f32>", devicePixelRatio: "f32", focalDistance: "f32", cameraPosition: "vec3<f32>", coordinateOrigin: "vec3<f32>", commonOrigin: "vec3<f32>", pseudoMeters: "f32" } // @ts-ignore TODO v9.1 }; // dist/shaderlib/project32/project32.js var source2 = ( /* wgsl */ `// Define a structure to hold both the clip-space position and the common position. struct ProjectResult { clipPosition: vec4<f32>, commonPosition: vec4<f32>, }; // This function mimics the GLSL version with the 'out' parameter by returning both values. fn project_position_to_clipspace_and_commonspace( position: vec3<f32>, position64Low: vec3<f32>, offset: vec3<f32> ) -> ProjectResult { // Compute the projected position. let projectedPosition: vec3<f32> = project_position_vec3_f64(position, position64Low); // Start with the provided offset. var finalOffset: vec3<f32> = offset; // Get whether a rotation is needed and the rotation matrix. let rotationResult = project_needs_rotation(projectedPosition); // If rotation is needed, update the offset. if (rotationResult.needsRotation) { finalOffset = rotationResult.transform * offset; } // Compute the common position. let commonPosition: vec4<f32> = vec4<f32>(projectedPosition + finalOffset, 1.0); // Convert to clip-space. let clipPosition: vec4<f32> = project_common_position_to_clipspace(commonPosition); return ProjectResult(clipPosition, commonPosition); } // A convenience overload that returns only the clip-space position. fn project_position_to_clipspace( position: vec3<f32>, position64Low: vec3<f32>, offset: vec3<f32> ) -> vec4<f32> { return project_position_to_clipspace_and_commonspace(position, position64Low, offset).clipPosition; } ` ); var vs2 = ( /* glsl */ `vec4 project_position_to_clipspace( vec3 position, vec3 position64Low, vec3 offset, out vec4 commonPosition ) { vec3 projectedPosition = project_position(position, position64Low); mat3 rotation; if (project_needs_rotation(projectedPosition, rotation)) { // offset is specified as ENU // when in globe projection, rotate offset so that the ground alighs with the surface of the globe offset = rotation * offset; } commonPosition = vec4(projectedPosition + offset, 1.0); return project_common_position_to_clipspace(commonPosition); } vec4 project_position_to_clipspace( vec3 position, vec3 position64Low, vec3 offset ) { vec4 commonPosition; return project_position_to_clipspace(position, position64Low, offset, commonPosition); } ` ); var project32_default = { name: "project32", dependencies: [project_default], source: source2, vs: vs2 }; // dist/shaderlib/shadow/shadow.js var import_core3 = require("@math.gl/core"); var import_web_mercator = require("@math.gl/web-mercator"); var uniformBlock2 = ( /* glsl */ ` uniform shadowUniforms { bool drawShadowMap; bool useShadowMap; vec4 color; highp int lightId; float lightCount; mat4 viewProjectionMatrix0; mat4 viewProjectionMatrix1; vec4 projectCenter0; vec4 projectCenter1; } shadow; ` ); var vertex = ( /* glsl */ ` const int max_lights = 2; out vec3 shadow_vPosition[max_lights]; vec4 shadow_setVertexPosition(vec4 position_commonspace) { mat4 viewProjectionMatrices[max_lights]; viewProjectionMatrices[0] = shadow.viewProjectionMatrix0; viewProjectionMatrices[1] = shadow.viewProjectionMatrix1; vec4 projectCenters[max_lights]; projectCenters[0] = shadow.projectCenter0; projectCenters[1] = shadow.projectCenter1; if (shadow.drawShadowMap) { return project_common_position_to_clipspace(position_commonspace, viewProjectionMatrices[shadow.lightId], projectCenters[shadow.lightId]); } if (shadow.useShadowMap) { for (int i = 0; i < max_lights; i++) { if(i < int(shadow.lightCount)) { vec4 shadowMap_position = project_common_position_to_clipspace(position_commonspace, viewProjectionMatrices[i], projectCenters[i]); shadow_vPosition[i] = (shadowMap_position.xyz / shadowMap_position.w + 1.0) / 2.0; } } } return gl_Position; } ` ); var vs3 = ` ${uniformBlock2} ${vertex} `; var fragment = ( /* glsl */ ` const int max_lights = 2; uniform sampler2D shadow_uShadowMap0; uniform sampler2D shadow_uShadowMap1; in vec3 shadow_vPosition[max_lights]; const vec4 bitPackShift = vec4(1.0, 255.0, 65025.0, 16581375.0); const vec4 bitUnpackShift = 1.0 / bitPackShift; const vec4 bitMask = vec4(1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0, 0.0); float shadow_getShadowWeight(vec3 position, sampler2D shadowMap) { vec4 rgbaDepth = texture(shadowMap, position.xy); float z = dot(rgbaDepth, bitUnpackShift); return smoothstep(0.001, 0.01, position.z - z); } vec4 shadow_filterShadowColor(vec4 color) { if (shadow.drawShadowMap) { vec4 rgbaDepth = fract(gl_FragCoord.z * bitPackShift); rgbaDepth -= rgbaDepth.gbaa * bitMask; return rgbaDepth; } if (shadow.useShadowMap) { float shadowAlpha = 0.0; shadowAlpha += shadow_getShadowWeight(shadow_vPosition[0], shadow_uShadowMap0); if(shadow.lightCount > 1.0) { shadowAlpha += shadow_getShadowWeight(shadow_vPosition[1], shadow_uShadowMap1); } shadowAlpha *= shadow.color.a / shadow.lightCount; float blendedAlpha = shadowAlpha + color.a * (1.0 - shadowAlpha); return vec4( mix(color.rgb, shadow.color.rgb, shadowAlpha / blendedAlpha), blendedAlpha ); } return color; } ` ); var fs2 = ` ${uniformBlock2} ${fragment} `; var getMemoizedViewportCenterPosition = memoize(getViewportCenterPosition); var getMemoizedViewProjectionMatrices = memoize(getViewProjectionMatrices); var DEFAULT_SHADOW_COLOR = [0, 0, 0, 1]; var VECTOR_TO_POINT_MATRIX2 = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]; function screenToCommonSpace(xyz, pixelUnprojectionMatrix) { const [x, y, z] = xyz; const coord = (0, import_web_mercator.pixelsToWorld)([x, y, z], pixelUnprojectionMatrix); if (Number.isFinite(z)) { return coord; } return [coord[0], coord[1], 0]; } function getViewportCenterPosition({ viewport, center }) { return new import_core3.Matrix4(viewport.viewProjectionMatrix).invert().transform(center); } function getViewProjectionMatrices({ viewport, shadowMatrices }) { const projectionMatrices = []; const pixelUnprojectionMatrix = viewport.pixelUnprojectionMatrix; const farZ = viewport.isGeospatial ? void 0 : 1; const corners = [ [0, 0, farZ], // top left ground [viewport.width, 0, farZ], // top right ground [0, viewport.height, farZ], // bottom left ground [viewport.width, viewport.height, farZ], // bottom right ground [0, 0, -1], // top left near [viewport.width, 0, -1], // top right near [0, viewport.height, -1], // bottom left near [viewport.width, viewport.height, -1] // bottom right near ].map((pixel) => ( // @ts-expect-error z may be undefined screenToCommonSpace(pixel, pixelUnprojectionMatrix) )); for (const shadowMatrix of shadowMatrices) { const viewMatrix2 = shadowMatrix.clone().translate(new import_core3.Vector3(viewport.center).negate()); const positions = corners.map((corner) => viewMatrix2.transform(corner)); const projectionMatrix = new import_core3.Matrix4().ortho({ left: Math.min(...positions.map((position) => position[0])), right: Math.max(...positions.map((position) => position[0])), bottom: Math.min(...positions.map((position) => position[1])), top: Math.max(...positions.map((position) => position[1])), near: Math.min(...positions.map((position) => -position[2])), far: Math.max(...positions.map((position) => -position[2])) }); projectionMatrices.push(projectionMatrix.multiplyRight(shadowMatrix)); } return projectionMatrices; } function createShadowUniforms(opts) { const { shadowEnabled = true, project: projectProps } = opts; if (!shadowEnabled || !projectProps || !opts.shadowMatrices || !opts.shadowMatrices.length) { return { drawShadowMap: false, useShadowMap: false, shadow_uShadowMap0: opts.dummyShadowMap, shadow_uShadowMap1: opts.dummyShadowMap }; } const projectUniforms = project_default.getUniforms(projectProps); const center = getMemoizedViewportCenterPosition({ viewport: projectProps.viewport, center: projectUniforms.center }); const projectCenters = []; const viewProjectionMatrices = getMemoizedViewProjectionMatrices({ shadowMatrices: opts.shadowMatrices, viewport: projectProps.viewport }).slice(); for (let i = 0; i < opts.shadowMatrices.length; i++) { const viewProjectionMatrix = viewProjectionMatrices[i]; const viewProjectionMatrixCentered = viewProjectionMatrix.clone().translate(new import_core3.Vector3(projectProps.viewport.center).negate()); if (projectUniforms.coordinateSystem === COORDINATE_SYSTEM.LNGLAT && projectUniforms.projectionMode === PROJECTION_MODE.WEB_MERCATOR) { viewProjectionMatrices[i] = viewProjectionMatrixCentered; projectCenters[i] = center; } else { viewProjectionMatrices[i] = viewProjectionMatrix.clone().multiplyRight(VECTOR_TO_POINT_MATRIX2); projectCenters[i] = viewProjectionMatrixCentered.transform(center); } } const uniforms = { drawShadowMap: Boolean(opts.drawToShadowMap), useShadowMap: opts.shadowMaps ? opts.shadowMaps.length > 0 : false, color: opts.shadowColor || DEFAULT_SHADOW_COLOR, lightId: opts.shadowLightId || 0, lightCount: opts.shadowMatrices.length, shadow_uShadowMap0: opts.dummyShadowMap, shadow_uShadowMap1: opts.dummyShadowMap }; for (let i = 0; i < viewProjectionMatrices.length; i++) { uniforms[`viewProjectionMatrix${i}`] = viewProjectionMatrices[i]; uniforms[`projectCenter${i}`] = projectCenters[i]; } for (let i = 0; i < 2; i++) { uniforms[`shadow_uShadowMap${i}`] = opts.shadowMaps && opts.shadowMaps[i] || opts.dummyShadowMap; } return uniforms; } var shadow_default = { name: "shadow", dependencies: [project_default], vs: vs3, fs: fs2, inject: { "vs:DECKGL_FILTER_GL_POSITION": `