/** * Point Shader - WGSL for WebGPU * * Renders scatter points with SDF-based symbols. * Supports: circle, square, diamond, triangle, triangleDown, cross, x, star */ export declare const POINT_SHADER_WGSL = "\n// Uniform buffer for transforms, color, point properties\nstruct Uniforms {\n scale: vec2,\n translate: vec2,\n color: vec4,\n pointSize: f32,\n symbol: i32, // 0=circle, 1=square, 2=diamond, 3=triangle, 4=triangleDown, 5=cross, 6=x, 7=star\n _padding: vec2,\n};\n\n@group(0) @binding(0)\nvar uniforms: Uniforms;\n\nstruct VSInput {\n @location(0) position: vec2,\n};\n\nstruct VSOutput {\n @builtin(position) pos: vec4,\n @location(0) @interpolate(flat) pointSize: f32,\n @location(1) @interpolate(flat) symbol: i32,\n};\n\n@vertex\nfn vs_main(in: VSInput, @builtin(vertex_index) vertexIndex: u32) -> VSOutput {\n var out: VSOutput;\n let transformed = in.position * uniforms.scale + uniforms.translate;\n out.pos = vec4(transformed, 0.0, 1.0);\n out.pointSize = uniforms.pointSize;\n out.symbol = uniforms.symbol;\n return out;\n}\n\n// SDF functions for symbols\nfn sdCircle(p: vec2, r: f32) -> f32 {\n return length(p) - r;\n}\n\nfn sdBox(p: vec2, b: vec2) -> f32 {\n let d = abs(p) - b;\n return length(max(d, vec2(0.0))) + min(max(d.x, d.y), 0.0);\n}\n\nfn sdDiamond(p: vec2, r: f32) -> f32 {\n return (abs(p.x) + abs(p.y)) - r;\n}\n\nfn sdTriangle(p_in: vec2, r: f32) -> f32 {\n let k = sqrt(3.0);\n var p = p_in;\n p.x = abs(p.x) - r;\n p.y = p.y + r / k;\n if (p.x + k * p.y > 0.0) {\n p = vec2(p.x - k * p.y, -k * p.x - p.y) / 2.0;\n }\n p.x = p.x - clamp(p.x, -2.0 * r, 0.0);\n return -length(p) * sign(p.y);\n}\n\nfn sdCross(p: vec2, r: f32, thickness: f32) -> f32 {\n let d = abs(p);\n let s1 = sdBox(d, vec2(r, thickness));\n let s2 = sdBox(d, vec2(thickness, r));\n return min(s1, s2);\n}\n\nfn sdX(p: vec2, r: f32, thickness: f32) -> f32 {\n let c = cos(0.785398);\n let s = sin(0.785398);\n let m = mat2x2(c, -s, s, c);\n return sdCross(m * p, r, thickness);\n}\n\nfn sdStar(p_in: vec2, r: f32, rf: f32) -> f32 {\n let k1 = vec2(0.80901699, -0.58778525);\n let k2 = vec2(-k1.x, k1.y);\n var p = p_in;\n p.x = abs(p.x);\n p = p - 2.0 * max(dot(k1, p), 0.0) * k1;\n p = p - 2.0 * max(dot(k2, p), 0.0) * k2;\n p.x = abs(p.x);\n p.y = p.y - r;\n let ba = rf * vec2(-k1.y, k1.x) - vec2(0.0, 1.0);\n let h = clamp(dot(p, ba) / dot(ba, ba), 0.0, r);\n return length(p - ba * h) * sign(p.y * ba.x - p.x * ba.y);\n}\n\n@fragment\nfn fs_main(in: VSOutput) -> @location(0) vec4 {\n // Note: WebGPU doesn't have gl_PointCoord directly\n // Points in WebGPU require rendering quads instead\n // This shader needs instanced rendering with quads for proper point rendering\n // For now, return the color directly\n return uniforms.color;\n}\n"; export declare const POINT_QUAD_SHADER_WGSL = "\n// Uniform buffer for transforms, color, point properties\nstruct Uniforms {\n scale: vec2,\n translate: vec2,\n color: vec4,\n pointSize: f32,\n symbol: i32,\n viewport: vec2, // viewport dimensions for proper sizing\n};\n\n@group(0) @binding(0)\nvar uniforms: Uniforms;\n\nstruct VSInput {\n @location(0) position: vec2, // point center position\n @location(1) quadOffset: vec2, // quad vertex offset (-1 to 1)\n};\n\nstruct VSOutput {\n @builtin(position) pos: vec4,\n @location(0) uv: vec2, // -0.5 to 0.5 for SDF\n};\n\n@vertex\nfn vs_main(in: VSInput) -> VSOutput {\n var out: VSOutput;\n \n // Transform point position to NDC\n let transformed = in.position * uniforms.scale + uniforms.translate;\n \n // Calculate point size in NDC\n let pointSizeNDC = vec2(\n uniforms.pointSize / uniforms.viewport.x * 2.0,\n uniforms.pointSize / uniforms.viewport.y * 2.0\n );\n \n // Apply quad offset\n let offset = in.quadOffset * pointSizeNDC * 0.5;\n \n out.pos = vec4(transformed + offset, 0.0, 1.0);\n out.uv = in.quadOffset * 0.5; // -0.5 to 0.5\n \n return out;\n}\n\n// SDF functions\nfn sdCircle(p: vec2, r: f32) -> f32 {\n return length(p) - r;\n}\n\nfn sdBox(p: vec2, b: vec2) -> f32 {\n let d = abs(p) - b;\n return length(max(d, vec2(0.0))) + min(max(d.x, d.y), 0.0);\n}\n\nfn sdDiamond(p: vec2, r: f32) -> f32 {\n return (abs(p.x) + abs(p.y)) - r;\n}\n\nfn sdTriangle(p_in: vec2, r: f32) -> f32 {\n let k = sqrt(3.0);\n var p = p_in;\n p.x = abs(p.x) - r;\n p.y = p.y + r / k;\n if (p.x + k * p.y > 0.0) {\n p = vec2(p.x - k * p.y, -k * p.x - p.y) / 2.0;\n }\n p.x = p.x - clamp(p.x, -2.0 * r, 0.0);\n return -length(p) * sign(p.y);\n}\n\nfn sdCross(p: vec2, r: f32, thickness: f32) -> f32 {\n let d = abs(p);\n let s1 = sdBox(d, vec2(r, thickness));\n let s2 = sdBox(d, vec2(thickness, r));\n return min(s1, s2);\n}\n\nfn sdX(p: vec2, r: f32, thickness: f32) -> f32 {\n let c = cos(0.785398);\n let s = sin(0.785398);\n let m = mat2x2(c, -s, s, c);\n return sdCross(m * p, r, thickness);\n}\n\nfn sdStar(p_in: vec2, r: f32, rf: f32) -> f32 {\n let k1 = vec2(0.80901699, -0.58778525);\n let k2 = vec2(-k1.x, k1.y);\n var p = p_in;\n p.x = abs(p.x);\n p = p - 2.0 * max(dot(k1, p), 0.0) * k1;\n p = p - 2.0 * max(dot(k2, p), 0.0) * k2;\n p.x = abs(p.x);\n p.y = p.y - r;\n let ba = rf * vec2(-k1.y, k1.x) - vec2(0.0, 1.0);\n let h = clamp(dot(p, ba) / dot(ba, ba), 0.0, r);\n return length(p - ba * h) * sign(p.y * ba.x - p.x * ba.y);\n}\n\n@fragment\nfn fs_main(in: VSOutput) -> @location(0) vec4 {\n var d: f32 = 0.0;\n \n if (uniforms.symbol == 0) {\n d = sdCircle(in.uv, 0.45);\n } else if (uniforms.symbol == 1) {\n d = sdBox(in.uv, vec2(0.35));\n } else if (uniforms.symbol == 2) {\n d = sdDiamond(in.uv, 0.45);\n } else if (uniforms.symbol == 3) {\n d = sdTriangle(vec2(in.uv.x, in.uv.y + 0.1), 0.4);\n } else if (uniforms.symbol == 4) {\n d = sdTriangle(vec2(in.uv.x, -in.uv.y + 0.1), 0.4);\n } else if (uniforms.symbol == 5) {\n d = sdCross(in.uv, 0.45, 0.15);\n } else if (uniforms.symbol == 6) {\n d = sdX(in.uv, 0.45, 0.15);\n } else if (uniforms.symbol == 7) {\n d = sdStar(in.uv, 0.45, 0.4);\n }\n \n if (d > 0.02) {\n discard;\n }\n \n let alpha = 1.0 - smoothstep(0.0, 0.02, d);\n return vec4(uniforms.color.rgb, uniforms.color.a * alpha);\n}\n"; export declare const POINT_VERTEX_STRIDE: number;