@godot-scene-web/effects 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/shaders/godot-shader.ts","../../src/shaders/transpile-wgsl.ts"],"sourcesContent":["// Godot Shading Language (`canvas_item` fragment subset) -> WebGL2 GLSL ES 3.00.\n//\n// This is NOT a full shading-language compiler. Godot's language is GLSL with\n// renamed built-ins and looser numeric typing, so most of a `fragment()` body is\n// already valid GLSL once we (a) declare the built-ins it reads as same-named\n// uniforms/locals, (b) pre-initialize `COLOR = texture(TEXTURE, UV)` and apply the\n// `MODULATE` auto-multiply rule, and (c) promote bare integer literals to float\n// (GLSL ES is strict where Godot implicitly converts, e.g. `smoothstep(0, ease,…)`).\n//\n// Constructs outside the supported subset (while loops, unsigned integer locals,\n// extra samplers, vertex-position built-ins, non-canvas_item shaders) throw\n// `UnsupportedShaderError`, which a renderer reports as a typed unsupported effect.\n// A strict single-canvas caller changes renderer mode for the whole stage rather than\n// mixing a per-node DOM fallback into an otherwise GPU-owned frame.\n// SCREEN_TEXTURE/SCREEN_PIXEL_SIZE transpile, but a renderer must explicitly provide\n// a painter-ordered accumulated target before executing them.\n\nexport class UnsupportedShaderError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"UnsupportedShaderError\";\n }\n}\n\nexport type GodotBlendMode = \"mix\" | \"add\" | \"sub\" | \"mul\" | \"premul_alpha\";\n\nexport interface ShaderUniform {\n /** Uniform name exactly as declared (matches `shader_parameter/<name>`). */\n name: string;\n /** GLSL type: float | int | bool | vec2 | vec3 | vec4 | mat2..4. */\n type: string;\n /** Array length for uniforms declared as `foo[N]`, if any. */\n arrayLength?: number;\n /** Parsed default from `= <literal>` (number, or component array), if any. */\n default?: number | number[];\n}\n\nexport interface ShaderSampler {\n /** Sampler uniform name (matches `shader_parameter/<name>`). */\n name: string;\n /** `: repeat_enable` hint -> the runtime sets wrap REPEAT (else CLAMP). */\n repeat: boolean;\n}\n\nexport interface ShaderVarying {\n /** GLSL type as declared (`vec4`, `float`, …) — Godot's spelling, not an emitter's. */\n type: string;\n name: string;\n}\n\nexport interface TranspiledShader {\n vertexGlsl: string;\n fragmentGlsl: string;\n /** User scalar/vector uniforms (built-ins + samplers excluded), in order. */\n uniforms: ShaderUniform[];\n /** User `sampler2D` uniforms; the runtime binds a texture per entry. */\n samplers: ShaderSampler[];\n blend: GodotBlendMode;\n /** The shader reads `TIME` -> the runtime must drive it from a clock (rAF). */\n usesTime: boolean;\n /** The shader reads `TEXTURE_PIXEL_SIZE` -> runtime supplies 1/textureSize. */\n usesTexturePixelSize: boolean;\n /** The shader reads `SCREEN_UV` -> runtime supplies the node's viewport rect. */\n usesScreenUv: boolean;\n /** The shader samples `SCREEN_TEXTURE` (the built-in token, or a declared\n * `hint_screen_texture` sampler) -> the runtime must supply a screen capture.\n * Only renderable when the runtime opts in (`enableScreenTextureCapture`). */\n usesScreenTexture: boolean;\n /** The shader reads `SCREEN_PIXEL_SIZE` -> runtime supplies 1/captureSize. */\n usesScreenPixelSize: boolean;\n}\n\nexport async function expandGodotShaderIncludes(\n source: string,\n resolveInclude: (\n path: string,\n ) => Promise<string | undefined> | string | undefined,\n seen: Set<string> = new Set(),\n depth = 0,\n): Promise<string> {\n if (depth > 16) {\n throw new UnsupportedShaderError(\"shader include depth exceeded\");\n }\n const includePattern = /^[ \\t]*#include\\s+\"([^\"]+)\"[ \\t]*$/gm;\n const chunks: string[] = [];\n let lastIndex = 0;\n for (const match of source.matchAll(includePattern)) {\n const index = match.index ?? 0;\n chunks.push(source.slice(lastIndex, index));\n const includePath = match[1];\n if (seen.has(includePath)) {\n chunks.push(`\\n/* skipped recursive include ${includePath} */\\n`);\n } else {\n const included = await resolveInclude(includePath);\n if (included === undefined) {\n chunks.push(match[0]);\n } else {\n const nextSeen = new Set(seen);\n nextSeen.add(includePath);\n chunks.push(\n await expandGodotShaderIncludes(\n included,\n resolveInclude,\n nextSeen,\n depth + 1,\n ),\n );\n }\n }\n lastIndex = index + match[0].length;\n }\n chunks.push(source.slice(lastIndex));\n return chunks.join(\"\");\n}\n\n// Built-ins we deliberately don't support yet (screen reads, vertex position,\n// point sprites, …). Presence of any of these -> UnsupportedShaderError.\nconst UNSUPPORTED_BUILTINS = [\n \"FRAGCOORD\",\n \"NORMAL\",\n \"NORMAL_TEXTURE\",\n \"POINT_COORD\",\n \"VERTEX\",\n \"INSTANCE_ID\",\n \"INSTANCE_CUSTOM\",\n \"SPECULAR_SHININESS\",\n \"LIGHT\",\n \"LIGHT_COLOR\",\n \"AT_LIGHT_PASS\",\n \"CUSTOM0\",\n \"CUSTOM1\",\n];\n\nconst GLSL_SAMPLER_TYPES = new Set([\"sampler2D\"]);\nconst SCALAR_OR_VECTOR =\n /^(float|int|bool|vec2|vec3|vec4|mat2|mat3|mat4|ivec2|ivec3|ivec4|bvec2|bvec3|bvec4)$/;\n\n/** The parsing front-end's output: Godot text in, emitter-neutral pieces out. Shared\n * by the GLSL emitter below and by any sibling emitter (the WGSL one) — parsing a\n * `.gdshader` twice, once per target language, is how the two would drift apart. */\nexport interface ParsedShader {\n blend: GodotBlendMode;\n uniforms: ShaderUniform[];\n samplers: ShaderSampler[];\n /** Names of `hint_screen_texture` sampler uniforms (conventionally\n * `SCREEN_TEXTURE`). Excluded from `samplers` — they bind the runtime's\n * screen capture, not a user texture. */\n screenTextureNames: string[];\n varyings: ShaderVarying[];\n vertexBody: string | null;\n fragmentBody: string;\n /** Top-level helper functions and consts (everything left after the directives,\n * uniforms, varyings, `vertex()` and `fragment()` are removed), verbatim. */\n helpers: string;\n /** Identifiers statically declared `int` (uniforms + locals). Bare integer\n * literals compared against these must NOT be promoted to float. */\n intIdentifiers: Set<string>;\n}\n\n/** One vertex-computed varying, hoisted into the fragment as a local because our\n * fullscreen quad makes it constant. Emitter-neutral: `type`/`name` are Godot's\n * spelling and `expr` is the vertex RHS with the vertex `COLOR` (the node's combined\n * modulate·self_modulate) already substituted by `MODULATE`. Each emitter formats\n * its own declaration syntax around these three fields. */\nexport interface ShaderVaryingHoist {\n type: string;\n name: string;\n expr: string;\n}\n\n/** Everything an emitter must know about a `ParsedShader` beyond its text: which\n * runtime-supplied built-ins to declare, how the node MODULATE has to be applied,\n * whether COLOR seeds opaque, and the varyings to hoist. Derived once by\n * `analyzeShader` so the GLSL and WGSL emitters cannot drift on the MODULATE /\n * opaque-fill rules, which encode measured Godot behavior rather than a preference. */\nexport interface ShaderAnalysis {\n /** The concatenated scan region the flags were derived from (helpers + vertex +\n * fragment). Hand this to `rejectUnsupported` — it must see the same text. */\n logic: string;\n /** Reads `TIME` -> the runtime must drive it from a clock (rAF). */\n usesTime: boolean;\n /** Reads `TEXTURE_PIXEL_SIZE` -> runtime supplies 1/textureSize. */\n usesTexturePixelSize: boolean;\n /** Reads `SCREEN_UV` -> runtime supplies the node's viewport rect. */\n usesScreenUv: boolean;\n /** Samples `SCREEN_TEXTURE` (built-in token or a `hint_screen_texture` sampler). */\n usesScreenTexture: boolean;\n /** Reads `SCREEN_PIXEL_SIZE` -> runtime supplies 1/captureSize. */\n usesScreenPixelSize: boolean;\n /** Reads `PI` -> the emitter must define the constant (Godot has it built in). */\n usesPi: boolean;\n /** A MODULATE uniform must be declared: the body names it, the engine multiply is\n * synthesized, or a hoisted varying was seeded from it. */\n needsModulate: boolean;\n /** Append the engine's `COLOR *= MODULATE` (see `analyzeShader` for when not to). */\n autoModulate: boolean;\n /** Seed `COLOR.a = 1` instead of the sampled texture alpha (pure-fill shaders). */\n opaqueColor: boolean;\n varyingHoists: ShaderVaryingHoist[];\n}\n\n/** Transpile a `.gdshader` source string. Throws `UnsupportedShaderError`. */\nexport function transpileGodotShader(source: string): TranspiledShader {\n // A `.tres` VisualShader carries its source in an escaped `code` property; unwrap BEFORE\n // stripping comments, which would otherwise eat `//` inside the container's strings.\n const cleaned = sanitizeReservedIdentifiers(\n stripComments(unwrapShaderResource(source)),\n );\n const parsed = parseShader(cleaned);\n\n // The fragment body + helpers + vertex passthrough, scanned together for\n // built-in usage and unsupported constructs. Guarding BEFORE analyzing keeps an\n // unsupported built-in reported as such, ahead of any varying-hoist complaint.\n const logic = shaderLogic(parsed);\n rejectUnsupported(logic, parsed);\n\n const analysis = analyzeShader(parsed);\n // Vertex-computed varyings are hoisted as locals in main(); `analyzeShader` already\n // substituted the vertex `COLOR` with MODULATE, so only the GLSL syntax is left.\n const varyingLocals = analysis.varyingHoists.map(\n (v) => `${v.type} ${v.name} = ${v.expr};`,\n );\n\n const fragmentGlsl = assembleFragment({ parsed, analysis, varyingLocals });\n\n return {\n vertexGlsl: VERTEX_GLSL,\n fragmentGlsl,\n uniforms: parsed.uniforms,\n samplers: parsed.samplers,\n blend: parsed.blend,\n usesTime: analysis.usesTime,\n usesTexturePixelSize: analysis.usesTexturePixelSize,\n usesScreenUv: analysis.usesScreenUv,\n usesScreenTexture: analysis.usesScreenTexture,\n usesScreenPixelSize: analysis.usesScreenPixelSize,\n };\n}\n\n// The fullscreen-quad vertex shader is fixed: a_pos covers clip space [-1,1]; v_uv\n// is the raw quad UV. The fragment prelude converts it to Godot's top-left UV.\nconst VERTEX_GLSL = `#version 300 es\nin vec2 a_pos;\nout vec2 v_uv;\nvoid main() {\n v_uv = a_pos * 0.5 + 0.5;\n gl_Position = vec4(a_pos, 0.0, 1.0);\n}\n`;\n\nfunction assembleFragment(input: {\n parsed: ParsedShader;\n analysis: ShaderAnalysis;\n varyingLocals: string[];\n}): string {\n const { parsed, analysis } = input;\n const decls: string[] = [\n \"uniform sampler2D TEXTURE;\",\n // Runtime-supplied UV fit (contain/cover/fill) mirroring TextureRect stretch.\n \"uniform vec2 _godot_uv_fit;\",\n // Runtime-supplied UV window (origin.xy + size.zw, node-local top-left fractions). Lets the runtime render\n // only a SUB-RECT of the node into a smaller canvas (e.g. clamping an off-screen-overflowing full-screen\n // background to the visible viewport) while the shader still samples the correct portion. Default (0,0,1,1)\n // ⇒ full node, identical to before.\n \"uniform vec4 _godot_uv_window;\",\n ...(analysis.usesTime ? [\"uniform float TIME;\"] : []),\n ...(analysis.usesTexturePixelSize\n ? [\"uniform vec2 TEXTURE_PIXEL_SIZE;\"]\n : []),\n ...(analysis.needsModulate ? [\"uniform vec4 MODULATE;\"] : []),\n // SCREEN_UV is the node's slice of the viewport: origin + the node-local UV\n // scaled by the node's normalized on-screen size (both runtime-supplied).\n ...(analysis.usesScreenUv\n ? [\n \"uniform vec2 _godot_screen_origin;\",\n \"uniform vec2 _godot_screen_size;\",\n ]\n : []),\n // SCREEN_TEXTURE is a runtime-captured composite of the content drawn before the\n // node, in VIEWPORT coordinates (the whole scene-root rect) — so the body's\n // `texture(SCREEN_TEXTURE, SCREEN_UV …)` samples it directly, no body rewriting.\n // A `hint_screen_texture` sampler under a non-conventional name aliases it.\n ...(analysis.usesScreenTexture\n ? [\n \"uniform sampler2D SCREEN_TEXTURE;\",\n ...parsed.screenTextureNames\n .filter((name) => name !== \"SCREEN_TEXTURE\")\n .map((name) => `#define ${name} SCREEN_TEXTURE`),\n ]\n : []),\n ...(analysis.usesScreenPixelSize\n ? [\"uniform vec2 SCREEN_PIXEL_SIZE;\"]\n : []),\n ...(analysis.usesPi ? [\"const float PI = 3.141592653589793;\"] : []),\n ];\n for (const u of parsed.uniforms) {\n decls.push(\n `uniform ${u.type} ${u.name}${u.arrayLength ? `[${u.arrayLength}]` : \"\"};`,\n );\n }\n for (const s of parsed.samplers) {\n decls.push(`uniform sampler2D ${s.name};`);\n }\n const helpers = promoteIntLiterals(\n parsed.helpers,\n parsed.intIdentifiers,\n ).trim();\n const body = promoteIntLiterals(parsed.fragmentBody, parsed.intIdentifiers);\n return `#version 300 es\nprecision highp float;\nin vec2 v_uv;\nout vec4 fragColor;\n${decls.join(\"\\n\")}\n${helpers ? `${helpers}\\n` : \"\"}\nvoid main() {\n vec2 GODOT_UV = _godot_uv_window.xy + vec2(v_uv.x, 1.0 - v_uv.y) * _godot_uv_window.zw;\n vec2 UV = (GODOT_UV - 0.5) / _godot_uv_fit + 0.5;\n${\n analysis.usesScreenUv\n ? \" vec2 SCREEN_UV = _godot_screen_origin + GODOT_UV * _godot_screen_size;\\n\"\n : \"\"\n} vec4 COLOR = ${analysis.opaqueColor ? \"vec4(texture(TEXTURE, UV).rgb, 1.0)\" : \"texture(TEXTURE, UV)\"};\n${input.varyingLocals.map((l) => ` ${l}`).join(\"\\n\")}\n${indent(body)}\n${analysis.autoModulate ? \" COLOR *= MODULATE;\" : \"\"}\n // PREMULTIPLIED. The shared canvas declares \\`premultipliedAlpha: true\\` (webgl/shared-gl.ts), so\n // this is THE canvas contract: return rgb*a with a. The shader backend draws with BLEND OFF, so\n // whatever this writes IS the buffer — returning straight COLOR here halos every partially\n // transparent node, and neither the compiler nor a readback of the canvas would say so.\n // Character-for-character the WGSL emitter's return (webgpu/transpile-wgsl.ts), on purpose: one\n // contract, two languages.\n fragColor = vec4(COLOR.rgb * COLOR.a, COLOR.a);\n}\n`;\n}\n\n// ---- analysis --------------------------------------------------------------\n\n/** The text every built-in flag is scanned over. The vertex body and the top-level\n * helpers count, not just `fragment()`: a helper may read TIME/PI, and a varying\n * computed in `vertex()` is hoisted into the fragment. `rejectUnsupported` must be\n * given this same region, or a guard would scan less text than the flags did. */\nexport function shaderLogic(parsed: ParsedShader): string {\n return `${parsed.helpers}\\n${parsed.vertexBody ?? \"\"}\\n${parsed.fragmentBody}`;\n}\n\n/** Derive the emitter-neutral facts about a parsed shader (see `ShaderAnalysis`).\n * Pure, and deliberately NOT a validator: run `rejectUnsupported(analysis.logic,\n * parsed)` for that, before analyzing, so an unsupported built-in outranks a\n * varying-hoist complaint. Throws `UnsupportedShaderError` only for a `vertex()`\n * body that cannot be reduced to constant varying assignments. */\nexport function analyzeShader(parsed: ParsedShader): ShaderAnalysis {\n const logic = shaderLogic(parsed);\n\n const usesTime = hasToken(logic, \"TIME\");\n const usesTexturePixelSize = hasToken(logic, \"TEXTURE_PIXEL_SIZE\");\n const usesScreenUv = hasToken(logic, \"SCREEN_UV\");\n // Either the built-in token or any declared `hint_screen_texture` sampler (Godot 4\n // spells the built-in as such a uniform; the conventional name is SCREEN_TEXTURE).\n const usesScreenTexture =\n hasToken(logic, \"SCREEN_TEXTURE\") ||\n parsed.screenTextureNames.some((name) => hasToken(logic, name));\n const usesScreenPixelSize = hasToken(logic, \"SCREEN_PIXEL_SIZE\");\n const usesPi = hasToken(logic, \"PI\");\n const usesModulateBuiltin = hasToken(parsed.fragmentBody, \"MODULATE\");\n // Godot bakes the node modulate into COLOR's INITIAL value (`texture·MODULATE`)\n // and never re-applies it after `fragment()`. We model that as a trailing\n // `COLOR *= MODULATE` — but ONLY when the shader leaves the modulate in COLOR.\n // It must be skipped when the shader:\n // - handles modulate itself (the MODULATE built-in, or reads the vertex\n // `COLOR` = the combined modulate·self_modulate in `vertex()`), or\n // - fully OVERWRITES `COLOR.rgb` (or the whole `COLOR`) with a plain `=`,\n // which DISCARDS the modulate (e.g. `COLOR.rgb = gradient`; the fill is the\n // gradient ALONE, not gradient·self_modulate). Re-multiplying would wrongly\n // darken it. A `COLOR.a =` / `COLOR.rgb +=` keeps the modulate in rgb, so\n // those are NOT matched.\n const vertexReadsModulate =\n parsed.vertexBody !== null && hasToken(parsed.vertexBody, \"COLOR\");\n const overwritesColorRgb = /\\bCOLOR(\\.rgb)?\\s*=(?!=)/.test(\n parsed.fragmentBody,\n );\n // Whether the fragment READS COLOR (the sampled `texture·MODULATE`) rather than only\n // assigning to it. Strip the plain `COLOR(.rgba) =` assignment targets; any COLOR\n // token that survives is a read. A shader that reads COLOR is a texture EFFECT — a\n // conditional recolor / tint that samples the sprite (e.g. `if (distance(COLOR.rgb,\n // key) < t) COLOR.rgb = repl;`) — so its `COLOR.rgb =` is a PARTIAL edit, not a fill.\n // Its texture rgb, its alpha (the sprite's SHAPE), and the node modulate must all be\n // kept, exactly as for a plain texture shader.\n const bodyReadsColor = hasToken(\n parsed.fragmentBody.replace(/\\bCOLOR(?:\\.[rgba]+)?\\s*=(?!=)/g, \"\"),\n \"COLOR\",\n );\n // A PURE FILL overwrites COLOR.rgb WITHOUT ever reading it (`COLOR.rgb = gradient`):\n // the texture rgb is discarded, so the modulate is dropped (a trailing multiply would\n // darken the fill) and the node paints opaque (see below). A recolor that reads COLOR\n // is NOT a pure fill, so neither rule applies to it.\n const pureFillOverwrite = overwritesColorRgb && !bodyReadsColor;\n const autoModulate =\n !usesModulateBuiltin && !vertexReadsModulate && !pureFillOverwrite;\n\n // OPAQUE init: when a shader is a PURE FILL (overwrites COLOR.rgb without reading it)\n // and never touches COLOR.a nor samples the node TEXTURE, the texture is only an\n // incidental alpha carrier — its soft nine-patch-cap alpha would otherwise feather\n // the node's edges. We seed COLOR.a = 1 so the node paints as a crisp solid (e.g. a\n // clean gradient-filled bar segment whose rounded shape comes from the parent clip\n // Mask, not a stretched texture cap that lets the layer behind leak through at the\n // edge). A recolor that READS COLOR keeps the texture alpha — forcing it opaque would\n // paint the sprite's transparent surround as a solid rectangle. Shaders that\n // read/write COLOR.a or sample TEXTURE also keep the texture alpha.\n const usesColorAlpha = /\\bCOLOR\\.a\\b/.test(parsed.fragmentBody);\n const samplesNodeTexture = hasToken(parsed.fragmentBody, \"TEXTURE\");\n const opaqueColor =\n pureFillOverwrite && !usesColorAlpha && !samplesNodeTexture;\n\n // Vertex-computed varyings are constant across our fullscreen quad, so they become\n // locals seeded from the MODULATE uniform — which is itself a reason to declare it.\n const varyingHoists = buildVaryingHoists(parsed);\n\n return {\n logic,\n usesTime,\n usesTexturePixelSize,\n usesScreenUv,\n usesScreenTexture,\n usesScreenPixelSize,\n usesPi,\n needsModulate:\n usesModulateBuiltin || autoModulate || varyingHoists.length > 0,\n autoModulate,\n opaqueColor,\n varyingHoists,\n };\n}\n\nfunction buildVaryingHoists(parsed: ParsedShader): ShaderVaryingHoist[] {\n if (parsed.vertexBody === null || parsed.varyings.length === 0) {\n return [];\n }\n const typeByName = new Map(parsed.varyings.map((v) => [v.name, v.type]));\n const hoists: ShaderVaryingHoist[] = [];\n // Only support a vertex body that is a sequence of `<varying> = <expr>;`\n // assignments whose expr references the vertex COLOR (modulate) / uniforms.\n const statements = parsed.vertexBody\n .split(\";\")\n .map((s) => s.trim())\n .filter(Boolean);\n for (const statement of statements) {\n const eq = statement.indexOf(\"=\");\n if (eq < 0) {\n throw new UnsupportedShaderError(\n `vertex(): only constant varying assignments are supported, got \"${statement}\"`,\n );\n }\n const lhs = statement.slice(0, eq).trim();\n const rhs = statement.slice(eq + 1).trim();\n const type = typeByName.get(lhs);\n if (!type) {\n throw new UnsupportedShaderError(\n `vertex(): assignment to non-varying \"${lhs}\" is not supported`,\n );\n }\n // The vertex COLOR is the node's combined modulate·self_modulate -> MODULATE.\n const expr = replaceToken(promoteIntLiterals(rhs), \"COLOR\", \"MODULATE\");\n hoists.push({ type, name: lhs, expr });\n }\n return hoists;\n}\n\n// ---- parsing ---------------------------------------------------------------\n\n/** Parse cleaned Godot source (run `stripComments` + `sanitizeReservedIdentifiers`\n * first) into the emitter-neutral `ParsedShader`. Throws `UnsupportedShaderError`. */\nexport function parseShader(src: string): ParsedShader {\n const shaderType = /shader_type\\s+([a-z_]+)\\s*;/.exec(src);\n if (!shaderType) {\n throw new UnsupportedShaderError(\"missing shader_type declaration\");\n }\n if (shaderType[1] !== \"canvas_item\") {\n throw new UnsupportedShaderError(\n `unsupported shader_type \"${shaderType[1]}\" (only canvas_item)`,\n );\n }\n\n const blend = parseBlendMode(src);\n const { uniforms, samplers, screenTextureNames } = parseUniforms(src);\n const varyings = parseVaryings(src);\n\n const fragment = extractFunction(src, \"fragment\");\n if (fragment === null) {\n throw new UnsupportedShaderError(\"missing fragment() function\");\n }\n const vertex = extractFunction(src, \"vertex\");\n\n // Whatever remains after removing the directives / uniforms / varyings /\n // vertex / fragment is top-level helper functions and consts.\n let helpers = src\n .replace(/shader_type\\s+[a-z_]+\\s*;/g, \"\")\n .replace(/render_mode[^;]*;/g, \"\")\n .replace(/uniform[^;]*;/g, \"\")\n .replace(/varying[^;]*;/g, \"\");\n helpers = removeFunction(helpers, \"fragment\");\n helpers = removeFunction(helpers, \"vertex\");\n\n // THE RESIDUAL IS EMITTED VERBATIM, so it has to be shader source and not \"whatever was\n // left over\". `helpers` is computed by SUBTRACTION — everything the parser recognised,\n // removed — which is exactly the shape that turns an unrecognised input into a silent\n // pass-through: hand this a Godot `.tres` and the leftovers are the container itself,\n // emitted into the GLSL between the declarations and `main()`.\n //\n // `unwrapShaderResource` is the fix and this is the INVARIANT behind it: even if some\n // future container shape slips past that check, it stops here as a named refusal (the\n // caller keeps its CSS/SVG fallback) rather than as an uncompilable shader. Keyed on the\n // SECTION headers rather than on a bare `[`, which is legal GLSL array syntax.\n const stray = RESOURCE_SECTION_RE.exec(helpers);\n if (stray) {\n throw new UnsupportedShaderError(\n `source is a Godot resource container, not shader code (found \"${stray[0]}\")`,\n );\n }\n\n return {\n blend,\n uniforms,\n samplers,\n screenTextureNames,\n varyings,\n vertexBody: vertex,\n fragmentBody: fragment,\n helpers: helpers.trim(),\n intIdentifiers: parseIntIdentifiers(src, uniforms),\n };\n}\n\nfunction parseBlendMode(src: string): GodotBlendMode {\n const match = /render_mode\\s+([^;]+);/.exec(src);\n if (!match) {\n return \"mix\";\n }\n const modes = match[1].split(\",\").map((m) => m.trim());\n for (const mode of modes) {\n if (mode === \"blend_add\") return \"add\";\n if (mode === \"blend_sub\") return \"sub\";\n if (mode === \"blend_mul\") return \"mul\";\n if (mode === \"blend_premul_alpha\") return \"premul_alpha\";\n if (mode === \"blend_mix\") return \"mix\";\n // Non-blend render_modes (unshaded, etc.) are ignored for canvas_item.\n }\n return \"mix\";\n}\n\nfunction parseUniforms(src: string): {\n uniforms: ShaderUniform[];\n samplers: ShaderSampler[];\n screenTextureNames: string[];\n} {\n const uniforms: ShaderUniform[] = [];\n const samplers: ShaderSampler[] = [];\n const screenTextureNames: string[] = [];\n const re = /uniform\\s+([a-zA-Z0-9_]+)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s*([^;]*);/g;\n for (const match of src.matchAll(re)) {\n const type = match[1];\n const name = match[2];\n const rest = match[3].trim(); // array length, hints, and/or `= default`\n const arrayLength = parseArrayLength(rest, src);\n if (GLSL_SAMPLER_TYPES.has(type)) {\n // A `hint_screen_texture` sampler is Godot 4's SCREEN_TEXTURE built-in, not a\n // user texture: it must NOT land in `samplers` (the runtime would try to resolve\n // it as a shader_parameter URL) — the runtime binds its screen capture instead.\n if (/\\bhint_screen_texture\\b/.test(rest)) {\n screenTextureNames.push(name);\n continue;\n }\n // Each user `sampler2D` is bound to its own texture unit by the runtime;\n // its image source (a procedural NoiseTexture2D/GradientTexture1D etc.) is\n // baked from the material's `shader_parameter/<name>`. Honor the\n // `repeat_enable` hint so scrolling samples wrap instead of clamping.\n samplers.push({ name, repeat: /\\brepeat_enable\\b/.test(rest) });\n continue;\n }\n if (!SCALAR_OR_VECTOR.test(type)) {\n throw new UnsupportedShaderError(`unsupported uniform type \"${type}\"`);\n }\n uniforms.push({\n type,\n name,\n ...(arrayLength ? { arrayLength } : {}),\n default: parseUniformDefault(rest),\n });\n }\n return { uniforms, samplers, screenTextureNames };\n}\n\nfunction parseArrayLength(rest: string, src: string): number | undefined {\n const match = /^\\[\\s*([^\\]]+)\\s*\\]/.exec(rest);\n if (!match) {\n return undefined;\n }\n const constants = parseConstInts(src);\n const expr = match[1].replace(/[A-Za-z_][A-Za-z0-9_]*/g, (name) =>\n constants.has(name) ? String(constants.get(name)) : \"NaN\",\n );\n if (!/^[0-9+\\-*/ ().NaN]+$/.test(expr)) {\n return undefined;\n }\n try {\n const value = Function(`\"use strict\"; return (${expr});`)();\n return Number.isFinite(value) && value > 0 ? Math.round(value) : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction parseConstInts(src: string): Map<string, number> {\n const out = new Map<string, number>();\n const re = /\\bconst\\s+int\\s+([A-Za-z_][A-Za-z0-9_]*)\\s*=\\s*(-?\\d+)\\s*;/g;\n for (const match of src.matchAll(re)) {\n out.set(match[1], Number.parseInt(match[2], 10));\n }\n return out;\n}\n\nfunction parseIntIdentifiers(\n src: string,\n uniforms: ShaderUniform[],\n): Set<string> {\n const out = new Set(\n uniforms.filter((u) => u.type === \"int\").map((u) => u.name),\n );\n const re = /\\b(?:const\\s+)?int\\s+([A-Za-z_][A-Za-z0-9_]*)/g;\n for (const match of src.matchAll(re)) {\n out.add(match[1]);\n }\n return out;\n}\n\nfunction parseUniformDefault(rest: string): number | number[] | undefined {\n const eq = rest.indexOf(\"=\");\n if (eq < 0) {\n return undefined;\n }\n const value = rest.slice(eq + 1).trim();\n const ctor = /^[a-z0-9]*vec[234]\\s*\\(([^)]*)\\)$/.exec(value);\n if (ctor) {\n return ctor[1].split(\",\").map((c) => scalarLiteral(c.trim()) ?? Number.NaN);\n }\n return scalarLiteral(value);\n}\n\n// A numeric OR boolean literal as a number (`true` -> 1, `false` -> 0): a\n// `uniform bool ... = true;` default must survive as 1, else the runtime's\n// `raw ?? default` fallback uploads 0 and silently flips the toggle.\nfunction scalarLiteral(value: string): number | undefined {\n if (value === \"true\") {\n return 1;\n }\n if (value === \"false\") {\n return 0;\n }\n const num = Number.parseFloat(value);\n return Number.isFinite(num) ? num : undefined;\n}\n\nfunction parseVaryings(src: string): ShaderVarying[] {\n const out: ShaderVarying[] = [];\n const re = /varying\\s+([a-zA-Z0-9_]+)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s*;/g;\n for (const match of src.matchAll(re)) {\n out.push({ type: match[1], name: match[2] });\n }\n return out;\n}\n\n// ---- guards ----------------------------------------------------------------\n\n/** Throw `UnsupportedShaderError` for constructs no emitter supports. Give it\n * `shaderLogic(parsed)` — the same region the analysis flags are scanned over. */\nexport function rejectUnsupported(logic: string, parsed: ParsedShader): void {\n for (const builtin of UNSUPPORTED_BUILTINS) {\n if (hasToken(logic, builtin)) {\n throw new UnsupportedShaderError(`unsupported built-in \"${builtin}\"`);\n }\n }\n // Global int-literal promotion is only safe when there are no genuine integer\n // contexts: reject int/uint locals, loops, and array indexing/declarations.\n if (/\\bwhile\\b/.test(logic)) {\n throw new UnsupportedShaderError(\"while loops are not supported\");\n }\n if (/\\b(uint|uvec[234])\\b/.test(logic)) {\n throw new UnsupportedShaderError(\n \"unsigned integer variables are not supported\",\n );\n }\n // Reject unknown ALL-CAPS built-in-looking tokens that aren't supported and\n // aren't a known mixed-case user identifier (defensive; GLSL compile is the\n // ultimate backstop).\n void parsed;\n}\n\n// ---- Godot resource containers ---------------------------------------------\n//\n// A Godot shader does not always arrive as a `.gdshader`. A VisualShader — the node\n// graph editor's output — is saved as a `.tres` TEXT RESOURCE: an INI-ish container of\n// `[gd_resource]` / `[sub_resource]` sections, with the generated shader source stored\n// as an escaped string in the `[resource]` section's `code` property. A caller that\n// fetches a shader by path and hands back `response.text()` therefore hands us the\n// CONTAINER, and it is not this module's caller's job to know the difference — Godot\n// itself loads either and gets a shader.\n//\n// UNWRAPPED HERE, ahead of `stripComments`, because comment-stripping a container would\n// eat `//` sequences inside its quoted strings. And CONSERVATIVELY: only a source whose\n// first non-whitespace is a `[gd_resource` header is treated as one, so a `.gdshader`\n// that merely mentions the word in a comment is untouched.\n\n/** The escapes Godot writes into a `.tres` string literal. */\nfunction unescapeResourceString(text: string): string {\n return text.replace(/\\\\(u[0-9a-fA-F]{4}|[\\s\\S])/g, (_all, esc: string) => {\n if (esc[0] === \"u\") {\n return String.fromCharCode(Number.parseInt(esc.slice(1), 16));\n }\n switch (esc) {\n case \"n\":\n return \"\\n\";\n case \"t\":\n return \"\\t\";\n case \"r\":\n return \"\\r\";\n case \"b\":\n return \"\\b\";\n case \"f\":\n return \"\\f\";\n default:\n // `\\\"` and `\\\\`, and anything else Godot ever adds: the escaped char itself.\n return esc;\n }\n });\n}\n\n/**\n * The shader source inside a Godot text-resource container, or `source` unchanged.\n *\n * Throws {@link UnsupportedShaderError} for a container with no usable `code` property —\n * NEVER returns the container. That refusal is the whole point: before it existed, every\n * parse step happened to succeed against a `.tres` (the `shader_type`, the `uniform`\n * declarations and the `fragment()` body all match INSIDE the escaped `code` string), and\n * then the subtractive `helpers` residual in `parseShader` carried the entire container\n * into the emitted GLSL — declarations, then `[gd_resource type=\"VisualShader\" …` as the\n * first line of what should have been shader code. The driver reported a syntax error at\n * a `[`, which is a long way from \"this file is not a shader\".\n */\nexport function unwrapShaderResource(source: string): string {\n if (!/^\\s*\\[gd_resource\\b/.test(source)) {\n return source;\n }\n // Godot writes resource properties at column 0, so the anchor is exact rather than a\n // guess: `code = \"…\"` with the usual backslash escapes.\n const match = /^code\\s*=\\s*\"((?:[^\"\\\\]|\\\\[\\s\\S])*)\"/m.exec(source);\n if (!match) {\n throw new UnsupportedShaderError(\n \"Godot resource container has no `code` property (not a shader resource)\",\n );\n }\n const code = unescapeResourceString(match[1]).trim();\n if (code === \"\") {\n throw new UnsupportedShaderError(\n \"Godot resource container has an empty `code` property\",\n );\n }\n return code;\n}\n\n/** Sections that can only come from a resource container — never legal shader source. */\nconst RESOURCE_SECTION_RE =\n /\\[(?:gd_resource|sub_resource|ext_resource|resource)\\b/;\n\n// ---- text utilities --------------------------------------------------------\n\nexport function stripComments(src: string): string {\n return src.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \" \").replace(/\\/\\/[^\\n]*/g, \"\");\n}\n\n// `input` is reserved in GLSL ES but a legal Godot identifier (the affliction erosion\n// include declares `float input`) — rename it once, here in the source text, so every\n// emitter downstream parses and emits a safe name rather than each re-discovering it.\nexport function sanitizeReservedIdentifiers(src: string): string {\n return replaceToken(src, \"input\", \"inputValue\");\n}\n\n// Extract the brace-matched body of `void <name>() { ... }` (inner text only),\n// or null if absent.\nexport function extractFunction(src: string, name: string): string | null {\n const head = new RegExp(`void\\\\s+${name}\\\\s*\\\\(\\\\s*\\\\)\\\\s*\\\\{`).exec(src);\n if (!head) {\n return null;\n }\n const open = head.index + head[0].length - 1; // index of `{`\n const end = matchBrace(src, open);\n return src.slice(open + 1, end);\n}\n\nfunction removeFunction(src: string, name: string): string {\n const head = new RegExp(`void\\\\s+${name}\\\\s*\\\\(\\\\s*\\\\)\\\\s*\\\\{`).exec(src);\n if (!head) {\n return src;\n }\n const open = head.index + head[0].length - 1;\n const end = matchBrace(src, open);\n return src.slice(0, head.index) + src.slice(end + 1);\n}\n\n/** Index of the `}` closing the `{` at `openIndex`. Brace depth only — enough for the\n * supported subset, which has no braces inside strings (Godot shaders have none). */\nexport function matchBrace(src: string, openIndex: number): number {\n let depth = 0;\n for (let i = openIndex; i < src.length; i += 1) {\n if (src[i] === \"{\") depth += 1;\n else if (src[i] === \"}\") {\n depth -= 1;\n if (depth === 0) return i;\n }\n }\n throw new UnsupportedShaderError(\"unbalanced braces\");\n}\n\n// Promote bare integer literals to float (`0` -> `0.0`), skipping anything that\n// is part of an identifier (`vec3`, `mat3`) or already a float (`6.28`, `.5`).\nexport function promoteIntLiterals(\n src: string,\n intIdentifiers: Iterable<string> = [],\n): string {\n const ranges = skipRanges(src);\n const intNames = [...intIdentifiers];\n return src.replace(/(?<![\\w.])(\\d+)(?![\\w.])/g, (match, _digits, offset) => {\n if (ranges.some(([start, end]) => offset >= start && offset < end)) {\n return match;\n }\n if (\n intNames.length > 0 &&\n isIntegerComparisonLiteral(src, offset, intNames)\n ) {\n return match;\n }\n return `${match}.0`;\n });\n}\n\nfunction skipRanges(src: string): Array<[number, number]> {\n const ranges: Array<[number, number]> = [];\n for (const re of [\n /\\[[^\\]]*\\]/g,\n /\\bfor\\s*\\([^)]*\\)/g,\n /\\b(?:const\\s+)?int\\s+[^;]+;/g,\n ]) {\n for (const match of src.matchAll(re)) {\n const index = match.index ?? 0;\n ranges.push([index, index + match[0].length]);\n }\n }\n return ranges;\n}\n\nfunction isIntegerComparisonLiteral(\n src: string,\n offset: number,\n tokens: string[],\n): boolean {\n let start = offset;\n while (start > 0 && !\";{}\\n\".includes(src[start - 1])) start -= 1;\n let end = offset;\n while (end < src.length && !\";{}\\n\".includes(src[end])) end += 1;\n const statement = src.slice(start, end);\n const localOffset = offset - start;\n const before = statement.slice(0, localOffset);\n const after = statement.slice(\n localOffset + String(src.slice(offset).match(/^\\d+/)?.[0] ?? \"\").length,\n );\n const comparison = \"(?:==|!=|<=|>=|<|>)\";\n return tokens.some((token) => {\n const escaped = token.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n return (\n new RegExp(`\\\\b${escaped}\\\\b\\\\s*${comparison}\\\\s*$`).test(before) ||\n new RegExp(`^\\\\s*${comparison}\\\\s*\\\\b${escaped}\\\\b`).test(after)\n );\n });\n}\n\n/** Whole-identifier match: `TIME` must not fire on `LIFETIME`, `COLOR` not on\n * `COLOR_KEY`. Every built-in probe in this file goes through it. */\nexport function hasToken(src: string, token: string): boolean {\n return new RegExp(`(?<![\\\\w])${escapeRegExp(token)}(?![\\\\w])`).test(src);\n}\n\n/** Whole-identifier replace, same boundary rule as `hasToken`. */\nexport function replaceToken(\n src: string,\n token: string,\n replacement: string,\n): string {\n return src.replace(\n new RegExp(`(?<![\\\\w])${escapeRegExp(token)}(?![\\\\w])`, \"g\"),\n replacement,\n );\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction indent(text: string): string {\n return text\n .split(\"\\n\")\n .map((line) => (line.trim() ? ` ${line.trim()}` : \"\"))\n .join(\"\\n\");\n}\n","// Godot Shading Language (`canvas_item` fragment subset) -> WGSL, for the WebGPU\n// effects renderer. Sibling of `webgl/transpile.ts`, NOT a replacement: both emitters\n// consume the same front-end (`parseShader` -> `rejectUnsupported` -> `analyzeShader`),\n// so the MODULATE / opaque-fill / varying-hoist rules — which encode measured Godot\n// behavior rather than a preference — cannot drift between the two backends.\n//\n// WGSL is not \"GLSL with different keywords\", so this is a real source-to-source pass\n// rather than a rename table. The constructs that actually differ, and are handled here:\n//\n// * declarations are `var name: T = e` (and zero-initialize without one),\n// * there is no ternary — `c ? a : b` becomes `select(b, a, c)`,\n// * a MULTI-component swizzle is not an assignable place (`COLOR.rgb = e` is illegal),\n// * `texture(s, uv)` is `textureSampleLevel(s, s_smp, uv, 0.0)` and a sampler is a\n// separate binding from its texture,\n// * `mod` is floor-signed in GLSL and `%` is trunc-signed in WGSL,\n// * `inverse()` does not exist,\n// * uniforms live in ONE host-shareable struct with explicit byte offsets, and a\n// WGSL `bool` is not host-shareable at all.\n//\n// Everything in this file is strings and plain numbers: no `GPU*` global is referenced\n// and nothing is imported from `webgpu/device.ts`, so it is safe to import from a node\n// CLI (the perf harness and the parity harness both do) and testable without a device.\n//\n// Constructs this emitter cannot express but WebGL can (SCREEN_TEXTURE and friends,\n// float/vec2 uniform arrays, ternaries outside a whole right-hand side, …) throw\n// `UnsupportedWgslShaderError`. The runtime catches THAT subclass at binding-compile\n// time and puts the one binding on WebGL — a plain `UnsupportedShaderError` from the\n// shared front-end keeps its stronger meaning, \"no backend can render this\".\n\nimport {\n analyzeShader,\n type GodotBlendMode,\n hasToken,\n matchBrace,\n type ParsedShader,\n parseShader,\n rejectUnsupported,\n replaceToken,\n type ShaderAnalysis,\n type ShaderSampler,\n sanitizeReservedIdentifiers,\n shaderLogic,\n stripComments,\n UnsupportedShaderError,\n unwrapShaderResource,\n} from \"./godot-shader\";\n\n/** \"WGSL can't, WebGL can.\" Thrown for shapes the GLSL emitter renders happily; the\n * runtime answers it with a per-binding WebGL fallback, not with the CSS fallback. */\nexport class UnsupportedWgslShaderError extends UnsupportedShaderError {\n constructor(message: string) {\n super(message);\n this.name = \"UnsupportedWgslShaderError\";\n }\n}\n\n/** One member of the single uniform struct, with the byte offset a writer needs. */\nexport interface WgslUniformField {\n /** Uniform name exactly as Godot declared it (matches `shader_parameter/<name>`).\n * NOT necessarily the emitted WGSL member name — a Godot name that collides with a\n * WGSL reserved word or with a built-in member is renamed inside the module only. */\n name: string;\n /** WGSL type of the member (`f32`, `i32`, `vec3f`, `vec2i`, `mat3x3f`, …). */\n type: string;\n /** Godot's own spelling (`float`, `bool`, `vec3`, …). A `bool` uniform is stored as\n * `f32` (WGSL `bool` is not host-shareable), so a writer needs this to know that an\n * `f32` member is really a 1/0 flag. */\n godotType: string;\n /** Element count for `foo[N]` uniforms. Elements are 16 bytes apart (WGSL uniform\n * address space rounds array stride up to 16). */\n arrayLength?: number;\n offsetBytes: number;\n sizeBytes: number;\n default?: number | number[];\n}\n\n/** Byte offsets of the runtime-supplied built-ins inside the SAME uniform struct.\n * `uvFit`/`uvWindow` are always present; the rest exist only when the shader reads\n * the corresponding built-in (`usesTime`, `usesTexturePixelSize`, MODULATE, SCREEN_UV). */\nexport interface WgslBuiltinOffsets {\n uvFit: number;\n uvWindow: number;\n time?: number;\n texturePixelSize?: number;\n modulate?: number;\n screenOrigin?: number;\n screenSize?: number;\n}\n\n/** The transpiler-owned `@group(0)` binding table. User sampler `i` (index into\n * `samplers`) occupies TWO bindings: `userSamplersBase + 2*i` for the texture and\n * `userSamplersBase + 2*i + 1` for its sampler. */\nexport interface WgslBindings {\n uniform: 0;\n texture: 1;\n textureSampler: 2;\n userSamplersBase: 3;\n}\n\nexport interface TranspiledWgslShader {\n /** ONE module: `vs_main` + `fs_main` + the polyfills and helpers actually used. */\n wgsl: string;\n vertexEntry: \"vs_main\";\n fragmentEntry: \"fs_main\";\n /** Size of the single uniform struct, rounded up to 16. */\n uniformStructSizeBytes: number;\n builtinOffsets: WgslBuiltinOffsets;\n /** User scalar/vector uniforms, offsets into the same struct, declaration order. */\n uniforms: WgslUniformField[];\n /** User `sampler2D` uniforms under their GODOT names, in binding order. */\n samplers: ShaderSampler[];\n bindings: WgslBindings;\n blend: GodotBlendMode;\n usesTime: boolean;\n usesTexturePixelSize: boolean;\n usesScreenUv: boolean;\n}\n\nconst VERTEX_ENTRY = \"vs_main\";\nconst FRAGMENT_ENTRY = \"fs_main\";\n\nconst BINDINGS: WgslBindings = {\n uniform: 0,\n texture: 1,\n textureSampler: 2,\n userSamplersBase: 3,\n};\n\n// ---- public entry ----------------------------------------------------------\n\n/** Transpile a `.gdshader` source string to one WGSL module plus its uniform layout.\n * Throws `UnsupportedShaderError` (no backend can) or `UnsupportedWgslShaderError`\n * (this backend can't — fall the binding back to WebGL). */\nexport function transpileGodotShaderWgsl(source: string): TranspiledWgslShader {\n // Same unwrap as the GLSL entry, and it has to be here too: both backends take the\n // caller's raw fetch, so a `.tres` reaches whichever one the runtime adopted.\n const cleaned = sanitizeReservedIdentifiers(\n stripComments(unwrapShaderResource(source)),\n );\n const parsed = parseShader(cleaned);\n\n // ORDERING CONTRACT, mirroring `transpileGodotShader`: guard BEFORE analyzing, so an\n // unsupported built-in is reported as such (and as the PLAIN error class) ahead of any\n // WGSL-specific complaint. A `while` loop must not come back as \"WGSL can't\" — no\n // backend can, and the runtime's fallback ladder reads the class to decide.\n const logic = shaderLogic(parsed);\n rejectUnsupported(logic, parsed);\n\n const analysis = analyzeShader(parsed);\n rejectScreenCapture(parsed, analysis);\n\n // `#define` has no WGSL equivalent. In practice it only reaches here from the\n // screen-texture alias (already rejected above), so a simple token alias is resolved\n // defensively and anything else is named and refused rather than emitted as garbage.\n const defines = extractDefines(parsed);\n\n const renames = buildRenameMap(parsed, defines);\n const plan = buildUniformPlan(parsed, analysis, renames);\n\n const globals = (text: string): string =>\n applyGlobals(text, defines, renames, plan);\n\n const helpersText = globals(parsed.helpers);\n const bodyText = globals(parsed.fragmentBody);\n rejectStrayDirectives(helpersText, bodyText);\n rejectFragmentLocalsInHelpers(parsed.helpers, plan);\n\n const ctx = createContext(parsed, plan, renames);\n const helpers = translateHelpers(helpersText, ctx);\n\n const fragmentCtx = childContext(ctx);\n seedFragmentScope(fragmentCtx, analysis);\n const bodyLines = translateBlock(bodyText, fragmentCtx);\n\n const varyingLines = analysis.varyingHoists.map((hoist) => {\n const name = renameOf(hoist.name, renames);\n const type = localWgslType(hoist.type, `varying \"${hoist.name}\"`);\n fragmentCtx.scope.set(name, type);\n return `var ${name}: ${type} = ${translateExpr(globals(hoist.expr), fragmentCtx)};`;\n });\n\n const wgsl = assembleModule({\n parsed,\n analysis,\n plan,\n renames,\n ctx,\n helpers,\n varyingLines,\n bodyLines,\n });\n\n return {\n wgsl,\n vertexEntry: VERTEX_ENTRY,\n fragmentEntry: FRAGMENT_ENTRY,\n uniformStructSizeBytes: plan.layout.sizeBytes,\n builtinOffsets: plan.builtinOffsets,\n uniforms: plan.uniformFields,\n samplers: parsed.samplers,\n bindings: BINDINGS,\n blend: parsed.blend,\n usesTime: analysis.usesTime,\n usesTexturePixelSize: analysis.usesTexturePixelSize,\n usesScreenUv: analysis.usesScreenUv,\n };\n}\n\n// ---- uniform struct layout -------------------------------------------------\n\nexport interface WgslStructField {\n name: string;\n /** WGSL type name (`f32`, `i32`, `vec2f`, `vec3f`, `vec4f`, `vec2i`, `mat3x3f`, …). */\n type: string;\n /** Element count when the member is an array. */\n arrayLength?: number;\n}\n\nexport interface WgslStructMember extends WgslStructField {\n offsetBytes: number;\n sizeBytes: number;\n alignBytes: number;\n}\n\nexport interface WgslStructLayout {\n members: WgslStructMember[];\n /** Struct size, rounded up to the struct alignment. */\n sizeBytes: number;\n alignBytes: number;\n}\n\nconst SCALAR_LAYOUT: Record<string, { align: number; size: number }> = {\n f32: { align: 4, size: 4 },\n i32: { align: 4, size: 4 },\n u32: { align: 4, size: 4 },\n vec2f: { align: 8, size: 8 },\n vec2i: { align: 8, size: 8 },\n vec3f: { align: 16, size: 12 },\n vec3i: { align: 16, size: 12 },\n vec4f: { align: 16, size: 16 },\n vec4i: { align: 16, size: 16 },\n mat2x2f: { align: 8, size: 16 },\n mat3x3f: { align: 16, size: 48 },\n mat4x4f: { align: 16, size: 64 },\n};\n\nfunction roundUp(multiple: number, value: number): number {\n return Math.ceil(value / multiple) * multiple;\n}\n\n/** Lay out a WGSL `var<uniform>` struct by the uniform address space rules: members keep\n * DECLARATION ORDER (a reorder would silently move every offset a writer already holds),\n * each is placed at the next multiple of its alignment, and the struct size is rounded up\n * to the struct alignment. Arrays get an element stride of `roundUp(align(E), size(E))`,\n * which the uniform address space additionally requires to be a multiple of 16 — so\n * `array<vec3f, N>` and `array<vec4f, N>` are natively fine and `array<f32, N>` /\n * `array<vec2f, N>` are refused (they would need per-element padding on the host side).\n *\n * These are exactly WGSL's own natural layout rules, applied to the members in the order\n * the module declares them, which is why the emitted struct carries no explicit padding\n * members: the compiler computes the same offsets this function records. */\nexport function wgslStructLayout(\n fields: readonly WgslStructField[],\n): WgslStructLayout {\n const members: WgslStructMember[] = [];\n let offset = 0;\n let structAlign = 16; // a uniform struct is always bound on a 16-byte-class boundary\n for (const field of fields) {\n const base = SCALAR_LAYOUT[field.type];\n if (!base) {\n throw new UnsupportedWgslShaderError(\n `uniform type \"${field.type}\" has no WGSL uniform layout`,\n );\n }\n let align = base.align;\n let size = base.size;\n if (field.arrayLength !== undefined) {\n const stride = roundUp(base.align, base.size);\n if (stride % 16 !== 0) {\n throw new UnsupportedWgslShaderError(\n `uniform array \"${field.name}\" of ${field.type} needs a 16-byte element stride in the WGSL uniform address space (got ${stride}); array-of-scalar uniforms are deferred`,\n );\n }\n align = Math.max(16, base.align);\n size = stride * field.arrayLength;\n }\n offset = roundUp(align, offset);\n members.push({\n name: field.name,\n type: field.type,\n ...(field.arrayLength !== undefined\n ? { arrayLength: field.arrayLength }\n : {}),\n offsetBytes: offset,\n sizeBytes: size,\n alignBytes: align,\n });\n offset += size;\n structAlign = Math.max(structAlign, align);\n }\n return {\n members,\n sizeBytes: roundUp(structAlign, offset),\n alignBytes: structAlign,\n };\n}\n\n// ---- screen capture / preprocessor guards ----------------------------------\n\nfunction rejectScreenCapture(\n parsed: ParsedShader,\n analysis: ShaderAnalysis,\n): void {\n if (parsed.screenTextureNames.length > 0) {\n throw new UnsupportedWgslShaderError(\n `hint_screen_texture sampler \"${parsed.screenTextureNames[0]}\" is not supported on WebGPU: capturing what was already composited is a runtime architecture question, so this binding falls back to WebGL`,\n );\n }\n if (analysis.usesScreenTexture) {\n throw new UnsupportedWgslShaderError(\n \"SCREEN_TEXTURE is not supported on WebGPU: capturing what was already composited is a runtime architecture question, so this binding falls back to WebGL\",\n );\n }\n if (analysis.usesScreenPixelSize) {\n throw new UnsupportedWgslShaderError(\n \"SCREEN_PIXEL_SIZE is not supported on WebGPU: it sizes the screen capture, which this backend does not produce\",\n );\n }\n}\n\n/** Simple `#define A B` token aliases, pulled out of the helper text so they can be\n * substituted (WGSL has no preprocessor). Anything more than a single-token alias is\n * named and refused. */\nfunction extractDefines(parsed: ParsedShader): Array<[string, string]> {\n const out: Array<[string, string]> = [];\n const re = /^[ \\t]*#define\\s+([A-Za-z_]\\w*)\\s+([^\\n]*)$/gm;\n for (const match of parsed.helpers.matchAll(re)) {\n const value = match[2].trim();\n if (!/^[A-Za-z_]\\w*$/.test(value)) {\n throw new UnsupportedWgslShaderError(\n `#define \"${match[1]}\" is not a simple token alias and WGSL has no preprocessor`,\n );\n }\n out.push([match[1], value]);\n }\n return out;\n}\n\nfunction rejectStrayDirectives(helpers: string, body: string): void {\n for (const text of [helpers, body]) {\n const stray = /^[ \\t]*#\\s*([a-z_]+)/m.exec(text);\n if (stray) {\n throw new UnsupportedWgslShaderError(\n `preprocessor directive \"#${stray[1]}\" has no WGSL equivalent`,\n );\n }\n }\n}\n\n/** `UV` / `SCREEN_UV` / `COLOR` are fragment-LOCAL in both emitters (the GLSL one declares\n * them inside `main()` too), so a top-level helper that reads one cannot be given them\n * without inventing a calling convention. Refuse per-binding rather than emit a module\n * that names an undeclared identifier. */\nfunction rejectFragmentLocalsInHelpers(\n helpers: string,\n plan: UniformPlan,\n): void {\n for (const token of [\"UV\", \"SCREEN_UV\", \"COLOR\", \"GODOT_UV\"]) {\n if (hasToken(helpers, token)) {\n throw new UnsupportedWgslShaderError(\n `helper function reads the fragment-local built-in \"${token}\"`,\n );\n }\n }\n for (const name of plan.boolUniformNames) {\n if (hasToken(helpers, name)) {\n throw new UnsupportedWgslShaderError(\n `helper function reads the bool uniform \"${name}\", which is hoisted as a fragment-local alias (WGSL bool is not host-shareable)`,\n );\n }\n }\n}\n\n// ---- identifier renaming ---------------------------------------------------\n\n// WGSL keywords and reserved words (the front-end already renamed GLSL's `input`).\n// Renaming is applied to the whole shader text at once — uniform names, sampler names,\n// helper names, params and locals together — so a rename can never split an identifier\n// from its uses. The suffix is spelled out rather than mangled so a compile error in a\n// browser still points at a recognisable name.\n// biome-ignore format: one keyword per line would make a 170-line wall of a lookup table.\nconst WGSL_RESERVED = new Set([\n // keywords\n \"alias\", \"break\", \"case\", \"const\", \"const_assert\", \"continue\", \"continuing\",\n \"default\", \"diagnostic\", \"discard\", \"else\", \"enable\", \"false\", \"fn\", \"for\",\n \"if\", \"let\", \"loop\", \"override\", \"requires\", \"return\", \"struct\", \"switch\",\n \"true\", \"var\", \"while\",\n // reserved words\n \"NULL\", \"Self\", \"abstract\", \"active\", \"alignas\", \"alignof\", \"as\", \"asm\",\n \"asm_fragment\", \"async\", \"attribute\", \"auto\", \"await\", \"become\",\n \"binding_array\", \"cast\", \"catch\", \"class\", \"co_await\", \"co_return\",\n \"co_yield\", \"coherent\", \"column_major\", \"common\", \"compile\",\n \"compile_fragment\", \"concept\", \"const_cast\", \"consteval\", \"constexpr\",\n \"constinit\", \"crate\", \"debugger\", \"decltype\", \"delete\", \"demote\",\n \"demote_to_helper\", \"do\", \"dynamic_cast\", \"enum\", \"explicit\", \"export\",\n \"extends\", \"extern\", \"external\", \"fallthrough\", \"filter\", \"final\", \"finally\",\n \"friend\", \"from\", \"fxgroup\", \"get\", \"goto\", \"groupshared\", \"highp\", \"impl\",\n \"implements\", \"import\", \"inline\", \"instanceof\", \"interface\", \"layout\",\n \"lowp\", \"macro\", \"macro_rules\", \"match\", \"mediump\", \"meta\", \"mod\", \"module\",\n \"move\", \"mut\", \"mutable\", \"namespace\", \"new\", \"nil\", \"noexcept\", \"noinline\",\n \"nointerpolation\", \"non_coherent\", \"noncoherent\", \"noperspective\", \"null\",\n \"nullptr\", \"of\", \"operator\", \"package\", \"packoffset\", \"partition\", \"pass\",\n \"patch\", \"pixelfragment\", \"precise\", \"precision\", \"premerge\", \"priv\",\n \"protected\", \"pub\", \"public\", \"readonly\", \"ref\", \"regardless\", \"register\",\n \"reinterpret_cast\", \"require\", \"resource\", \"restrict\", \"self\", \"set\",\n \"shared\", \"sizeof\", \"smooth\", \"snorm\", \"static\", \"static_assert\",\n \"static_cast\", \"std\", \"subroutine\", \"super\", \"target\", \"template\", \"this\",\n \"thread_local\", \"throw\", \"trait\", \"try\", \"type\", \"typedef\", \"typeid\",\n \"typename\", \"union\", \"unless\", \"unorm\", \"unsafe\", \"unsized\", \"use\", \"using\",\n \"varying\", \"virtual\", \"volatile\", \"wgsl\", \"where\", \"write\", \"writeonly\",\n \"yield\",\n]);\n\n// Names this emitter puts in the module itself. A shader identifier that collides with\n// one of them is renamed for the same reason a reserved word is: the collision would\n// otherwise be a silently wrong program (a user uniform named `time` would land on the\n// built-in TIME member). The uniform-struct MEMBER names are in here too.\nconst EMITTER_OWNED = new Set([\n \"_u\",\n \"Uniforms\",\n \"VsOut\",\n \"raw_uv\",\n VERTEX_ENTRY,\n FRAGMENT_ENTRY,\n \"godot_mod\",\n \"godot_mod2\",\n \"godot_mod3\",\n \"godot_mod4\",\n \"godot_inverse3\",\n \"TEXTURE_smp\",\n \"GODOT_UV\",\n \"uv_fit\",\n \"uv_window\",\n \"time\",\n \"texture_pixel_size\",\n \"modulate\",\n \"screen_origin\",\n \"screen_size\",\n]);\n\nconst RENAME_SUFFIX = \"_gsw\";\n\ntype RenameMap = Map<string, string>;\n\nfunction renameOf(name: string, renames: RenameMap): string {\n return renames.get(name) ?? name;\n}\n\nfunction buildRenameMap(\n parsed: ParsedShader,\n defines: Array<[string, string]>,\n): RenameMap {\n const text = `${parsed.helpers}\\n${parsed.fragmentBody}`;\n if (/(?<![\\w])_swz\\d*(?![\\w])/.test(text)) {\n throw new UnsupportedWgslShaderError(\n 'the identifier prefix \"_swz\" is reserved for swizzle-assignment temporaries',\n );\n }\n // Only names the shader DECLARES are candidates. Scanning every word instead would\n // \"rename\" GLSL syntax that happens to be a WGSL keyword too (`if`, `const`, `return`),\n // which is not an identifier collision at all.\n const candidates = new Set<string>();\n const declared =\n /(?<![\\w])(?:const\\s+)?(?:void|float|int|bool|uint|vec[234]|ivec[234]|bvec[234]|mat[234])\\s+([A-Za-z_]\\w*)/g;\n for (const match of text.matchAll(declared)) {\n candidates.add(match[1]);\n }\n for (const uniform of parsed.uniforms) candidates.add(uniform.name);\n for (const sampler of parsed.samplers) candidates.add(sampler.name);\n for (const varying of parsed.varyings) candidates.add(varying.name);\n for (const [name] of defines) candidates.delete(name);\n\n const renames: RenameMap = new Map();\n for (const name of candidates) {\n if (WGSL_RESERVED.has(name) || EMITTER_OWNED.has(name)) {\n renames.set(name, `${name}${RENAME_SUFFIX}`);\n }\n }\n return renames;\n}\n\n/** The two whole-text passes every chunk of shader logic goes through before it is\n * parsed statement by statement: resolve `#define` aliases and reserved-word renames,\n * then bind every uniform / built-in read to its member of the one uniform struct. */\nfunction applyGlobals(\n text: string,\n defines: Array<[string, string]>,\n renames: RenameMap,\n plan: UniformPlan,\n): string {\n let out = text.replace(/^[ \\t]*#define\\s+[A-Za-z_]\\w*\\s+[^\\n]*$/gm, \"\");\n for (const [name, value] of defines) {\n out = replaceToken(out, name, value);\n }\n for (const [from, to] of renames) {\n out = replaceToken(out, from, to);\n }\n // User uniforms first, built-ins second: the built-in member names are in\n // EMITTER_OWNED, so a user uniform can never still be spelled `time` here.\n for (const [wgslName, member] of plan.memberByWgslName) {\n if (plan.boolUniformNames.has(wgslName)) {\n // Left alone on purpose: a bool uniform resolves to the `let` alias hoisted at the\n // top of fs_main, because WGSL cannot store a `bool` in a uniform buffer.\n continue;\n }\n if (member.builtin) continue;\n out = replaceToken(out, wgslName, `_u.${wgslName}`);\n }\n if (plan.builtinOffsets.time !== undefined) {\n out = replaceToken(out, \"TIME\", \"_u.time\");\n }\n if (plan.builtinOffsets.texturePixelSize !== undefined) {\n out = replaceToken(out, \"TEXTURE_PIXEL_SIZE\", \"_u.texture_pixel_size\");\n }\n if (plan.builtinOffsets.modulate !== undefined) {\n out = replaceToken(out, \"MODULATE\", \"_u.modulate\");\n }\n return out;\n}\n\n// ---- uniform plan ----------------------------------------------------------\n\ninterface PlannedMember {\n wgslName: string;\n type: string;\n builtin: boolean;\n arrayLength?: number;\n}\n\ninterface UniformPlan {\n layout: WgslStructLayout;\n builtinOffsets: WgslBuiltinOffsets;\n uniformFields: WgslUniformField[];\n members: PlannedMember[];\n memberByWgslName: Map<string, PlannedMember>;\n boolUniformNames: Set<string>;\n /** WGSL member name -> its type, for expression typing (`_u.foo`). */\n memberTypes: Map<string, string>;\n}\n\nconst UNIFORM_WGSL_TYPE: Record<string, string> = {\n float: \"f32\",\n int: \"i32\",\n bool: \"f32\", // WGSL bool is not host-shareable; stored as a 1/0 flag\n vec2: \"vec2f\",\n vec3: \"vec3f\",\n vec4: \"vec4f\",\n ivec2: \"vec2i\",\n ivec3: \"vec3i\",\n ivec4: \"vec4i\",\n mat2: \"mat2x2f\",\n mat3: \"mat3x3f\",\n mat4: \"mat4x4f\",\n};\n\nfunction buildUniformPlan(\n parsed: ParsedShader,\n analysis: ShaderAnalysis,\n renames: RenameMap,\n): UniformPlan {\n // Built-ins first, in an order chosen to leave as few alignment holes as the WGSL\n // rules allow (vec4 then vec2 then scalars), then user uniforms in DECLARATION order.\n const members: PlannedMember[] = [\n { wgslName: \"uv_window\", type: \"vec4f\", builtin: true },\n { wgslName: \"uv_fit\", type: \"vec2f\", builtin: true },\n ];\n if (analysis.usesTime) {\n members.push({ wgslName: \"time\", type: \"f32\", builtin: true });\n }\n if (analysis.usesTexturePixelSize) {\n members.push({\n wgslName: \"texture_pixel_size\",\n type: \"vec2f\",\n builtin: true,\n });\n }\n if (analysis.usesScreenUv) {\n members.push({ wgslName: \"screen_origin\", type: \"vec2f\", builtin: true });\n members.push({ wgslName: \"screen_size\", type: \"vec2f\", builtin: true });\n }\n if (analysis.needsModulate) {\n members.push({ wgslName: \"modulate\", type: \"vec4f\", builtin: true });\n }\n\n const boolUniformNames = new Set<string>();\n for (const uniform of parsed.uniforms) {\n const type = UNIFORM_WGSL_TYPE[uniform.type];\n if (!type) {\n throw new UnsupportedWgslShaderError(\n `uniform type \"${uniform.type}\" has no WGSL uniform equivalent`,\n );\n }\n if (/^bvec[234]$/.test(uniform.type)) {\n throw new UnsupportedWgslShaderError(\n `bool-vector uniform \"${uniform.name}\" is not host-shareable in WGSL`,\n );\n }\n const wgslName = renameOf(uniform.name, renames);\n if (uniform.type === \"bool\") {\n if (uniform.arrayLength !== undefined) {\n throw new UnsupportedWgslShaderError(\n `bool array uniform \"${uniform.name}\" is not supported`,\n );\n }\n boolUniformNames.add(wgslName);\n }\n members.push({\n wgslName,\n type,\n builtin: false,\n ...(uniform.arrayLength !== undefined\n ? { arrayLength: uniform.arrayLength }\n : {}),\n });\n }\n\n const layout = wgslStructLayout(\n members.map((m) => ({\n name: m.wgslName,\n type: m.type,\n ...(m.arrayLength !== undefined ? { arrayLength: m.arrayLength } : {}),\n })),\n );\n const offsetOf = new Map(\n layout.members.map((m) => [m.name, m.offsetBytes] as const),\n );\n const sizeOf = new Map(\n layout.members.map((m) => [m.name, m.sizeBytes] as const),\n );\n\n const builtinOffsets: WgslBuiltinOffsets = {\n uvFit: offsetOf.get(\"uv_fit\") ?? 0,\n uvWindow: offsetOf.get(\"uv_window\") ?? 0,\n };\n if (analysis.usesTime) builtinOffsets.time = offsetOf.get(\"time\");\n if (analysis.usesTexturePixelSize) {\n builtinOffsets.texturePixelSize = offsetOf.get(\"texture_pixel_size\");\n }\n if (analysis.usesScreenUv) {\n builtinOffsets.screenOrigin = offsetOf.get(\"screen_origin\");\n builtinOffsets.screenSize = offsetOf.get(\"screen_size\");\n }\n if (analysis.needsModulate) {\n builtinOffsets.modulate = offsetOf.get(\"modulate\");\n }\n\n const uniformFields: WgslUniformField[] = parsed.uniforms.map((uniform) => {\n const wgslName = renameOf(uniform.name, renames);\n return {\n name: uniform.name,\n type: UNIFORM_WGSL_TYPE[uniform.type],\n godotType: uniform.type,\n ...(uniform.arrayLength !== undefined\n ? { arrayLength: uniform.arrayLength }\n : {}),\n offsetBytes: offsetOf.get(wgslName) ?? 0,\n sizeBytes: sizeOf.get(wgslName) ?? 0,\n ...(uniform.default !== undefined ? { default: uniform.default } : {}),\n };\n });\n\n const memberByWgslName = new Map(\n members.map((m) => [m.wgslName, m] as const),\n );\n const memberTypes = new Map<string, string>();\n for (const member of members) {\n memberTypes.set(\n `_u.${member.wgslName}`,\n member.arrayLength !== undefined\n ? `array<${member.type},${member.arrayLength}>`\n : member.type,\n );\n }\n\n return {\n layout,\n builtinOffsets,\n uniformFields,\n members,\n memberByWgslName,\n boolUniformNames,\n memberTypes,\n };\n}\n\n// ---- translation context ---------------------------------------------------\n\ninterface Ctx {\n /** identifier (or `_u.member`) -> WGSL type, for the narrow inference `mod` and\n * `inverse` need. Function-local; the module scope is copied in. */\n scope: Map<string, string>;\n fnReturns: Map<string, string>;\n needMod: Set<number>;\n needInverse: { mat3: boolean };\n swizzle: { next: number };\n textures: Set<string>;\n uniformNames: Set<string>;\n}\n\nfunction createContext(\n parsed: ParsedShader,\n plan: UniformPlan,\n renames: RenameMap,\n): Ctx {\n const scope = new Map<string, string>(plan.memberTypes);\n for (const name of plan.boolUniformNames) scope.set(name, \"bool\");\n const textures = new Set<string>([\"TEXTURE\"]);\n for (const sampler of parsed.samplers) {\n textures.add(renameOf(sampler.name, renames));\n }\n const uniformNames = new Set<string>();\n for (const uniform of parsed.uniforms) {\n uniformNames.add(renameOf(uniform.name, renames));\n }\n // A local (or param) named like a uniform would be silently rewritten to `_u.x` by the\n // whole-text uniform pass and stop being a local. Refuse rather than mis-emit.\n const declared =\n /(?<![\\w])(?:const\\s+)?(?:float|int|bool|uint|vec[234]|ivec[234]|bvec[234]|mat[234])\\s+([A-Za-z_]\\w*)/g;\n for (const match of `${parsed.helpers}\\n${parsed.fragmentBody}`.matchAll(\n declared,\n )) {\n const name = renameOf(match[1], renames);\n if (uniformNames.has(name)) {\n throw new UnsupportedWgslShaderError(\n `local \"${match[1]}\" shadows the uniform of the same name`,\n );\n }\n }\n return {\n scope,\n fnReturns: new Map(),\n needMod: new Set<number>(),\n needInverse: { mat3: false },\n swizzle: { next: 0 },\n textures,\n uniformNames,\n };\n}\n\nfunction childContext(ctx: Ctx): Ctx {\n return { ...ctx, scope: new Map(ctx.scope) };\n}\n\nfunction seedFragmentScope(ctx: Ctx, analysis: ShaderAnalysis): void {\n ctx.scope.set(\"COLOR\", \"vec4f\");\n ctx.scope.set(\"UV\", \"vec2f\");\n ctx.scope.set(\"GODOT_UV\", \"vec2f\");\n ctx.scope.set(\"PI\", \"f32\");\n if (analysis.usesScreenUv) ctx.scope.set(\"SCREEN_UV\", \"vec2f\");\n}\n\n// ---- helpers (top-level consts + functions) --------------------------------\n\ninterface TranslatedHelpers {\n consts: string[];\n fns: string[];\n}\n\nfunction translateHelpers(helpers: string, ctx: Ctx): TranslatedHelpers {\n const consts: string[] = [];\n const fns: string[] = [];\n const parsedFns: Array<{\n name: string;\n ret: string;\n params: string;\n body: string;\n }> = [];\n\n let i = 0;\n while (i < helpers.length) {\n while (i < helpers.length && /\\s/.test(helpers[i])) i += 1;\n if (i >= helpers.length) break;\n if (helpers[i] === \";\") {\n i += 1;\n continue;\n }\n const rest = helpers.slice(i);\n const constMatch =\n /^const\\s+([A-Za-z_]\\w*)\\s+([A-Za-z_]\\w*)\\s*=([\\s\\S]*?);/.exec(rest);\n if (constMatch) {\n const type = localWgslType(constMatch[1], `const \"${constMatch[2]}\"`);\n ctx.scope.set(constMatch[2], type);\n consts.push(\n `const ${constMatch[2]}: ${type} = ${translateExpr(constMatch[3], ctx)};`,\n );\n i += constMatch[0].length;\n continue;\n }\n const fnMatch = /^([A-Za-z_]\\w*)\\s+([A-Za-z_]\\w*)\\s*\\(/.exec(rest);\n if (fnMatch) {\n const open = i + fnMatch[0].length - 1;\n const closeParen = matchParen(helpers, open);\n let k = closeParen + 1;\n while (k < helpers.length && /\\s/.test(helpers[k])) k += 1;\n if (helpers[k] !== \"{\") {\n throw new UnsupportedWgslShaderError(\n `helper \"${fnMatch[2]}\" has no body (forward declarations are not supported)`,\n );\n }\n const closeBrace = matchBrace(helpers, k);\n parsedFns.push({\n ret: fnMatch[1],\n name: fnMatch[2],\n params: helpers.slice(open + 1, closeParen),\n body: helpers.slice(k + 1, closeBrace),\n });\n i = closeBrace + 1;\n continue;\n }\n throw new UnsupportedWgslShaderError(\n `unsupported top-level construct \"${rest.slice(0, 40).trim()}\"`,\n );\n }\n\n // Return types first: WGSL module declarations are order-independent, and a helper may\n // call one declared below it.\n for (const fn of parsedFns) {\n if (fn.ret !== \"void\") {\n ctx.fnReturns.set(fn.name, localWgslType(fn.ret, `helper \"${fn.name}\"`));\n }\n }\n for (const fn of parsedFns) {\n const fnCtx = childContext(ctx);\n const params = parseParams(fn.params, fn.name, fnCtx);\n const signature =\n fn.ret === \"void\"\n ? `fn ${fn.name}(${params.join(\", \")}) {`\n : `fn ${fn.name}(${params.join(\", \")}) -> ${ctx.fnReturns.get(fn.name)} {`;\n fns.push(\n [signature, ...indentLines(translateBlock(fn.body, fnCtx)), \"}\"].join(\n \"\\n\",\n ),\n );\n }\n return { consts, fns };\n}\n\nfunction parseParams(params: string, fnName: string, ctx: Ctx): string[] {\n const trimmed = params.trim();\n if (!trimmed || trimmed === \"void\") return [];\n return splitTopLevel(trimmed, \",\").map((param) => {\n const match =\n /^(?:(in|out|inout)\\s+)?([A-Za-z_]\\w*)\\s+([A-Za-z_]\\w*)$/.exec(\n param.trim(),\n );\n if (!match) {\n throw new UnsupportedWgslShaderError(\n `helper \"${fnName}\" has an unsupported parameter \"${param.trim()}\"`,\n );\n }\n if (match[1] === \"out\" || match[1] === \"inout\") {\n throw new UnsupportedWgslShaderError(\n `helper \"${fnName}\" uses an ${match[1]} parameter; WGSL would need a pointer`,\n );\n }\n const type = localWgslType(match[2], `parameter \"${match[3]}\"`);\n if (ctx.uniformNames.has(match[3])) {\n throw new UnsupportedWgslShaderError(\n `parameter \"${match[3]}\" of helper \"${fnName}\" shadows a uniform`,\n );\n }\n ctx.scope.set(match[3], type);\n return `${match[3]}: ${type}`;\n });\n}\n\n// ---- statements ------------------------------------------------------------\n\nconst LOCAL_WGSL_TYPE: Record<string, string> = {\n ...UNIFORM_WGSL_TYPE,\n bool: \"bool\", // a LOCAL bool is a plain WGSL bool; only uniforms need the f32 flag\n bvec2: \"vec2<bool>\",\n bvec3: \"vec3<bool>\",\n bvec4: \"vec4<bool>\",\n};\n\nfunction localWgslType(godotType: string, what: string): string {\n const type = LOCAL_WGSL_TYPE[godotType];\n if (!type) {\n throw new UnsupportedWgslShaderError(\n `${what} has unsupported type \"${godotType}\"`,\n );\n }\n return type;\n}\n\nconst DECLARATION =\n /^(const\\s+)?(float|int|bool|uint|vec[234]|ivec[234]|bvec[234]|mat[234])\\s+([A-Za-z_]\\w*)\\s*(\\[[^\\]]*\\])?\\s*(?:=([\\s\\S]*))?$/;\n\nfunction translateBlock(src: string, ctx: Ctx): string[] {\n const lines: string[] = [];\n let i = 0;\n while (i < src.length) {\n while (i < src.length && /\\s/.test(src[i])) i += 1;\n if (i >= src.length) break;\n if (src[i] === \";\") {\n i += 1;\n continue;\n }\n if (src[i] === \"{\") {\n const close = matchBrace(src, i);\n lines.push(\"{\");\n lines.push(...indentLines(translateBlock(src.slice(i + 1, close), ctx)));\n lines.push(\"}\");\n i = close + 1;\n continue;\n }\n let depth = 0;\n let stop = -1;\n let stopChar = \"\";\n for (let j = i; j < src.length; j += 1) {\n const c = src[j];\n if (c === \"(\" || c === \"[\") depth += 1;\n else if (c === \")\" || c === \"]\") depth -= 1;\n else if (depth === 0 && (c === \";\" || c === \"{\" || c === \"}\")) {\n stop = j;\n stopChar = c;\n break;\n }\n }\n if (stop < 0) {\n const tail = src.slice(i).trim();\n if (tail) {\n throw new UnsupportedWgslShaderError(\n `unterminated statement \"${tail}\"`,\n );\n }\n break;\n }\n if (stopChar === \"}\") {\n throw new UnsupportedWgslShaderError(\n `unbalanced braces near \"${src.slice(i, stop).trim()}\"`,\n );\n }\n if (stopChar === \"{\") {\n const header = src.slice(i, stop).trim();\n const close = matchBrace(src, stop);\n lines.push(...translateControl(header, src.slice(stop + 1, close), ctx));\n i = close + 1;\n while (i < src.length && /\\s/.test(src[i])) i += 1;\n if (src[i] === \";\") i += 1;\n continue;\n }\n lines.push(...translateStatement(src.slice(i, stop).trim(), ctx));\n i = stop + 1;\n }\n return mergeElse(lines);\n}\n\nfunction translateControl(header: string, inner: string, ctx: Ctx): string[] {\n if (/^while\\b/.test(header)) {\n throw new UnsupportedShaderError(\"while loops are not supported\");\n }\n if (/^for\\b/.test(header)) {\n const open = header.indexOf(\"(\");\n if (open < 0 || matchParen(header, open) !== header.length - 1) {\n throw new UnsupportedWgslShaderError(\n `unsupported for header \"${header}\"`,\n );\n }\n const clauses = splitTopLevel(\n header.slice(open + 1, header.length - 1),\n \";\",\n );\n if (clauses.length !== 3) {\n throw new UnsupportedWgslShaderError(\n `for loop needs init/condition/increment, got \"${header}\"`,\n );\n }\n const loop = childContext(ctx);\n const init = oneLine(clauses[0], loop);\n const cond = clauses[1].trim() ? translateExpr(clauses[1], loop) : \"\";\n const inc = oneLine(clauses[2], loop);\n return [\n `for (${init}; ${cond}; ${inc}) {`,\n ...indentLines(translateBlock(inner, loop)),\n \"}\",\n ];\n }\n const ifMatch = /^(else\\s+if|if)\\b/.exec(header);\n if (ifMatch) {\n const open = header.indexOf(\"(\");\n if (open < 0) {\n throw new UnsupportedWgslShaderError(`unsupported if header \"${header}\"`);\n }\n const close = matchParen(header, open);\n const cond = translateExpr(header.slice(open + 1, close), ctx);\n const keyword = ifMatch[1].startsWith(\"else\") ? \"else if\" : \"if\";\n return [\n `${keyword} (${cond}) {`,\n ...indentLines(translateBlock(inner, childContext(ctx))),\n \"}\",\n ];\n }\n if (/^else$/.test(header)) {\n return [\n \"else {\",\n ...indentLines(translateBlock(inner, childContext(ctx))),\n \"}\",\n ];\n }\n throw new UnsupportedWgslShaderError(`unsupported block header \"${header}\"`);\n}\n\n/** A for-clause: one statement, rendered without its terminating `;`. */\nfunction oneLine(clause: string, ctx: Ctx): string {\n const trimmed = clause.trim();\n if (!trimmed) return \"\";\n const lines = translateStatement(trimmed, ctx);\n if (lines.length !== 1) {\n throw new UnsupportedWgslShaderError(\n `for clause \"${trimmed}\" does not translate to a single statement`,\n );\n }\n return lines[0].replace(/;$/, \"\");\n}\n\nfunction translateStatement(stmt: string, ctx: Ctx): string[] {\n if (!stmt) return [];\n\n // A control statement whose body has no braces. WGSL REQUIRES braces on if/for bodies,\n // so `if (c) continue;` has to grow a block rather than pass through.\n const controlMatch = /^(if|for|while|else\\s+if|else)\\b/.exec(stmt);\n if (controlMatch) {\n if (controlMatch[1] === \"while\") {\n throw new UnsupportedShaderError(\"while loops are not supported\");\n }\n if (controlMatch[1] === \"else\") {\n return translateControl(\"else\", `${stmt.slice(4).trim()};`, ctx);\n }\n const open = stmt.indexOf(\"(\");\n if (open < 0) {\n throw new UnsupportedWgslShaderError(`unsupported statement \"${stmt}\"`);\n }\n const close = matchParen(stmt, open);\n return translateControl(\n stmt.slice(0, close + 1).trim(),\n `${stmt.slice(close + 1).trim()};`,\n ctx,\n );\n }\n\n if (stmt === \"continue\" || stmt === \"break\" || stmt === \"discard\") {\n return [`${stmt};`];\n }\n if (/^return\\b/.test(stmt)) {\n const value = stmt.slice(\"return\".length).trim();\n return value ? [`return ${translateExpr(value, ctx)};`] : [\"return;\"];\n }\n\n const decl = DECLARATION.exec(stmt);\n if (decl) {\n if (decl[4]) {\n throw new UnsupportedWgslShaderError(\n `local array declaration \"${decl[3]}\" is not supported`,\n );\n }\n const type = localWgslType(decl[2], `local \"${decl[3]}\"`);\n ctx.scope.set(decl[3], type);\n if (decl[5] === undefined) {\n // WGSL zero-initializes a `var` without an initializer, matching the GLSL default\n // the shipped shaders already rely on (`float lastmask;` read after a loop).\n return [`var ${decl[3]}: ${type};`];\n }\n const keyword = decl[1] ? \"let\" : \"var\";\n return [`${keyword} ${decl[3]}: ${type} = ${translateExpr(decl[5], ctx)};`];\n }\n\n if (/^[A-Za-z_][\\w.[\\]]*\\s*(\\+\\+|--)$/.test(stmt)) {\n return [`${stmt.replace(/\\s+/g, \"\")};`];\n }\n const prefixInc = /^(\\+\\+|--)\\s*([A-Za-z_][\\w.[\\]]*)$/.exec(stmt);\n if (prefixInc) {\n // WGSL has no prefix form; as a STATEMENT the two are the same effect.\n return [`${prefixInc[2]}${prefixInc[1]};`];\n }\n\n const assign = findAssignment(stmt);\n if (assign) return translateAssignment(assign, ctx);\n\n if (/^[A-Za-z_]\\w*\\s*\\(/.test(stmt)) {\n return [`${translateExpr(stmt, ctx)};`];\n }\n throw new UnsupportedWgslShaderError(`unsupported statement \"${stmt}\"`);\n}\n\ninterface Assignment {\n lvalue: string;\n op: string;\n rvalue: string;\n}\n\nfunction findAssignment(stmt: string): Assignment | null {\n let depth = 0;\n for (let i = 0; i < stmt.length; i += 1) {\n const c = stmt[i];\n if (c === \"(\" || c === \"[\") depth += 1;\n else if (c === \")\" || c === \"]\") depth -= 1;\n else if (depth === 0 && c === \"=\") {\n if (stmt[i + 1] === \"=\") {\n i += 1;\n continue;\n }\n const prev = stmt[i - 1];\n if (prev === \"=\" || prev === \"!\" || prev === \"<\" || prev === \">\")\n continue;\n if (prev === \"+\" || prev === \"-\" || prev === \"*\" || prev === \"/\") {\n return {\n lvalue: stmt.slice(0, i - 1),\n op: `${prev}=`,\n rvalue: stmt.slice(i + 1),\n };\n }\n return { lvalue: stmt.slice(0, i), op: \"=\", rvalue: stmt.slice(i + 1) };\n }\n }\n return null;\n}\n\nconst LVALUE = /^[A-Za-z_]\\w*(?:\\.[A-Za-z_]\\w*|\\[[^\\]]*\\])*$/;\n// biome-ignore format: the rgba/xyzw pairing reads as two rows, not as eight lines.\nconst COMPONENT: Record<string, string> = {\n x: \"x\", y: \"y\", z: \"z\", w: \"w\",\n r: \"x\", g: \"y\", b: \"z\", a: \"w\",\n};\n\nfunction translateAssignment(assign: Assignment, ctx: Ctx): string[] {\n const lvalue = assign.lvalue.trim();\n if (lvalue.startsWith(\"_u.\")) {\n throw new UnsupportedWgslShaderError(\n `assignment to the uniform \"${lvalue.slice(3)}\"`,\n );\n }\n if (!LVALUE.test(lvalue)) {\n throw new UnsupportedWgslShaderError(\n `unsupported assignment target \"${lvalue}\"`,\n );\n }\n const rvalue = translateExpr(assign.rvalue, ctx);\n\n const swizzle = /^(.+)\\.([xyzwrgba]{2,4})$/.exec(lvalue);\n if (!swizzle) {\n return [`${lvalue} ${assign.op} ${rvalue};`];\n }\n // A multi-component swizzle is NOT an assignable place in WGSL (only a single component\n // is). Evaluate the right-hand side ONCE into a temp and store per component. The temp\n // goes through the target's own vector constructor so that a scalar right-hand side\n // (legal GLSL: `COLOR.rgb += f`) splats and a vector one is copied unchanged — which\n // avoids having to type-infer the right-hand side at all.\n const base = swizzle[1];\n const comps = [...swizzle[2]];\n const ctor = swizzleConstructor(base, comps.length, ctx);\n const temp = `_swz${ctx.swizzle.next}`;\n ctx.swizzle.next += 1;\n const lines = [`let ${temp} = ${ctor}(${rvalue});`];\n comps.forEach((component, index) => {\n const dst = `${base}.${COMPONENT[component]}`;\n const src = `${temp}.${\"xyzw\"[index]}`;\n lines.push(\n assign.op === \"=\"\n ? `${dst} = ${src};`\n : `${dst} = ${dst} ${assign.op[0]} ${src};`,\n );\n });\n return lines;\n}\n\nfunction swizzleConstructor(base: string, width: number, ctx: Ctx): string {\n const type = inferType(base, ctx);\n const suffix = type && /^vec[234]i$/.test(type) ? \"i\" : \"f\";\n return `vec${width}${suffix}`;\n}\n\n// ---- expressions -----------------------------------------------------------\n\nfunction translateExpr(expr: string, ctx: Ctx): string {\n const trimmed = expr.trim();\n const ternary = splitTernary(trimmed);\n if (ternary) {\n // WGSL has no `?:`. `select(f, t, cond)` evaluates BOTH sides eagerly; every corpus\n // use is a pure read (at worst an out-of-range uniform-array index, which WGSL\n // bounds-clamps rather than faults), so the eager side is unobservable.\n return `select(${translateExpr(ternary.whenFalse, ctx)}, ${translateExpr(\n ternary.whenTrue,\n ctx,\n )}, ${translateExpr(ternary.cond, ctx)})`;\n }\n let out = rewriteTextureCalls(trimmed, ctx);\n out = rewriteIntrinsics(out, ctx);\n out = renameConstructors(out);\n if (out.includes(\"?\")) {\n throw new UnsupportedWgslShaderError(\n `ternary \"?:\" is only supported as a complete right-hand side, got \"${trimmed}\"`,\n );\n }\n return out.trim();\n}\n\ninterface Ternary {\n cond: string;\n whenTrue: string;\n whenFalse: string;\n}\n\nfunction splitTernary(expr: string): Ternary | null {\n let depth = 0;\n let question = -1;\n for (let i = 0; i < expr.length; i += 1) {\n const c = expr[i];\n if (c === \"(\" || c === \"[\") depth += 1;\n else if (c === \")\" || c === \"]\") depth -= 1;\n else if (depth === 0 && c === \"?\") {\n question = i;\n break;\n }\n }\n if (question < 0) return null;\n depth = 0;\n let pending = 0;\n for (let i = question + 1; i < expr.length; i += 1) {\n const c = expr[i];\n if (c === \"(\" || c === \"[\") depth += 1;\n else if (c === \")\" || c === \"]\") depth -= 1;\n else if (depth === 0 && c === \"?\") pending += 1;\n else if (depth === 0 && c === \":\") {\n if (pending > 0) {\n pending -= 1;\n continue;\n }\n return {\n cond: expr.slice(0, question),\n whenTrue: expr.slice(question + 1, i),\n whenFalse: expr.slice(i + 1),\n };\n }\n }\n throw new UnsupportedWgslShaderError(`ternary without a \":\" in \"${expr}\"`);\n}\n\n/** `texture(t, uv)` -> `textureSampleLevel(t, t_smp, uv, 0.0)`. Explicit level 0 rather\n * than `textureSample`: it sidesteps WGSL's non-uniform-control-flow rule for implicit\n * derivatives (the corpus samples inside `if`/`for`), and the canvas textures this\n * runtime binds are single-mip, so level 0 IS the only level — visually identical. */\nfunction rewriteTextureCalls(src: string, ctx: Ctx): string {\n return mapCalls(src, \"texture\", (args, raw) => {\n if (args.length !== 2) {\n throw new UnsupportedWgslShaderError(\n `texture() with ${args.length} arguments is not supported (\"${raw}\")`,\n );\n }\n const sampler = args[0].trim();\n if (!ctx.textures.has(sampler)) {\n throw new UnsupportedWgslShaderError(\n `texture() on \"${sampler}\", which is not a declared sampler2D uniform`,\n );\n }\n return `textureSampleLevel(${sampler}, ${sampler}_smp, ${args[1].trim()}, 0.0)`;\n });\n}\n\nfunction rewriteIntrinsics(src: string, ctx: Ctx): string {\n let out = mapCalls(src, \"mod\", (args, raw) => {\n if (args.length !== 2) {\n throw new UnsupportedWgslShaderError(\n `mod() with ${args.length} arguments`,\n );\n }\n const left = widthOf(args[0], ctx, raw);\n const right = widthOf(args[1], ctx, raw);\n const width = Math.max(left, right);\n ctx.needMod.add(width);\n const fn = width === 1 ? \"godot_mod\" : `godot_mod${width}`;\n return `${fn}(${broadcast(args[0].trim(), left, width)}, ${broadcast(\n args[1].trim(),\n right,\n width,\n )})`;\n });\n out = mapCalls(out, \"atan\", (args) =>\n args.length === 2\n ? `atan2(${args[0].trim()}, ${args[1].trim()})`\n : `atan(${args[0].trim()})`,\n );\n out = mapCalls(out, \"inverse\", (args, raw) => {\n const type = inferType(args[0], ctx);\n if (type !== \"mat3x3f\") {\n throw new UnsupportedWgslShaderError(\n `inverse() is only supported on a mat3 (got ${type ?? \"an untyped expression\"} in \"${raw}\")`,\n );\n }\n ctx.needInverse.mat3 = true;\n return `godot_inverse3(${args[0].trim()})`;\n });\n return out;\n}\n\nfunction broadcast(expr: string, from: number, to: number): string {\n return from === to ? expr : `vec${to}f(${expr})`;\n}\n\nfunction widthOf(expr: string, ctx: Ctx, raw: string): number {\n const type = inferType(expr, ctx);\n const width = type ? typeWidth(type) : null;\n if (width === null) {\n throw new UnsupportedWgslShaderError(\n `cannot infer the component count of \"${expr.trim()}\" in \"${raw}\" (WGSL has no function overloading, so mod()'s polyfill is chosen by width)`,\n );\n }\n return width;\n}\n\n// `float(` -> `f32(` etc. The lookbehind keeps the pass off identifiers that merely END\n// with a type name (`myvec3(`), and the alternatives never match an already-emitted WGSL\n// spelling (`vec3f(` has an `f` where the pattern wants `(`).\nconst CONSTRUCTORS: Record<string, string> = {\n float: \"f32\",\n int: \"i32\",\n vec2: \"vec2f\",\n vec3: \"vec3f\",\n vec4: \"vec4f\",\n ivec2: \"vec2i\",\n ivec3: \"vec3i\",\n ivec4: \"vec4i\",\n bvec2: \"vec2<bool>\",\n bvec3: \"vec3<bool>\",\n bvec4: \"vec4<bool>\",\n mat2: \"mat2x2f\",\n mat3: \"mat3x3f\",\n mat4: \"mat4x4f\",\n};\n\nfunction renameConstructors(src: string): string {\n return src.replace(\n /(?<![\\w.])(float|int|vec[234]|ivec[234]|bvec[234]|mat[234])(\\s*)\\(/g,\n (_match, name: string, space: string) => `${CONSTRUCTORS[name]}${space}(`,\n );\n}\n\n// ---- narrow type inference -------------------------------------------------\n//\n// Deliberately NOT a type checker: the only two rules that need a type are `mod` (WGSL\n// has no user-function overloading, so the polyfill's component count is part of its\n// name) and `inverse` (mat3 only). Everything else is either declared with an explicit\n// type or is passed through untouched. `null` means \"don't know\", and the two callers\n// turn that into a named UnsupportedWgslShaderError rather than a guess.\n\nconst VECTOR_TYPE = /^vec([234])([fi])$/;\n\nfunction typeWidth(type: string): number | null {\n if (type === \"f32\" || type === \"i32\" || type === \"u32\" || type === \"bool\") {\n return 1;\n }\n const match = VECTOR_TYPE.exec(type);\n return match ? Number(match[1]) : null;\n}\n\nconst SCALAR_RETURN = new Set([\"length\", \"dot\", \"distance\", \"determinant\"]);\nconst VEC4_RETURN = new Set([\"texture\", \"textureSampleLevel\", \"textureLoad\"]);\nconst BOOL_RETURN = new Set([\"any\", \"all\"]);\n\nfunction inferType(expr: string, ctx: Ctx): string | null {\n let e = expr.trim();\n while (e.startsWith(\"(\") && matchParen(e, 0) === e.length - 1) {\n e = e.slice(1, -1).trim();\n }\n if (!e) return null;\n if (hasTopLevelComparison(e)) return \"bool\";\n\n const operands = splitOperands(e);\n if (operands.length > 1) {\n let best: string | null = null;\n for (const operand of operands) {\n const type = inferType(operand, ctx);\n if (!type) continue;\n const width = typeWidth(type);\n const bestWidth = best ? typeWidth(best) : null;\n if (best === null || (width ?? 0) > (bestWidth ?? 0)) best = type;\n }\n return best;\n }\n if (/^[-+!~]/.test(e)) return inferType(e.slice(1), ctx);\n if (/^\\d/.test(e) || /^\\.\\d/.test(e)) return \"f32\";\n\n const call = /^([A-Za-z_]\\w*)\\s*\\(/.exec(e);\n if (call && matchParen(e, e.indexOf(\"(\")) === e.length - 1) {\n return inferCallType(call[1], e, ctx);\n }\n\n const swizzle = /^(.+)\\.([xyzwrgba]+)$/.exec(e);\n if (swizzle) {\n const baseType = inferType(swizzle[1], ctx);\n const match = baseType ? VECTOR_TYPE.exec(baseType) : null;\n if (match) {\n const width = swizzle[2].length;\n return width === 1 ? scalarOf(match[2]) : `vec${width}${match[2]}`;\n }\n }\n\n const index = /^(.+)\\[[^\\]]*\\]$/.exec(e);\n if (index) {\n const arrayType = inferType(index[1], ctx);\n const element = arrayType ? /^array<([^,]+),/.exec(arrayType) : null;\n if (element) return element[1];\n if (arrayType === \"mat3x3f\") return \"vec3f\";\n if (arrayType === \"mat2x2f\") return \"vec2f\";\n if (arrayType === \"mat4x4f\") return \"vec4f\";\n }\n\n return ctx.scope.get(e) ?? null;\n}\n\nfunction scalarOf(suffix: string): string {\n return suffix === \"i\" ? \"i32\" : \"f32\";\n}\n\nfunction inferCallType(name: string, expr: string, ctx: Ctx): string | null {\n const ctor = CONSTRUCTORS[name];\n if (ctor) return ctor;\n if (/^(f32|i32|u32|vec[234][fi]|mat[234]x[234]f)$/.test(name)) return name;\n if (SCALAR_RETURN.has(name)) return \"f32\";\n if (VEC4_RETURN.has(name)) return \"vec4f\";\n if (BOOL_RETURN.has(name)) return \"bool\";\n const helper = ctx.fnReturns.get(name);\n if (helper) return helper;\n // Everything else that survives here (abs, min, mix, smoothstep, clamp, pow, …) is\n // component-wise in both languages: the result is as wide as the widest argument.\n const open = expr.indexOf(\"(\");\n const args = splitTopLevel(expr.slice(open + 1, expr.length - 1), \",\");\n let best: string | null = null;\n for (const arg of args) {\n if (!arg.trim()) continue;\n const type = inferType(arg, ctx);\n if (!type) continue;\n const bestWidth = best ? typeWidth(best) : null;\n if (best === null || (typeWidth(type) ?? 0) > (bestWidth ?? 0)) best = type;\n }\n return best;\n}\n\nfunction hasTopLevelComparison(expr: string): boolean {\n let depth = 0;\n for (let i = 0; i < expr.length; i += 1) {\n const c = expr[i];\n if (c === \"(\" || c === \"[\") depth += 1;\n else if (c === \")\" || c === \"]\") depth -= 1;\n else if (depth === 0) {\n const pair = expr.slice(i, i + 2);\n if (pair === \"&&\" || pair === \"||\" || pair === \"==\" || pair === \"!=\") {\n return true;\n }\n if (\n (c === \"<\" || c === \">\") &&\n expr[i + 1] !== \"<\" &&\n expr[i + 1] !== \">\"\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\n/** Split on top-level `+ - * /`, skipping the unary uses (leading, or right after\n * another operator or an opening delimiter). Only used to find the WIDEST operand. */\nfunction splitOperands(expr: string): string[] {\n const parts: string[] = [];\n let depth = 0;\n let start = 0;\n for (let i = 0; i < expr.length; i += 1) {\n const c = expr[i];\n if (c === \"(\" || c === \"[\") depth += 1;\n else if (c === \")\" || c === \"]\") depth -= 1;\n else if (depth === 0 && \"+-*/%\".includes(c)) {\n const before = expr.slice(start, i).trim();\n if (!before) continue;\n if (/[-+*/%<>=!&|,(]$/.test(before)) continue;\n parts.push(before);\n start = i + 1;\n }\n }\n const tail = expr.slice(start).trim();\n if (tail) parts.push(tail);\n return parts;\n}\n\n// ---- call rewriting utilities ----------------------------------------------\n\nfunction mapCalls(\n src: string,\n name: string,\n transform: (args: string[], raw: string) => string,\n): string {\n const pattern = new RegExp(`(?<![\\\\w.])${name}\\\\s*\\\\(`, \"g\");\n let out = \"\";\n let index = 0;\n for (;;) {\n pattern.lastIndex = index;\n const match = pattern.exec(src);\n if (!match) {\n out += src.slice(index);\n return out;\n }\n const open = match.index + match[0].length - 1;\n const close = matchParen(src, open);\n const raw = src.slice(match.index, close + 1);\n // Arguments first: a nested `mod(mod(...))` must be rewritten inside out.\n const args = splitTopLevel(src.slice(open + 1, close), \",\").map((arg) =>\n mapCalls(arg, name, transform),\n );\n out += src.slice(index, match.index);\n out += transform(args, raw);\n index = close + 1;\n }\n}\n\nfunction matchParen(src: string, openIndex: number): number {\n let depth = 0;\n for (let i = openIndex; i < src.length; i += 1) {\n if (src[i] === \"(\") depth += 1;\n else if (src[i] === \")\") {\n depth -= 1;\n if (depth === 0) return i;\n }\n }\n throw new UnsupportedWgslShaderError(\n `unbalanced parentheses in \"${src.slice(openIndex, openIndex + 40)}\"`,\n );\n}\n\nfunction splitTopLevel(src: string, separator: string): string[] {\n const parts: string[] = [];\n let depth = 0;\n let start = 0;\n for (let i = 0; i < src.length; i += 1) {\n const c = src[i];\n if (c === \"(\" || c === \"[\" || c === \"{\") depth += 1;\n else if (c === \")\" || c === \"]\" || c === \"}\") depth -= 1;\n else if (depth === 0 && c === separator) {\n parts.push(src.slice(start, i));\n start = i + 1;\n }\n }\n parts.push(src.slice(start));\n return parts;\n}\n\nfunction indentLines(lines: string[]): string[] {\n return lines.map((line) => (line ? ` ${line}` : line));\n}\n\nfunction mergeElse(lines: string[]): string[] {\n const out: string[] = [];\n for (const line of lines) {\n const previous = out[out.length - 1];\n if (\n previous !== undefined &&\n previous.trim() === \"}\" &&\n /^\\s*else\\b/.test(line)\n ) {\n out[out.length - 1] = `${previous} ${line.trim()}`;\n continue;\n }\n out.push(line);\n }\n return out;\n}\n\n// ---- module assembly -------------------------------------------------------\n\nconst MOD_POLYFILL_HEADER = `// GLSL's mod() is FLOOR-signed (x - y*floor(x/y)); WGSL's % is TRUNC-signed, so they\n// disagree wherever x goes negative — a scrolling UV crossing zero would tear. WGSL has\n// no user-defined function overloading, so the component count lives in the name.`;\n\nconst INVERSE_POLYFILL = `// WGSL has no inverse(). Cofactor / determinant, column-major like both languages.\nfn godot_inverse3(m: mat3x3f) -> mat3x3f {\n let a = m[0];\n let b = m[1];\n let c = m[2];\n let b01 = c.z * b.y - b.z * c.y;\n let b11 = b.z * c.x - c.z * b.x;\n let b21 = c.y * b.x - b.y * c.x;\n let det = a.x * b01 + a.y * b11 + a.z * b21;\n let inv = mat3x3f(\n vec3f(b01, a.z * c.y - c.z * a.y, b.z * a.y - a.z * b.y),\n vec3f(b11, c.z * a.x - a.z * c.x, a.z * b.x - b.z * a.x),\n vec3f(b21, a.y * c.x - c.y * a.x, b.y * a.x - a.y * b.x)\n );\n return inv * (1.0 / det);\n}`;\n\nconst VS_MAIN = `struct VsOut {\n @builtin(position) pos: vec4f,\n @location(0) uv: vec2f,\n}\n\n@vertex\nfn ${VERTEX_ENTRY}(@builtin(vertex_index) index: u32) -> VsOut {\n // TRIANGLE_STRIP corner order: (-1,-1) (1,-1) (-1,1) (1,1).\n var corners = array<vec2f, 4>(\n vec2f(-1.0, -1.0),\n vec2f(1.0, -1.0),\n vec2f(-1.0, 1.0),\n vec2f(1.0, 1.0)\n );\n let xy = corners[index];\n var out: VsOut;\n out.pos = vec4f(xy, 0.0, 1.0);\n // Godot's UV is node-local with a TOP-LEFT origin; clip Y is up. The flip lives HERE,\n // in the vertex stage, so the fragment prelude below is the GLSL one MINUS its\n // \"1.0 - v_uv.y\" — one place to get wrong instead of one per fragment.\n out.uv = vec2f(xy.x * 0.5 + 0.5, 0.5 - xy.y * 0.5);\n return out;\n}`;\n\ninterface AssembleInput {\n parsed: ParsedShader;\n analysis: ShaderAnalysis;\n plan: UniformPlan;\n renames: RenameMap;\n ctx: Ctx;\n helpers: TranslatedHelpers;\n varyingLines: string[];\n bodyLines: string[];\n}\n\nfunction assembleModule(input: AssembleInput): string {\n const { parsed, analysis, plan, renames, ctx } = input;\n\n const memberLines = plan.members.map((member) => {\n const type =\n member.arrayLength !== undefined\n ? `array<${member.type}, ${member.arrayLength}>`\n : member.type;\n return ` ${member.wgslName}: ${type},`;\n });\n const structText = [\n \"// One uniform struct for everything the fragment reads. Members are laid out by\",\n \"// WGSL's own uniform address space rules IN DECLARATION ORDER, which is exactly what\",\n \"// `wgslStructLayout` records — so the byte offsets a writer holds and the offsets the\",\n \"// compiler computes are the same numbers, with no explicit padding members to drift.\",\n \"struct Uniforms {\",\n ...memberLines,\n \"}\",\n ].join(\"\\n\");\n\n const bindingLines = [\n `@group(0) @binding(${BINDINGS.uniform}) var<uniform> _u: Uniforms;`,\n `@group(0) @binding(${BINDINGS.texture}) var TEXTURE: texture_2d<f32>;`,\n `@group(0) @binding(${BINDINGS.textureSampler}) var TEXTURE_smp: sampler;`,\n ];\n parsed.samplers.forEach((sampler, i) => {\n const name = renameOf(sampler.name, renames);\n bindingLines.push(\n `@group(0) @binding(${BINDINGS.userSamplersBase + i * 2}) var ${name}: texture_2d<f32>;`,\n );\n bindingLines.push(\n `@group(0) @binding(${BINDINGS.userSamplersBase + i * 2 + 1}) var ${name}_smp: sampler;`,\n );\n });\n\n const consts: string[] = [];\n if (analysis.usesPi) {\n consts.push(\"const PI: f32 = 3.141592653589793;\");\n }\n consts.push(...input.helpers.consts);\n\n const polyfills: string[] = [];\n if (ctx.needMod.size > 0) {\n const widths = [...ctx.needMod].sort((a, b) => a - b);\n polyfills.push(\n [\n MOD_POLYFILL_HEADER,\n ...widths.map((width) => {\n const type = width === 1 ? \"f32\" : `vec${width}f`;\n const fn = width === 1 ? \"godot_mod\" : `godot_mod${width}`;\n return `fn ${fn}(x: ${type}, y: ${type}) -> ${type} { return x - y * floor(x / y); }`;\n }),\n ].join(\"\\n\"),\n );\n }\n if (ctx.needInverse.mat3) polyfills.push(INVERSE_POLYFILL);\n\n const fragment: string[] = [];\n const bodyTogether = input.bodyLines.join(\"\\n\");\n for (const name of plan.boolUniformNames) {\n // WGSL bool is not host-shareable, so the uniform holds a 1/0 f32 and the shader body\n // reads this alias under the Godot name. Only the ones the body actually reads get an\n // alias; a declared-but-unused bool uniform still keeps its struct member (the runtime\n // writes by offset, and dropping the member would move every offset after it).\n if (hasToken(bodyTogether, name)) {\n fragment.push(`let ${name}: bool = (_u.${name} != 0.0);`);\n }\n }\n fragment.push(\"let raw_uv = in.uv;\");\n fragment.push(\n \"let GODOT_UV = _u.uv_window.xy + raw_uv * _u.uv_window.zw;\",\n \"let UV = (GODOT_UV - vec2f(0.5)) / _u.uv_fit + vec2f(0.5);\",\n );\n if (analysis.usesScreenUv) {\n fragment.push(\n \"let SCREEN_UV = _u.screen_origin + GODOT_UV * _u.screen_size;\",\n );\n }\n fragment.push(\n analysis.opaqueColor\n ? \"var COLOR: vec4f = vec4f(textureSampleLevel(TEXTURE, TEXTURE_smp, UV, 0.0).rgb, 1.0);\"\n : \"var COLOR: vec4f = textureSampleLevel(TEXTURE, TEXTURE_smp, UV, 0.0);\",\n );\n fragment.push(...input.varyingLines);\n fragment.push(...input.bodyLines);\n if (analysis.autoModulate) {\n fragment.push(\"COLOR = COLOR * _u.modulate;\");\n }\n fragment.push(\n '// PREMULTIPLIED. A GPUCanvasContext offers only alphaMode \"opaque\" | \"premultiplied\",',\n \"// so this is THE canvas contract: return rgb*a with a, and let the pipeline blend\",\n \"// one / one-minus-src-alpha on colour AND alpha. Returning straight alpha here halos;\",\n \"// returning premultiplied under a src-alpha blend double-multiplies. Neither errors.\",\n \"return vec4f(COLOR.rgb * COLOR.a, COLOR.a);\",\n );\n\n const fsMain = [\n \"@fragment\",\n `fn ${FRAGMENT_ENTRY}(in: VsOut) -> @location(0) vec4f {`,\n ...indentLines(fragment),\n \"}\",\n ].join(\"\\n\");\n\n const sections = [\n \"// Generated by transpileGodotShaderWgsl (packages/html/src/webgpu/transpile-wgsl.ts).\",\n structText,\n bindingLines.join(\"\\n\"),\n consts.length > 0 ? consts.join(\"\\n\") : \"\",\n polyfills.join(\"\\n\\n\"),\n input.helpers.fns.join(\"\\n\\n\"),\n VS_MAIN,\n fsMain,\n ].filter((section) => section !== \"\");\n\n return `${sections.join(\"\\n\\n\")}\\n`;\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@godot-scene-web/effects",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "description": "Portable Godot particle, shader, and easing simulation utilities.",
7
+ "publishConfig": {
8
+ "access": "public",
9
+ "registry": "https://registry.npmjs.org/"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/tfoxy/godot-scene-web.git"
14
+ },
15
+ "homepage": "https://github.com/tfoxy/godot-scene-web#readme",
16
+ "bugs": {
17
+ "url": "https://github.com/tfoxy/godot-scene-web/issues"
18
+ },
19
+ "sideEffects": false,
20
+ "exports": {
21
+ ".": {
22
+ "development": "./src/index.ts",
23
+ "types": "./dist/index.d.ts",
24
+ "import": "./dist/index.js"
25
+ },
26
+ "./particles": {
27
+ "development": "./src/particles/index.ts",
28
+ "types": "./dist/particles/index.d.ts",
29
+ "import": "./dist/particles/index.js"
30
+ },
31
+ "./shaders": {
32
+ "development": "./src/shaders/index.ts",
33
+ "types": "./dist/shaders/index.d.ts",
34
+ "import": "./dist/shaders/index.js"
35
+ },
36
+ "./easing": {
37
+ "development": "./src/easing/index.ts",
38
+ "types": "./dist/easing/index.d.ts",
39
+ "import": "./dist/easing/index.js"
40
+ }
41
+ },
42
+ "main": "./dist/index.js",
43
+ "types": "./dist/index.d.ts",
44
+ "files": [
45
+ "dist",
46
+ "LICENSE"
47
+ ],
48
+ "scripts": {
49
+ "build": "tsdown",
50
+ "typecheck": "tsc -p tsconfig.json --noEmit",
51
+ "test": "cd ../.. && vitest run --config vitest.config.ts packages/effects/test"
52
+ }
53
+ }