/** * Instanced Line Shader - For ultra-large datasets * * Uses instancing to render line segments efficiently. * Each instance renders a line segment between two consecutive points. */ export declare const INSTANCED_LINE_SHADER_WGSL = "\nstruct Uniforms {\n scale: vec2,\n translate: vec2,\n color: vec4,\n lineWidth: f32,\n aspectRatio: f32,\n pointCount: u32,\n padding: u32,\n}\n\nstruct Point {\n x: f32,\n y: f32,\n}\n\n@group(0) @binding(0) var uniforms: Uniforms;\n@group(0) @binding(1) var points: array;\n\nstruct VertexOut {\n @builtin(position) position: vec4,\n @location(0) @interpolate(flat) segment_index: u32,\n}\n\n@vertex\nfn vs_main(\n @builtin(vertex_index) vertex_index: u32,\n @builtin(instance_index) instance_index: u32\n) -> VertexOut {\n var out: VertexOut;\n out.segment_index = instance_index;\n \n // Skip if beyond point count\n if (instance_index >= uniforms.pointCount - 1u) {\n out.position = vec4(0.0, 0.0, 0.0, 1.0);\n return out;\n }\n \n // Get the two points for this segment\n let p0 = points[instance_index];\n let p1 = points[instance_index + 1u];\n \n // Transform points to clip space\n let pos0 = vec2(p0.x * uniforms.scale.x + uniforms.translate.x,\n p0.y * uniforms.scale.y + uniforms.translate.y);\n let pos1 = vec2(p1.x * uniforms.scale.x + uniforms.translate.x,\n p1.y * uniforms.scale.y + uniforms.translate.y);\n \n // Calculate line direction and perpendicular\n let dir = normalize(pos1 - pos0);\n let perp = vec2(-dir.y, dir.x);\n \n // Adjust for aspect ratio\n let width = uniforms.lineWidth / 500.0; // Normalized width\n let offset = perp * width;\n \n // Each segment is a quad (2 triangles, 6 vertices)\n // vertex_index: 0,1,2 = first triangle, 3,4,5 = second triangle\n var pos: vec2;\n \n switch (vertex_index % 6u) {\n case 0u: { pos = pos0 - offset; } // bottom-left of start\n case 1u: { pos = pos0 + offset; } // top-left of start\n case 2u: { pos = pos1 - offset; } // bottom-left of end\n case 3u: { pos = pos1 - offset; } // bottom-left of end\n case 4u: { pos = pos0 + offset; } // top-left of start\n case 5u: { pos = pos1 + offset; } // top-left of end\n default: { pos = pos0; }\n }\n \n out.position = vec4(pos, 0.0, 1.0);\n return out;\n}\n\n@fragment\nfn fs_main(in: VertexOut) -> @location(0) vec4 {\n return uniforms.color;\n}\n"; /** * Instanced Point Shader - For ultra-large scatter datasets * * Uses instancing with a quad per point. * Supports SDF-based symbols. */ export declare const INSTANCED_POINT_SHADER_WGSL = "\nstruct Uniforms {\n scale: vec2,\n translate: vec2,\n color: vec4,\n pointSize: f32,\n symbolType: i32,\n viewportWidth: f32,\n viewportHeight: f32,\n pointCount: u32,\n padding: vec3,\n}\n\nstruct Point {\n x: f32,\n y: f32,\n}\n\n@group(0) @binding(0) var uniforms: Uniforms;\n@group(0) @binding(1) var points: array;\n\nstruct VertexOut {\n @builtin(position) position: vec4,\n @location(0) uv: vec2,\n}\n\n@vertex\nfn vs_main(\n @builtin(vertex_index) vertex_index: u32,\n @builtin(instance_index) instance_index: u32\n) -> VertexOut {\n var out: VertexOut;\n \n if (instance_index >= uniforms.pointCount) {\n out.position = vec4(0.0, 0.0, 0.0, 1.0);\n out.uv = vec2(0.0, 0.0);\n return out;\n }\n \n let pt = points[instance_index];\n \n // Transform point center to clip space\n let center = vec2(\n pt.x * uniforms.scale.x + uniforms.translate.x,\n pt.y * uniforms.scale.y + uniforms.translate.y\n );\n \n // Calculate point size in clip space\n let sizeX = uniforms.pointSize / uniforms.viewportWidth * 2.0;\n let sizeY = uniforms.pointSize / uniforms.viewportHeight * 2.0;\n \n // Quad vertices (6 for 2 triangles)\n var offset: vec2;\n var uv: vec2;\n \n switch (vertex_index % 6u) {\n case 0u: { offset = vec2(-sizeX, -sizeY); uv = vec2(-1.0, -1.0); }\n case 1u: { offset = vec2( sizeX, -sizeY); uv = vec2( 1.0, -1.0); }\n case 2u: { offset = vec2(-sizeX, sizeY); uv = vec2(-1.0, 1.0); }\n case 3u: { offset = vec2(-sizeX, sizeY); uv = vec2(-1.0, 1.0); }\n case 4u: { offset = vec2( sizeX, -sizeY); uv = vec2( 1.0, -1.0); }\n case 5u: { offset = vec2( sizeX, sizeY); uv = vec2( 1.0, 1.0); }\n default: { offset = vec2(0.0, 0.0); uv = vec2(0.0, 0.0); }\n }\n \n out.position = vec4(center + offset, 0.0, 1.0);\n out.uv = uv;\n return out;\n}\n\n// SDF functions\nfn sdCircle(p: vec2) -> f32 {\n return length(p) - 0.8;\n}\n\nfn sdSquare(p: vec2) -> f32 {\n let d = abs(p) - vec2(0.7);\n return length(max(d, vec2(0.0))) + min(max(d.x, d.y), 0.0);\n}\n\nfn sdDiamond(p: vec2) -> f32 {\n return (abs(p.x) + abs(p.y)) - 0.8;\n}\n\n@fragment\nfn fs_main(in: VertexOut) -> @location(0) vec4 {\n var d: f32;\n \n switch (uniforms.symbolType) {\n case 0: { d = sdCircle(in.uv); } // circle\n case 1: { d = sdSquare(in.uv); } // square\n case 2: { d = sdDiamond(in.uv); } // diamond\n default: { d = sdCircle(in.uv); }\n }\n \n if (d > 0.05) {\n discard;\n }\n \n let alpha = 1.0 - smoothstep(0.0, 0.05, d);\n return vec4(uniforms.color.rgb, uniforms.color.a * alpha);\n}\n"; export declare const INSTANCED_LINE_VERTEX_STRIDE = 8; export declare const INSTANCED_POINT_VERTEX_STRIDE = 8;