@deck.gl-community/layers
Version:
Add-on layers for deck.gl
1,414 lines (1,355 loc) • 45.7 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
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 = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
// dist/index.js
var dist_exports = {};
__export(dist_exports, {
DependencyArrowLayer: () => DependencyArrowLayer,
PathDirection: () => PathDirection,
PathMarkerLayer: () => PathMarkerLayer,
PathOutlineLayer: () => PathOutlineLayer,
SkyboxLayer: () => SkyboxLayer
});
module.exports = __toCommonJS(dist_exports);
// dist/path-outline-layer/path-outline-layer.js
var import_layers = require("@deck.gl/layers");
// dist/path-outline-layer/outline.js
var INITIAL_STATE = {
outlineEnabled: false,
outlineRenderShadowmap: false,
outlineShadowmap: null
};
function getUniforms({ outlineEnabled, outlineRenderShadowmap, outlineShadowmap } = INITIAL_STATE) {
const uniforms = {};
if (outlineEnabled !== void 0) {
uniforms.outline_uEnabled = outlineEnabled;
}
if (outlineRenderShadowmap !== void 0) {
uniforms.outline_uRenderOutlines = outlineRenderShadowmap;
}
if (outlineShadowmap !== void 0) {
uniforms.outline_uShadowmap = outlineShadowmap;
}
return uniforms;
}
var vs = `in float instanceZLevel;
out float outline_vzLevel;
out vec4 outline_vPosition;
// Set the z level for the outline shadowmap rendering
void outline_setZLevel(float zLevel) {
outline_vzLevel = zLevel;
}
// Store an adjusted position for texture2DProj
void outline_setUV(vec4 position) {
// mat4(
// 0.5, 0.0, 0.0, 0.0,
// 0.0, 0.5, 0.0, 0.0,
// 0.0, 0.0, 0.5, 0.0,
// 0.5, 0.5, 0.5, 1.0
// ) * position;
outline_vPosition = vec4(position.xyz * 0.5 + position.w * 0.5, position.w);
}
`;
var fs = `uniform bool outline_uEnabled;
uniform bool outline_uRenderOutlines;
uniform sampler2D outline_uShadowmap;
in float outline_vzLevel;
// in vec2 outline_vUV;
in vec4 outline_vPosition;
const float OUTLINE_Z_LEVEL_ERROR = 0.01;
// Return a darker color in shadowmap
vec4 outline_filterShadowColor(vec4 color) {
return vec4(outline_vzLevel / 255., outline_vzLevel / 255., outline_vzLevel / 255., 1.);
}
// Return a darker color if in shadowmap
vec4 outline_filterDarkenColor(vec4 color) {
if (outline_uEnabled) {
float maxZLevel;
if (outline_vPosition.q > 0.0) {
maxZLevel = textureProj(outline_uShadowmap, outline_vPosition).r * 255.;
} else {
discard;
}
if (maxZLevel < outline_vzLevel + OUTLINE_Z_LEVEL_ERROR) {
return vec4(color.rgb * 0.5, color.a);
} else {
discard;
}
}
return color;
}
// if enabled and rendering outlines - Render depth to shadowmap
// if enabled and rendering colors - Return a darker color if in shadowmap
// if disabled, just return color
vec4 outline_filterColor(vec4 color) {
if (outline_uEnabled) {
return outline_uRenderOutlines ?
outline_filterShadowColor(color) :
outline_filterDarkenColor(color);
}
return color;
}
`;
var outline = {
name: "outline",
vs,
fs,
getUniforms
};
// dist/path-outline-layer/path-outline-layer.js
var UNIT = {
common: 0,
meters: 1,
pixels: 2
};
function injectShaderCode({ source, code = "" }) {
const INJECT_CODE = /}[^{}]*$/;
return source.replace(INJECT_CODE, code.concat("\n}\n"));
}
var VS_CODE = ` outline_setUV(gl_Position);
outline_setZLevel(instanceZLevel);
`;
var FS_CODE = ` fragColor = outline_filterColor(fragColor);
`;
var OUTLINE_SHADOWMAP_PARAMETERS = {
blend: true,
blendColorSrcFactor: "one",
blendColorDstFactor: "one",
blendColorOperation: "max",
blendAlphaSrcFactor: "one",
blendAlphaDstFactor: "one",
blendAlphaOperation: "max",
depthWriteEnabled: false,
depthCompare: "always"
};
var OUTLINE_RENDER_PARAMETERS = {
blend: false,
depthWriteEnabled: false,
depthCompare: "always"
};
var defaultProps = {
getZLevel: () => 0
};
var PathOutlineLayer = class extends import_layers.PathLayer {
state = void 0;
// Override getShaders to inject the outline module
getShaders() {
const shaders = super.getShaders();
return Object.assign({}, shaders, {
modules: shaders.modules.concat([outline]),
vs: injectShaderCode({ source: shaders.vs, code: VS_CODE }),
fs: injectShaderCode({ source: shaders.fs, code: FS_CODE })
});
}
// @ts-expect-error PathLayer is missing LayerContext arg
initializeState(context) {
super.initializeState();
const attributeManager = this.getAttributeManager();
if (!attributeManager) {
throw new Error("PathOutlineLayer requires an attribute manager during initialization.");
}
const outlineFramebuffer = context.device.createFramebuffer({
colorAttachments: [
context.device.createTexture({
format: "rgba8unorm",
width: 1,
height: 1,
mipLevels: 1
})
]
});
const outlineEmptyTexture = context.device.createTexture({
format: "rgba8unorm",
width: 1,
height: 1,
mipLevels: 1
});
attributeManager.addInstanced({
instanceZLevel: {
size: 1,
type: "uint8",
accessor: "getZLevel"
}
});
this.setState({
outlineFramebuffer,
outlineEmptyTexture,
model: this._getModel()
});
}
finalizeState(context) {
var _a, _b;
(_a = this.state.outlineFramebuffer) == null ? void 0 : _a.destroy();
(_b = this.state.outlineEmptyTexture) == null ? void 0 : _b.destroy();
super.finalizeState(context);
}
// Override draw to add render module
draw({ parameters = {} }) {
const model = this.state.model;
const outlineFramebuffer = this.state.outlineFramebuffer;
const outlineEmptyTexture = this.state.outlineEmptyTexture;
if (!model || !outlineFramebuffer || !outlineEmptyTexture) {
return;
}
const viewport = this.context.viewport;
const viewportWidth = Math.max(1, Math.ceil(viewport.width));
const viewportHeight = Math.max(1, Math.ceil(viewport.height));
outlineFramebuffer.resize({ width: viewportWidth, height: viewportHeight });
const shadowmapTexture = getFramebufferTexture(outlineFramebuffer);
if (!shadowmapTexture) {
return;
}
const { jointRounded, capRounded, billboard, miterLimit, widthUnits, widthScale, widthMinPixels, widthMaxPixels } = this.props;
const basePathProps = {
jointType: Number(jointRounded),
capType: Number(capRounded),
billboard,
widthUnits: UNIT[widthUnits],
widthScale,
miterLimit,
widthMinPixels,
widthMaxPixels
};
this.setShaderModuleProps({
outline: {
outlineEnabled: true,
outlineRenderShadowmap: true,
outlineShadowmap: outlineEmptyTexture
}
});
model.shaderInputs.setProps({
path: {
...basePathProps,
jointType: 0,
widthScale: widthScale * 1.3
}
});
model.setParameters({ ...parameters, ...OUTLINE_SHADOWMAP_PARAMETERS });
const shadowRenderPass = this.context.device.beginRenderPass({
id: `${this.props.id}-outline-shadowmap`,
framebuffer: outlineFramebuffer,
parameters: { viewport: [0, 0, viewportWidth, viewportHeight] },
clearColor: [0, 0, 0, 0],
clearDepth: 1,
clearStencil: 0
});
model.draw(shadowRenderPass);
shadowRenderPass.end();
this.setShaderModuleProps({
outline: {
outlineEnabled: true,
outlineRenderShadowmap: false,
outlineShadowmap: shadowmapTexture
}
});
model.shaderInputs.setProps({
path: basePathProps
});
model.setParameters(isPickingPass(parameters) ? parameters : { ...parameters, ...OUTLINE_RENDER_PARAMETERS });
model.draw(this.context.renderPass);
}
};
__publicField(PathOutlineLayer, "layerName", "PathOutlineLayer");
__publicField(PathOutlineLayer, "defaultProps", defaultProps);
function isPickingPass(parameters) {
return parameters.blend === true && parameters.blendAlphaSrcFactor === "constant";
}
function getFramebufferTexture(framebuffer) {
const colorAttachment = framebuffer.colorAttachments[0];
if (!colorAttachment) {
return null;
}
return "texture" in colorAttachment ? colorAttachment.texture : colorAttachment;
}
// dist/path-marker-layer/path-marker-layer.js
var import_core3 = require("@deck.gl/core");
var import_layers2 = require("@deck.gl/layers");
var import_mesh_layers = require("@deck.gl/mesh-layers");
// dist/path-marker-layer/arrow-2d-geometry.js
var import_engine = require("@luma.gl/engine");
var Arrow2DGeometry = class extends import_engine.Geometry {
constructor(opts = {}) {
super(Object.assign({}, opts, {
attributes: getArrowAttributes(opts),
topology: "triangle-list"
}));
}
};
function getArrowAttributes({ length = 1, headSize = 0.2, tailWidth = 0.05, tailStart = 0.05 }) {
const texCoords = [
// HEAD
0.5,
1,
0,
0.5 - headSize / 2,
1 - headSize,
0,
0.5 + headSize / 2,
1 - headSize,
0,
0.5 - tailWidth / 2,
tailStart,
0,
0.5 + tailWidth / 2,
1 - headSize,
0,
0.5 + tailWidth / 2,
tailStart,
0,
0.5 - tailWidth / 2,
tailStart,
0,
0.5 - tailWidth / 2,
1 - headSize,
0,
0.5 + tailWidth / 2,
1 - headSize,
0
];
const normals = [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1];
const positions = new Array(texCoords.length);
for (let i = 0; i < texCoords.length / 3; i++) {
const i3 = i * 3;
positions[i3 + 0] = (texCoords[i3 + 0] - 0.5) * length;
positions[i3 + 1] = (texCoords[i3 + 1] - 0.5) * length;
positions[i3 + 2] = 0;
}
return {
positions: { size: 3, value: new Float32Array(positions) },
normals: { size: 3, value: new Float32Array(normals) },
texCoords: { size: 2, value: new Float32Array(texCoords) }
};
}
// dist/path-marker-layer/create-path-markers.js
var import_core = require("@math.gl/core");
function getLineLength(vPoints) {
let lineLength = 0;
for (let i = 0; i < vPoints.length - 1; i++) {
lineLength += vPoints[i].distance(vPoints[i + 1]);
}
return lineLength;
}
var DEFAULT_COLOR = [0, 0, 0, 255];
var DEFAULT_DIRECTION = { forward: true, backward: false };
function createPathMarkers({ data, getPath = (x, context) => x.path, getDirection = (x) => x.direction, getColor = (_x) => DEFAULT_COLOR, getMarkerPercentages = (x, info) => [0.5], projectFlat }) {
const markers = [];
for (const object of data) {
const path = getPath(object, null);
const direction = getDirection(object) || DEFAULT_DIRECTION;
const color = getColor(object);
const vPoints = path.map((p) => new import_core.Vector2(p));
const vPointsReverse = vPoints.slice(0).reverse();
const lineLength = getLineLength(vPoints);
const percentages = getMarkerPercentages(object, { lineLength });
for (const percentage of percentages) {
if (direction.forward) {
const marker = createMarkerAlongPath({
path: vPoints,
percentage,
lineLength,
color,
object,
projectFlat
});
markers.push(marker);
}
if (direction.backward) {
const marker = createMarkerAlongPath({
path: vPointsReverse,
percentage,
lineLength,
color,
object,
projectFlat
});
markers.push(marker);
}
}
}
return markers;
}
function createMarkerAlongPath({ path, percentage, lineLength, color, object, projectFlat }) {
const distanceAlong = lineLength * percentage;
let currentDistance = 0;
let previousDistance = 0;
let i = 0;
for (i = 0; i < path.length - 1; i++) {
currentDistance += path[i].distance(path[i + 1]);
if (currentDistance > distanceAlong) {
break;
}
previousDistance = currentDistance;
}
if (i === path.length - 1) {
i -= 1;
}
const vDirection = path[i + 1].clone().subtract(path[i]).normalize();
const along = distanceAlong - previousDistance;
const vCenter = vDirection.clone().multiply(new import_core.Vector2(along, along)).add(path[i]);
const vDirection2 = new import_core.Vector2(projectFlat(path[i + 1])).subtract(projectFlat(path[i]));
const angle = vDirection2.verticalAngle() * 180 / Math.PI;
return { position: [vCenter.x, vCenter.y, 0], angle, color, object };
}
// dist/path-marker-layer/polyline.js
var import_core2 = require("@math.gl/core");
function getClosestPointOnLine({ p, p1, p2, clampToLine = true }) {
const lineVector = new import_core2.Vector3(p2).subtract(p1);
const pointVector = new import_core2.Vector3(p).subtract(p1);
let dotProduct = lineVector.dot(pointVector);
if (clampToLine) {
dotProduct = (0, import_core2.clamp)(dotProduct, 0, 1);
}
return lineVector.lerp(p1, p2, dotProduct);
}
function getClosestPointOnPolyline({ p, points }) {
p = new import_core2.Vector3(p);
let pClosest = null;
let distanceSquared = Infinity;
let index = -1;
for (let i = 0; i < points.length - 1; ++i) {
const p1 = points[i];
const p2 = points[i + 1];
const pClosestOnLine = getClosestPointOnLine({ p, p1, p2 });
const distanceToLineSquared = p.distanceSquared(pClosestOnLine);
if (distanceToLineSquared < distanceSquared) {
distanceSquared = distanceToLineSquared;
pClosest = pClosestOnLine;
index = i;
}
}
return {
point: pClosest,
index,
p1: points[index],
p2: points[index + 1],
distanceSquared,
distance: Math.sqrt(distanceSquared)
};
}
// dist/path-marker-layer/path-marker-layer.js
var DISTANCE_FOR_MULTI_ARROWS = 0.1;
var ARROW_HEAD_SIZE = 0.2;
var ARROW_TAIL_WIDTH = 0.05;
var DEFAULT_MARKER_LAYER = import_mesh_layers.SimpleMeshLayer;
var DEFAULT_MARKER_LAYER_PROPS = {
mesh: new Arrow2DGeometry({ headSize: ARROW_HEAD_SIZE, tailWidth: ARROW_TAIL_WIDTH })
};
var defaultProps2 = Object.assign({}, PathOutlineLayer.defaultProps, {
MarkerLayer: DEFAULT_MARKER_LAYER,
markerLayerProps: DEFAULT_MARKER_LAYER_PROPS,
sizeScale: 100,
fp64: false,
highlightIndex: -1,
highlightPoint: null,
getPath: (x) => x.path,
getColor: (x) => x.color,
getMarkerColor: (_x) => [0, 0, 0, 255],
getDirection: (x) => x.direction,
getMarkerPercentages: (object, { lineLength }) => lineLength > DISTANCE_FOR_MULTI_ARROWS ? [0.25, 0.5, 0.75] : [0.5]
});
var PathMarkerLayer = class extends import_core3.CompositeLayer {
state = void 0;
initializeState() {
this.state = {
markers: [],
mesh: new Arrow2DGeometry({ headSize: ARROW_HEAD_SIZE, tailWidth: ARROW_TAIL_WIDTH }),
closestPoint: null,
closestPoints: []
};
}
projectFlat(xyz, viewport, coordinateSystem, coordinateOrigin) {
if (coordinateSystem === import_core3.COORDINATE_SYSTEM.METER_OFFSETS) {
const [dx, dy] = viewport.metersToLngLatDelta(xyz);
const [x, y] = coordinateOrigin;
return viewport.projectFlat([x + dx, dy + y]);
} else if (coordinateSystem === import_core3.COORDINATE_SYSTEM.LNGLAT_OFFSETS) {
const [dx, dy] = xyz;
const [x, y] = coordinateOrigin;
return viewport.projectFlat([x + dx, dy + y]);
}
return viewport.projectFlat(xyz);
}
updateState({ props, oldProps, changeFlags }) {
if (changeFlags.dataChanged || changeFlags.updateTriggersChanged) {
const { data, getPath, getDirection, getMarkerColor, getMarkerPercentages, coordinateSystem, coordinateOrigin } = this.props;
const { viewport } = this.context;
const projectFlat = (o) => this.projectFlat(o, viewport, coordinateSystem, coordinateOrigin);
this.state.markers = createPathMarkers({
data,
getPath,
getDirection,
getColor: getMarkerColor,
getMarkerPercentages,
projectFlat
});
this._recalculateClosestPoint();
}
if (changeFlags.propsChanged) {
if (props.point !== oldProps.point) {
this._recalculateClosestPoint();
}
}
}
_recalculateClosestPoint() {
const { highlightPoint, highlightIndex } = this.props;
if (highlightPoint && highlightIndex >= 0) {
const object = this.props.data[highlightIndex];
const points = this.props.getPath(object, null);
const { point } = getClosestPointOnPolyline({ points, p: highlightPoint });
this.state.closestPoints = [{ position: point }];
} else {
this.state.closestPoints = [];
}
}
getPickingInfo({ info }) {
return Object.assign(info, {
// override object with picked feature
object: info.object && info.object.path || info.object
});
}
renderLayers() {
return [
new PathOutlineLayer(this.props, this.getSubLayerProps({
id: "paths",
// Note: data has to be passed explicitly like this to avoid being empty
data: this.props.data
})),
new this.props.MarkerLayer(this.getSubLayerProps(Object.assign({}, this.props.markerLayerProps, {
id: "markers",
data: this.state.markers,
getOrientation: (x) => [0, -x.angle, 0],
getColor: (x) => x.color,
sizeScale: this.props.sizeScale,
fp64: this.props.fp64,
pickable: false,
parameters: {
blend: false,
depthTest: false
}
}))),
this.state.closestPoints && new import_layers2.ScatterplotLayer({
id: `${this.props.id}-highlight`,
data: this.state.closestPoints,
fp64: this.props.fp64
})
];
}
};
__publicField(PathMarkerLayer, "layerName", "PathMarkerLayer");
__publicField(PathMarkerLayer, "defaultProps", defaultProps2);
// dist/dependency-arrow-layer/dependency-arrow-layer.js
var import_core7 = require("@deck.gl/core");
var import_layers3 = require("@deck.gl/layers");
// dist/dependency-arrow-layer/create-path-markers.js
var import_core4 = require("@deck.gl/core");
var import_core5 = require("@math.gl/core");
var PathDirection;
(function(PathDirection2) {
PathDirection2[PathDirection2["NONE"] = 0] = "NONE";
PathDirection2[PathDirection2["FORWARD"] = 1] = "FORWARD";
PathDirection2[PathDirection2["BACKWARD"] = 2] = "BACKWARD";
PathDirection2[PathDirection2["BOTH"] = 3] = "BOTH";
})(PathDirection || (PathDirection = {}));
function createPathMarkers2({ data, getPath, positionSize, getDirection, getMarkerPlacements, mode }) {
const markers = [];
if (!data || typeof data === "string" || !(Symbol.iterator in Object(data))) {
return markers;
}
const { iterable, objectInfo } = (0, import_core4.createIterable)(data);
for (const object of iterable) {
objectInfo.index++;
const path = normalizePath(getPath(object, objectInfo), positionSize);
if (path.length < 2) {
continue;
}
if (mode !== "path") {
path.splice(1, path.length - 2);
}
const direction = typeof getDirection === "function" ? getDirection(object, objectInfo) : getDirection;
const lineLength = getLineLength2(path);
if (!Number.isFinite(lineLength) || lineLength <= 0) {
continue;
}
objectInfo.lineLength = lineLength;
const placements = typeof getMarkerPlacements === "function" ? getMarkerPlacements(object, objectInfo) : getMarkerPlacements;
const sourceObject = { object, index: objectInfo.index };
for (const dir of [PathDirection.FORWARD, PathDirection.BACKWARD]) {
if (!(direction & dir))
continue;
if (dir === PathDirection.BACKWARD) {
path.reverse();
}
for (const percentage of placements) {
const marker = mode === "arc" ? {
source: path[0],
target: path[1],
percentage,
__source: sourceObject
} : createMarkerAlongPath2({
path,
percentage,
lineLength,
sourceObject
});
markers.push(marker);
}
}
}
return markers;
}
function normalizePath(path, size) {
if (!path) {
return [];
}
if (Array.isArray(path[0])) {
return path.map(([x, y]) => new import_core5.Vector2(x, y));
}
const flatPath = path;
const length = flatPath.length / size;
const points = new Array(length);
for (let i = 0; i < length; i++) {
points[i] = new import_core5.Vector2(flatPath[i * size], flatPath[i * size + 1]);
}
return points;
}
function getLineLength2(vPoints) {
let lineLength = 0;
for (let i = 0; i < vPoints.length - 1; i++) {
lineLength += vPoints[i].distance(vPoints[i + 1]);
}
return lineLength;
}
function createMarkerAlongPath2({ path, percentage, lineLength, sourceObject }) {
const distanceAlong = lineLength * percentage;
let currentDistance = 0;
let previousDistance = 0;
let i = 0;
for (i = 0; i < path.length - 1; i++) {
currentDistance += path[i].distance(path[i + 1]);
if (currentDistance >= distanceAlong) {
break;
}
previousDistance = currentDistance;
}
if (i === path.length - 1) {
i -= 1;
}
const along = distanceAlong - previousDistance;
const segmentLength = path[i + 1].distance(path[i]);
return {
source: path[i],
target: path[i + 1],
percentage: segmentLength > 0 ? along / segmentLength : 0,
__source: sourceObject
};
}
// dist/dependency-arrow-layer/geometry-layer.js
var import_core6 = require("@deck.gl/core");
var import_engine2 = require("@luma.gl/engine");
var geometryLayerUniforms = {
name: "geometryLayer",
vs: `uniform geometryLayerUniforms {
float sizeScale;
highp int sizeUnits;
highp int interpolationMode;
} geometryLayer;
`,
fs: `uniform geometryLayerUniforms {
float sizeScale;
highp int sizeUnits;
highp int interpolationMode;
} geometryLayer;
`,
uniformTypes: {
sizeScale: "f32",
sizeUnits: "i32",
interpolationMode: "i32"
}
};
var defaultProps3 = {
sizeUnits: "common",
sizeScale: { type: "number", min: 0, value: 1 },
interpolationMode: "line",
getPickingColor: { type: "accessor", value: [0, 0, 0] },
getSourcePosition: { type: "accessor", value: (x) => x.source },
getTargetPosition: { type: "accessor", value: (x) => x.target },
getPositionRatio: { type: "accessor", value: 1 },
getSize: { type: "accessor", value: [1, 1] },
getColor: { type: "accessor", value: [0, 0, 0, 255] },
getArcHeight: { type: "accessor", value: 1 },
getArcTilt: { type: "accessor", value: 0 }
};
var vs2 = `#version 300 es
#define SHADER_NAME geometry-layer-vertex-shader
in vec2 positions;
in vec3 instanceSourcePositions;
in vec3 instanceSourcePositions64Low;
in vec3 instanceTargetPositions;
in vec3 instanceTargetPositions64Low;
in float instanceRatios;
in vec2 instanceSizes;
in vec4 instanceColors;
in float instanceArcHeights;
in float instanceArcTilts;
in vec3 instancePickingColors;
out vec4 vColor;
out vec2 vPosition;
flat out vec2 vPixelSize;
const int GEOMETRY_LINE = 0;
const int GEOMETRY_ARC = 1;
// START ARC LAYER VERTEX
float paraboloid(float distance, float sourceZ, float targetZ, float ratio) {
float deltaZ = targetZ - sourceZ;
float dh = distance * instanceArcHeights;
if (dh == 0.0) {
return sourceZ + deltaZ * ratio;
}
float unitZ = deltaZ / dh;
float p2 = unitZ * unitZ + 1.0;
// sqrt does not deal with negative values, manually flip source and target if delta.z < 0
float dir = step(deltaZ, 0.0);
float z0 = mix(sourceZ, targetZ, dir);
float r = mix(ratio, 1.0 - ratio, dir);
return sqrt(r * (p2 - r)) * dh + z0;
}
vec3 interpolateArc(vec3 source, vec3 target, float ratio) {
float distance = length(source.xy - target.xy);
float z = paraboloid(distance, source.z, target.z, ratio);
float tiltAngle = radians(instanceArcTilts);
vec2 tiltDirection = normalize(target.xy - source.xy);
vec2 tilt = vec2(-tiltDirection.y, tiltDirection.x) * z * sin(tiltAngle);
return vec3(
mix(source.xy, target.xy, ratio) + tilt,
z * cos(tiltAngle)
);
}
// END ARC LAYER VERTEX
vec3 interplolatePath(vec3 source, vec3 target, float ratio) {
if (geometryLayer.interpolationMode == GEOMETRY_ARC) {
return interpolateArc(source, target, ratio);
}
return mix(source, target, ratio);
}
void main(void) {
geometry.worldPosition = instanceSourcePositions;
geometry.worldPositionAlt = instanceTargetPositions;
vPosition = (positions + 1.0) / 2.0;
geometry.uv = vPosition;
vec3 source = project_position(instanceSourcePositions, instanceSourcePositions64Low);
vec3 target = project_position(instanceTargetPositions, instanceTargetPositions64Low);
vec3 curr = interplolatePath(source, target, instanceRatios);
vec2 normal;
if (instanceRatios < 0.01) {
vec3 next = interplolatePath(source, target, instanceRatios + 0.01);
normal = next.xy - curr.xy;
} else {
vec3 prev = interplolatePath(source, target, instanceRatios - 0.01);
normal = curr.xy - prev.xy;
}
vec2 scaledSize = instanceSizes * geometryLayer.sizeScale;
// Anchor the marker at the triangle tip, so ratio 1.0 places the arrowhead on the endpoint.
vec2 markerPosition = vec2((positions.x - 1.0) / 2.0, positions.y / 2.0);
vec2 offset = markerPosition * scaledSize;
float angle = atan(normal.y, normal.x);
float cosA = cos(angle);
float sinA = sin(angle);
offset = vec2(
offset.x * cosA - offset.y * sinA,
offset.x * sinA + offset.y * cosA
);
vec3 offsetCommon = vec3(offset, 0.);
if (geometryLayer.sizeUnits == UNIT_PIXELS) {
offsetCommon.xy = project_pixel_size(offset);
vPixelSize = scaledSize;
} else {
vPixelSize = project_size(scaledSize);
}
geometry.pickingColor = instancePickingColors;
geometry.position = vec4(curr + offsetCommon, 0.1);
gl_Position = project_common_position_to_clipspace(geometry.position);
DECKGL_FILTER_GL_POSITION(gl_Position, geometry);
vColor = vec4(instanceColors.rgb, instanceColors.a * layer.opacity);
DECKGL_FILTER_COLOR(vColor, geometry);
}
`;
var fs2 = `#version 300 es
#define SHADER_NAME geometry-layer-fragment-shader
precision highp float;
in vec4 vColor;
in vec2 vPosition;
flat in vec2 vPixelSize;
out vec4 fragColor;
float smoothedgeSigned(float signedDistance) {
float edgeRadius = fwidth(signedDistance);
return smoothstep(-edgeRadius, edgeRadius, signedDistance);
}
float inTriangle(vec2 bbox, vec2 uv) {
float w = max(bbox.x, 1.0);
float h = max(bbox.y, 1.0);
float d = ((1.0 - abs(1.0 - uv.y * 2.0)) - uv.x) * w;
return smoothedgeSigned(d);
}
void main(void) {
geometry.uv = vPosition;
float inShape = inTriangle(vPixelSize, vPosition);
if (inShape == 0.0) {
discard;
}
fragColor = vColor;
fragColor.a *= inShape;
DECKGL_FILTER_COLOR(fragColor, geometry);
}
`;
var GeometryLayer = class extends import_core6.Layer {
state = {};
getShaders() {
return super.getShaders({ vs: vs2, fs: fs2, modules: [import_core6.project32, import_core6.picking, geometryLayerUniforms] });
}
initializeState() {
this.getAttributeManager().addInstanced({
instanceSourcePositions: {
size: 3,
type: "float64",
fp64: this.use64bitPositions(),
transition: true,
accessor: "getSourcePosition"
},
instanceTargetPositions: {
size: 3,
type: "float64",
fp64: this.use64bitPositions(),
transition: true,
accessor: "getTargetPosition"
},
instanceRatios: {
size: 1,
transition: true,
accessor: "getPositionRatio"
},
instanceArcHeights: {
size: 1,
transition: true,
accessor: "getArcHeight"
},
instanceArcTilts: {
size: 1,
transition: true,
accessor: "getArcTilt"
},
instanceSizes: {
size: 2,
transition: true,
accessor: "getSize"
},
instanceColors: {
size: 4,
transition: true,
type: "unorm8",
accessor: "getColor",
defaultValue: [0, 0, 0, 255]
},
instancePickingColors: {
size: 3,
type: "uint8",
accessor: "getPickingColor"
}
});
}
updateState(params) {
var _a;
super.updateState(params);
if (params.changeFlags.extensionsChanged) {
(_a = this.state.model) == null ? void 0 : _a.destroy();
this.state.model = this._getModel();
this.getAttributeManager().invalidateAll();
}
}
draw() {
const model = this.state.model;
if (!model) {
return;
}
const { sizeScale, sizeUnits, interpolationMode } = this.props;
const geometryLayerProps = {
sizeScale,
sizeUnits: import_core6.UNIT[sizeUnits],
interpolationMode: interpolationMode === "line" ? 0 : 1
};
model.shaderInputs.setProps({ geometryLayer: geometryLayerProps });
model.draw(this.context.renderPass);
}
_getModel() {
const positions = [-1, -1, 1, -1, -1, 1, 1, 1];
return new import_engine2.Model(this.context.device, {
...this.getShaders(),
id: this.props.id,
bufferLayout: this.getAttributeManager().getBufferLayouts(),
geometry: new import_engine2.Geometry({
topology: "triangle-strip",
attributes: {
positions: { size: 2, value: new Float32Array(positions) }
}
}),
isInstanced: true
});
}
};
__publicField(GeometryLayer, "defaultProps", defaultProps3);
__publicField(GeometryLayer, "layerName", "GeometryLayer");
// dist/dependency-arrow-layer/dependency-arrow-layer.js
var defaultProps4 = {
getPath: import_layers3.PathLayer.defaultProps.getPath,
getColor: import_layers3.LineLayer.defaultProps.getColor,
getWidth: import_layers3.LineLayer.defaultProps.getWidth,
widthUnits: import_layers3.LineLayer.defaultProps.widthUnits,
widthScale: import_layers3.LineLayer.defaultProps.widthScale,
widthMinPixels: import_layers3.LineLayer.defaultProps.widthMinPixels,
widthMaxPixels: import_layers3.LineLayer.defaultProps.widthMaxPixels,
arcNumSegments: import_layers3.ArcLayer.defaultProps.numSegments,
getArcHeight: import_layers3.ArcLayer.defaultProps.getHeight,
getArcTilt: import_layers3.ArcLayer.defaultProps.getTilt,
mode: "path",
markerSizeScale: 10,
highlightIndex: -1,
highlightPoint: null,
getMarkerColor: { type: "accessor", value: void 0 },
getDirection: { type: "accessor", value: PathDirection.FORWARD },
getMarkerSize: { type: "accessor", value: [1, 1] },
getMarkerPlacements: { type: "accessor", value: [0.5] }
};
var DependencyArrowLayer = class extends import_core7.CompositeLayer {
state = {
markers: []
};
updateState({ props, oldProps, changeFlags }) {
const shouldRebuildMarkers = changeFlags.dataChanged || props.mode !== oldProps.mode || props.positionFormat !== oldProps.positionFormat || props.getPath !== oldProps.getPath || props.getDirection !== oldProps.getDirection || props.getMarkerPlacements !== oldProps.getMarkerPlacements || changeFlags.updateTriggersChanged && (changeFlags.updateTriggersChanged["getPath"] || changeFlags.updateTriggersChanged["getDirection"] || changeFlags.updateTriggersChanged["getMarkerPlacements"]);
if (shouldRebuildMarkers) {
const { data, mode, getPath, getDirection, getMarkerPlacements } = this.props;
this.state.markers = createPathMarkers2({
data,
positionSize: props.positionFormat.length,
getPath,
getDirection,
getMarkerPlacements,
mode
});
}
}
getPickingInfo({ info }) {
const pickedObject = info.object;
if (pickedObject && pickedObject.__source) {
info.object = pickedObject.__source.object;
}
return info;
}
renderLayers() {
const { mode, getPath, getColor, getMarkerColor, getMarkerSize, markerSizeScale, updateTriggers = {} } = this.props;
let pathLayer = null;
if (mode === "path") {
pathLayer = new import_layers3.PathLayer(this.props, this.getSubLayerProps({
id: "links-path",
updateTriggers: {
getPath: updateTriggers["getPath"],
getColor: updateTriggers["getColor"],
getWidth: updateTriggers["getWidth"]
}
}));
} else {
const positionSize = this.props.positionFormat.length;
const sharedProps = {
...this.props,
data: this.props.data,
getSourcePosition: (datum, info) => {
const path = getPath(datum, info);
return getFirstPoint(path, positionSize) ?? [NaN, NaN];
},
getTargetPosition: (datum, info) => {
const path = getPath(datum, info);
return getLastPoint(path, positionSize) ?? [NaN, NaN];
}
};
if (mode === "arc") {
pathLayer = new import_layers3.ArcLayer(sharedProps, {
getSourceColor: this.props.getColor,
getTargetColor: this.props.getColor,
numSegments: this.props.arcNumSegments,
getHeight: this.props.getArcHeight,
getTilt: this.props.getArcTilt
}, this.getSubLayerProps({
id: "links-arc",
updateTriggers: {
getSourcePosition: updateTriggers["getPath"],
getTargetPosition: updateTriggers["getPath"],
getSourceColor: updateTriggers["getColor"],
getTargetColor: updateTriggers["getColor"],
getWidth: updateTriggers["getWidth"],
getHeight: updateTriggers["getArcHeight"],
getTilt: updateTriggers["getArcTilt"]
}
}));
} else {
pathLayer = new import_layers3.LineLayer(sharedProps, this.getSubLayerProps({
id: "links-line",
updateTriggers: {
getSourcePosition: updateTriggers["getPath"],
getTargetPosition: updateTriggers["getPath"],
getColor: updateTriggers["getColor"],
getWidth: updateTriggers["getWidth"]
}
}));
}
}
return [
pathLayer,
new GeometryLayer(this.getSubLayerProps({
id: "arrows",
updateTriggers: {
getSize: updateTriggers["getMarkerSize"],
getColor: getMarkerColor ? updateTriggers["getMarkerColor"] : updateTriggers["getColor"],
getArcHeight: updateTriggers["getArcHeight"],
getArcTilt: updateTriggers["getArcTilt"]
}
}), {
data: this.state.markers,
sizeUnits: "pixels",
sizeScale: markerSizeScale,
interpolationMode: mode === "arc" ? "arc" : "line",
getSourcePosition: (d) => d.source,
getTargetPosition: (d) => d.target,
getPositionRatio: (d) => d.percentage,
getSize: this.getSubLayerAccessor(getMarkerSize),
getColor: this.getSubLayerAccessor(getMarkerColor ?? getColor),
getArcHeight: this.getSubLayerAccessor(this.props.getArcHeight),
getArcTilt: this.getSubLayerAccessor(this.props.getArcTilt),
getPickingColor: (d) => this.encodePickingColor(d.__source.index)
})
];
}
};
__publicField(DependencyArrowLayer, "layerName", "DependencyArrowLayer");
__publicField(DependencyArrowLayer, "defaultProps", defaultProps4);
function getFirstPoint(path, size) {
if (!path || path.length === 0)
return null;
if (Array.isArray(path[0])) {
return path[0];
}
return path.slice(0, size);
}
function getLastPoint(path, size) {
if (!path || path.length === 0)
return null;
if (Array.isArray(path[0])) {
return path[path.length - 1];
}
const len = Math.floor(path.length / size) * size;
return path.slice(len - size, len);
}
// dist/skybox-layer/skybox-layer.js
var import_core8 = require("@loaders.gl/core");
var import_textures = require("@loaders.gl/textures");
var import_core9 = require("@deck.gl/core");
var import_core10 = require("@math.gl/core");
var import_engine3 = require("@luma.gl/engine");
// dist/skybox-layer/cubemap-utils.js
var CUBE_FACES = ["+X", "-X", "+Y", "-Y", "+Z", "-Z"];
function createCubemapLoadOptions(cubemap, loadOptions) {
var _a;
if (!loadOptions) {
return void 0;
}
if (typeof cubemap === "string" || ((_a = loadOptions.core) == null ? void 0 : _a.baseUrl) || !loadOptions.baseUrl) {
return loadOptions;
}
return {
...loadOptions,
core: {
...loadOptions.core,
baseUrl: loadOptions.baseUrl
}
};
}
function convertLoadedCubemapToTextureData(texture) {
if (texture.type !== "cube" || !Array.isArray(texture.data) || texture.data.length !== 6) {
throw new Error("SkyboxLayer expected a cubemap texture with six faces.");
}
return Object.fromEntries(CUBE_FACES.map((face, index) => [face, normalizeTextureSlice(texture.data[index], face)]));
}
function normalizeTextureSlice(faceData, face) {
if (Array.isArray(faceData)) {
if (faceData.length === 0) {
throw new Error(`SkyboxLayer received an empty mip chain for face ${face}.`);
}
return faceData.map((level, mipLevel) => normalizeTextureLevel(level, face, mipLevel));
}
return normalizeTextureLevel(faceData, face, 0);
}
function normalizeTextureLevel(faceData, face, mipLevel) {
if (typeof ImageBitmap !== "undefined" && faceData instanceof ImageBitmap) {
return faceData;
}
const level = faceData;
if (level == null ? void 0 : level.imageBitmap) {
return level.imageBitmap;
}
if (level && ArrayBuffer.isView(level.data) && level.width && level.height) {
return {
data: level.data,
width: level.width,
height: level.height,
format: typeof level.textureFormat === "string" ? level.textureFormat : typeof level.format === "string" ? level.format : "rgba8unorm"
};
}
throw new Error(`SkyboxLayer could not normalize cubemap face ${face} mip ${mipLevel}.`);
}
// dist/skybox-layer/skybox-layer.js
var app = {
name: "app",
uniformTypes: {
modelMatrix: "mat4x4<f32>",
viewMatrix: "mat4x4<f32>",
projectionMatrix: "mat4x4<f32>"
}
};
var SKYBOX_PARAMETERS = {
cullMode: "front",
depthWriteEnabled: false,
depthCompare: "less-equal"
};
var SKYBOX_SCALE = new import_core10.Matrix4().scale([2, 2, 2]);
var defaultProps5 = {
cubemap: null,
loadOptions: null,
orientation: "default"
};
var SkyboxLayer = class extends import_core9.Layer {
state = void 0;
/** Initializes the cube model and starts loading the cubemap texture. */
initializeState() {
const attributeManager = this.getAttributeManager();
attributeManager == null ? void 0 : attributeManager.remove(["instancePickingColors"]);
const shaderInputs = new import_engine3.ShaderInputs(createShaderInputModules(this.context.defaultShaderModules), {
disableWarnings: true
});
const model = this._getModel(shaderInputs);
this.setState({
cubemapTexture: null,
loadCount: 0,
model,
shaderInputs
});
this._loadCubemap().catch(() => {
});
}
/** Reloads the cubemap when its source manifest or load options change. */
updateState({ props, oldProps }) {
if (props.cubemap !== oldProps.cubemap || props.loadOptions !== oldProps.loadOptions) {
this._loadCubemap().catch(() => {
});
}
}
/** Releases GPU resources owned by the layer. */
finalizeState() {
var _a, _b;
(_a = this.state.cubemapTexture) == null ? void 0 : _a.destroy();
(_b = this.state.model) == null ? void 0 : _b.destroy();
}
/** Draws the skybox cube for the current viewport. */
draw() {
const { model, cubemapTexture, shaderInputs } = this.state;
if (!model || !cubemapTexture || !shaderInputs) {
return;
}
const viewport = this.context.viewport;
shaderInputs.setProps({
app: {
modelMatrix: getSkyboxModelMatrix(this.props.orientation),
viewMatrix: getSkyboxViewMatrix(viewport),
projectionMatrix: viewport.projectionMatrix
}
});
model.draw(this.context.renderPass);
}
/** Creates the luma.gl model used to render the skybox cube. */
_getModel(shaderInputs) {
var _a;
return new import_engine3.Model(this.context.device, {
...this.getShaders(),
id: this.props.id,
bufferLayout: ((_a = this.getAttributeManager()) == null ? void 0 : _a.getBufferLayouts()) || [],
geometry: new import_engine3.CubeGeometry({ indices: true }),
shaderInputs,
isInstanced: false,
parameters: SKYBOX_PARAMETERS
});
}
/** Returns the WGSL/GLSL shader pair used by the layer. */
getShaders() {
return {
source: SKYBOX_WGSL,
vs: SKYBOX_VS,
fs: SKYBOX_FS
};
}
/** Starts an asynchronous cubemap load for the current props. */
async _loadCubemap() {
const { cubemap, loadOptions } = this.props;
const nextLoadCount = this.state.loadCount + 1;
this.setState({ loadCount: nextLoadCount });
if (!cubemap) {
this._setCubemapTexture(null);
return;
}
try {
const loadedTexture = await loadCubemapSource(cubemap, loadOptions);
if (this.state.loadCount !== nextLoadCount || !this.state.model) {
return;
}
const cubemapData = convertLoadedCubemapToTextureData(loadedTexture);
this._setCubemapTexture(createCubemapTexture(this.context.device, cubemapData));
} catch (error) {
if (this.state.loadCount === nextLoadCount) {
this.raiseError(error, "SkyboxLayer failed to load cubemap");
}
}
}
/** Swaps the active GPU cubemap texture and updates model bindings. */
_setCubemapTexture(texture) {
const { cubemapTexture, model } = this.state;
if (cubemapTexture === texture) {
return;
}
cubemapTexture == null ? void 0 : cubemapTexture.destroy();
this.setState({ cubemapTexture: texture });
if (texture && model) {
model.setBindings({ cubeTexture: texture });
}
this.setNeedsRedraw();
}
};
__publicField(SkyboxLayer, "defaultProps", defaultProps5);
__publicField(SkyboxLayer, "layerName", "SkyboxLayer");
async function loadCubemapSource(cubemap, loadOptions) {
const normalizedLoadOptions = createCubemapLoadOptions(cubemap, loadOptions);
if (typeof cubemap === "string") {
return await (0, import_core8.load)(cubemap, import_textures.TextureCubeLoader, normalizedLoadOptions);
}
return await import_textures.TextureCubeLoader.parseText(JSON.stringify(cubemap), normalizedLoadOptions);
}
function createCubemapTexture(device, data) {
return new import_engine3.DynamicTexture(device, {
dimension: "cube",
data,
mipmaps: true,
sampler: {
addressModeU: "clamp-to-edge",
addressModeV: "clamp-to-edge",
addressModeW: "clamp-to-edge",
magFilter: "linear",
minFilter: "linear",
mipmapFilter: "linear"
}
});
}
function getSkyboxViewMatrix(viewport) {
const viewMatrix = new import_core10.Matrix4(viewport.viewMatrixUncentered || viewport.viewMatrix);
viewMatrix[12] = 0;
viewMatrix[13] = 0;
viewMatrix[14] = 0;
return viewMatrix;
}
function getSkyboxModelMatrix(orientation = "default") {
if (orientation === "y-up") {
return new import_core10.Matrix4().rotateX(Math.PI / 2).scale([2, 2, 2]);
}
return new import_core10.Matrix4(SKYBOX_SCALE);
}
function createShaderInputModules(defaultShaderModules) {
return Object.fromEntries([app, ...defaultShaderModules].map((module2) => [module2.name, module2]));
}
var SKYBOX_WGSL = (
/* wgsl */
`
struct appUniforms {
modelMatrix: mat4x4<f32>,
viewMatrix: mat4x4<f32>,
projectionMatrix: mat4x4<f32>,
};
var<uniform> app : appUniforms;
var cubeTexture : texture_cube<f32>;
var cubeTextureSampler : sampler;
struct VertexInputs {
positions : vec3<f32>,
};
struct VertexOutputs {
position : vec4<f32>,
direction : vec3<f32>,
};
fn vertexMain(inputs: VertexInputs) -> VertexOutputs {
var outputs : VertexOutputs;
let clipPosition =
app.projectionMatrix *
app.viewMatrix *
app.modelMatrix *
vec4<f32>(inputs.positions, 1.0);
outputs.position = vec4<f32>(clipPosition.x, clipPosition.y, clipPosition.w, clipPosition.w);
outputs.direction = inputs.positions;
return outputs;
}
fn fragmentMain(inputs: VertexOutputs) -> vec4<f32> {
return textureSample(cubeTexture, cubeTextureSampler, normalize(inputs.direction));
}
`
);
var SKYBOX_VS = (
/* glsl */
`#version 300 es
in vec3 positions;
uniform appUniforms {
mat4 modelMatrix;
mat4 viewMatrix;
mat4 projectionMatrix;
} app;
out vec3 vDirection;
void main(void) {
vec4 clipPosition =
app.projectionMatrix * app.viewMatrix * app.modelMatrix * vec4(positions, 1.0);
gl_Position = clipPosition.xyww;
vDirection = positions;
}
`
);
var SKYBOX_FS = (
/* glsl */
`#version 300 es
precision highp float;
uniform samplerCube cubeTexture;
in vec3 vDirection;
out vec4 fragColor;
void main(void) {
fragColor = texture(cubeTexture, normalize(vDirection));
}
`
);
//# sourceMappingURL=index.cjs.map