UNPKG

@deck.gl/layers

Version:

deck.gl core layers

181 lines (152 loc) 6.46 kB
// deck.gl // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors export const shaderWGSL = /* wgsl */ `\ // TODO(ibgreen): Hack for Layer uniforms (move to new "color" module?) struct LayerUniforms { opacity: f32, }; var<private> layer: LayerUniforms = LayerUniforms(1.0); // @group(0) @binding(1) var<uniform> layer: LayerUniforms; // ---------- Helper Structures & Functions ---------- // Placeholder filter functions. fn deckgl_filter_size(offset: vec3<f32>, geometry: Geometry) -> vec3<f32> { return offset; } fn deckgl_filter_gl_position(p: vec4<f32>, geometry: Geometry) -> vec4<f32> { return p; } fn deckgl_filter_color(color: vec4<f32>, geometry: Geometry) -> vec4<f32> { return color; } // Compute an extrusion offset given a line direction (in clipspace), // an offset direction (-1 or 1), and a width in pixels. // Assumes a uniform "project" with a viewportSize field is available. fn getExtrusionOffset(line_clipspace: vec2<f32>, offset_direction: f32, width: f32) -> vec2<f32> { // project.viewportSize should be provided as a uniform (not shown here) let dir_screenspace = normalize(line_clipspace * project.viewportSize); // Rotate by 90°: (x,y) becomes (-y,x) let rotated = vec2<f32>(-dir_screenspace.y, dir_screenspace.x); return rotated * offset_direction * width / 2.0; } // Splits the line between two points at a given x coordinate. // Interpolates the y and z components. fn splitLine(a: vec3<f32>, b: vec3<f32>, x: f32) -> vec3<f32> { let t: f32 = (x - a.x) / (b.x - a.x); return vec3<f32>(x, a.yz + t * (b.yz - a.yz)); } // ---------- Uniforms & Global Structures ---------- // Uniforms for line, layer, and project are assumed to be defined elsewhere. // For example: // // @group(0) @binding(0) // var<uniform> line: LineUniform; // // struct LayerUniform { // opacity: f32, // }; // @group(0) @binding(1) // var<uniform> layer: LayerUniform; // // struct ProjectUniform { // viewportSize: vec2<f32>, // }; // @group(0) @binding(2) // var<uniform> project: ProjectUniform; // ---------- Vertex Output Structure ---------- struct Varyings { @builtin(position) gl_Position: vec4<f32>, @location(0) vColor: vec4<f32>, @location(1) uv: vec2<f32>, }; // ---------- Vertex Shader Entry Point ---------- @vertex fn vertexMain( @location(0) positions: vec3<f32>, @location(1) instanceSourcePositions: vec3<f32>, @location(2) instanceTargetPositions: vec3<f32>, @location(3) instanceSourcePositions64Low: vec3<f32>, @location(4) instanceTargetPositions64Low: vec3<f32>, @location(5) instanceColors: vec4<f32>, @location(6) instancePickingColors: vec3<f32>, @location(7) instanceWidths: f32 ) -> Varyings { var geometry: Geometry; geometry.worldPosition = instanceSourcePositions; geometry.worldPositionAlt = instanceTargetPositions; var source_world: vec3<f32> = instanceSourcePositions; var target_world: vec3<f32> = instanceTargetPositions; var source_world_64low: vec3<f32> = instanceSourcePositions64Low; var target_world_64low: vec3<f32> = instanceTargetPositions64Low; // Apply shortest-path adjustments if needed. if (line.useShortestPath > 0.5 || line.useShortestPath < -0.5) { source_world.x = (source_world.x + 180.0 % 360.0) - 180.0; target_world.x = (target_world.x + 180.0 % 360.0) - 180.0; let deltaLng: f32 = target_world.x - source_world.x; if (deltaLng * line.useShortestPath > 180.0) { source_world.x = source_world.x + 360.0 * line.useShortestPath; source_world = splitLine(source_world, target_world, 180.0 * line.useShortestPath); source_world_64low = vec3<f32>(0.0, 0.0, 0.0); } else if (deltaLng * line.useShortestPath < -180.0) { target_world.x = target_world.x + 360.0 * line.useShortestPath; target_world = splitLine(source_world, target_world, 180.0 * line.useShortestPath); target_world_64low = vec3<f32>(0.0, 0.0, 0.0); } else if (line.useShortestPath < 0.0) { var abortOut: Varyings; abortOut.gl_Position = vec4<f32>(0.0); abortOut.vColor = vec4<f32>(0.0); abortOut.uv = vec2<f32>(0.0); return abortOut; } } // Project Pos and target positions to clip space. let sourceResult = project_position_to_clipspace_and_commonspace(source_world, source_world_64low, vec3<f32>(0.0)); let targetResult = project_position_to_clipspace_and_commonspace(target_world, target_world_64low, vec3<f32>(0.0)); let sourcePos: vec4<f32> = sourceResult.clipPosition; let targetPos: vec4<f32> = targetResult.clipPosition; let source_commonspace: vec4<f32> = sourceResult.commonPosition; let target_commonspace: vec4<f32> = targetResult.commonPosition; // Interpolate along the line segment. let segmentIndex: f32 = positions.x; let p: vec4<f32> = sourcePos + segmentIndex * (targetPos - sourcePos); geometry.position = source_commonspace + segmentIndex * (target_commonspace - source_commonspace); let uv: vec2<f32> = positions.xy; geometry.uv = uv; geometry.pickingColor = instancePickingColors; // Determine width in pixels. let widthPixels: f32 = clamp( project_unit_size_to_pixel(instanceWidths * line.widthScale, line.widthUnits), line.widthMinPixels, line.widthMaxPixels ); // Compute extrusion offset. let extrusion: vec2<f32> = getExtrusionOffset(targetPos.xy - sourcePos.xy, positions.y, widthPixels); let offset: vec3<f32> = vec3<f32>(extrusion, 0.0); // Apply deck.gl filter functions. let filteredOffset = deckgl_filter_size(offset, geometry); let filteredP = deckgl_filter_gl_position(p, geometry); let clipOffset: vec2<f32> = project_pixel_size_to_clipspace(filteredOffset.xy); let finalPosition: vec4<f32> = filteredP + vec4<f32>(clipOffset, 0.0, 0.0); // Compute color. var vColor: vec4<f32> = vec4<f32>(instanceColors.rgb, instanceColors.a * layer.opacity); // vColor = deckgl_filter_color(vColor, geometry); var output: Varyings; output.gl_Position = finalPosition; output.vColor = vColor; output.uv = uv; return output; } @fragment fn fragmentMain( @location(0) vColor: vec4<f32>, @location(1) uv: vec2<f32> ) -> @location(0) vec4<f32> { // Create and initialize geometry with the provided uv. var geometry: Geometry; geometry.uv = uv; // Start with the input color. var fragColor: vec4<f32> = vColor; // Apply the deck.gl filter to the color. fragColor = deckgl_filter_color(fragColor, geometry); return fragColor; } `;