@framefields/node-blur 2.0.2

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":"renderers-DAmsgkhH.mjs","names":[],"sources":["../src/shared/config.ts","../src/renderers/webgpu-renderer.ts","../src/renderers/index.ts"],"sourcesContent":["import {\n\tconfigBuilder,\n\tImageResultSchema,\n\tVideoResultSchema,\n} from \"@framefields/node-sdk\";\nimport { z } from \"zod\";\n\nexport const MAX_BLUR = 100;\n\nexport const blurConfig = configBuilder()\n\t.field(\n\t\t\"blurType\",\n\t\tz\n\t\t\t.enum([\n\t\t\t\t\"Gaussian\",\n\t\t\t\t\"Box\",\n\t\t\t\t\"Median\",\n\t\t\t\t\"Motion\",\n\t\t\t\t\"Bilateral\",\n\t\t\t\t\"Edge-preserving\",\n\t\t\t\t\"Radial\",\n\t\t\t\t\"Zoom\",\n\t\t\t])\n\t\t\t.default(\"Gaussian\"),\n\t\t{\n\t\t\tbindable: false,\n\t\t\tlabel: \"Blur Type\",\n\t\t},\n\t)\n\t.field(\"strength\", z.number().min(0).max(MAX_BLUR).default(5), {\n\t\tbindable: true,\n\t\tdataTypes: [\"Number\", \"Signal\"],\n\t\tlabel: \"Strength Signal\",\n\t\tdescription:\n\t\t\t\"The intensity of the blur. 0 = no blur. Can be modulated by a static number or a dynamic signal.\",\n\t})\n\t.field(\"angle\", z.number().int().min(0).max(360).default(0), {\n\t\tbindable: false,\n\t\t// No editor handle, but effect signals are sampled per frame before the\n\t\t// renderer runs, so authoring code may animate it.\n\t\tsignal: true,\n\t\tlabel: \"Angle\",\n\t\tdescription: \"Direction of a Motion blur, in degrees.\",\n\t})\n\t.field(\"sigmaColor\", z.number().min(0.01).max(1.0).default(0.1), {\n\t\tbindable: true,\n\t\tdataTypes: [\"Number\", \"Signal\"],\n\t\tlabel: \"Color Sigma Signal\",\n\t\tdescription:\n\t\t\t\"Sigma value for color space in Bilateral / Edge-preserving blurs. Can be modulated by a static number or a dynamic signal.\",\n\t})\n\t.field(\"centerX\", z.number().min(0).max(1.0).default(0.5), {\n\t\tbindable: true,\n\t\tdataTypes: [\"Number\", \"Signal\"],\n\t\tlabel: \"Center X Signal\",\n\t\tdescription:\n\t\t\t\"The X coordinate of the blur center (0.0 to 1.0). Can be modulated by a static number or a dynamic signal.\",\n\t})\n\t.field(\"centerY\", z.number().min(0).max(1.0).default(0.5), {\n\t\tbindable: true,\n\t\tdataTypes: [\"Number\", \"Signal\"],\n\t\tlabel: \"Center Y Signal\",\n\t\tdescription:\n\t\t\t\"The Y coordinate of the blur center (0.0 to 1.0). Can be modulated by a static number or a dynamic signal.\",\n\t})\n\t.field(\"partialBlur\", z.boolean().default(false), {\n\t\tbindable: false,\n\t\tsignal: true,\n\t\tlabel: \"Partial Blur\",\n\t\tdescription: \"Blurs only a specific circular area around center point.\",\n\t})\n\t.field(\"radius\", z.number().min(0.01).max(1.0).default(0.3), {\n\t\tbindable: true,\n\t\tdataTypes: [\"Number\", \"Signal\"],\n\t\tlabel: \"Partial Radius Signal\",\n\t\tdescription:\n\t\t\t\"Radius of the partial blur region (0.01 to 1.0). Can be modulated by a static number or a dynamic signal.\",\n\t})\n\t.field(\"radiusY\", z.number().min(0).max(1.0).default(0), {\n\t\tbindable: true,\n\t\tdataTypes: [\"Number\", \"Signal\"],\n\t\tlabel: \"Partial Radius Y Signal\",\n\t\tdescription:\n\t\t\t\"Vertical radius of the partial blur region (0 to 1.0). 0 reuses the horizontal radius.\",\n\t})\n\t.field(\"shape\", z.enum([\"ellipse\", \"circle\", \"rect\"]).default(\"circle\"), {\n\t\tbindable: false,\n\t\tlabel: \"Partial Shape\",\n\t\tdescription: \"Shape of the partial blur region.\",\n\t})\n\t.build();\n\nexport const BlurNodeConfigSchema = blurConfig.schema;\n\nexport type BlurNodeConfig = z.infer<typeof BlurNodeConfigSchema>;\n\nexport const BlurResultSchema = z.union([ImageResultSchema, VideoResultSchema]);\n\nexport type BlurResult = z.infer<typeof BlurResultSchema>;\n\nexport const BLUR_OUTPUT_TYPE_MAP: Record<string, \"Image\" | \"Video\" | \"GIF\"> = {\n\tVideo: \"Video\",\n\tLottie: \"Video\",\n\tGIF: \"GIF\",\n\tImage: \"Image\",\n\tSVG: \"Image\",\n};\n","/// <reference types=\"webgpu\" />\nimport type { SignalData } from \"@framefields/core\";\nimport type { WebGPUNodeRenderer } from \"@framefields/node-sdk\";\nimport { signalRegistry } from \"@framefields/webgpu-renderers\";\nimport { MAX_BLUR } from \"../shared/config.js\";\n\ninterface BlurOp {\n\top: \"Blur\";\n\tblurType?:\n\t\t| \"Gaussian\"\n\t\t| \"Box\"\n\t\t| \"Median\"\n\t\t| \"Motion\"\n\t\t| \"Bilateral\"\n\t\t| \"Edge-preserving\"\n\t\t| \"Radial\"\n\t\t| \"Zoom\";\n\tstrength?: number;\n\tangle?: number;\n\tsigmaColor?: number;\n\tcenterX?: number;\n\tcenterY?: number;\n\tpartialBlur?: boolean;\n\tradius?: number;\n\tradiusY?: number;\n\tshape?: \"ellipse\" | \"circle\" | \"rect\";\n\tstrengthHandleId?: string | null;\n\tsigmaColorHandleId?: string | null;\n\tcenterXHandleId?: string | null;\n\tcenterYHandleId?: string | null;\n\tradiusHandleId?: string | null;\n\tradiusYHandleId?: string | null;\n\topacity?: number;\n\tinputs?: Record<\n\t\tstring,\n\t\t{\n\t\t\tconnectionValid: boolean;\n\t\t\toutputItem: {\n\t\t\t\ttype: string;\n\t\t\t\tdata: unknown;\n\t\t\t} | null;\n\t\t}\n\t>;\n}\n\ntype BlurSignalData = SignalData & { nodeId?: string };\n\nconst WGSL_BLUR_UNIFORMS = `\nstruct BlurUniforms {\n\tdirX : f32,\n\tdirY : f32,\n\tstrength : f32,\n\tangle : f32,\n\n\tsigmaColor : f32,\n\tcenterX : f32,\n\tcenterY : f32,\n\tradius : f32,\n\n\tpartialBlur : f32,\n\thasStrengthSig : f32,\n\thasSigmaColorSig: f32,\n\thasCenterXSig : f32,\n\n\thasCenterYSig : f32,\n\thasRadiusSig : f32,\n\tradiusY : f32,\n\tshape : f32,\n};\n\n@group(0) @binding(0) var<uniform> u : BlurUniforms;\n@group(1) @binding(0) var tex : texture_2d<f32>;\n@group(1) @binding(1) var samp : sampler;\n@group(1) @binding(2) var origTex : texture_2d<f32>;\n\n@group(2) @binding(0) var strengthSigTex : texture_2d<f32>;\n@group(2) @binding(1) var sigmaColorSigTex : texture_2d<f32>;\n@group(2) @binding(2) var centerXSigTex : texture_2d<f32>;\n@group(2) @binding(3) var centerYSigTex : texture_2d<f32>;\n@group(2) @binding(4) var radiusSigTex : texture_2d<f32>;\n@group(2) @binding(5) var signalSamp : sampler;\n\nfn applyPartialBlur(blurred: vec4<f32>, uv: vec2<f32>, dimensions: vec2<f32>) -> vec4<f32> {\n\tif (u.partialBlur <= 0.5) {\n\t\treturn blurred;\n\t}\n\tlet orig = textureSampleLevel(origTex, samp, uv, 0.0);\n\tvar centerX = u.centerX;\n\tif (u.hasCenterXSig > 0.5) {\n\t\tcenterX = textureSampleLevel(centerXSigTex, signalSamp, vec2<f32>(0.5, 0.5), 0.0).r;\n\t}\n\tvar centerY = u.centerY;\n\tif (u.hasCenterYSig > 0.5) {\n\t\tcenterY = textureSampleLevel(centerYSigTex, signalSamp, vec2<f32>(0.5, 0.5), 0.0).r;\n\t}\n\tvar radiusX = u.radius;\n\tif (u.hasRadiusSig > 0.5) {\n\t\tradiusX = textureSampleLevel(radiusSigTex, signalSamp, vec2<f32>(0.5, 0.5), 0.0).r;\n\t}\n\tvar radiusY = u.radiusY;\n\n\tvar mask = 0.0;\n\tif (radiusY <= 0.0) {\n\t\tlet aspect = dimensions.x / dimensions.y;\n\t\tlet diff = (uv - vec2<f32>(centerX, centerY)) * vec2<f32>(aspect, 1.0);\n\t\tlet dist = length(diff);\n\t\tlet feather = 0.05;\n\t\tmask = 1.0 - smoothstep(radiusX - feather, radiusX + feather, dist);\n\t} else {\n\t\tlet diff = abs(uv - vec2<f32>(centerX, centerY));\n\t\tif (u.shape > 0.5) {\n\t\t\tlet feather = 0.02;\n\t\t\tlet edgeX = 1.0 - smoothstep(radiusX - feather, radiusX + feather, diff.x);\n\t\t\tlet edgeY = 1.0 - smoothstep(radiusY - feather, radiusY + feather, diff.y);\n\t\t\tmask = edgeX * edgeY;\n\t\t} else {\n\t\t\tlet normDist = length(vec2<f32>(diff.x / max(1e-4, radiusX), diff.y / max(1e-4, radiusY)));\n\t\t\tlet feather = 0.08;\n\t\t\tmask = 1.0 - smoothstep(1.0 - feather, 1.0 + feather, normDist);\n\t\t}\n\t}\n\treturn mix(orig, blurred, mask);\n}\n`;\n\nexport const GAUSSIAN_BLUR_SHADER = `\n${WGSL_BLUR_UNIFORMS}\n\nstruct VSOut {\n\t@builtin(position) pos : vec4<f32>,\n\t@location(0) uv : vec2<f32>,\n};\n\n@vertex fn vs(@builtin(vertex_index) vi: u32) -> VSOut {\n\tvar pos = array<vec2<f32>, 4>(\n\t\tvec2<f32>(-1.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0),\n\t\tvec2<f32>(-1.0, -1.0),\n\t\tvec2<f32>(1.0, -1.0)\n\t);\n\tvar uv = array<vec2<f32>, 4>(\n\t\tvec2<f32>(0.0, 0.0),\n\t\tvec2<f32>(1.0, 0.0),\n\t\tvec2<f32>(0.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0)\n\t);\n\treturn VSOut(vec4<f32>(pos[vi], 0.0, 1.0), uv[vi]);\n}\n\n@fragment fn fs(in : VSOut) -> @location(0) vec4<f32> {\n\tlet c = textureSampleLevel(tex, samp, in.uv, 0.0);\n\tvar spatial_sigma = u.strength;\n\tif (u.hasStrengthSig > 0.5) {\n\t\tspatial_sigma = textureSampleLevel(strengthSigTex, signalSamp, vec2<f32>(0.5, 0.5), 0.0).r;\n\t}\n\n\tlet dimensions = vec2<f32>(textureDimensions(tex));\n\tif (spatial_sigma <= 0.0) {\n\t\treturn applyPartialBlur(c, in.uv, dimensions);\n\t}\n\n\tlet texelSize = 1.0 / dimensions;\n\tlet stepScale = max(1.0, spatial_sigma / 20.0);\n\tlet effectiveSigma = spatial_sigma / stepScale;\n\tlet radius = min(i32(ceil(3.0 * effectiveSigma)), 64);\n\t\n\tlet direction = vec2<f32>(u.dirX, u.dirY);\n\t\n\tvar color = vec4<f32>(0.0);\n\tvar totalWeight = 0.0;\n\n\tfor (var i = -radius; i <= radius; i++) {\n\t\tlet offset = vec2<f32>(f32(i) * stepScale) * direction * texelSize;\n\t\tlet x = f32(i) * stepScale;\n\t\tlet weight = exp(-0.5 * (x / spatial_sigma) * (x / spatial_sigma));\n\t\tcolor += textureSampleLevel(tex, samp, in.uv + offset, 0.0) * weight;\n\t\ttotalWeight += weight;\n\t}\n\n\tlet blurred = color / totalWeight;\n\treturn applyPartialBlur(blurred, in.uv, dimensions);\n}\n`;\n\nexport const BOX_BLUR_SHADER = `\n${WGSL_BLUR_UNIFORMS}\n\nstruct VSOut {\n\t@builtin(position) pos : vec4<f32>,\n\t@location(0) uv : vec2<f32>,\n};\n\n@vertex fn vs(@builtin(vertex_index) vi: u32) -> VSOut {\n\tvar pos = array<vec2<f32>, 4>(\n\t\tvec2<f32>(-1.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0),\n\t\tvec2<f32>(-1.0, -1.0),\n\t\tvec2<f32>(1.0, -1.0)\n\t);\n\tvar uv = array<vec2<f32>, 4>(\n\t\tvec2<f32>(0.0, 0.0),\n\t\tvec2<f32>(1.0, 0.0),\n\t\tvec2<f32>(0.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0)\n\t);\n\treturn VSOut(vec4<f32>(pos[vi], 0.0, 1.0), uv[vi]);\n}\n\n@fragment fn fs(in : VSOut) -> @location(0) vec4<f32> {\n\tlet c = textureSampleLevel(tex, samp, in.uv, 0.0);\n\tvar strength = u.strength;\n\tif (u.hasStrengthSig > 0.5) {\n\t\tstrength = textureSampleLevel(strengthSigTex, signalSamp, vec2<f32>(0.5, 0.5), 0.0).r;\n\t}\n\n\tlet dimensions = vec2<f32>(textureDimensions(tex));\n\tlet radius = i32(round(strength));\n\tif (radius <= 0) {\n\t\treturn applyPartialBlur(c, in.uv, dimensions);\n\t}\n\n\tlet texelSize = 1.0 / dimensions;\n\tlet direction = vec2<f32>(u.dirX, u.dirY);\n\t\n\tvar color = vec4<f32>(0.0);\n\tvar count = 0.0;\n\n\tfor (var i = -radius; i <= radius; i++) {\n\t\tlet offset = vec2<f32>(f32(i)) * direction * texelSize;\n\t\tcolor += textureSampleLevel(tex, samp, in.uv + offset, 0.0);\n\t\tcount += 1.0;\n\t}\n\n\tlet blurred = color / count;\n\treturn applyPartialBlur(blurred, in.uv, dimensions);\n}\n`;\n\nexport const MEDIAN_BLUR_SHADER = `\n${WGSL_BLUR_UNIFORMS}\n\nstruct VSOut {\n\t@builtin(position) pos : vec4<f32>,\n\t@location(0) uv : vec2<f32>,\n};\n\nstruct Val {\n\tluma : f32,\n\tcolor : vec4<f32>,\n};\n\n@vertex fn vs(@builtin(vertex_index) vi: u32) -> VSOut {\n\tvar pos = array<vec2<f32>, 4>(\n\t\tvec2<f32>(-1.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0),\n\t\tvec2<f32>(-1.0, -1.0),\n\t\tvec2<f32>(1.0, -1.0)\n\t);\n\tvar uv = array<vec2<f32>, 4>(\n\t\tvec2<f32>(0.0, 0.0),\n\t\tvec2<f32>(1.0, 0.0),\n\t\tvec2<f32>(0.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0)\n\t);\n\treturn VSOut(vec4<f32>(pos[vi], 0.0, 1.0), uv[vi]);\n}\n\n@fragment fn fs(in : VSOut) -> @location(0) vec4<f32> {\n\tlet centerCol = textureSampleLevel(tex, samp, in.uv, 0.0);\n\tvar strength = u.strength;\n\tif (u.hasStrengthSig > 0.5) {\n\t\tstrength = textureSampleLevel(strengthSigTex, signalSamp, vec2<f32>(0.5, 0.5), 0.0).r;\n\t}\n\n\tlet dimensions = vec2<f32>(textureDimensions(tex));\n\tlet radius = min(i32(round(strength)), 16);\n\tif (radius <= 0) {\n\t\treturn applyPartialBlur(centerCol, in.uv, dimensions);\n\t}\n\n\tlet count = radius * 2 + 1;\n\tlet texelSize = 1.0 / dimensions;\n\tlet direction = vec2<f32>(u.dirX, u.dirY);\n\n\tvar values : array<Val, 33>;\n\n\tfor (var i = 0; i < 33; i++) {\n\t\tif (i >= count) { break; }\n\t\tlet offset = vec2<f32>(f32(i - radius)) * direction * texelSize;\n\t\tlet col = textureSampleLevel(tex, samp, in.uv + offset, 0.0);\n\t\tvalues[i] = Val(dot(col.rgb, vec3<f32>(0.299, 0.587, 0.114)), col);\n\t}\n\n\t// Selection sort\n\tfor (var i = 0; i < 33; i++) {\n\t\tif (i >= count - 1) { break; }\n\t\tvar minIdx = i;\n\t\tfor (var j = 0; j < 33; j++) {\n\t\t\tif (j <= i) { continue; }\n\t\t\tif (j >= count) { break; }\n\t\t\tif (values[j].luma < values[minIdx].luma) {\n\t\t\t\tminIdx = j;\n\t\t\t}\n\t\t}\n\t\tif (minIdx != i) {\n\t\t\tlet temp = values[i];\n\t\t\tvalues[i] = values[minIdx];\n\t\t\tvalues[minIdx] = temp;\n\t\t}\n\t}\n\n\tlet medianIdx = count / 2;\n\treturn applyPartialBlur(values[medianIdx].color, in.uv, dimensions);\n}\n`;\n\nexport const MOTION_BLUR_SHADER = `\n${WGSL_BLUR_UNIFORMS}\n\nstruct VSOut {\n\t@builtin(position) pos : vec4<f32>,\n\t@location(0) uv : vec2<f32>,\n};\n\n@vertex fn vs(@builtin(vertex_index) vi: u32) -> VSOut {\n\tvar pos = array<vec2<f32>, 4>(\n\t\tvec2<f32>(-1.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0),\n\t\tvec2<f32>(-1.0, -1.0),\n\t\tvec2<f32>(1.0, -1.0)\n\t);\n\tvar uv = array<vec2<f32>, 4>(\n\t\tvec2<f32>(0.0, 0.0),\n\t\tvec2<f32>(1.0, 0.0),\n\t\tvec2<f32>(0.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0)\n\t);\n\treturn VSOut(vec4<f32>(pos[vi], 0.0, 1.0), uv[vi]);\n}\n\n@fragment fn fs(in : VSOut) -> @location(0) vec4<f32> {\n\tlet c = textureSampleLevel(tex, samp, in.uv, 0.0);\n\tvar strength = u.strength;\n\tif (u.hasStrengthSig > 0.5) {\n\t\tstrength = textureSampleLevel(strengthSigTex, signalSamp, vec2<f32>(0.5, 0.5), 0.0).r;\n\t}\n\n\tlet dimensions = vec2<f32>(textureDimensions(tex));\n\tif (strength <= 0.0) {\n\t\treturn applyPartialBlur(c, in.uv, dimensions);\n\t}\n\n\tlet PI = 3.14159265359;\n\tlet angleRad = u.angle * PI / 180.0;\n\tlet dir = vec2<f32>(cos(angleRad), sin(angleRad));\n\n\tlet texelSize = 1.0 / dimensions;\n\tlet step = dir * texelSize;\n\n\tlet numSamples = i32(clamp(strength, 1.0, 64.0));\n\tvar color = vec4<f32>(0.0);\n\t\n\tfor (var i = 0; i < 64; i++) {\n\t\tif (i >= numSamples) { break; }\n\t\tlet offset = f32(i - numSamples / 2) * step;\n\t\tcolor += textureSampleLevel(tex, samp, in.uv + offset, 0.0);\n\t}\n\n\tlet blurred = color / f32(numSamples);\n\treturn applyPartialBlur(blurred, in.uv, dimensions);\n}\n`;\n\nexport const BILATERAL_BLUR_SHADER = `\n${WGSL_BLUR_UNIFORMS}\n\nstruct VSOut {\n\t@builtin(position) pos : vec4<f32>,\n\t@location(0) uv : vec2<f32>,\n};\n\n@vertex fn vs(@builtin(vertex_index) vi: u32) -> VSOut {\n\tvar pos = array<vec2<f32>, 4>(\n\t\tvec2<f32>(-1.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0),\n\t\tvec2<f32>(-1.0, -1.0),\n\t\tvec2<f32>(1.0, -1.0)\n\t);\n\tvar uv = array<vec2<f32>, 4>(\n\t\tvec2<f32>(0.0, 0.0),\n\t\tvec2<f32>(1.0, 0.0),\n\t\tvec2<f32>(0.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0)\n\t);\n\treturn VSOut(vec4<f32>(pos[vi], 0.0, 1.0), uv[vi]);\n}\n\n@fragment fn fs(in : VSOut) -> @location(0) vec4<f32> {\n\tlet centerCol = textureSampleLevel(tex, samp, in.uv, 0.0);\n\tvar spatial_sigma = u.strength;\n\tif (u.hasStrengthSig > 0.5) {\n\t\tspatial_sigma = textureSampleLevel(strengthSigTex, signalSamp, vec2<f32>(0.5, 0.5), 0.0).r;\n\t}\n\tvar sigmaColor = u.sigmaColor;\n\tif (u.hasSigmaColorSig > 0.5) {\n\t\tsigmaColor = textureSampleLevel(sigmaColorSigTex, signalSamp, vec2<f32>(0.5, 0.5), 0.0).r;\n\t}\n\n\tlet dimensions = vec2<f32>(textureDimensions(tex));\n\tif (spatial_sigma <= 0.0) {\n\t\treturn applyPartialBlur(centerCol, in.uv, dimensions);\n\t}\n\n\tlet texelSize = 1.0 / dimensions;\n\tlet radius = min(i32(ceil(3.0 * spatial_sigma)), 32);\n\tlet direction = vec2<f32>(u.dirX, u.dirY);\n\t\n\tvar color = vec4<f32>(0.0);\n\tvar totalWeight = 0.0;\n\n\tfor (var i = -32; i <= 32; i++) {\n\t\tif (i < -radius || i > radius) { continue; }\n\t\tlet offset = vec2<f32>(f32(i)) * direction * texelSize;\n\t\tlet sampleCol = textureSampleLevel(tex, samp, in.uv + offset, 0.0);\n\t\t\n\t\tlet spatialDistSq = f32(i * i);\n\t\tlet spatialWeight = exp(-0.5 * spatialDistSq / (spatial_sigma * spatial_sigma));\n\t\t\n\t\tlet diff = sampleCol - centerCol;\n\t\tlet colorDistSq = dot(diff, diff);\n\t\tlet rangeWeight = exp(-0.5 * colorDistSq / (sigmaColor * sigmaColor));\n\t\t\n\t\tlet weight = spatialWeight * rangeWeight;\n\t\tcolor += sampleCol * weight;\n\t\ttotalWeight += weight;\n\t}\n\n\tvar blurred = centerCol;\n\tif (totalWeight > 0.0) {\n\t\tblurred = color / totalWeight;\n\t}\n\treturn applyPartialBlur(blurred, in.uv, dimensions);\n}\n`;\n\nexport const EDGE_PRESERVING_SHADER = `\n${WGSL_BLUR_UNIFORMS}\n\nstruct VSOut {\n\t@builtin(position) pos : vec4<f32>,\n\t@location(0) uv : vec2<f32>,\n};\n\n@vertex fn vs(@builtin(vertex_index) vi: u32) -> VSOut {\n\tvar pos = array<vec2<f32>, 4>(\n\t\tvec2<f32>(-1.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0),\n\t\tvec2<f32>(-1.0, -1.0),\n\t\tvec2<f32>(1.0, -1.0)\n\t);\n\tvar uv = array<vec2<f32>, 4>(\n\t\tvec2<f32>(0.0, 0.0),\n\t\tvec2<f32>(1.0, 0.0),\n\t\tvec2<f32>(0.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0)\n\t);\n\treturn VSOut(vec4<f32>(pos[vi], 0.0, 1.0), uv[vi]);\n}\n\n@fragment fn fs(in : VSOut) -> @location(0) vec4<f32> {\n\tlet centerCol = textureSampleLevel(tex, samp, in.uv, 0.0);\n\tvar strength = u.strength;\n\tif (u.hasStrengthSig > 0.5) {\n\t\tstrength = textureSampleLevel(strengthSigTex, signalSamp, vec2<f32>(0.5, 0.5), 0.0).r;\n\t}\n\n\t// Map strength (1-10) to radius (1-6)\n\tlet radius = i32(clamp(round(strength * 5.0 / 10.0) + 1.0, 1.0, 6.0));\n\n\tlet dimensions = vec2<f32>(textureDimensions(tex));\n\tlet texelSize = 1.0 / dimensions;\n\n\tvar m0 = vec3<f32>(0.0); var m1 = vec3<f32>(0.0); var m2 = vec3<f32>(0.0); var m3 = vec3<f32>(0.0);\n\tvar s0 = vec3<f32>(0.0); var s1 = vec3<f32>(0.0); var s2 = vec3<f32>(0.0); var s3 = vec3<f32>(0.0);\n\n\tlet n = f32((radius + 1) * (radius + 1));\n\n\tfor (var j = -6; j <= 6; j++) {\n\t\tif (j < -radius || j > radius) { continue; }\n\t\tfor (var i = -6; i <= 6; i++) {\n\t\t\tif (i < -radius || i > radius) { continue; }\n\t\t\t\n\t\t\tlet c = textureSampleLevel(tex, samp, in.uv + vec2<f32>(f32(i), f32(j)) * texelSize, 0.0).rgb;\n\t\t\t\n\t\t\tif (i <= 0 && j <= 0) {\n\t\t\t\tm0 += c;\n\t\t\t\ts0 += c * c;\n\t\t\t}\n\t\t\tif (i >= 0 && j <= 0) {\n\t\t\t\tm1 += c;\n\t\t\t\ts1 += c * c;\n\t\t\t}\n\t\t\tif (i <= 0 && j >= 0) {\n\t\t\t\tm2 += c;\n\t\t\t\ts2 += c * c;\n\t\t\t}\n\t\t\tif (i >= 0 && j >= 0) {\n\t\t\t\tm3 += c;\n\t\t\t\ts3 += c * c;\n\t\t\t}\n\t\t}\n\t}\n\n\tm0 = m0 / n; s0 = abs(s0 / n - m0 * m0);\n\tm1 = m1 / n; s1 = abs(s1 / n - m1 * m1);\n\tm2 = m2 / n; s2 = abs(s2 / n - m2 * m2);\n\tm3 = m3 / n; s3 = abs(s3 / n - m3 * m3);\n\n\tlet v0 = s0.r + s0.g + s0.b;\n\tlet v1 = s1.r + s1.g + s1.b;\n\tlet v2 = s2.r + s2.g + s2.b;\n\tlet v3 = s3.r + s3.g + s3.b;\n\n\tvar minVar = v0;\n\tvar finalCol = m0;\n\n\tif (v1 < minVar) {\n\t\tminVar = v1;\n\t\tfinalCol = m1;\n\t}\n\tif (v2 < minVar) {\n\t\tminVar = v2;\n\t\tfinalCol = m2;\n\t}\n\tif (v3 < minVar) {\n\t\tminVar = v3;\n\t\tfinalCol = m3;\n\t}\n\n\tlet blurred = vec4<f32>(finalCol, centerCol.a);\n\treturn applyPartialBlur(blurred, in.uv, dimensions);\n}\n`;\n\nexport const RADIAL_BLUR_SHADER = `\n${WGSL_BLUR_UNIFORMS}\n\nstruct VSOut {\n\t@builtin(position) pos : vec4<f32>,\n\t@location(0) uv : vec2<f32>,\n};\n\n@vertex fn vs(@builtin(vertex_index) vi: u32) -> VSOut {\n\tvar pos = array<vec2<f32>, 4>(\n\t\tvec2<f32>(-1.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0),\n\t\tvec2<f32>(-1.0, -1.0),\n\t\tvec2<f32>(1.0, -1.0)\n\t);\n\tvar uv = array<vec2<f32>, 4>(\n\t\tvec2<f32>(0.0, 0.0),\n\t\tvec2<f32>(1.0, 0.0),\n\t\tvec2<f32>(0.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0)\n\t);\n\treturn VSOut(vec4<f32>(pos[vi], 0.0, 1.0), uv[vi]);\n}\n\n@fragment fn fs(in : VSOut) -> @location(0) vec4<f32> {\n\tlet centerCol = textureSampleLevel(tex, samp, in.uv, 0.0);\n\tvar strength = u.strength;\n\tif (u.hasStrengthSig > 0.5) {\n\t\tstrength = textureSampleLevel(strengthSigTex, signalSamp, vec2<f32>(0.5, 0.5), 0.0).r;\n\t}\n\tvar centerX = u.centerX;\n\tif (u.hasCenterXSig > 0.5) {\n\t\tcenterX = textureSampleLevel(centerXSigTex, signalSamp, vec2<f32>(0.5, 0.5), 0.0).r;\n\t}\n\tvar centerY = u.centerY;\n\tif (u.hasCenterYSig > 0.5) {\n\t\tcenterY = textureSampleLevel(centerYSigTex, signalSamp, vec2<f32>(0.5, 0.5), 0.0).r;\n\t}\n\n\tlet dimensions = vec2<f32>(textureDimensions(tex));\n\tif (strength <= 0.0) {\n\t\treturn applyPartialBlur(centerCol, in.uv, dimensions);\n\t}\n\n\tlet center = vec2<f32>(centerX, centerY);\n\tlet toPixel = in.uv - center;\n\tlet dist = length(toPixel);\n\tif (dist <= 0.0) {\n\t\treturn applyPartialBlur(centerCol, in.uv, dimensions);\n\t}\n\n\tlet dir = vec2<f32>(-toPixel.y, toPixel.x);\n\tlet blurAmount = (strength / 100.0) * 0.1 * dist;\n\n\tlet numSamples = 24;\n\tvar color = vec4<f32>(0.0);\n\tlet step = dir * (blurAmount / f32(numSamples));\n\n\tfor (var i = 0; i < 24; i++) {\n\t\tlet offset = step * f32(i - 12);\n\t\tcolor += textureSampleLevel(tex, samp, in.uv + offset, 0.0);\n\t}\n\n\tlet blurred = color / 24.0;\n\treturn applyPartialBlur(blurred, in.uv, dimensions);\n}\n`;\n\nexport const ZOOM_BLUR_SHADER = `\n${WGSL_BLUR_UNIFORMS}\n\nstruct VSOut {\n\t@builtin(position) pos : vec4<f32>,\n\t@location(0) uv : vec2<f32>,\n};\n\n@vertex fn vs(@builtin(vertex_index) vi: u32) -> VSOut {\n\tvar pos = array<vec2<f32>, 4>(\n\t\tvec2<f32>(-1.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0),\n\t\tvec2<f32>(-1.0, -1.0),\n\t\tvec2<f32>(1.0, -1.0)\n\t);\n\tvar uv = array<vec2<f32>, 4>(\n\t\tvec2<f32>(0.0, 0.0),\n\t\tvec2<f32>(1.0, 0.0),\n\t\tvec2<f32>(0.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0)\n\t);\n\treturn VSOut(vec4<f32>(pos[vi], 0.0, 1.0), uv[vi]);\n}\n\n@fragment fn fs(in : VSOut) -> @location(0) vec4<f32> {\n\tlet centerCol = textureSampleLevel(tex, samp, in.uv, 0.0);\n\tvar strength = u.strength;\n\tif (u.hasStrengthSig > 0.5) {\n\t\tstrength = textureSampleLevel(strengthSigTex, signalSamp, vec2<f32>(0.5, 0.5), 0.0).r;\n\t}\n\tvar centerX = u.centerX;\n\tif (u.hasCenterXSig > 0.5) {\n\t\tcenterX = textureSampleLevel(centerXSigTex, signalSamp, vec2<f32>(0.5, 0.5), 0.0).r;\n\t}\n\tvar centerY = u.centerY;\n\tif (u.hasCenterYSig > 0.5) {\n\t\tcenterY = textureSampleLevel(centerYSigTex, signalSamp, vec2<f32>(0.5, 0.5), 0.0).r;\n\t}\n\n\tlet dimensions = vec2<f32>(textureDimensions(tex));\n\tif (strength <= 0.0) {\n\t\treturn applyPartialBlur(centerCol, in.uv, dimensions);\n\t}\n\n\tlet center = vec2<f32>(centerX, centerY);\n\tlet toPixel = in.uv - center;\n\tlet blurAmount = (strength / 100.0) * 0.15;\n\n\tlet numSamples = 24;\n\tvar color = vec4<f32>(0.0);\n\tlet step = toPixel * (blurAmount / f32(numSamples));\n\n\tfor (var i = 0; i < 24; i++) {\n\t\tlet offset = step * f32(i - 12);\n\t\tcolor += textureSampleLevel(tex, samp, in.uv + offset, 0.0);\n\t}\n\n\tlet blurred = color / 24.0;\n\treturn applyPartialBlur(blurred, in.uv, dimensions);\n}\n`;\n\ninterface DeviceBlurResources {\n\tblurUniformLayout: GPUBindGroupLayout;\n\tsingleTextureLayout: GPUBindGroupLayout;\n\tsignalTextureLayout: GPUBindGroupLayout;\n\tpipelineCache: Map<string, GPURenderPipeline>;\n}\n\nconst deviceResourceCache = new WeakMap<GPUDevice, DeviceBlurResources>();\n\nfunction getDeviceLayouts(device: GPUDevice): DeviceBlurResources {\n\tlet res = deviceResourceCache.get(device);\n\tif (res) return res;\n\n\tconst blurUniformLayout = device.createBindGroupLayout({\n\t\tentries: [\n\t\t\t{\n\t\t\t\tbinding: 0,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\tbuffer: { type: \"uniform\" },\n\t\t\t},\n\t\t],\n\t});\n\n\tconst singleTextureLayout = device.createBindGroupLayout({\n\t\tentries: [\n\t\t\t{\n\t\t\t\tbinding: 0,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\ttexture: { sampleType: \"float\" },\n\t\t\t},\n\t\t\t{\n\t\t\t\tbinding: 1,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\tsampler: { type: \"filtering\" },\n\t\t\t},\n\t\t\t{\n\t\t\t\tbinding: 2,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\ttexture: { sampleType: \"float\" },\n\t\t\t},\n\t\t],\n\t});\n\n\tconst signalTextureLayout = device.createBindGroupLayout({\n\t\tentries: [\n\t\t\t{\n\t\t\t\tbinding: 0,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\ttexture: { sampleType: \"float\" },\n\t\t\t},\n\t\t\t{\n\t\t\t\tbinding: 1,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\ttexture: { sampleType: \"float\" },\n\t\t\t},\n\t\t\t{\n\t\t\t\tbinding: 2,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\ttexture: { sampleType: \"float\" },\n\t\t\t},\n\t\t\t{\n\t\t\t\tbinding: 3,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\ttexture: { sampleType: \"float\" },\n\t\t\t},\n\t\t\t{\n\t\t\t\tbinding: 4,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\ttexture: { sampleType: \"float\" },\n\t\t\t},\n\t\t\t{\n\t\t\t\tbinding: 5,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\tsampler: { type: \"filtering\" },\n\t\t\t},\n\t\t],\n\t});\n\n\tres = {\n\t\tblurUniformLayout,\n\t\tsingleTextureLayout,\n\t\tsignalTextureLayout,\n\t\tpipelineCache: new Map(),\n\t};\n\tdeviceResourceCache.set(device, res);\n\treturn res;\n}\n\nfunction getBlurResources(\n\tdevice: GPUDevice,\n\tformat: GPUTextureFormat,\n\tblurType: string,\n) {\n\tconst layouts = getDeviceLayouts(device);\n\n\tconst cacheKey = `blur_${blurType}_${format}`;\n\tlet pipeline = layouts.pipelineCache.get(cacheKey);\n\tif (!pipeline) {\n\t\tlet code = GAUSSIAN_BLUR_SHADER;\n\t\tif (blurType === \"Box\") {\n\t\t\tcode = BOX_BLUR_SHADER;\n\t\t} else if (blurType === \"Median\") {\n\t\t\tcode = MEDIAN_BLUR_SHADER;\n\t\t} else if (blurType === \"Motion\") {\n\t\t\tcode = MOTION_BLUR_SHADER;\n\t\t} else if (blurType === \"Bilateral\") {\n\t\t\tcode = BILATERAL_BLUR_SHADER;\n\t\t} else if (blurType === \"Edge-preserving\") {\n\t\t\tcode = EDGE_PRESERVING_SHADER;\n\t\t} else if (blurType === \"Radial\") {\n\t\t\tcode = RADIAL_BLUR_SHADER;\n\t\t} else if (blurType === \"Zoom\") {\n\t\t\tcode = ZOOM_BLUR_SHADER;\n\t\t}\n\n\t\tconst blurModule = device.createShaderModule({\n\t\t\tlabel: `blur_${blurType}_${format}.wgsl`,\n\t\t\tcode,\n\t\t});\n\n\t\tpipeline = device.createRenderPipeline({\n\t\t\tlabel: `BlurPipeline_${blurType}_${format}`,\n\t\t\tlayout: device.createPipelineLayout({\n\t\t\t\tbindGroupLayouts: [\n\t\t\t\t\tlayouts.blurUniformLayout,\n\t\t\t\t\tlayouts.singleTextureLayout,\n\t\t\t\t\tlayouts.signalTextureLayout,\n\t\t\t\t],\n\t\t\t}),\n\t\t\tvertex: { module: blurModule, entryPoint: \"vs\" },\n\t\t\tfragment: {\n\t\t\t\tmodule: blurModule,\n\t\t\t\tentryPoint: \"fs\",\n\t\t\t\ttargets: [{ format }],\n\t\t\t},\n\t\t\tprimitive: { topology: \"triangle-strip\" },\n\t\t});\n\t\tlayouts.pipelineCache.set(cacheKey, pipeline);\n\t}\n\n\treturn {\n\t\tblurPipeline: pipeline,\n\t\tblurUniformLayout: layouts.blurUniformLayout,\n\t\tsingleTextureLayout: layouts.singleTextureLayout,\n\t\tsignalTextureLayout: layouts.signalTextureLayout,\n\t};\n}\n\nexport const BlurWebGPURenderer: WebGPUNodeRenderer = async (args) => {\n\tconst {\n\t\tctx,\n\t\tencoder,\n\t\tpass,\n\t\ttargetView,\n\t\ttargetTexture,\n\t\ttargetWidth,\n\t\ttargetHeight,\n\t\tprops,\n\t\tdrawChild,\n\t} = args;\n\tconst frame = props.frame ?? 0;\n\tconst fps = props.fps || 30;\n\tconst op = props.virtualMedia?.operation as BlurOp | undefined;\n\tif (op?.op !== \"Blur\" || !op) return;\n\n\tconst childMedia = props.virtualMedia.children?.[0];\n\tif (!childMedia) return;\n\n\t// End the provided pass\n\tpass.end();\n\n\tconst blurData = new Float32Array(16);\n\n\tconst width = targetWidth;\n\tconst height = targetHeight;\n\n\tconst logicalWidth =\n\t\tprops.containerWidth ??\n\t\tctx.surface.width /\n\t\t\t(typeof window !== \"undefined\" ? window.devicePixelRatio : 1);\n\tconst dpiScale = width / logicalWidth;\n\tconst nodeId = op.inputs ? Object.keys(op.inputs)[0] : \"blur_node\";\n\n\tconst resolveBindable = (\n\t\tconfigKey: \"strength\" | \"sigmaColor\" | \"centerX\" | \"centerY\" | \"radius\" | \"radiusY\",\n\t\tdefaultValue: number,\n\t\tminVal: number,\n\t\tmaxVal: number,\n\t\tscaleByDpi = false,\n\t) => {\n\t\tconst handleIdKey = `${configKey}HandleId` as keyof BlurOp;\n\t\tconst handleId = op[handleIdKey] as string | null | undefined;\n\t\tconst input = handleId ? op.inputs?.[handleId] : null;\n\n\t\tconst hasSignal = !!(\n\t\t\tinput?.connectionValid &&\n\t\t\t(input.outputItem?.type === \"Signal\" ||\n\t\t\t\tinput.outputItem?.type === \"Numeric\")\n\t\t);\n\n\t\tconst sd =\n\t\t\thasSignal && input?.outputItem?.data\n\t\t\t\t? (input.outputItem.data as BlurSignalData)\n\t\t\t\t: null;\n\n\t\tlet val = defaultValue;\n\t\tlet hasStaticSig = false;\n\n\t\tlet gpuTextureView: GPUTextureView | undefined = undefined;\n\n\t\tif (!hasSignal) {\n\t\t\tif (input?.connectionValid && input.outputItem?.type === \"Number\") {\n\t\t\t\tconst rawVal = Number(input.outputItem.data ?? defaultValue);\n\t\t\t\tval = Math.max(minVal, Math.min(maxVal, rawVal));\n\t\t\t\tif (scaleByDpi) val *= dpiScale;\n\t\t\t} else {\n\t\t\t\tlet rawVal = op[configKey] as unknown;\n\t\t\t\tif (rawVal !== undefined && rawVal !== null) {\n\t\t\t\t\tif (typeof rawVal === \"object\") {\n\t\t\t\t\t\tif (\"get\" in (rawVal as Record<string, unknown>) && typeof (rawVal as Record<string, unknown>).get === \"function\") {\n\t\t\t\t\t\t\trawVal = (rawVal as { get: (ctx: { frame: number; fps: number }) => unknown }).get({ frame, fps });\n\t\t\t\t\t\t} else if (\"value\" in (rawVal as Record<string, unknown>)) {\n\t\t\t\t\t\t\tconst sig = rawVal as { value: unknown; gpuBinding?: { textureView?: GPUTextureView } };\n\t\t\t\t\t\t\tif (sig.gpuBinding?.textureView) {\n\t\t\t\t\t\t\t\tgpuTextureView = sig.gpuBinding.textureView;\n\t\t\t\t\t\t\t\thasStaticSig = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\trawVal = sig.value;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (typeof rawVal === \"function\") {\n\t\t\t\t\t\trawVal = (rawVal as (f: number, fps: number) => unknown)(frame, fps);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst numVal = Number(rawVal ?? defaultValue);\n\t\t\t\tval = Math.max(minVal, Math.min(maxVal, isNaN(numVal) ? defaultValue : numVal));\n\t\t\t\tif (scaleByDpi) val *= dpiScale;\n\t\t\t}\n\t\t} else if (sd) {\n\t\t\tconst rawVal = Number(sd.offset ?? 0.0);\n\t\t\tval = Math.max(minVal, Math.min(maxVal, rawVal));\n\t\t\tif (scaleByDpi) val *= dpiScale;\n\t\t\thasStaticSig = true;\n\t\t}\n\n\t\treturn { val, hasStaticSig, sd, gpuTextureView };\n\t};\n\n\tconst strengthRes = resolveBindable(\"strength\", 5, 0, MAX_BLUR, true);\n\tconst sigmaColorRes = resolveBindable(\"sigmaColor\", 0.1, 0.01, 1.0, false);\n\tconst centerXRes = resolveBindable(\"centerX\", 0.5, 0.0, 1.0, false);\n\tconst centerYRes = resolveBindable(\"centerY\", 0.5, 0.0, 1.0, false);\n\tconst radiusRes = resolveBindable(\"radius\", 0.3, 0.001, 1.0, false);\n\tconst radiusYRes = resolveBindable(\"radiusY\", 0.0, 0.0, 1.0, false);\n\n\tconst tmpTex = ctx.renderer.getTemporaryTexture(width, height, [\n\t\t...(props.excludeTextures || []),\n\t\ttargetTexture,\n\t]);\n\tconst tmpView = tmpTex.createView();\n\n\t// Clear intermediate texture\n\tconst childPass = ctx.renderer.beginFrame(\n\t\tencoder,\n\t\ttmpView,\n\t\t{ r: 0, g: 0, b: 0, a: 0 },\n\t\twidth,\n\t\theight,\n\t\t\"clear\",\n\t);\n\tchildPass.end();\n\n\tctx.renderer.pushScissor({ x: 0, y: 0, width, height });\n\tctx.renderer.pushIdentity();\n\tawait drawChild(\n\t\tchildMedia,\n\t\t{ ...props, virtualMedia: childMedia },\n\t\ttmpView,\n\t\ttmpTex,\n\t\twidth,\n\t\theight,\n\t);\n\tctx.renderer.popTransform();\n\tctx.renderer.popScissor();\n\n\tconst blurType = op.blurType ?? \"Gaussian\";\n\tconst isSeparable =\n\t\tblurType === \"Gaussian\" ||\n\t\tblurType === \"Box\" ||\n\t\tblurType === \"Median\" ||\n\t\tblurType === \"Bilateral\";\n\n\t// Fetch static resources and compile pipeline once\n\tconst {\n\t\tblurPipeline: pipeline,\n\t\tblurUniformLayout: uLayout,\n\t\tsingleTextureLayout: tLayout,\n\t\tsignalTextureLayout: sigLayout,\n\t} = getBlurResources(ctx.device, ctx.renderer.format, blurType);\n\n\tconst sampler = ctx.renderer.samplerCache.getSampler(ctx.device);\n\n\t// Fetch dynamic signal texture views on-demand\n\tconst elapsedSeconds =\n\t\tprops.elapsedMs !== undefined ? props.elapsedMs / 1000 : frame / fps;\n\tconst durationSeconds = props.virtualMedia?.metadata?.durationMs\n\t\t? props.virtualMedia.metadata.durationMs / 1000\n\t\t: props.durationMs !== undefined\n\t\t\t? props.durationMs / 1000\n\t\t\t: 0;\n\n\t// Pre-extract audio features if any connected bindable signals use audio sources\n\tfor (const bindableRes of [\n\t\tstrengthRes,\n\t\tsigmaColorRes,\n\t\tcenterXRes,\n\t\tcenterYRes,\n\t\tradiusRes,\n\t]) {\n\t\tif (bindableRes.hasStaticSig && bindableRes.sd) {\n\t\t\tawait signalRegistry.ensureAudioSourcesExtracted(\n\t\t\t\tctx.device,\n\t\t\t\tbindableRes.sd,\n\t\t\t\tfps,\n\t\t\t\tprops.renderId,\n\t\t\t);\n\t\t}\n\t}\n\n\tconst getSignalView = (\n\t\tres: {\n\t\t\tval: number;\n\t\t\thasStaticSig: boolean;\n\t\t\tsd: BlurSignalData | null;\n\t\t\tgpuTextureView?: GPUTextureView;\n\t\t},\n\t\tsuffix: string,\n\t) => {\n\t\tif (res.gpuTextureView) {\n\t\t\treturn res.gpuTextureView;\n\t\t}\n\t\tif (res.hasStaticSig && res.sd) {\n\t\t\treturn signalRegistry.getOrCreate2DTextureView(\n\t\t\t\tctx.device,\n\t\t\t\tencoder,\n\t\t\t\tres.sd.nodeId ?? `${nodeId}_${suffix}`,\n\t\t\t\telapsedSeconds,\n\t\t\t\tdurationSeconds,\n\t\t\t\tres.sd,\n\t\t\t\twidth,\n\t\t\t\theight,\n\t\t\t\tprops.renderId,\n\t\t\t\tframe,\n\t\t\t\tfps,\n\t\t\t);\n\t\t}\n\t\treturn signalRegistry.getDummy1x1TextureView(ctx.device);\n\t};\n\n\tconst strengthView = getSignalView(strengthRes, \"strength_sig\");\n\tconst sigmaColorView = getSignalView(sigmaColorRes, \"sigmacolor_sig\");\n\tconst centerXView = getSignalView(centerXRes, \"centerx_sig\");\n\tconst centerYView = getSignalView(centerYRes, \"centery_sig\");\n\tconst radiusView = getSignalView(radiusRes, \"radius_sig\");\n\n\tconst createBlurBindGroup1 = (inputTex: GPUTexture, origTex: GPUTexture) =>\n\t\tctx.device.createBindGroup({\n\t\t\tlayout: tLayout,\n\t\t\tentries: [\n\t\t\t\t{ binding: 0, resource: inputTex.createView() },\n\t\t\t\t{ binding: 1, resource: sampler },\n\t\t\t\t{ binding: 2, resource: origTex.createView() },\n\t\t\t],\n\t\t});\n\n\t// Prepare uniform template (64 bytes / 16 floats)\n\tconst isPartial = Boolean(\n\t\top.partialBlur &&\n\t\t(op.partialBlur as unknown) !== \"false\" &&\n\t\t(op.partialBlur as unknown) !== 0,\n\t);\n\tblurData[2] = strengthRes.val;\n\tblurData[3] = Number(op.angle ?? 0.0);\n\n\tblurData[4] = sigmaColorRes.val;\n\tblurData[5] = centerXRes.val;\n\tblurData[6] = centerYRes.val;\n\tblurData[7] = radiusRes.val;\n\n\tblurData[8] = isPartial ? 1.0 : 0.0;\n\tblurData[9] = strengthRes.hasStaticSig ? 1.0 : 0.0;\n\tblurData[10] = sigmaColorRes.hasStaticSig ? 1.0 : 0.0;\n\tblurData[11] = centerXRes.hasStaticSig ? 1.0 : 0.0;\n\n\tblurData[12] = centerYRes.hasStaticSig ? 1.0 : 0.0;\n\tblurData[13] = radiusRes.hasStaticSig ? 1.0 : 0.0;\n\tblurData[14] = radiusYRes.val;\n\tblurData[15] = op.shape === \"rect\" ? 1.0 : 0.0;\n\n\tlet outTex2: GPUTexture;\n\n\tif (isSeparable) {\n\t\tconst outTex1 = ctx.renderer.getTemporaryTexture(width, height, [\n\t\t\ttmpTex,\n\t\t\ttargetTexture,\n\t\t\t...(props.excludeTextures || []),\n\t\t]);\n\t\toutTex2 = ctx.renderer.getTemporaryTexture(width, height, [\n\t\t\ttmpTex,\n\t\t\toutTex1,\n\t\t\ttargetTexture,\n\t\t\t...(props.excludeTextures || []),\n\t\t]);\n\n\t\t// Pass 1: Horizontal (full blur, partialBlur disabled)\n\t\tblurData[0] = 1.0;\n\t\tblurData[1] = 0.0;\n\t\tblurData[8] = 0.0;\n\t\tconst hBuffer = ctx.renderer.getTemporaryBuffer(blurData);\n\n\t\tconst hPass = encoder.beginRenderPass({\n\t\t\tcolorAttachments: [\n\t\t\t\t{\n\t\t\t\t\tview: outTex1.createView(),\n\t\t\t\t\tloadOp: \"clear\",\n\t\t\t\t\tstoreOp: \"store\",\n\t\t\t\t\tclearValue: { r: 0, g: 0, b: 0, a: 0 },\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\t\thPass.setPipeline(pipeline);\n\t\thPass.setBindGroup(\n\t\t\t0,\n\t\t\tctx.device.createBindGroup({\n\t\t\t\tlayout: uLayout,\n\t\t\t\tentries: [{ binding: 0, resource: { buffer: hBuffer } }],\n\t\t\t}),\n\t\t);\n\t\thPass.setBindGroup(1, createBlurBindGroup1(tmpTex, tmpTex));\n\t\thPass.setBindGroup(\n\t\t\t2,\n\t\t\tctx.device.createBindGroup({\n\t\t\t\tlayout: sigLayout,\n\t\t\t\tentries: [\n\t\t\t\t\t{ binding: 0, resource: strengthView },\n\t\t\t\t\t{ binding: 1, resource: sigmaColorView },\n\t\t\t\t\t{ binding: 2, resource: centerXView },\n\t\t\t\t\t{ binding: 3, resource: centerYView },\n\t\t\t\t\t{ binding: 4, resource: radiusView },\n\t\t\t\t\t{ binding: 5, resource: sampler },\n\t\t\t\t],\n\t\t\t}),\n\t\t);\n\t\thPass.draw(4);\n\t\thPass.end();\n\n\t\t// Pass 2: Vertical (applies partialBlur mask with original tmpTex)\n\t\tblurData[0] = 0.0;\n\t\tblurData[1] = 1.0;\n\t\tblurData[8] = isPartial ? 1.0 : 0.0;\n\t\tconst vBuffer = ctx.renderer.getTemporaryBuffer(blurData);\n\n\t\tconst vPass = encoder.beginRenderPass({\n\t\t\tcolorAttachments: [\n\t\t\t\t{\n\t\t\t\t\tview: outTex2.createView(),\n\t\t\t\t\tloadOp: \"clear\",\n\t\t\t\t\tstoreOp: \"store\",\n\t\t\t\t\tclearValue: { r: 0, g: 0, b: 0, a: 0 },\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\t\tvPass.setPipeline(pipeline);\n\t\tvPass.setBindGroup(\n\t\t\t0,\n\t\t\tctx.device.createBindGroup({\n\t\t\t\tlayout: uLayout,\n\t\t\t\tentries: [{ binding: 0, resource: { buffer: vBuffer } }],\n\t\t\t}),\n\t\t);\n\t\tvPass.setBindGroup(1, createBlurBindGroup1(outTex1, tmpTex));\n\t\tvPass.setBindGroup(\n\t\t\t2,\n\t\t\tctx.device.createBindGroup({\n\t\t\t\tlayout: sigLayout,\n\t\t\t\tentries: [\n\t\t\t\t\t{ binding: 0, resource: strengthView },\n\t\t\t\t\t{ binding: 1, resource: sigmaColorView },\n\t\t\t\t\t{ binding: 2, resource: centerXView },\n\t\t\t\t\t{ binding: 3, resource: centerYView },\n\t\t\t\t\t{ binding: 4, resource: radiusView },\n\t\t\t\t\t{ binding: 5, resource: sampler },\n\t\t\t\t],\n\t\t\t}),\n\t\t);\n\t\tvPass.draw(4);\n\t\tvPass.end();\n\t} else {\n\t\t// 1-Pass Filters (Motion, Edge-preserving, Radial, Zoom)\n\t\toutTex2 = ctx.renderer.getTemporaryTexture(width, height, [\n\t\t\ttmpTex,\n\t\t\ttargetTexture,\n\t\t\t...(props.excludeTextures || []),\n\t\t]);\n\n\t\tblurData[0] = 0.0;\n\t\tblurData[1] = 0.0;\n\t\tblurData[8] = isPartial ? 1.0 : 0.0;\n\t\tconst singleBuffer = ctx.renderer.getTemporaryBuffer(blurData);\n\n\t\tconst singlePass = encoder.beginRenderPass({\n\t\t\tcolorAttachments: [\n\t\t\t\t{\n\t\t\t\t\tview: outTex2.createView(),\n\t\t\t\t\tloadOp: \"clear\",\n\t\t\t\t\tstoreOp: \"store\",\n\t\t\t\t\tclearValue: { r: 0, g: 0, b: 0, a: 0 },\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\t\tsinglePass.setPipeline(pipeline);\n\t\tsinglePass.setBindGroup(\n\t\t\t0,\n\t\t\tctx.device.createBindGroup({\n\t\t\t\tlayout: uLayout,\n\t\t\t\tentries: [{ binding: 0, resource: { buffer: singleBuffer } }],\n\t\t\t}),\n\t\t);\n\t\tsinglePass.setBindGroup(1, createBlurBindGroup1(tmpTex, tmpTex));\n\t\tsinglePass.setBindGroup(\n\t\t\t2,\n\t\t\tctx.device.createBindGroup({\n\t\t\t\tlayout: sigLayout,\n\t\t\t\tentries: [\n\t\t\t\t\t{ binding: 0, resource: strengthView },\n\t\t\t\t\t{ binding: 1, resource: sigmaColorView },\n\t\t\t\t\t{ binding: 2, resource: centerXView },\n\t\t\t\t\t{ binding: 3, resource: centerYView },\n\t\t\t\t\t{ binding: 4, resource: radiusView },\n\t\t\t\t\t{ binding: 5, resource: sampler },\n\t\t\t\t],\n\t\t\t}),\n\t\t);\n\t\tsinglePass.draw(4);\n\t\tsinglePass.end();\n\t}\n\n\t// Final Pass: Draw result to targetView using standard drawTexture for blending/opacity\n\tconst finalPass = ctx.renderer.beginFrame(\n\t\tencoder,\n\t\ttargetView,\n\t\t{ r: 0, g: 0, b: 0, a: 0 },\n\t\ttargetWidth,\n\t\ttargetHeight,\n\t\t\"load\",\n\t);\n\tctx.renderer.drawTexture(\n\t\tfinalPass,\n\t\toutTex2,\n\t\t{ x: 0, y: 0, width: targetWidth, height: targetHeight },\n\t\t{ opacity: op.opacity ?? 1 },\n\t);\n\n\targs.pass = finalPass;\n};\n","import { defineRenderer } from \"@framefields/node-sdk/renderer\";\nimport { BlurWebGPURenderer } from \"./webgpu-renderer.js\";\n\nexport default defineRenderer({\n\tWebGPURenderer: BlurWebGPURenderer,\n});\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@framefields/node-blur",
3
+ "version": "2.0.2",
4
+ "private": false,
5
+ "framefields": {
6
+ "type": "Blur",
7
+ "kind": "effect",
8
+ "schema": "BlurNodeConfigSchema",
9
+ "custom": true
10
+ },
11
+ "type": "module",
12
+ "license": "Apache-2.0",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.mts",
16
+ "development": "./src/index.ts",
17
+ "import": "./dist/index.mjs",
18
+ "default": "./dist/index.mjs"
19
+ },
20
+ "./renderer": {
21
+ "types": "./dist/renderer.d.mts",
22
+ "development": "./src/renderers/index.ts",
23
+ "import": "./dist/renderer.mjs",
24
+ "default": "./dist/renderer.mjs"
25
+ }
26
+ },
27
+ "dependencies": {
28
+ "zod": "^4.3.6",
29
+ "@framefields/core": "2.0.2",
30
+ "@framefields/webgpu-renderers": "2.0.2",
31
+ "@framefields/node-sdk": "2.0.2"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^24.1.0",
35
+ "tsdown": "^0.19.0",
36
+ "typescript": "^5.8.3",
37
+ "webgpu": "^0.4.0",
38
+ "@framefields/tsconfig": "2.0.2"
39
+ },
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "scripts": {
44
+ "build": "tsdown",
45
+ "dev": "tsdown --watch",
46
+ "clean": "rm -rf dist .turbo"
47
+ }
48
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./shared/index.js";
2
+ export * from "./renderers/index.js";
@@ -0,0 +1,6 @@
1
+ import { defineRenderer } from "@framefields/node-sdk/renderer";
2
+ import { BlurWebGPURenderer } from "./webgpu-renderer.js";
3
+
4
+ export default defineRenderer({
5
+ WebGPURenderer: BlurWebGPURenderer,
6
+ });