@cyberluke/three-particles 4.0.1

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,"sources":["../src/js/effects/three-particles/webgpu/compute-collision-planes.ts","../src/js/effects/three-particles/three-particles-bezier.ts","../src/js/effects/three-particles/three-particles-utils.ts","../src/js/effects/three-particles/webgpu/compute-force-fields.ts","../src/js/effects/three-particles/webgpu/curve-bake.ts","../src/js/effects/three-particles/webgpu/tsl-noise.ts","../src/js/effects/three-particles/color-utils.ts","../src/js/effects/three-particles/webgpu/compute-modifiers.ts","../src/js/effects/three-particles/three-particles-constants.ts","../src/js/effects/three-particles/webgpu/tsl-shared.ts","../src/js/effects/three-particles/webgpu/tsl-instanced-billboard-material.ts","../src/js/effects/three-particles/webgpu/tsl-mesh-particle-material.ts","../src/js/effects/three-particles/webgpu/tsl-point-sprite-material.ts","../src/js/effects/three-particles/webgpu/tsl-trail-ribbon-material.ts","../src/js/effects/three-particles/webgpu/tsl-materials.ts","../src/webgpu.ts"],"names":["_encodeBuf","uniform","float","Fn","Loop","If","Continue","vec3","buffer","dot","vec4","tuint","tslMin","floor","tslMax","Vector3","min","max","mod","vec2","abs","length","cos","sin","Discard","texture","attribute","varyingProperty","positionLocal","modelViewMatrix","cameraProjectionMatrix","MeshBasicNodeMaterial","normalize","cross","mix","smoothstep","screenUV","StorageBufferAttribute"],"mappings":"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","file":"webgpu.js","sourcesContent":["/**\n * GPU collision plane computation for particle systems.\n *\n * Encodes collision plane configurations into a flat Float32Array that can be\n * written into the packed read-mostly f32 uniform table (avoiding an extra\n * storage buffer binding that would exceed the WebGPU per-stage limit of 8).\n *\n * Provides a TSL helper function that iterates over the encoded planes\n * and applies collision responses (kill, clamp, bounce) to particles.\n *\n * Collision plane modes:\n * - KILL (0): deactivate the particle immediately\n * - CLAMP (1): project position onto plane, zero velocity along normal\n * - BOUNCE (2): reflect velocity with damping, project position\n *\n * @module\n */\nimport {\n Fn,\n float,\n vec3,\n vec4,\n uniform,\n If,\n Loop,\n Continue,\n dot,\n type ShaderNodeObject,\n type Node,\n} from 'three/tsl';\n\nimport { CollisionPlaneMode } from '../three-particles-enums.js';\nimport type { NormalizedCollisionPlaneConfig } from '../types.js';\n\n// ─── Encoding Layout ─────────────────────────────────────────────────────────\n\n/**\n * Per-plane stride in the packed Float32Array.\n *\n * Layout per collision plane (12 floats):\n * [0] isActive (0 or 1)\n * [1] mode (0 = KILL, 1 = CLAMP, 2 = BOUNCE)\n * [2-4] position (x, y, z)\n * [5-7] normal (x, y, z) — normalized\n * [8] dampen (0–1)\n * [9] lifetimeLoss (0–1)\n * [10-11] padding (reserved)\n */\nconst PLANE_STRIDE = 12;\n\n/** Maximum collision planes supported per particle system. */\nexport const MAX_COLLISION_PLANES = 16;\n\n/** Total floats reserved for collision plane data in the packed f32 uniform table. */\nexport const COLLISION_PLANE_DATA_SIZE = MAX_COLLISION_PLANES * PLANE_STRIDE;\n\n/** Pre-allocated encoding buffer, reused every frame to avoid GC pressure. */\nlet _encodeBuf: Float32Array | null = null;\n\n// ─── CPU-side Encoding ───────────────────────────────────────────────────────\n\n/**\n * Packs an array of collision plane configs into a flat Float32Array for GPU upload.\n *\n * @param planes - Normalized collision plane configs from the particle system.\n * @returns A Float32Array of `MAX_COLLISION_PLANES * PLANE_STRIDE` floats.\n */\nexport function encodeCollisionPlanesForGPU(\n planes: ReadonlyArray<NormalizedCollisionPlaneConfig>\n): Float32Array {\n if (!_encodeBuf || _encodeBuf.length !== COLLISION_PLANE_DATA_SIZE) {\n _encodeBuf = new Float32Array(COLLISION_PLANE_DATA_SIZE);\n }\n const data = _encodeBuf;\n data.fill(0);\n\n const count = Math.min(planes.length, MAX_COLLISION_PLANES);\n for (let i = 0; i < count; i++) {\n const cp = planes[i];\n const base = i * PLANE_STRIDE;\n\n data[base] = cp.isActive ? 1 : 0;\n\n let modeCode = 0;\n if (cp.mode === CollisionPlaneMode.CLAMP) modeCode = 1;\n else if (cp.mode === CollisionPlaneMode.BOUNCE) modeCode = 2;\n data[base + 1] = modeCode;\n\n data[base + 2] = cp.position.x;\n data[base + 3] = cp.position.y;\n data[base + 4] = cp.position.z;\n data[base + 5] = cp.normal.x;\n data[base + 6] = cp.normal.y;\n data[base + 7] = cp.normal.z;\n data[base + 8] = cp.dampen;\n data[base + 9] = cp.lifetimeLoss;\n data[base + 10] = 0; // padding\n data[base + 11] = 0; // padding\n }\n\n return data;\n}\n\n// ─── TSL Collision Plane Application ─────────────────────────────────────────\n\n/**\n * Creates the TSL uniform and helper function for applying collision planes\n * in a GPU compute shader.\n *\n * Collision plane data is read from the packed f32 uniform buffer at a\n * fixed offset, avoiding an additional storage buffer binding.\n *\n * @param sCurveData - The packed f32 uniform-buffer node (non-atomic).\n * @param collisionPlaneOffset - Float offset into curveData where collision plane data starts.\n * @param collisionPlaneCount - Number of active collision planes (0 to MAX_COLLISION_PLANES).\n * @returns Object with the count uniform and the TSL apply function.\n */\nexport function createCollisionPlaneTSL(\n sCurveData: ShaderNodeObject<Node>,\n collisionPlaneOffset: number,\n collisionPlaneCount: number\n) {\n const count = Math.min(collisionPlaneCount, MAX_COLLISION_PLANES);\n const uCollisionPlaneCount = uniform(float(count));\n const cpBase = collisionPlaneOffset;\n\n /**\n * TSL function that applies all collision planes to a particle.\n *\n * @param pos - Current particle position (vec3, modified in place)\n * @param vel - Current particle velocity (vec3, modified in place)\n * @param oiaVec - orbitalIsActive vec4 (w = isActive, modified for KILL)\n * @param sColor - Color storage node (modified for KILL)\n * @param ps - particleState vec4 (x = lifetime, modified for lifetime loss)\n * @param startLife - Start lifetime scalar (for lifetime loss)\n * @param i - Particle index (for storage buffer element access)\n * @param sOrbitalIsActive - orbitalIsActive storage node (for KILL)\n */\n const applyCollisionPlanesTSL = Fn(\n ({\n pos,\n vel,\n oiaVec,\n sColorNode,\n ps,\n startLife,\n particleIdx,\n sOrbitalIsActiveNode,\n }: {\n pos: ShaderNodeObject<Node>;\n vel: ShaderNodeObject<Node>;\n oiaVec: ShaderNodeObject<Node>;\n sColorNode: ShaderNodeObject<Node>;\n ps: ShaderNodeObject<Node>;\n startLife: ShaderNodeObject<Node>;\n particleIdx: ShaderNodeObject<Node>;\n sOrbitalIsActiveNode: ShaderNodeObject<Node>;\n }) => {\n Loop(uCollisionPlaneCount, ({ i }: { i: ShaderNodeObject<Node> }) => {\n const base = i.mul(PLANE_STRIDE).add(cpBase);\n\n const isActive = sCurveData.element(base);\n If(isActive.lessThan(0.5), () => {\n Continue();\n });\n\n const mode = sCurveData.element(base.add(1));\n const planePos = vec3(\n sCurveData.element(base.add(2)),\n sCurveData.element(base.add(3)),\n sCurveData.element(base.add(4))\n );\n const planeNormal = vec3(\n sCurveData.element(base.add(5)),\n sCurveData.element(base.add(6)),\n sCurveData.element(base.add(7))\n );\n const dampen = sCurveData.element(base.add(8));\n const lifetimeLoss = sCurveData.element(base.add(9));\n\n // Signed distance from particle to plane\n const toParticle = pos.sub(planePos);\n const signedDist = dot(toParticle, planeNormal);\n\n // Only respond when particle is on the wrong side (signedDist < 0).\n // Mode dispatch uses If/ElseIf so only one branch writes to shared\n // state (pos/vel/ps.x) in the generated WGSL — equivalent nested\n // `If()` blocks on the same variables have been observed to emit\n // WGSL that TSL cannot lower cleanly under some driver/runtime\n // combinations, producing intermittent writes.\n If(signedDist.lessThan(0.0), () => {\n // KILL mode (0). Set lifetime far past startLifetime so the\n // death check at the end of the kernel deactivates the\n // particle and zeroes color AFTER all modifiers have run\n // (modifiers would otherwise overwrite our color).\n If(mode.lessThan(0.5), () => {\n ps.x.assign(startLife.add(float(1.0)));\n })\n // CLAMP mode (1)\n .ElseIf(mode.lessThan(1.5), () => {\n // Project position onto the plane surface\n pos.assign(pos.sub(planeNormal.mul(signedDist)));\n\n // Remove velocity component along the normal only when moving\n // into the plane.\n const velDotN = dot(vel, planeNormal);\n If(velDotN.lessThan(0.0), () => {\n vel.assign(vel.sub(planeNormal.mul(velDotN)));\n });\n })\n // BOUNCE mode (2)\n .Else(() => {\n // Project position onto the plane surface\n pos.assign(pos.sub(planeNormal.mul(signedDist)));\n\n // Reflect velocity: v' = (v - 2 * dot(v, n) * n) * dampen\n const vDotN = dot(vel, planeNormal);\n const reflected = vel.sub(planeNormal.mul(vDotN.mul(2.0)));\n vel.assign(reflected.mul(dampen));\n\n // Apply lifetime loss\n If(lifetimeLoss.greaterThan(0.0), () => {\n ps.x.assign(ps.x.add(lifetimeLoss.mul(startLife).mul(1000.0)));\n });\n });\n });\n });\n },\n 'void'\n );\n\n return {\n /** Uniform for the active collision plane count. */\n countUniform: uCollisionPlaneCount,\n /** TSL function to call in the compute kernel: apply({ pos, vel, ... }) */\n apply: applyCollisionPlanesTSL,\n };\n}\n","import { BezierPoint, CurveFunction } from './types.js';\n\nconst cache: Array<{\n bezierPoints: Array<BezierPoint>;\n curveFunction: CurveFunction;\n referencedBy: Array<number>;\n}> = [];\n\nconst nCr = (n: number, k: number) => {\n let z = 1;\n for (let i = 1; i <= k; i++) z *= (n + 1 - i) / i;\n return z;\n};\n\nexport const createBezierCurveFunction = (\n particleSystemId: number,\n bezierPoints: Array<BezierPoint>\n) => {\n const cacheEntry = cache.find((item) => item.bezierPoints === bezierPoints);\n\n if (cacheEntry) {\n if (!cacheEntry.referencedBy.includes(particleSystemId))\n cacheEntry.referencedBy.push(particleSystemId);\n return cacheEntry.curveFunction;\n }\n\n const entry = {\n referencedBy: [particleSystemId],\n bezierPoints,\n curveFunction: (percentage: number): number => {\n if (percentage < 0) return bezierPoints[0].y;\n if (percentage > 1) return bezierPoints[bezierPoints.length - 1].y;\n\n let start = 0;\n let stop = bezierPoints.length - 1;\n\n // Plain loop instead of Array.find — this runs per particle per frame,\n // so it must not allocate a callback closure.\n for (let i = 0; i < bezierPoints.length; i++) {\n const point = bezierPoints[i];\n if (percentage < (point.percentage ?? 0)) {\n stop = i;\n break;\n }\n if (point.percentage !== undefined) start = i;\n }\n\n const n = stop - start;\n const calculatedPercentage =\n (percentage - (bezierPoints[start].percentage ?? 0)) /\n ((bezierPoints[stop].percentage ?? 1) -\n (bezierPoints[start].percentage ?? 0));\n\n let value = 0;\n for (let i = 0; i <= n; i++) {\n const p = bezierPoints[start + i];\n const c =\n nCr(n, i) *\n Math.pow(1 - calculatedPercentage, n - i) *\n Math.pow(calculatedPercentage, i);\n value += c * p.y;\n }\n return value;\n },\n };\n\n cache.push(entry);\n return entry.curveFunction;\n};\n\nexport const removeBezierCurveFunction = (particleSystemId: number) => {\n while (true) {\n const index = cache.findIndex((item) =>\n item.referencedBy.includes(particleSystemId)\n );\n if (index === -1) break;\n const entry = cache[index];\n entry.referencedBy = entry.referencedBy.filter(\n (id) => id !== particleSystemId\n );\n if (entry.referencedBy.length === 0) cache.splice(index, 1);\n }\n};\n\nexport const getBezierCacheSize = () => cache.length;\n","import * as THREE from 'three';\n\nimport { createBezierCurveFunction } from './three-particles-bezier.js';\nimport { EmitFrom, LifeTimeCurve } from './three-particles-enums.js';\nimport {\n Constant,\n LifetimeCurve,\n Point3D,\n RandomBetweenTwoConstants,\n} from './types.js';\n\n/**\n * Calculates random position and velocity for particles emitted from a sphere.\n *\n * Supports emission from the entire volume or just the shell of the sphere.\n * Uses spherical coordinates for uniform distribution across the surface.\n *\n * @param position - Output vector for the particle's starting position\n * @param quaternion - Rotation to apply to the emission shape\n * @param velocity - Output vector for the particle's initial velocity\n * @param speed - Speed multiplier for the velocity\n * @param params - Sphere configuration\n * @param params.radius - Radius of the sphere\n * @param params.radiusThickness - Controls emission from volume (1.0) vs shell (0.0)\n * @param params.arc - Arc angle in degrees (360 = full sphere, 180 = hemisphere)\n *\n * @remarks\n * - `radiusThickness = 1.0`: Emit from entire volume\n * - `radiusThickness = 0.0`: Emit only from surface shell\n * - Particles are emitted radially outward from the center\n *\n * @see {@link Sphere} - Configuration type for sphere shape\n */\nexport const calculateRandomPositionAndVelocityOnSphere = (\n position: THREE.Vector3,\n quaternion: THREE.Quaternion,\n velocity: THREE.Vector3,\n speed: number,\n {\n radius,\n radiusThickness,\n arc,\n }: { radius: number; radiusThickness: number; arc: number }\n) => {\n const u = Math.random() * (arc / 360);\n const v = Math.random();\n const randomizedDistanceRatio = Math.random();\n const theta = 2 * Math.PI * u;\n const phi = Math.acos(2 * v - 1);\n const sinPhi = Math.sin(phi);\n\n const xDirection = sinPhi * Math.cos(theta);\n const yDirection = sinPhi * Math.sin(theta);\n const zDirection = Math.cos(phi);\n const normalizedThickness = 1 - radiusThickness;\n\n position.x =\n radius * normalizedThickness * xDirection +\n radius * radiusThickness * randomizedDistanceRatio * xDirection;\n position.y =\n radius * normalizedThickness * yDirection +\n radius * radiusThickness * randomizedDistanceRatio * yDirection;\n position.z =\n radius * normalizedThickness * zDirection +\n radius * radiusThickness * randomizedDistanceRatio * zDirection;\n\n position.applyQuaternion(quaternion);\n\n const speedMultiplierByPosition = 1 / position.length();\n velocity.set(\n position.x * speedMultiplierByPosition * speed,\n position.y * speedMultiplierByPosition * speed,\n position.z * speedMultiplierByPosition * speed\n );\n velocity.applyQuaternion(quaternion);\n};\n\n/**\n * Calculates random position and velocity for particles emitted from a cone.\n *\n * Useful for directional particle effects like fire, smoke plumes, fountains,\n * or spray effects. The cone emits particles in a spreading pattern.\n *\n * @param position - Output vector for the particle's starting position\n * @param quaternion - Rotation to apply to the emission shape\n * @param velocity - Output vector for the particle's initial velocity\n * @param speed - Speed multiplier for the velocity\n * @param params - Cone configuration\n * @param params.radius - Base radius of the cone\n * @param params.radiusThickness - Controls emission from volume (1.0) vs shell (0.0)\n * @param params.arc - Arc angle in degrees (360 = full cone, 180 = half cone)\n * @param params.angle - Cone opening angle in degrees (default: 90)\n * Smaller values create tighter cones\n *\n * @remarks\n * - The cone emits from its base (circular area) outward\n * - Particles travel in a conical spread pattern\n * - `angle = 0`: Straight line (no spread)\n * - `angle = 90`: Wide cone\n * - Common for fire (10-30°), smoke (30-60°), explosions (60-90°)\n *\n * @see {@link Cone} - Configuration type for cone shape\n */\nexport const calculateRandomPositionAndVelocityOnCone = (\n position: THREE.Vector3,\n quaternion: THREE.Quaternion,\n velocity: THREE.Vector3,\n speed: number,\n {\n radius,\n radiusThickness,\n arc,\n angle = 90,\n }: {\n radius: number;\n radiusThickness: number;\n arc: number;\n angle?: number;\n }\n) => {\n const theta = 2 * Math.PI * Math.random() * (arc / 360);\n const randomizedDistanceRatio = Math.random();\n\n const xDirection = Math.cos(theta);\n const yDirection = Math.sin(theta);\n const normalizedThickness = 1 - radiusThickness;\n\n position.x =\n radius * normalizedThickness * xDirection +\n radius * radiusThickness * randomizedDistanceRatio * xDirection;\n position.y =\n radius * normalizedThickness * yDirection +\n radius * radiusThickness * randomizedDistanceRatio * yDirection;\n position.z = 0;\n\n position.applyQuaternion(quaternion);\n\n const positionLength = position.length();\n const normalizedAngle = Math.abs(\n (positionLength / radius) * THREE.MathUtils.degToRad(angle)\n );\n const sinNormalizedAngle = Math.sin(normalizedAngle);\n\n const speedMultiplierByPosition = 1 / positionLength;\n velocity.set(\n position.x * sinNormalizedAngle * speedMultiplierByPosition * speed,\n position.y * sinNormalizedAngle * speedMultiplierByPosition * speed,\n Math.cos(normalizedAngle) * speed\n );\n velocity.applyQuaternion(quaternion);\n};\n\n/**\n * Calculates random position and velocity for particles emitted from a box.\n *\n * Supports three emission modes: volume, shell (surface), and edges.\n * Useful for area-based effects like dust clouds, rain, or geometric patterns.\n *\n * @param position - Output vector for the particle's starting position\n * @param quaternion - Rotation to apply to the emission shape\n * @param velocity - Output vector for the particle's initial velocity\n * @param speed - Speed multiplier for the velocity\n * @param params - Box configuration\n * @param params.scale - Size of the box on each axis (width, height, depth)\n * @param params.emitFrom - Emission mode:\n * - `VOLUME`: Random positions throughout the entire box volume\n * - `SHELL`: Random positions on the 6 faces (surface)\n * - `EDGE`: Random positions along the 12 edges\n *\n * @remarks\n * - All particles emit with velocity along the +Z axis (forward)\n * - Box is centered at the origin before rotation\n * - VOLUME mode: Best for rain, snow, or volumetric clouds\n * - SHELL mode: Best for hollow effects or surface particles\n * - EDGE mode: Best for wireframe effects or particle outlines\n *\n * @see {@link Box} - Configuration type for box shape\n * @see {@link EmitFrom} - Emission mode enum\n */\nexport const calculateRandomPositionAndVelocityOnBox = (\n position: THREE.Vector3,\n quaternion: THREE.Quaternion,\n velocity: THREE.Vector3,\n speed: number,\n { scale, emitFrom }: { scale: Point3D; emitFrom: EmitFrom }\n) => {\n const _scale = scale as Required<Point3D>;\n switch (emitFrom) {\n case EmitFrom.VOLUME:\n position.x = Math.random() * _scale.x - _scale.x / 2;\n position.y = Math.random() * _scale.y - _scale.y / 2;\n position.z = Math.random() * _scale.z - _scale.z / 2;\n break;\n\n case EmitFrom.SHELL:\n const side = Math.floor(Math.random() * 6);\n const perpendicularAxis = side % 3;\n const shellResult = [];\n shellResult[perpendicularAxis] = side > 2 ? 1 : 0;\n shellResult[(perpendicularAxis + 1) % 3] = Math.random();\n shellResult[(perpendicularAxis + 2) % 3] = Math.random();\n position.x = shellResult[0] * _scale.x - _scale.x / 2;\n position.y = shellResult[1] * _scale.y - _scale.y / 2;\n position.z = shellResult[2] * _scale.z - _scale.z / 2;\n break;\n\n case EmitFrom.EDGE:\n const side2 = Math.floor(Math.random() * 6);\n const perpendicularAxis2 = side2 % 3;\n const edge = Math.floor(Math.random() * 4);\n const edgeResult = [];\n edgeResult[perpendicularAxis2] = side2 > 2 ? 1 : 0;\n edgeResult[(perpendicularAxis2 + 1) % 3] =\n edge < 2 ? Math.random() : edge - 2;\n edgeResult[(perpendicularAxis2 + 2) % 3] =\n edge < 2 ? edge : Math.random();\n position.x = edgeResult[0] * _scale.x - _scale.x / 2;\n position.y = edgeResult[1] * _scale.y - _scale.y / 2;\n position.z = edgeResult[2] * _scale.z - _scale.z / 2;\n break;\n }\n\n position.applyQuaternion(quaternion);\n\n velocity.set(0, 0, speed);\n velocity.applyQuaternion(quaternion);\n};\n\n/**\n * Calculates random position and velocity for particles emitted from a circle.\n *\n * Emits particles from a circular area or ring. Useful for ground impacts,\n * radial effects, magic circles, or any circular planar emission.\n *\n * @param position - Output vector for the particle's starting position\n * @param quaternion - Rotation to apply to the emission shape\n * @param velocity - Output vector for the particle's initial velocity\n * @param speed - Speed multiplier for the velocity\n * @param params - Circle configuration\n * @param params.radius - Radius of the circle\n * @param params.radiusThickness - Controls emission from area (1.0) vs edge (0.0)\n * @param params.arc - Arc angle in degrees (360 = full circle, 180 = semicircle)\n *\n * @remarks\n * - Circle lies in the XY plane by default (Z = 0)\n * - Particles emit along the +Z axis (perpendicular to circle)\n * - `radiusThickness = 1.0`: Filled circle (disc)\n * - `radiusThickness = 0.0`: Ring (circle edge only)\n * - Good for ground impact effects, teleport circles, or radial bursts\n *\n * @see {@link Circle} - Configuration type for circle shape\n */\nexport const calculateRandomPositionAndVelocityOnCircle = (\n position: THREE.Vector3,\n quaternion: THREE.Quaternion,\n velocity: THREE.Vector3,\n speed: number,\n {\n radius,\n radiusThickness,\n arc,\n }: { radius: number; radiusThickness: number; arc: number }\n) => {\n const theta = 2 * Math.PI * Math.random() * (arc / 360);\n const randomizedDistanceRatio = Math.random();\n\n const xDirection = Math.cos(theta);\n const yDirection = Math.sin(theta);\n const normalizedThickness = 1 - radiusThickness;\n\n position.x =\n radius * normalizedThickness * xDirection +\n radius * radiusThickness * randomizedDistanceRatio * xDirection;\n position.y =\n radius * normalizedThickness * yDirection +\n radius * radiusThickness * randomizedDistanceRatio * yDirection;\n position.z = 0;\n\n position.applyQuaternion(quaternion);\n\n const positionLength = position.length();\n const speedMultiplierByPosition = 1 / positionLength;\n velocity.set(\n position.x * speedMultiplierByPosition * speed,\n position.y * speedMultiplierByPosition * speed,\n 0\n );\n velocity.applyQuaternion(quaternion);\n};\n\n/**\n * Calculates random position and velocity for particles emitted from a rectangle.\n *\n * Emits particles from a rectangular planar area. Useful for rain on a surface,\n * screen-space effects, or any planar emission pattern.\n *\n * @param position - Output vector for the particle's starting position\n * @param quaternion - Rotation to apply to the emission shape\n * @param velocity - Output vector for the particle's initial velocity\n * @param speed - Speed multiplier for the velocity\n * @param params - Rectangle configuration\n * @param params.rotation - Local rotation of the rectangle (degrees) before\n * applying quaternion\n * @param params.scale - Size of the rectangle (width and height)\n *\n * @remarks\n * - Rectangle lies in the XY plane by default\n * - Particles emit along the +Z axis (perpendicular to rectangle)\n * - The rotation parameter allows tilting the rectangle before the main\n * quaternion rotation is applied\n * - Good for rain effects, screen particles, or planar area emissions\n *\n * @see {@link Rectangle} - Configuration type for rectangle shape\n */\nexport const calculateRandomPositionAndVelocityOnRectangle = (\n position: THREE.Vector3,\n quaternion: THREE.Quaternion,\n velocity: THREE.Vector3,\n speed: number,\n { rotation, scale }: { rotation: Point3D; scale: Point3D }\n) => {\n const _scale = scale as Required<Point3D>;\n const _rotation = rotation as Required<Point3D>;\n\n const xOffset = Math.random() * _scale.x - _scale.x / 2;\n const yOffset = Math.random() * _scale.y - _scale.y / 2;\n const rotationX = THREE.MathUtils.degToRad(_rotation.x);\n const rotationY = THREE.MathUtils.degToRad(_rotation.y);\n position.x = xOffset * Math.cos(rotationY);\n position.y = yOffset * Math.cos(rotationX);\n position.z = xOffset * Math.sin(rotationY) - yOffset * Math.sin(rotationX);\n\n position.applyQuaternion(quaternion);\n\n velocity.set(0, 0, speed);\n velocity.applyQuaternion(quaternion);\n};\n\n/**\n * Creates a solid white 1x1 texture for mesh particles.\n * Unlike the circle texture used by point/billboard renderers, mesh particles\n * need a neutral texture so the geometry shape is visible.\n * @returns {THREE.CanvasTexture | null} The generated texture or null if context fails.\n */\nexport const createDefaultMeshTexture = (): THREE.CanvasTexture | null => {\n try {\n const canvas = document.createElement('canvas');\n canvas.width = 1;\n canvas.height = 1;\n const context = canvas.getContext('2d');\n if (context) {\n context.fillStyle = 'white';\n context.fillRect(0, 0, 1, 1);\n const texture = new THREE.CanvasTexture(canvas);\n texture.needsUpdate = true;\n return texture;\n }\n return null;\n } catch {\n return null;\n }\n};\n\n/**\n * Creates a default white circle texture using CanvasTexture.\n * @returns {THREE.CanvasTexture | null} The generated texture or null if context fails.\n */\nexport const createDefaultParticleTexture = (): THREE.CanvasTexture | null => {\n try {\n const canvas = document.createElement('canvas');\n const size = 64;\n canvas.width = size;\n canvas.height = size;\n const context = canvas.getContext('2d');\n if (context) {\n const centerX = size / 2;\n const centerY = size / 2;\n const radius = size / 2 - 2; // Small padding\n\n context.beginPath();\n context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);\n context.fillStyle = 'white';\n context.fill();\n const texture = new THREE.CanvasTexture(canvas);\n texture.needsUpdate = true;\n return texture;\n } else {\n // eslint-disable-next-line no-console\n console.warn(\n 'Could not get 2D context to generate default particle texture.'\n );\n return null;\n }\n } catch (error) {\n // Handle potential errors (e.g., document not available in non-browser env)\n // eslint-disable-next-line no-console\n console.warn('Error creating default particle texture:', error);\n return null;\n }\n};\n\nexport const isLifeTimeCurve = (\n value: Constant | RandomBetweenTwoConstants | LifetimeCurve\n): value is LifetimeCurve => {\n return typeof value !== 'number' && 'type' in value;\n};\n\nexport const getCurveFunctionFromConfig = (\n particleSystemId: number,\n lifetimeCurve: LifetimeCurve\n) => {\n if (lifetimeCurve.type === LifeTimeCurve.BEZIER) {\n return createBezierCurveFunction(\n particleSystemId,\n lifetimeCurve.bezierPoints\n ); // Bézier curve\n }\n\n if (lifetimeCurve.type === LifeTimeCurve.EASING) {\n return lifetimeCurve.curveFunction; // Easing curve\n }\n\n // Serialized (type-elided) configs: infer from the present payload. The\n // shared JSON examples omit `type` because the editor converters normally\n // fill it in; the runtime accepts both forms.\n const raw = lifetimeCurve as unknown as {\n bezierPoints?: unknown;\n curveFunction?: unknown;\n };\n if (Array.isArray(raw.bezierPoints)) {\n return createBezierCurveFunction(\n particleSystemId,\n raw.bezierPoints as Parameters<typeof createBezierCurveFunction>[1]\n );\n }\n if (typeof raw.curveFunction === 'function') {\n return raw.curveFunction as (t: number) => number;\n }\n\n throw new Error(`Unsupported value type: ${lifetimeCurve}`);\n};\n\nexport const calculateValue = (\n particleSystemId: number,\n value: Constant | RandomBetweenTwoConstants | LifetimeCurve,\n time: number = 0\n): number => {\n if (typeof value === 'number') {\n return value; // Constant value\n }\n\n if ('min' in value && 'max' in value) {\n if (value.min === value.max) {\n return value.min ?? 0; // Constant value\n }\n return THREE.MathUtils.randFloat(value.min ?? 0, value.max ?? 1); // Random range\n }\n\n const lifetimeCurve = value as LifetimeCurve;\n return (\n getCurveFunctionFromConfig(particleSystemId, lifetimeCurve)(time) *\n (lifetimeCurve.scale ?? 1)\n );\n};\n","/**\n * GPU force field computation for particle systems.\n *\n * Encodes force field configurations into a flat Float32Array that can be\n * written into the packed read-mostly f32 uniform table (avoiding an extra\n * storage buffer binding that would exceed the WebGPU per-stage limit of 8).\n *\n * Provides a TSL helper function that iterates over the encoded fields\n * and applies forces to particle velocity.\n *\n * Force field types:\n * - POINT: radial attract/repel toward a position with distance falloff\n * - DIRECTIONAL: constant force along a direction vector\n *\n * Falloff modes (POINT only):\n * - NONE: full strength regardless of distance\n * - LINEAR: 1 - (d / range)\n * - QUADRATIC: 1 - (d / range)²\n *\n * @module\n */\nimport {\n Fn,\n float,\n vec3,\n uniform,\n If,\n Loop,\n Continue,\n normalize,\n length,\n type ShaderNodeObject,\n type Node,\n} from 'three/tsl';\n\nimport { ForceFieldFalloff, ForceFieldType } from '../three-particles-enums.js';\nimport { calculateValue } from '../three-particles-utils.js';\nimport type { NormalizedForceFieldConfig } from '../types.js';\n\n// ─── Encoding Layout ─────────────────────────────────────────────────────────\n\n/**\n * Per-field stride in the packed Float32Array.\n *\n * Layout per force field (12 floats):\n * [0] isActive (0 or 1)\n * [1] type (0 = POINT, 1 = DIRECTIONAL)\n * [2-4] position (x, y, z)\n * [5-7] direction (x, y, z) — normalized\n * [8] strength (constant, evaluated at bake time)\n * [9] range (Infinity encoded as a very large number: 1e10)\n * [10] falloff (0 = NONE, 1 = LINEAR, 2 = QUADRATIC)\n * [11] padding (reserved)\n */\nconst FIELD_STRIDE = 12;\n\n/** Maximum force fields supported per particle system. */\nexport const MAX_FORCE_FIELDS = 16;\n\n/** Total floats reserved for force field data in the packed f32 uniform table. */\nexport const FORCE_FIELD_DATA_SIZE = MAX_FORCE_FIELDS * FIELD_STRIDE;\n\n/** Sentinel value for \"infinite\" range on GPU (avoids Infinity in Float32). */\nconst GPU_INFINITY = 1e10;\n\n/** Pre-allocated encoding buffer, reused every frame to avoid GC pressure. */\nlet _encodeBuf: Float32Array | null = null;\n\n// ─── CPU-side Encoding ───────────────────────────────────────────────────────\n\n/**\n * Packs an array of force field configs into a flat Float32Array for GPU upload.\n *\n * @param forceFields - Normalized force field configs from the particle system.\n * @param particleSystemId - System ID for curve evaluation.\n * @param systemLifetimePercentage - Current system lifetime progress for strength curves.\n * @returns A Float32Array of `MAX_FORCE_FIELDS * FIELD_STRIDE` floats.\n */\nexport function encodeForceFieldsForGPU(\n forceFields: ReadonlyArray<NormalizedForceFieldConfig>,\n particleSystemId: number,\n systemLifetimePercentage: number\n): Float32Array {\n if (!_encodeBuf || _encodeBuf.length !== FORCE_FIELD_DATA_SIZE) {\n _encodeBuf = new Float32Array(FORCE_FIELD_DATA_SIZE);\n }\n const data = _encodeBuf;\n data.fill(0);\n\n const count = Math.min(forceFields.length, MAX_FORCE_FIELDS);\n for (let i = 0; i < count; i++) {\n const ff = forceFields[i];\n const base = i * FIELD_STRIDE;\n\n data[base] = ff.isActive ? 1 : 0;\n data[base + 1] = ff.type === ForceFieldType.POINT ? 0 : 1;\n data[base + 2] = ff.position.x;\n data[base + 3] = ff.position.y;\n data[base + 4] = ff.position.z;\n data[base + 5] = ff.direction.x;\n data[base + 6] = ff.direction.y;\n data[base + 7] = ff.direction.z;\n data[base + 8] = calculateValue(\n particleSystemId,\n ff.strength,\n systemLifetimePercentage\n );\n data[base + 9] = ff.range === Infinity ? GPU_INFINITY : ff.range;\n\n let falloffCode = 0;\n if (ff.falloff === ForceFieldFalloff.LINEAR) falloffCode = 1;\n else if (ff.falloff === ForceFieldFalloff.QUADRATIC) falloffCode = 2;\n data[base + 10] = falloffCode;\n data[base + 11] = 0; // padding\n }\n\n return data;\n}\n\n// ─── TSL Force Field Application ─────────────────────────────────────────────\n\n/**\n * Creates the TSL uniform and helper function for applying force fields\n * in a GPU compute shader.\n *\n * Force field data is read from the packed f32 uniform buffer at a\n * fixed offset, avoiding an additional storage buffer binding.\n *\n * @param sCurveData - The packed f32 uniform-buffer node (non-atomic).\n * @param forceFieldOffset - Float offset into curveData where force field data starts.\n * @param forceFieldCount - Number of active force fields (0 to MAX_FORCE_FIELDS).\n * @returns Object with the count uniform and the TSL apply function.\n */\nexport function createForceFieldTSL(\n sCurveData: ShaderNodeObject<Node>,\n forceFieldOffset: number,\n forceFieldCount: number\n) {\n const count = Math.min(forceFieldCount, MAX_FORCE_FIELDS);\n const uForceFieldCount = uniform(float(count));\n const ffBase = forceFieldOffset;\n\n /**\n * TSL function that applies all force fields to a particle's velocity.\n *\n * @param pos - Current particle position (vec3, read-only)\n * @param vel - Current particle velocity (vec3, modified in place)\n * @param delta - Frame time in seconds (float)\n */\n const applyForceFieldsTSL = Fn(\n ({\n pos,\n vel,\n delta,\n }: {\n pos: ShaderNodeObject<Node>;\n vel: ShaderNodeObject<Node>;\n delta: ShaderNodeObject<Node>;\n }) => {\n Loop(uForceFieldCount, ({ i }: { i: ShaderNodeObject<Node> }) => {\n const base = i.mul(FIELD_STRIDE).add(ffBase);\n\n const isActive = sCurveData.element(base);\n If(isActive.lessThan(0.5), () => {\n Continue();\n });\n\n const fieldType = sCurveData.element(base.add(1));\n const fieldPos = vec3(\n sCurveData.element(base.add(2)),\n sCurveData.element(base.add(3)),\n sCurveData.element(base.add(4))\n );\n const fieldDir = vec3(\n sCurveData.element(base.add(5)),\n sCurveData.element(base.add(6)),\n sCurveData.element(base.add(7))\n );\n const strength = sCurveData.element(base.add(8));\n const range = sCurveData.element(base.add(9));\n const falloffType = sCurveData.element(base.add(10));\n\n If(strength.equal(0.0), () => {\n Continue();\n });\n\n // DIRECTIONAL force (type == 1)\n If(fieldType.greaterThan(0.5), () => {\n const force = strength.mul(delta);\n vel.assign(vel.add(fieldDir.mul(force)));\n });\n\n // POINT force (type == 0)\n If(fieldType.lessThan(0.5), () => {\n const toField = fieldPos.sub(pos);\n const dist = length(toField);\n\n // Skip if too close (avoid division by zero)\n If(dist.greaterThan(0.0001), () => {\n // Skip if outside range (range > GPU_INFINITY means infinite)\n const inRange = dist.lessThan(range);\n If(inRange, () => {\n const dir = normalize(toField);\n\n // Compute falloff multiplier\n const normDist = dist.div(range);\n\n // NONE falloff (type == 0): multiplier = 1.0\n // LINEAR falloff (type == 1): multiplier = 1 - normDist\n // QUADRATIC falloff (type == 2): multiplier = 1 - normDist²\n const falloffNone = float(1.0);\n const falloffLinear = float(1.0).sub(normDist);\n const falloffQuadratic = float(1.0).sub(normDist.mul(normDist));\n\n // Select based on falloff type\n const useLinear = falloffType.greaterThan(0.5);\n const useQuadratic = falloffType.greaterThan(1.5);\n const falloff = useQuadratic.select(\n falloffQuadratic,\n useLinear.select(falloffLinear, falloffNone)\n );\n\n // Apply force\n const force = strength.mul(falloff).mul(delta);\n vel.assign(vel.add(dir.mul(force)));\n });\n });\n });\n });\n },\n 'void'\n );\n\n return {\n /** Uniform for the active force field count. */\n countUniform: uForceFieldCount,\n /** TSL function to call in the compute kernel: apply({ pos, vel, delta }) */\n apply: applyForceFieldsTSL,\n };\n}\n","/**\n * Curve baking utilities for WebGPU compute shader lookup.\n *\n * Converts JavaScript lifetime curve functions (Bezier and Easing) into packed\n * Float32Arrays that can be uploaded as GPU storage buffers or data textures.\n * The GPU shader looks up a baked value with:\n *\n * value = data[curveIndex * CURVE_RESOLUTION + floor(t * (CURVE_RESOLUTION - 1))]\n *\n * with linear interpolation between adjacent samples for smooth results.\n *\n * @module\n */\n\nimport {\n getCurveFunctionFromConfig,\n isLifeTimeCurve,\n} from '../three-particles-utils.js';\nimport type {\n NormalizedParticleSystemConfig,\n LifetimeCurve,\n} from '../types.js';\n\n// ─── Constants ────────────────────────────────────────────────────────────────\n\n/**\n * Number of samples per baked curve.\n *\n * 256 gives sub-0.4% maximum interpolation error for smooth curves while\n * keeping each curve to exactly one kilobyte of Float32 data (256 × 4 bytes).\n * The GPU shader indexes: `data[curveIndex * CURVE_RESOLUTION + floor(t * 255)]`.\n */\nexport const CURVE_RESOLUTION = 256;\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/**\n * Result of baking all active lifetime curves from a particle system config.\n *\n * All curves are packed sequentially into a single `data` Float32Array.\n * Each slot stores a curve index (≥ 0) if the corresponding modifier is active,\n * or `-1` when the modifier is inactive / uses a constant value.\n *\n * The GPU shader accesses a sample via:\n * ```glsl\n * float t01 = clamp(particleLifetime / startLifetime, 0.0, 1.0);\n * int idx = curveIndex * CURVE_RESOLUTION + int(t01 * 255.0);\n * float val = data[idx]; // + optional linear interpolation\n * ```\n */\nexport type BakedCurveMap = {\n /** All baked curves packed sequentially (curveCount × CURVE_RESOLUTION floats). */\n data: Float32Array;\n /** Total number of baked curves stored in `data`. */\n curveCount: number;\n /** Curve index for `sizeOverLifetime.lifetimeCurve` (-1 if inactive). */\n sizeOverLifetime: number;\n /** Curve index for `opacityOverLifetime.lifetimeCurve` (-1 if inactive). */\n opacityOverLifetime: number;\n /** Curve index for `colorOverLifetime.r` (-1 if inactive). */\n colorR: number;\n /** Curve index for `colorOverLifetime.g` (-1 if inactive). */\n colorG: number;\n /** Curve index for `colorOverLifetime.b` (-1 if inactive). */\n colorB: number;\n /** Curve index for `velocityOverLifetime.linear.x` (-1 if not a curve). */\n linearVelX: number;\n /** Curve index for `velocityOverLifetime.linear.y` (-1 if not a curve). */\n linearVelY: number;\n /** Curve index for `velocityOverLifetime.linear.z` (-1 if not a curve). */\n linearVelZ: number;\n /** Curve index for `velocityOverLifetime.orbital.x` (-1 if not a curve). */\n orbitalVelX: number;\n /** Curve index for `velocityOverLifetime.orbital.y` (-1 if not a curve). */\n orbitalVelY: number;\n /** Curve index for `velocityOverLifetime.orbital.z` (-1 if not a curve). */\n orbitalVelZ: number;\n};\n\n// ─── Core Sampling ────────────────────────────────────────────────────────────\n\n/**\n * Samples a curve function at `resolution` evenly-spaced points over [0, 1]\n * and returns the results as a `Float32Array`.\n *\n * The i-th element is `curveFn(i / (resolution - 1))`, so both endpoints\n * (t = 0 and t = 1) are always included.\n *\n * @param curveFn - Any `(t: number) => number` function. t is in [0, 1].\n * @param resolution - Number of samples to take. Defaults to {@link CURVE_RESOLUTION}.\n * @returns A `Float32Array` of length `resolution` with the sampled values.\n *\n * @example\n * ```typescript\n * const linear = bakeCurve(t => t); // [0, 1/255, 2/255, …, 1]\n * const stepped = bakeCurve(t => t, 4); // [0, 0.333, 0.667, 1]\n * ```\n */\nexport function bakeCurve(\n curveFn: (t: number) => number,\n resolution: number = CURVE_RESOLUTION\n): Float32Array {\n const samples = new Float32Array(resolution);\n const lastIndex = resolution - 1;\n\n for (let i = 0; i < resolution; i++) {\n // Evenly space samples from 0 to 1 inclusive.\n const t = lastIndex === 0 ? 0 : i / lastIndex;\n samples[i] = curveFn(t);\n }\n\n return samples;\n}\n\n// ─── Internal helpers ─────────────────────────────────────────────────────────\n\n/**\n * Bakes a single {@link LifetimeCurve} config into the packed buffer at the\n * given write offset and returns the next free write offset.\n *\n * @param buffer - The destination Float32Array.\n * @param writeOffset - The first float index to write into.\n * @param particleSystemId - Used by the Bezier caching layer.\n * @param curve - The curve configuration to bake.\n * @returns The next available write offset (writeOffset + CURVE_RESOLUTION).\n */\nfunction bakeCurveIntoBuffer(\n buffer: Float32Array,\n writeOffset: number,\n particleSystemId: number,\n curve: LifetimeCurve\n): number {\n const curveFn = getCurveFunctionFromConfig(particleSystemId, curve);\n const lastIndex = CURVE_RESOLUTION - 1;\n\n for (let i = 0; i < CURVE_RESOLUTION; i++) {\n const t = lastIndex === 0 ? 0 : i / lastIndex;\n buffer[writeOffset + i] = curveFn(t);\n }\n\n return writeOffset + CURVE_RESOLUTION;\n}\n\n/**\n * Bakes a velocity axis value into the buffer. Only lifetime curves take a\n * table slot; constants and random ranges are NOT baked flat — they are\n * stored PER PARTICLE by the emission kernel (oracle parity: a flat\n * mid-point destroyed the per-particle random variance).\n */\nfunction bakeVelocityAxisIntoBuffer(\n buffer: Float32Array,\n writeOffset: number,\n particleSystemId: number,\n value:\n | import('../types.js').Constant\n | import('../types.js').RandomBetweenTwoConstants\n | LifetimeCurve\n): number {\n if (isLifeTimeCurve(value)) {\n return bakeCurveIntoBuffer(buffer, writeOffset, particleSystemId, value);\n }\n return writeOffset;\n}\n\n// ─── Particle System Curve Baking ─────────────────────────────────────────────\n\n/**\n * Bakes all active lifetime curves from a normalized particle system config\n * into a single, GPU-ready {@link BakedCurveMap}.\n *\n * The function inspects each modifier in order:\n * 1. `sizeOverLifetime` — baked if `isActive` is true\n * 2. `opacityOverLifetime` — baked if `isActive` is true\n * 3. `colorOverLifetime` (r, g, b) — all three baked if `isActive` is true\n * 4. `velocityOverLifetime.linear` (x, y, z) — each axis baked if the value\n * is a {@link LifetimeCurve} (constants and random ranges are skipped)\n * 5. `velocityOverLifetime.orbital` (x, y, z) — same rule as linear\n *\n * Curves are packed sequentially into a single `Float32Array`:\n * ```\n * [curve0_sample0, …, curve0_sample255, curve1_sample0, …, curveN_sample255]\n * ```\n *\n * @param normalizedConfig - A fully normalized particle system configuration\n * (all properties required, produced by the particle system initialization).\n * @param particleSystemId - Numeric ID passed to the Bezier caching layer so\n * it can reuse pre-evaluated Bezier functions for the same particle system.\n * @returns A {@link BakedCurveMap} with the packed data and per-modifier\n * curve indices. Inactive modifiers / constant axes have index `-1`.\n *\n * @example\n * ```typescript\n * const map = bakeParticleSystemCurves(normalizedConfig, systemId);\n * // Upload map.data to a GPU buffer.\n * // Pass map.sizeOverLifetime, map.opacityOverLifetime, … as uniforms.\n * ```\n */\nexport function bakeParticleSystemCurves(\n normalizedConfig: NormalizedParticleSystemConfig,\n particleSystemId: number\n): BakedCurveMap {\n // ── Phase 1: count how many curves will be baked ──────────────────────────\n let curveCount = 0;\n\n const {\n sizeOverLifetime,\n opacityOverLifetime,\n colorOverLifetime,\n velocityOverLifetime,\n } = normalizedConfig;\n\n const hasSizeOverLifetime = sizeOverLifetime.isActive;\n const hasOpacityOverLifetime = opacityOverLifetime.isActive;\n const hasColorOverLifetime = colorOverLifetime.isActive;\n\n // Velocity axes: ONLY lifetime curves get flat-table slots now; constant\n // and random-range axes are per-particle state written at emission.\n const isVelActive = velocityOverLifetime.isActive;\n const isCurveAxis = (v: unknown): boolean =>\n isVelActive && v !== undefined && isLifeTimeCurve(v as never);\n const hasLinearVelX = isCurveAxis(velocityOverLifetime.linear.x);\n const hasLinearVelY = isCurveAxis(velocityOverLifetime.linear.y);\n const hasLinearVelZ = isCurveAxis(velocityOverLifetime.linear.z);\n const hasOrbitalVelX = isCurveAxis(velocityOverLifetime.orbital.x);\n const hasOrbitalVelY = isCurveAxis(velocityOverLifetime.orbital.y);\n const hasOrbitalVelZ = isCurveAxis(velocityOverLifetime.orbital.z);\n\n if (hasSizeOverLifetime) curveCount++;\n if (hasOpacityOverLifetime) curveCount++;\n if (hasColorOverLifetime) curveCount += 3; // r, g, b always together\n if (hasLinearVelX) curveCount++;\n if (hasLinearVelY) curveCount++;\n if (hasLinearVelZ) curveCount++;\n if (hasOrbitalVelX) curveCount++;\n if (hasOrbitalVelY) curveCount++;\n if (hasOrbitalVelZ) curveCount++;\n\n // ── Phase 2: allocate the packed buffer ───────────────────────────────────\n const data = new Float32Array(curveCount * CURVE_RESOLUTION);\n\n // ── Phase 3: bake curves in a consistent, sequential order ────────────────\n let writeOffset = 0;\n let nextIndex = 0;\n\n // Index slots — -1 signals \"not active / not a curve\".\n let sizeOverLifetimeIdx = -1;\n let opacityOverLifetimeIdx = -1;\n let colorRIdx = -1;\n let colorGIdx = -1;\n let colorBIdx = -1;\n let linearVelXIdx = -1;\n let linearVelYIdx = -1;\n let linearVelZIdx = -1;\n let orbitalVelXIdx = -1;\n let orbitalVelYIdx = -1;\n let orbitalVelZIdx = -1;\n\n if (hasSizeOverLifetime) {\n sizeOverLifetimeIdx = nextIndex++;\n writeOffset = bakeCurveIntoBuffer(\n data,\n writeOffset,\n particleSystemId,\n sizeOverLifetime.lifetimeCurve\n );\n }\n\n if (hasOpacityOverLifetime) {\n opacityOverLifetimeIdx = nextIndex++;\n writeOffset = bakeCurveIntoBuffer(\n data,\n writeOffset,\n particleSystemId,\n opacityOverLifetime.lifetimeCurve\n );\n }\n\n if (hasColorOverLifetime) {\n colorRIdx = nextIndex++;\n writeOffset = bakeCurveIntoBuffer(\n data,\n writeOffset,\n particleSystemId,\n colorOverLifetime.r\n );\n\n colorGIdx = nextIndex++;\n writeOffset = bakeCurveIntoBuffer(\n data,\n writeOffset,\n particleSystemId,\n colorOverLifetime.g\n );\n\n colorBIdx = nextIndex++;\n writeOffset = bakeCurveIntoBuffer(\n data,\n writeOffset,\n particleSystemId,\n colorOverLifetime.b\n );\n }\n\n if (hasLinearVelX) {\n linearVelXIdx = nextIndex++;\n writeOffset = bakeVelocityAxisIntoBuffer(\n data,\n writeOffset,\n particleSystemId,\n velocityOverLifetime.linear.x!\n );\n }\n\n if (hasLinearVelY) {\n linearVelYIdx = nextIndex++;\n writeOffset = bakeVelocityAxisIntoBuffer(\n data,\n writeOffset,\n particleSystemId,\n velocityOverLifetime.linear.y!\n );\n }\n\n if (hasLinearVelZ) {\n linearVelZIdx = nextIndex++;\n writeOffset = bakeVelocityAxisIntoBuffer(\n data,\n writeOffset,\n particleSystemId,\n velocityOverLifetime.linear.z!\n );\n }\n\n if (hasOrbitalVelX) {\n orbitalVelXIdx = nextIndex++;\n writeOffset = bakeVelocityAxisIntoBuffer(\n data,\n writeOffset,\n particleSystemId,\n velocityOverLifetime.orbital.x!\n );\n }\n\n if (hasOrbitalVelY) {\n orbitalVelYIdx = nextIndex++;\n writeOffset = bakeVelocityAxisIntoBuffer(\n data,\n writeOffset,\n particleSystemId,\n velocityOverLifetime.orbital.y!\n );\n }\n\n if (hasOrbitalVelZ) {\n orbitalVelZIdx = nextIndex++;\n writeOffset = bakeVelocityAxisIntoBuffer(\n data,\n writeOffset,\n particleSystemId,\n velocityOverLifetime.orbital.z!\n );\n }\n\n return {\n data,\n curveCount,\n sizeOverLifetime: sizeOverLifetimeIdx,\n opacityOverLifetime: opacityOverLifetimeIdx,\n colorR: colorRIdx,\n colorG: colorGIdx,\n colorB: colorBIdx,\n linearVelX: linearVelXIdx,\n linearVelY: linearVelYIdx,\n linearVelZ: linearVelZIdx,\n orbitalVelX: orbitalVelXIdx,\n orbitalVelY: orbitalVelYIdx,\n orbitalVelZ: orbitalVelZIdx,\n };\n}\n\n// ─── GPU Upload Helpers ───────────────────────────────────────────────────────\n\n/**\n * Wraps a {@link BakedCurveMap}'s packed data in a `THREE.DataTexture` that\n * can be bound as a 1D lookup texture in a WebGL or WebGPU material.\n *\n * The texture is `curveCount × CURVE_RESOLUTION` pixels wide and 1 pixel tall,\n * using a single red-channel (`RedFormat`) 32-bit float format. A GPU shader\n * can sample it with:\n * ```glsl\n * float u = (float(curveIndex * RESOLUTION) + t255 + 0.5)\n * / float(curveCount * RESOLUTION);\n * float val = texture2D(curveTex, vec2(u, 0.5)).r;\n * ```\n *\n * @param bakedCurves - The result of {@link bakeParticleSystemCurves}.\n * @returns A `THREE.DataTexture` ready for use as a material uniform, or\n * `null` when `curveCount` is 0 (no curves to upload).\n *\n * @remarks\n * - `needsUpdate` is set to `true` so Three.js uploads the data on first use.\n * - The caller is responsible for calling `.dispose()` when the particle system\n * is destroyed to release GPU memory.\n * - For WebGPU storage-buffer binding, use `bakedCurves.data` directly instead.\n */\nexport function createCurveDataTexture(\n bakedCurves: BakedCurveMap\n): import('three').DataTexture | null {\n if (bakedCurves.curveCount === 0) {\n return null;\n }\n\n // Deferred import so this module remains usable in non-browser / test\n // environments where the THREE globals may not be set up.\n\n const THREE = require('three') as typeof import('three');\n\n const width = bakedCurves.curveCount * CURVE_RESOLUTION;\n const texture = new THREE.DataTexture(\n bakedCurves.data,\n width,\n 1,\n THREE.RedFormat,\n THREE.FloatType\n );\n\n texture.minFilter = THREE.LinearFilter;\n texture.magFilter = THREE.LinearFilter;\n texture.wrapS = THREE.ClampToEdgeWrapping;\n texture.wrapT = THREE.ClampToEdgeWrapping;\n texture.needsUpdate = true;\n\n return texture;\n}\n","/**\n * 3D Simplex Noise implemented in TSL (Three Shading Language).\n *\n * Adapted from the classic Ashima Arts / Stefan Gustavson simplex noise\n * implementation (MIT licence) for use in Three.js GPU compute shaders.\n *\n * References:\n * - Stefan Gustavson, \"Simplex noise demystified\", 2005\n * - https://github.com/ashima/webgl-noise\n *\n * @module\n */\nimport {\n Fn,\n vec2,\n vec3,\n vec4,\n float,\n floor,\n dot,\n step,\n abs,\n min,\n max,\n mod,\n type ShaderNodeObject,\n type Node,\n} from 'three/tsl';\n\n// ─── Internal helpers ─────────────────────────────────────────────────────────\n\n/**\n * Hash / permutation helper.\n *\n * Equivalent to the classic `mod289` + multiply-and-fold scheme:\n * permute(x) = mod(((x * 34.0) + 10.0) * x, 289.0)\n *\n * The extra `10.0` (vs the original `1.0`) avoids degenerate runs near zero\n * and is widely used in TSL/WGSL ports of the Ashima implementation.\n */\nconst permute = Fn(({ x }: Record<string, ShaderNodeObject<Node>>) => {\n // ((x * 34.0 + 10.0) * x) mod 289.0\n return mod(x.mul(34.0).add(10.0).mul(x), float(289.0));\n});\n\n/**\n * Fast inverse square-root approximation.\n *\n * taylorInvSqrt(r) = 1.79284291400159 - 0.85373472095314 * r\n *\n * Used to normalise gradient vectors without a true sqrt.\n */\nconst taylorInvSqrt = Fn(({ r }: Record<string, ShaderNodeObject<Node>>) => {\n return float(1.79284291400159).sub(float(0.85373472095314).mul(r));\n});\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * 3D simplex noise implemented in TSL.\n *\n * Algorithm overview:\n * 1. Skew the input point into the simplex (tetrahedral) grid.\n * 2. Determine which of the six tetrahedra the skewed point occupies.\n * 3. Un-skew the four integer lattice corners back to real space.\n * 4. Compute pseudo-random gradient vectors at each corner via two rounds of\n * `permute` (one for the iy/iz hash, one for ix), yielding per-corner\n * gradient (gx, gy, gz) extracted using the \"ns\" mapping.\n * 5. Weight each corner's contribution by a radially-symmetric falloff\n * `max(0, 0.5 - |x|²)⁴` and accumulate.\n * 6. Scale the result so the output lies in approximately [-1, 1].\n *\n * @param v - Input position (vec3).\n * @returns Noise value in approximately [-1, 1] (float).\n */\nexport const snoise3D: ReturnType<typeof Fn> = Fn(\n ({ v }: Record<string, ShaderNodeObject<Node>>) => {\n // ── Step 1: Skew input space ──────────────────────────────────────────────\n // F3 = 1/3. Skew the input space to determine which simplex cell we're in.\n const ONE_THIRD = float(1.0 / 3.0);\n const ONE_SIXTH = float(1.0 / 6.0);\n\n // i = floor(v + dot(v, vec3(1/3)))\n const i = floor(\n v.add(dot(v, vec3(ONE_THIRD, ONE_THIRD, ONE_THIRD)))\n ).toVar();\n\n // ── Step 2: Un-skew back to (x0,y0,z0) ──────────────────────────────────\n // x0 = v - i + dot(i, vec3(1/6))\n const x0 = v\n .sub(i)\n .add(dot(i, vec3(ONE_SIXTH, ONE_SIXTH, ONE_SIXTH)))\n .toVar();\n\n // ── Step 3: Determine simplex (tetrahedron) ───────────────────────────────\n // Which of the six tetrahedra is point x0 in?\n // Compare x0 components pairwise to rank them and identify the two\n // intermediate simplex corners (i1, i2).\n //\n // g = step(x0.yzx, x0.xyz): 1 where x0[i] >= x0[i-1 mod 3]\n // l = 1 - g.zxy (complement for the other direction)\n const g = step(x0.yzx, x0.xyz).toVar();\n const l = float(1.0).sub(g).toVar();\n\n // i1: first offset (one unit step toward the dominant axis)\n // i2: second offset (two unit steps)\n const i1 = min(g.xyz, l.zxy).toVar();\n const i2 = max(g.xyz, l.zxy).toVar();\n\n // Un-skew the three corner displacements from x0:\n // x1 = x0 - i1 + G3\n // x2 = x0 - i2 + 2*G3\n // x3 = x0 - 1 + 3*G3\n const x1 = x0.sub(i1).add(ONE_SIXTH).toVar();\n const x2 = x0.sub(i2).add(ONE_SIXTH.mul(2.0)).toVar();\n const x3 = x0.sub(float(1.0)).add(ONE_SIXTH.mul(3.0)).toVar();\n\n // ── Step 4: Permutation hashes → gradient directions ─────────────────────\n // Wrap i into [0, 289) so the hash stays well-behaved.\n const iw = mod(i, float(289.0)).toVar();\n\n // Hash yz layers first, then mix in x.\n // For each of the 4 corners, hash iz then iy:\n // p_yz_c = permute(permute(iz_c) + iy_c)\n // Then hash ix:\n // p_c = permute(p_yz_c + ix_c)\n // Each final p_c is a scalar hash that encodes the full gradient direction.\n\n // Corner z-components: iz, iz+i1.z, iz+i2.z, iz+1\n const p0_yz = permute({\n x: permute({\n x: vec4(\n vec2(iw.z, iw.z.add(i1.z)),\n vec2(iw.z.add(i2.z), iw.z.add(1.0))\n ),\n }).add(\n vec4(vec2(iw.y, iw.y.add(i1.y)), vec2(iw.y.add(i2.y), iw.y.add(1.0)))\n ),\n });\n\n // Final hash: mix in x-components\n const p = permute({\n x: p0_yz.add(\n vec4(vec2(iw.x, iw.x.add(i1.x)), vec2(iw.x.add(i2.x), iw.x.add(1.0)))\n ),\n });\n\n // ── Step 5: Convert hash to gradient directions ───────────────────────────\n // Standard Ashima/Gustavson gradient extraction via octahedral mapping.\n //\n // The hash values `p` are in [0, 289). We reduce them to a 7×7 grid\n // (49 entries) to extract two gradient components (gx, gy), then derive\n // gz via octahedral projection: gz = 1 - |gx| - |gy|.\n //\n // When gz < 0 the gradient lies outside the octahedron's upper hemisphere;\n // a fold-back correction shifts gx/gy inward so the gradient stays on\n // the octahedron surface, giving 12 well-distributed directions that\n // closely approximate the original simplex gradient set.\n //\n // Constants (from Ashima `vec3 ns = n_ * D.wyz - D.xzx`):\n // ns.x = 2/7 ≈ 0.285714 (grid step size)\n // ns.y = -13/14 ≈ -0.928571 (grid offset: 1/14 - 1)\n // ns.z = 1/7 ≈ 0.142857 (used for p mod 49)\n\n const n_ = float(0.142857142857142); // 1/7\n\n // j = p mod 49 — reduces hash to [0, 48]\n // p * ns.z * ns.z = p * (1/7)^2 = p / 49\n const j = p.sub(float(49.0).mul(floor(p.mul(n_).mul(n_)))).toVar();\n\n // x_ = floor(j / 7) ∈ [0, 6]\n const x_ = floor(j.mul(n_)).toVar();\n // y_ = floor(j - 7 * x_) ∈ [0, 6]\n const y_ = floor(j.sub(float(7.0).mul(x_))).toVar();\n\n // Map grid indices to gradient components in approximately [-1, 1]:\n // gx = x_ * (2/7) + (-13/14) ∈ [-0.929, 0.786]\n // gy = y_ * (2/7) + (-13/14) ∈ [-0.929, 0.786]\n const NS_X = float(0.285714285714286); // 2/7\n const NS_Y = float(-0.928571428571429); // 1/14 - 1\n\n const gx = x_.mul(NS_X).add(NS_Y);\n const gy = y_.mul(NS_X).add(NS_Y);\n\n // gz = octahedral budget: 1 - |gx| - |gy|\n const gz = float(1.0).sub(abs(gx)).sub(abs(gy)).toVar();\n\n // Octahedral fold-back: when gz < 0, shift gx/gy toward the origin\n // step(gz, 0) → 1 when gz <= 0, 0 when gz > 0\n // correction = (floor(component) + 0.5) when gz <= 0, else 0\n // gx -= correction_x, gy -= correction_y\n const gz_neg = step(gz, vec4(0.0)); // 1 where gz <= 0\n const ox = gz_neg.mul(floor(gx).add(0.5));\n const oy = gz_neg.mul(floor(gy).add(0.5));\n const gx_final = gx.sub(ox);\n const gy_final = gy.sub(oy);\n\n // Build the four un-normalised gradient vectors\n const g0 = vec3(gx_final.x, gy_final.x, gz.x).toVar();\n const g1 = vec3(gx_final.y, gy_final.y, gz.y).toVar();\n const g2 = vec3(gx_final.z, gy_final.z, gz.z).toVar();\n const g3 = vec3(gx_final.w, gy_final.w, gz.w).toVar();\n\n // Normalise gradients using the Taylor inverse-sqrt approximation\n const norm = taylorInvSqrt({\n r: vec4(vec2(dot(g0, g0), dot(g1, g1)), vec2(dot(g2, g2), dot(g3, g3))),\n });\n g0.assign(g0.mul(norm.x));\n g1.assign(g1.mul(norm.y));\n g2.assign(g2.mul(norm.z));\n g3.assign(g3.mul(norm.w));\n\n // ── Step 6: Compute corner contributions ─────────────────────────────────\n // Falloff: m = max(0, 0.5 - |x|²)⁴ (C² continuity)\n const m = max(\n vec4(\n vec2(float(0.5).sub(dot(x0, x0)), float(0.5).sub(dot(x1, x1))),\n vec2(float(0.5).sub(dot(x2, x2)), float(0.5).sub(dot(x3, x3)))\n ),\n float(0.0)\n ).toVar();\n\n const m2 = m.mul(m).toVar();\n const m4 = m2.mul(m2).toVar();\n\n // Dot the gradients with the un-skewed displacement vectors\n const gdot = vec4(\n vec2(dot(g0, x0), dot(g1, x1)),\n vec2(dot(g2, x2), dot(g3, x3))\n );\n\n // Accumulate: sum(m4 * gdot), then scale to [-1, 1]\n // The scale factor 42.0 is the classical Gustavson normalisation constant\n // for 3D simplex noise with this gradient set.\n return float(42.0).mul(dot(m4, gdot));\n }\n);\n\n/**\n * Evaluates noise at three different input configurations matching\n * the CPU noise modifier pattern from `three-particles-modifiers.ts`:\n *\n * ```\n * noiseX = snoise3D(pos, 0, 0) // pos = (t, 0, 0)\n * noiseY = snoise3D(pos, pos, 0) // pos = (t, t, 0)\n * noiseZ = snoise3D(pos, pos, pos) // pos = (t, t, t)\n * ```\n *\n * where `t` is the scalar noise position (e.g. `lifePercent * strength * 10`).\n *\n * This matches the three calls in the CPU path:\n * ```typescript\n * noiseInput.set(noisePosition, 0, 0 ); // → posX\n * noiseInput.set(noisePosition, noisePosition, 0 ); // → posY\n * noiseInput.set(noisePosition, noisePosition, noisePosition); // → posZ\n * ```\n *\n * @param t - Scalar noise position (float). Typically `lifePercent * strength * 10`.\n * @returns vec3(noiseX, noiseY, noiseZ) — each component in approximately [-1, 1].\n */\nexport const particleNoise3: ReturnType<typeof Fn> = Fn(\n ({ t }: Record<string, ShaderNodeObject<Node>>) => {\n const noiseX = snoise3D({ v: vec3(t, float(0.0), float(0.0)) });\n const noiseY = snoise3D({ v: vec3(t, t, float(0.0)) });\n const noiseZ = snoise3D({ v: vec3(t, t, t) });\n return vec3(noiseX, noiseY, noiseZ);\n }\n);\n\n// Re-export TSL types for callers that need them\nexport type { ShaderNodeObject, Node };\n","/**\n * Standard IEC 61966-2-1 sRGB → linear transfer function.\n * Matches `THREE.ColorManagement.SRGBToLinear` and the GLSL\n * `ShaderChunk.colorspace_fragment` implementation, so that user-provided\n * colors go through the exact same conversion the rest of the Three.js\n * pipeline uses for sRGB-tagged inputs.\n *\n * Input: a channel value in [0, 1] interpreted as sRGB.\n * Output: the corresponding linear value in [0, 1].\n */\nexport const sRGBToLinear = (c: number): number =>\n c < 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n\n/**\n * Standard IEC 61966-2-1 linear → sRGB transfer function.\n * Inverse of {@link sRGBToLinear}. Useful for one-shot migration of\n * legacy color values that were authored under the old raw-byte pipeline.\n */\nexport const linearToSRGB = (c: number): number =>\n c < 0.0031308 ? c * 12.92 : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;\n\n/**\n * Converts an sRGB {r, g, b} triplet to linear space.\n * Used when uploading user-authored colors (e.g. `backgroundColor`) as\n * shader uniforms that must match the linear-space texture samples and\n * vertex colors used elsewhere in the pipeline. Missing channels default\n * to 0 to mirror the permissive shape of the `Rgb` config type.\n */\nexport const rgbSRGBToLinear = (c: {\n r?: number;\n g?: number;\n b?: number;\n}): { r: number; g: number; b: number } => ({\n r: sRGBToLinear(c.r ?? 0),\n g: sRGBToLinear(c.g ?? 0),\n b: sRGBToLinear(c.b ?? 0),\n});\n","/**\n * GPU-owned WebGPU compute kernels for @cyberluke/three-particles 4.0.0.\n *\n * Per-particle state lives ONLY in GPU storage buffers. The CPU never\n * walks slots; it only writes 12 scalar uniforms per frame and issues\n * two `renderer.compute(...)` calls (emission, then simulation).\n *\n * Storage pool (8 storage bindings = the WebGPU compute guarantee\n * `minStorageBuffersPerStage = 8`; read-mostly tables live in uniform\n * bindings, which are counted separately, `minUniformBuffersPerStage = 4`):\n * 1. position : vec4 * maxParticles (xyz, w = padding)\n * 2. velocity : vec4 * maxParticles (xyz, w = padding)\n * 3. color : vec4 * maxParticles (r, g, b, a)\n * 4. particleState : vec4 * maxParticles (lifetime, size, rotation, startFrame)\n * 5. startValues : vec4 * maxParticles (startLife, startSize, startOpac, startColorR)\n * 6. startColorsExt : vec4 * maxParticles (startColorG, startColorB, rotSpeed, noiseOffset)\n * 7. orbitalIsActive : vec4 * maxParticles (orbitalOffset.xyz, isActive)\n * 8. allocator : atomic<u32> * (maxParticles + 1) (UINT, not f32)\n * [0] : freeCount (stack size)\n * [1 .. maxParticles]: free slot ids\n *\n * One extra UNIFORM binding carries the read-mostly f32 tables (non-atomic,\n * so the curve / force-field / collision hot path stays a plain `f32` load):\n * [0 .. curveLen-1] baked curve samples\n * [curveLen ...] force-field records (optional)\n * [...] collision-plane records (optional)\n *\n * The allocator is managed entirely on the GPU with integer `atomicAdd` /\n * `atomicSub` / `atomicLoad` / `atomicStore`; the CPU initialises it once at\n * pipeline creation and never touches it again.\n *\n * @module\n */\nimport { Vector3, Vector4 } from 'three';\nimport {\n Fn,\n float,\n vec3,\n vec4,\n uint as tuint,\n mix,\n floor,\n fract,\n sin,\n cos,\n sqrt,\n min as tslMin,\n max as tslMax,\n rand,\n storage,\n buffer,\n atomicAdd,\n atomicSub,\n atomicLoad,\n atomicStore,\n instanceIndex,\n uniform,\n If,\n compute,\n type ShaderNodeObject,\n type Node,\n} from 'three/tsl';\nimport {\n StorageBufferAttribute,\n StorageInstancedBufferAttribute,\n} from 'three/webgpu';\nimport {\n CURVE_RESOLUTION,\n bakeCurve,\n type BakedCurveMap,\n} from './curve-bake.js';\nimport { snoise3D } from './tsl-noise.js';\nimport {\n FORCE_FIELD_DATA_SIZE,\n createForceFieldTSL,\n} from './compute-force-fields.js';\nimport {\n COLLISION_PLANE_DATA_SIZE,\n createCollisionPlaneTSL,\n} from './compute-collision-planes.js';\nimport { sRGBToLinear } from '../color-utils.js';\n\n// ??? Buffer layout constants ????????????????????????????????????????????????\n// Each `vec4 * maxParticles` slot is stored as 4 floats in row order. Indices\n// match the \"1..8 = binding order\" numbering above.\nexport const S_PSX = 0; // particleState.x: lifetime (ms)\nexport const S_PSY = 1; // particleState.y: size\nexport const S_PSZ = 2; // particleState.z: rotation (rad)\nexport const S_PSW = 3; // particleState.w: startFrame (0-based sheet index)\nexport const S_SVX = 0; // startValues.x: startLifetime (ms)\nexport const S_SVY = 1; // startValues.y: startSize\nexport const S_SVZ = 2; // startValues.z: startOpacity\nexport const S_SVW = 3; // startValues.w: startColorR\nexport const S_EXX = 0; // startColorsExt.x: startColorG\nexport const S_EXY = 1; // startColorsExt.y: startColorB\nexport const S_EXZ = 2; // startColorsExt.z: rotationSpeed (rad/s)\nexport const S_EXW = 3; // startColorsExt.w: noiseOffset\nexport const S_ORW = 3; // orbitalIsActive.w: isActive flag\n\n// ??? Modifier flags ?????????????????????????????????????????????????????????\nexport type ModifierFlags = {\n sizeOverLifetime: boolean;\n opacityOverLifetime: boolean;\n colorOverLifetime: boolean;\n rotationOverLifetime: boolean;\n linearVelocity: boolean;\n orbitalVelocity: boolean;\n noise: boolean;\n forceFields: boolean;\n collisionPlanes: boolean;\n};\n\n/**\n * GPU shape enum. Matches the public {@link Shape} strings one-to-one:\n * 0 SPHERE | 1 CONE | 2 CIRCLE | 3 RECTANGLE | 4 BOX\n */\nexport const SHAPE_KIND = {\n SPHERE: 0,\n CONE: 1,\n CIRCLE: 2,\n RECTANGLE: 3,\n BOX: 4,\n} as const;\n\n/** {@link EmitFrom} encoded for the compute kernel: 0 VOLUME | 1 SHELL | 2 EDGE. */\nexport const BOX_EMIT_FROM = {\n VOLUME: 0,\n SHELL: 1,\n EDGE: 2,\n} as const;\n\n/**\n * Shape-emission parameters used by the emission compute kernel. One flat,\n * fully-resolved record: every field comes from the *nested* public\n * `ShapeConfig` branch (`shape.sphere` / `shape.cone` / …), never from\n * flattened `shapeType` / top-level `radius` keys.\n */\nexport type ShapeEmitParams = {\n /** 0 SPHERE | 1 CONE | 2 CIRCLE | 3 RECTANGLE | 4 BOX. */\n shapeKind: 0 | 1 | 2 | 3 | 4;\n /** sphere / cone / circle base radius. */\n radius: number;\n /** 1 = full volume, 0 = shell only (sphere, cone, circle). */\n radiusThickness: number;\n /** angular arc in **degrees** (360 = full). */\n arcDeg: number;\n /** cone opening angle in **degrees** (oracle default 90). */\n coneAngleDeg: number;\n /** rectangle local rotation (degrees, oracle x/y used). */\n rectangleRotXDeg: number;\n rectangleRotYDeg: number;\n /** rectangle scale. */\n rectangleScaleX: number;\n rectangleScaleY: number;\n /** box scale. */\n boxScaleX: number;\n boxScaleY: number;\n boxScaleZ: number;\n /** box emission mode: 0 VOLUME | 1 SHELL | 2 EDGE. */\n boxEmitFrom: 0 | 1 | 2;\n speedMin: number;\n speedMax: number;\n sizeMin: number;\n sizeMax: number;\n rotMin: number;\n rotMax: number;\n opacityMin: number;\n opacityMax: number;\n lifeMin: number; // startLifetime min (ms ? seconds to match GPU kernel)\n lifeMax: number;\n colorRMin: number;\n colorRMax: number;\n colorGMin: number;\n colorGMax: number;\n colorBMin: number;\n colorBMax: number;\n startFrameMin: number;\n startFrameMax: number;\nrotationCurveActive: boolean;\n rotationalXCurve: number; // index or -1\n rotationalYCurve: number;\n rotationalZCurve: number;\n linearXCurve: number;\n linearYCurve: number;\n linearZCurve: number;\n /** rotationOverLifetime speed range (SEPARATE from startRotation rotMin/rotMax). */\n rotOverLifeMin: number;\n rotOverLifeMax: number;\n /** noise.octaves (FBM octave count; 1 = single snoise sample). */\n noiseOctaves: number;\n /** noise.useRandomOffset — per-particle random offset in [0,100). */\n noiseUseRandomOffset: boolean;\n};\n\n/**\n * One GPU sub-emitter event channel, split into integer metadata + plain\n * float payload (WGSL integer atomics only):\n * counter : `array<atomic<u32>, 2>` — ping-pong window counters (event\n * counts written this cycle; slot = window index 0/1).\n * payload : ordinary f32 storage; window w starts at `w * 6 * capacity`,\n * event k lives at `windowBase + 6*k + 0..5 =\n * (x, y, z, velX, velY, velZ)`.\n * The parent kernels append events; the child init kernel consumes them.\n */\nexport type SubEmitterFifo = {\n /** `atomic<u32>` ping-pong counters (itemSize 1, 2 elements). */\n counter: StorageBufferAttribute;\n /** 6 floats per event, 2 ping-pong windows, plain f32 storage. */\n payload: StorageBufferAttribute;\n /** 0 = BIRTH (written by the emission kernel), 1 = DEATH (sim kernel). */\n trigger: 0 | 1;\n /** Event capacity == `maxInstances` of the sub-emitter config. */\n capacity: number;\n /** Floats per window: 6 per event in the payload buffer. */\n windowSize: number;\n};\n\n/** Floats stored per sub-emitter event (position xyz + velocity xyz). */\nexport const SUB_EMITTER_EVENT_STRIDE = 6;\n\n/** Floats in one FIFO payload window. */\nexport const subEmitterWindowSize = (capacity: number): number =>\n SUB_EMITTER_EVENT_STRIDE * Math.max(1, capacity);\n\n// ─── u32 PCG birth hashing (§1: integer-first, uint-first) ────────────────\n// Same arithmetic as Three.js r186 `nodes/math/Hash.js` (`hash()`), but\n// implemented locally so every intermediate stays in u32; the final stage is\n// the ONLY `uintBitsToFloat`-free f32 conversion. three's float `rand()` is\n// intentionally not used for the primary birth entropy.\n\n/** Raw uint PCG word (u32 chain: mul/add/shift/xor, no f32 intermediates). */\n// r186 detail: `uint()` / `.toUint()` emit an empty snippet for atomic-result\n// nodes (their nodeType is already 'uint'), so pass those through untouched.\nconst asU32 = (n: ShaderNodeObject<Node>): ShaderNodeObject<Node> =>\n n.nodeType === 'uint' ? n : n.toUint();\n\nexport const pcgRawU32 = (\n seedU: ShaderNodeObject<Node>\n): ShaderNodeObject<Node> => {\n const stateU = asU32(seedU).mul(tuint(747796405)).add(tuint(2891336453));\n const wordU = stateU\n .shiftRight(stateU.shiftRight(tuint(28)).add(tuint(4)))\n .bitXor(stateU)\n .mul(tuint(277803737));\n return wordU.shiftRight(tuint(22)).bitXor(wordU);\n};\n\n/** PCG hash in [0,1): integer mixing first, single f32 conversion at the end. */\nexport const pcg01 = (seedU: ShaderNodeObject<Node>): ShaderNodeObject<Node> =>\n pcgRawU32(seedU).toFloat().mul(float(1 / 4294967296));\n\n/** Integer channel mix (all u32): birthNo*Knuth_odd ^ systemSeed ^ channel. */\nexport const mixBirthSeed = (\n birthNoU: ShaderNodeObject<Node>,\n systemSeedU: ShaderNodeObject<Node>,\n channelU: ShaderNodeObject<Node>\n): ShaderNodeObject<Node> =>\n asU32(birthNoU)\n .mul(tuint(2654435761))\n .bitXor(asU32(systemSeedU))\n .bitXor(asU32(channelU));\n\n/** Independent random channel from (birth number, system seed, channel id). */\nexport const randomChannel = (\n birthNoU: ShaderNodeObject<Node>,\n systemSeedU: ShaderNodeObject<Node>,\n channelU: ShaderNodeObject<Node>\n): ShaderNodeObject<Node> => pcg01(mixBirthSeed(birthNoU, systemSeedU, channelU));\n\n/** 24-bit exact-in-f32 stable seed stored in `startColorsExt.w`. */\nexport const stableSeedU32 = (\n birthNoU: ShaderNodeObject<Node>,\n systemSeedU: ShaderNodeObject<Node>\n): ShaderNodeObject<Node> =>\n pcgRawU32(mixBirthSeed(birthNoU, systemSeedU, CH.STABLE_SEED)).bitAnd(\n tuint(0x00ffffff)\n );\n\n/** Stable seed recovered from `startColorsExt.w` (exact integer round-trip). */\nexport const stableSeedFromExt = (\n extW: ShaderNodeObject<Node>\n): ShaderNodeObject<Node> => extW.toUint();\n\n/** One-time host seed for a pipeline (§5): u32 value written ONCE at creation. */\nexport const nextSystemSeed = (): number =>\n Math.floor(Math.random() * 0x100000000) >>> 0;\n\n/** Dedicated uint channel constants (never reuse one id inside a pass). */\nexport const CH = {\n SHAPE_A: tuint(1),\n SHAPE_B: tuint(2),\n SHAPE_C: tuint(3),\n START_FRAME: tuint(4),\n SPEED: tuint(5),\n SIZE: tuint(6),\n ROTATION: tuint(7),\n OPACITY: tuint(8),\n LIFETIME: tuint(9),\n COLOR: tuint(10),\n ROTOL: tuint(11),\n STABLE_SEED: tuint(12),\n LIN_X: tuint(13),\n LIN_Y: tuint(14),\n LIN_Z: tuint(15),\n ORB_X: tuint(16),\n ORB_Y: tuint(17),\n ORB_Z: tuint(18),\n NOISE_PHASE: tuint(19),\n} as const;\n\n/**\n * Allocates the FIFO buffers for one sub-emitter channel: an integer\n * `atomic<u32>` counter pair (ping-pong) plus two ordinary f32 payload\n * windows. Float payload never goes through an atomic; counters are integer.\n */\nexport const createSubEmitterFifoAttribute = (capacity: number): SubEmitterFifo =>\n ({\n counter: new StorageBufferAttribute(new Uint32Array(2), 1),\n payload: new StorageBufferAttribute(\n new Float32Array(\n 2 * SUB_EMITTER_EVENT_STRIDE * Math.max(1, capacity)\n ),\n 1\n ),\n trigger: 1,\n capacity: Math.max(1, capacity),\n windowSize: subEmitterWindowSize(capacity),\n }) as SubEmitterFifo;\n\n/** Trail-history descriptor consumed by the simulation kernel. */\nexport type TrailHistoryDesc = {\n /** Ordinary (non-atomic) vec4 f32 history ring: `(L+1)` rows per particle. */\n attribute: StorageBufferAttribute;\n /**\n * Integer ring metadata, `array<atomic<u32>>`, 2 words per particle:\n * word 2i = cursor, word 2i+1 = valid sample count (no float atomics).\n */\n meta: StorageBufferAttribute;\n /** Ring length `L` (`trail.length`). */\n length: number;\n /** Adaptive sampling threshold in world units (`trail.minVertexDistance`). */\n minVertexDistance: number;\n /** Sample age limit in ms (`trail.maxTime`, 0 = unlimited). */\n maxTime: number;\n};\n\n/** Ribbon build descriptor for {@link createTrailRibbonUpdate}. */\nexport type TrailRibbonDesc = {\n /** vec4 * (maxParticles*2L): (x, y, z, halfWidth). */\n position: StorageBufferAttribute;\n /** vec4 * (maxParticles*2L): (nextX, nextY, nextZ, alpha). */\n next: StorageBufferAttribute;\n /** vec4 * (maxParticles*2L): (uv.x = side 0/1, uv.y = t, colorR, colorG). */\n uvColorA: StorageBufferAttribute;\n /** vec4 * (maxParticles*2L): (colorB, colorA, 0, 0). */\n colorB: StorageBufferAttribute;\n /** Shared trail history buffer: ordinary vec4 f32 storage (same as {@link TrailHistoryDesc}). */\n history: StorageBufferAttribute;\n /** Shared integer ring metadata (atomic<u32>, 2 words per particle). */\n meta: StorageBufferAttribute;\n /** Particle RGBA pool of the owning system (read-mostly). */\n particleColor: StorageBufferAttribute | StorageInstancedBufferAttribute;\n /** Curve functions along the trail (t = 0 head \\u2192 1 tail); omitted = identity. */\n curveFns: {\n width?: (t: number) => number;\n opacity?: (t: number) => number;\n colorR?: (t: number) => number;\n colorG?: (t: number) => number;\n colorB?: (t: number) => number;\n };\n /** Ribbon width in world units (`trail.width`). */\n width: number;\n /** Ring length `L` (`trail.length`). */\n length: number;\n /** Sample age limit in ms; 0 = unlimited. */\n maxTime: number;\n /** Number of particle slots. */\n maxParticles: number;\n};\n\n/** Per-frame compute-pipeline uniforms (CPU-side scalar writes only). */\nexport type ModifierUniforms = {\n delta: ShaderNodeObject<Node>;\n deltaMs: ShaderNodeObject<Node>;\n /** Current clock in ms, used for trail sample stamps. */\n nowMs: ShaderNodeObject<Node>;\n gravityVelocity: ShaderNodeObject<Node>;\n noiseStrength: ShaderNodeObject<Node>;\n noisePower: ShaderNodeObject<Node>;\n noiseFrequency: ShaderNodeObject<Node>;\n noisePositionAmount: ShaderNodeObject<Node>;\n noiseRotationAmount: ShaderNodeObject<Node>;\n noiseSizeAmount: ShaderNodeObject<Node>;\n /** Scalar count of new particles for this frame; also written to `emitNode.count`. */\n emitCount: ShaderNodeObject<Node>;\n /** Seed for GPU-side randomness (updated per frame by CPU). */\n seed: ShaderNodeObject<Node>;\n};\n\n/** GPU storage buffer references. */\nexport type ModifierStorageBuffers = {\n position: StorageBufferAttribute | StorageInstancedBufferAttribute;\n velocity: StorageBufferAttribute | StorageInstancedBufferAttribute;\n color: StorageBufferAttribute | StorageInstancedBufferAttribute;\n particleState: StorageBufferAttribute | StorageInstancedBufferAttribute;\n startValues: StorageBufferAttribute | StorageInstancedBufferAttribute;\n startColorsExt: StorageBufferAttribute | StorageInstancedBufferAttribute;\n orbitalIsActive: StorageBufferAttribute | StorageInstancedBufferAttribute;\n /** `array<atomic<u32>, 1>` ring-allocation counter (integer atomic only). */\n allocator: StorageBufferAttribute;\n /** Trail ring integer metadata (`atomic<u32>`, 2 words per particle), or null. */\n trailMeta: StorageBufferAttribute | null;\n /** Packed read-mostly f32 tables (curves + force fields + collision planes), uniform-backed. */\n packedData: Float32Array;\n};\n\n/** Actual per-pass resource budget derived from that pass's bound nodes. */\nexport type PassLayout = {\n name: string;\n storageBindings: number;\n uniformBindings: number;\n};\n\n/** The complete GPU-owned pipeline handle returned by `createComputePipeline`. */\nexport type ModifierComputePipeline = {\n /** Emission compute node (dispatched before simulation each frame). */\n emitNode: ReturnType<typeof compute>;\n /** Per-frame simulation compute node. */\n simNode: ReturnType<typeof compute>;\n /** Dedicated trail-history pass node (null when no TRAIL renderer). */\n trailHistoryNode: ReturnType<typeof compute> | null;\n /** Dedicated sub-emitter BIRTH event pass node (null without BIRTH FIFOs). */\n subBirthEventsNode: ReturnType<typeof compute> | null;\n /** Dedicated sub-emitter DEATH event pass node (null without DEATH FIFOs). */\n subDeathEventsNode: ReturnType<typeof compute> | null;\n /** Convenience: every node of this pipeline in dispatch order. */\n computeNodes: ReturnType<typeof compute>[];\n /** Real per-pass storage/uniform budgets (no synthetic totals). */\n passLayouts: PassLayout[];\n /** Uniforms the CPU writes before each pair of compute dispatches. */\n uniforms: ModifierUniforms;\n /** Shape / curve parameters (scalar float uniforms) baked at creation. */\n shapeUniforms: Record<string, ShaderNodeObject<Node>>;\n /** Storage buffers (shared by both kernels). */\n buffers: ModifierStorageBuffers;\n /** Element count of the uint atomic allocator stack (`maxParticles + 1`). */\n allocatorCount: number;\n /** Non-atomic f32 uniform-table node (baked curves + force fields + collision planes). */\n packedDataNode: ShaderNodeObject<Node>;\n /** Semantic compute-pass names in dispatch order (for `[PS:pipeline]` logging). */\n passNames: string[];\n /** Trail ring integer meta attribute (null when the system has no trail). */\n trailMeta: StorageBufferAttribute | null;\n\n /** Emitter-pose uniform values for sub-emitter init kernel. */\n emitterPose: {\n /** (x, y, z, isWorldFlag) ? translation only in WORLD simulation. */\n positionW: ShaderNodeObject<Node> | null;\n wrapperQuat: ShaderNodeObject<Node> | null;\n worldScale: ShaderNodeObject<Node> | null;\n };\n /** Force field offset + count uniform (null when disabled). */\n forceFieldInfo: {\n offset: number;\n countUniform: ShaderNodeObject<Node>;\n } | null;\n /** Collision plane offset + count uniform (null when disabled). */\n collisionPlaneInfo: {\n offset: number;\n countUniform: ShaderNodeObject<Node>;\n } | null;\n};\n\n// ??? Storage pool creation ??????????????????????????????????????????????????\n/**\n * Creates GPU buffers for one particle system.\n *\n * 8 storage bindings: the 7 per-particle `vec4` state buffers plus one\n * `uint`-typed atomic allocator; the read-mostly f32 tables (baked curves,\n * force fields, collision planes) live in a plain `Float32Array` that is bound\n * as a uniform buffer, so they do not consume a storage binding and stay\n * non-atomic `f32` loads on the hot path.\n *\n * The CPU only fills the two CPU-owned buffers once; after the first upload\n * the compute kernels own all changes.\n */\nexport function createModifierStorageBuffers(\n maxParticles: number,\n instanced: boolean,\n curveData: Float32Array,\n hasForceFields = false,\n hasCollisionPlanes = false,\n trailLength = 0\n): { buffers: ModifierStorageBuffers; allocatorCount: number } {\n const Cls = instanced\n ? StorageInstancedBufferAttribute\n : StorageBufferAttribute;\n\n const curveLen = Math.max(curveData.length, 1);\n const ffSize = hasForceFields ? FORCE_FIELD_DATA_SIZE : 0;\n const cpSize = hasCollisionPlanes ? COLLISION_PLANE_DATA_SIZE : 0;\n // Read-mostly f32 table layout (uniform-backed, non-atomic):\n // [0 .. curveLen-1] baked curve samples\n // [curveLen .. curveLen + ffSize - 1] force-field records (if any)\n // [... .. + cpSize - 1] collision-plane records (if any)\n const packedData = new Float32Array(curveLen + ffSize + cpSize);\n packedData.set(curveData, 0);\n\n // Ring allocator: ONE integer `atomic<u32>` counter (index 0 of the binding,\n // the tail padding keeps the binding size identical to legacy). Allocation\n // is `slot = fetchAdd(counter) % (maxParticles + 1)`, so the counter can\n // never underflow and every slot index is always in range (a plain\n // atomicSub stack wraps 0 -> 0xffffffff and indexes out of bounds).\n const allocatorCount = maxParticles + 1;\n const allocatorData = new Uint32Array(allocatorCount);\n allocatorData[0] = 0;\n for (let i = 0; i < maxParticles; i++) allocatorData[i + 1] = i;\n\n // Trail ring metadata: integer atomic words only (cursor, count per slot).\n const trailMeta =\n trailLength > 0\n ? new StorageBufferAttribute(\n new Uint32Array(Math.max(1, maxParticles) * 2),\n 1\n )\n : null;\n\n return {\n buffers: {\n position: new Cls(new Float32Array(maxParticles * 4), 4),\n velocity: new StorageBufferAttribute(new Float32Array(maxParticles * 4), 4),\n color: new Cls(new Float32Array(maxParticles * 4), 4),\n particleState: new Cls(new Float32Array(maxParticles * 4), 4),\n startValues: new Cls(new Float32Array(maxParticles * 4), 4),\n startColorsExt: new StorageBufferAttribute(new Float32Array(maxParticles * 4), 4),\n orbitalIsActive: new StorageBufferAttribute(new Float32Array(maxParticles * 4), 4),\n allocator: new StorageBufferAttribute(allocatorData, 1),\n trailMeta,\n packedData,\n },\n allocatorCount,\n };\n}\n\n// ??? Curve lookup helper ????????????????????????????????????????????????????\nfunction createCurveLookup(sCurveData: ShaderNodeObject<Node>) {\n return Fn(({ curveIndex, t }: { curveIndex: ShaderNodeObject<Node>; t: ShaderNodeObject<Node> }) => {\n const clamped = tslMin(t, float(1.0));\n const pos = clamped.mul(CURVE_RESOLUTION - 1);\n const idx0 = floor(pos);\n const f = fract(pos);\n const base = curveIndex.mul(CURVE_RESOLUTION);\n const v0 = sCurveData.element(base.add(idx0));\n const v1 = sCurveData.element(base.add(tslMin(idx0.add(1.0), float(CURVE_RESOLUTION - 1))));\n return mix(v0, v1, f);\n });\n}\n\n// ??? Kernel builder ????????????????????????????????????????????????????????\n/**\n * Builds two compute kernels sharing the same buffers: a small \"emission\" pass\n * (count = per-frame `emitCount`) and a full \"simulation\" pass (count =\n * `maxParticles`). The emission pass is 1-based sized at creation and its\n * `ComputeNode.count` is refreshed from `emitCount` every frame, which also\n * regenerates the shader-side `instanceIndex >= count` bound guard.\n *\n * Both kernels address the same `uint` atomic allocator stack with\n * `atomicSub` / `atomicAdd` / `atomicLoad` / `atomicStore`, so a slot returned\n * by the sim kernel's death handling is immediately available to the emission\n * kernel on the next frame.\n */\n/** Fully-resolved scalar node set consumed by {@link shapeEmitNodes}. */\ntype ShapeNodeUniforms = {\n kind: ShaderNodeObject<Node>;\n radius: ShaderNodeObject<Node>;\n thickness: ShaderNodeObject<Node>;\n arcDeg: ShaderNodeObject<Node>;\n coneAngleDeg: ShaderNodeObject<Node>;\n rectRX: ShaderNodeObject<Node>;\n rectRY: ShaderNodeObject<Node>;\n rectSX: ShaderNodeObject<Node>;\n rectSY: ShaderNodeObject<Node>;\n boxSX: ShaderNodeObject<Node>;\n boxSY: ShaderNodeObject<Node>;\n boxSZ: ShaderNodeObject<Node>;\n boxFrom: ShaderNodeObject<Node>;\n speedMin: ShaderNodeObject<Node>;\n speedMax: ShaderNodeObject<Node>;\n};\n\n/**\n * Oracle-faithful shape emission in the emitter's LOCAL frame for all 5 kinds\n * (0 SPHERE | 1 CONE | 2 CIRCLE | 3 RECTANGLE | 4 BOX), ported formula-by-\n * formula from the CPU helpers in `three-particles-utils.ts`.\n *\n * `rA` / `rB` / `rC` are three independent 0..1 randoms and `rSpeed` the speed\n * random; the returned components are still unrotated (the caller applies the\n * wrapper quaternion). Shared by the emission kernel and the sub-emitter init\n * kernel so both use identical shape math.\n */\nfunction shapeEmitNodes(\n u: ShapeNodeUniforms,\n rA: ShaderNodeObject<Node>,\n rB: ShaderNodeObject<Node>,\n rC: ShaderNodeObject<Node>,\n rSpeed: ShaderNodeObject<Node>\n): {\n px: ShaderNodeObject<Node>;\n py: ShaderNodeObject<Node>;\n pz: ShaderNodeObject<Node>;\n vx: ShaderNodeObject<Node>;\n vy: ShaderNodeObject<Node>;\n vz: ShaderNodeObject<Node>;\n} {\n // Arc / cone angle are degrees; PI/180 = 0.01745329.\n const DEG = float(0.01745329);\n const uRadius = u.radius;\n const uRadiusThickness = u.thickness;\n\n // SPHERE: theta = 2*PI*u, phi = acos(2v-1), dir*sphereDistance.\n const thetaS = rA.mul(u.arcDeg).mul(DEG);\n const cosPhi = rB.mul(float(2.0)).sub(float(1.0));\n const sinPhi = sqrt(float(1.0).sub(cosPhi.mul(cosPhi)));\n const dirSx = sinPhi.mul(cos(thetaS));\n const dirSy = sinPhi.mul(sin(thetaS));\n const dirSz = cosPhi;\n const distS = uRadius\n .mul(float(1.0).sub(uRadiusThickness))\n .add(uRadius.mul(uRadiusThickness).mul(rC));\n const pSx = dirSx.mul(distS);\n const pSy = dirSy.mul(distS);\n const pSz = dirSz.mul(distS);\n // vel = position * (1/|position|) * speed = dir * speed.\n const spS = mix(u.speedMin, u.speedMax, rSpeed);\n const vSx = dirSx.mul(spS);\n const vSy = dirSy.mul(spS);\n const vSz = dirSz.mul(spS);\n\n // CONE + CIRCLE share the base-disc position (same oracle math).\n const thetaB = rA.mul(u.arcDeg).mul(DEG);\n const dirBx = cos(thetaB);\n const dirBy = sin(thetaB);\n const distB = uRadius\n .mul(float(1.0).sub(uRadiusThickness))\n .add(uRadius.mul(uRadiusThickness).mul(rB));\n const pBx = dirBx.mul(distB);\n const pBy = dirBy.mul(distB);\n const pBz = float(0.0);\n // CONE velocity: spread by the opening angle, |dist|/radius * angle(rad).\n const nAngle = distB\n .div(uRadius.max(float(1e-6)))\n .mul(u.coneAngleDeg.mul(DEG));\n const spB = mix(u.speedMin, u.speedMax, rSpeed);\n const sinNA = sin(nAngle);\n const vCx = dirBx.mul(sinNA).mul(spB);\n const vCy = dirBy.mul(sinNA).mul(spB);\n const vCz = cos(nAngle).mul(spB);\n // CIRCLE velocity: radial in XY, no Z.\n const vIx = dirBx.mul(spB);\n const vIy = dirBy.mul(spB);\n const vIz = float(0.0);\n\n // RECTANGLE: uniform XY inside scale, tilted by the local rotation.\n const rxOff = rA.mul(u.rectSX).sub(u.rectSX.mul(float(0.5)));\n const ryOff = rB.mul(u.rectSY).sub(u.rectSY.mul(float(0.5)));\n const rotXr = u.rectRX.mul(DEG);\n const rotYr = u.rectRY.mul(DEG);\n const pRx = rxOff.mul(cos(rotYr));\n const pRy = ryOff.mul(cos(rotXr));\n const pRz = rxOff.mul(sin(rotYr)).sub(ryOff.mul(sin(rotXr)));\n\n // BOX: VOLUME / SHELL / EDGE on the +-scale/2 lattice.\n const halfX = u.boxSX.mul(float(0.5));\n const halfY = u.boxSY.mul(float(0.5));\n const halfZ = u.boxSZ.mul(float(0.5));\n const pVx = rA.mul(u.boxSX).sub(halfX);\n const pVy = rB.mul(u.boxSY).sub(halfY);\n const pVz = rC.mul(u.boxSZ).sub(halfZ);\n const side = floor(rA.mul(float(6.0))).min(float(5.0));\n const pa = side.sub(floor(side.div(float(3.0))).mul(float(3.0)));\n const a0 = side.greaterThan(float(2.0)).select(float(1.0), float(0.0));\n const isPa0 = pa.equal(float(0.0));\n const isPa1 = pa.equal(float(1.0));\n // SHELL lattice coordinates (a0 on `pa`, rB / rC on the other two axes).\n const shX = isPa0.select(a0, isPa1.select(rC, rB));\n const shY = isPa0.select(rB, isPa1.select(a0, rC));\n const shZ = isPa0.select(rC, isPa1.select(rB, a0));\n const pShx = shX.mul(u.boxSX).sub(halfX);\n const pShy = shY.mul(u.boxSY).sub(halfY);\n const pShz = shZ.mul(u.boxSZ).sub(halfZ);\n // EDGE lattice: one axis pinned, one of four edges, one free coordinate.\n const edge = floor(rB.mul(float(4.0))).min(float(3.0));\n const lowEdge = edge.lessThan(float(2.0));\n const e1 = lowEdge.select(rC, edge.sub(float(2.0)));\n const e2 = lowEdge.select(edge, rC);\n const edX = isPa0.select(a0, isPa1.select(e2, e1));\n const edY = isPa0.select(e1, isPa1.select(a0, e2));\n const edZ = isPa0.select(e2, isPa1.select(e1, a0));\n const pEdx = edX.mul(u.boxSX).sub(halfX);\n const pEdy = edY.mul(u.boxSY).sub(halfY);\n const pEdz = edZ.mul(u.boxSZ).sub(halfZ);\n const boxFrom = u.boxFrom;\n const pBX = boxFrom\n .equal(float(0.0))\n .select(pVx, boxFrom.equal(float(1.0)).select(pShx, pEdx));\n const pBY = boxFrom\n .equal(float(0.0))\n .select(pVy, boxFrom.equal(float(1.0)).select(pShy, pEdy));\n const pBZ = boxFrom\n .equal(float(0.0))\n .select(pVz, boxFrom.equal(float(1.0)).select(pShz, pEdz));\n // RECTANGLE / BOX velocities are straight local +Z at `speed`.\n const vPlaneZ = mix(u.speedMin, u.speedMax, rSpeed);\n\n // Kind dispatch: 0 SPHERE | 1 CONE | 2 CIRCLE | 3 RECTANGLE | 4 BOX.\n const kind = u.kind;\n const isSphereKind = kind.equal(float(0.0));\n const isConeKind = kind.equal(float(1.0));\n const isCircleKind = kind.equal(float(2.0));\n const isRectKind = kind.equal(float(3.0));\n const planeX = isRectKind.select(pRx, pBX);\n const planeY = isRectKind.select(pRy, pBY);\n const planeZ = isRectKind.select(pRz, pBZ);\n // CONE and CIRCLE both use the base-disc position; only RECT/BOX take the\n // planar branch (CIRCLE no longer \"falls through\" to the BOX lattice).\n const isDiscKind = isConeKind.or(isCircleKind);\n const discX = isDiscKind.select(pBx, planeX);\n const discY = isDiscKind.select(pBy, planeY);\n const discZ = isDiscKind.select(pBz, planeZ);\n const px = isSphereKind.select(pSx, discX);\n const py = isSphereKind.select(pSy, discY);\n const pz = isSphereKind.select(pSz, discZ);\n const cOrI_X = isConeKind.select(vCx, vIx);\n const cOrI_Y = isConeKind.select(vCy, vIy);\n const cOrI_Z = isConeKind.select(vCz, vIz);\n const isDisc = isConeKind.or(isCircleKind);\n const nonSphereVX = isDisc.select(cOrI_X, float(0.0));\n const nonSphereVY = isDisc.select(cOrI_Y, float(0.0));\n const nonSphereVZ = isDisc.select(cOrI_Z, vPlaneZ);\n const vx = isSphereKind.select(vSx, nonSphereVX);\n const vy = isSphereKind.select(vSy, nonSphereVY);\n const vz = isSphereKind.select(vSz, nonSphereVZ);\n\n return { px, py, pz, vx, vy, vz };\n}\n\n/**\n * Rotates a local-frame vector by a unit quaternion stored as (x, y, z, w).\n * v' = v*(2w^2-1) + 2*(q.xyz . v)*q.xyz + 2w*(q.xyz x v)\n */\nfunction quatRotateNodes(\n x: ShaderNodeObject<Node>,\n y: ShaderNodeObject<Node>,\n z: ShaderNodeObject<Node>,\n q: ShaderNodeObject<Node>\n): [ShaderNodeObject<Node>, ShaderNodeObject<Node>, ShaderNodeObject<Node>] {\n const qx = q.x;\n const qy = q.y;\n const qz = q.z;\n const qw = q.w;\n const projD = qx.mul(x).add(qy.mul(y)).add(qz.mul(z)).mul(float(2.0));\n const scaleV = qw.mul(qw).mul(float(2.0)).sub(float(1.0));\n const twoW = qw.mul(float(2.0));\n return [\n x.mul(scaleV).add(qx.mul(projD)).add(qy.mul(z).sub(qz.mul(y)).mul(twoW)),\n y.mul(scaleV).add(qy.mul(projD)).add(qz.mul(x).sub(qx.mul(z)).mul(twoW)),\n z.mul(scaleV).add(qz.mul(projD)).add(qx.mul(y).sub(qy.mul(x)).mul(twoW)),\n ];\n}\n\n/** Raw velocity-over-lifetime axis values (constant / range / curve). */\nexport type VelocityAxisValues = {\n linear: Array<\n | import('../types.js').Constant\n | import('../types.js').RandomBetweenTwoConstants\n | import('../types.js').LifetimeCurve\n | undefined\n >;\n orbital: Array<\n | import('../types.js').Constant\n | import('../types.js').RandomBetweenTwoConstants\n | import('../types.js').LifetimeCurve\n | undefined\n >;\n};\n\nexport function createModifierComputeUpdate(\n buffers: ModifierStorageBuffers,\n maxParticles: number,\n curveMap: BakedCurveMap,\n flags: ModifierFlags,\n shapeParams: ShapeEmitParams,\n forceFieldCount = 0,\n collisionPlaneCount = 0,\n subFifos: SubEmitterFifo[] = [],\n trailDesc?: TrailHistoryDesc,\n velocityValues?: VelocityAxisValues\n): ModifierComputePipeline {\n // ?? Per-frame uniforms ??\n const uDelta = uniform(float(0));\n const uDeltaMs = uniform(float(0));\n const uNowMs = uniform(float(0));\n const uGravityVelocity = uniform(new Vector3(0, 0, 0));\n // One-time system seed (§5): u32, written ONCE at pipeline creation, never\n // per frame. All birth entropy is derived from it by integer channel mixes.\n const uSystemSeed = uniform(nextSystemSeed(), 'uint');\n const uSeed = uSystemSeed;\n // Declared u32 so it matches instanceIndex exactly in the WGSL guard and in\n // If(i.lessThan(uEmitCount), ...); the CPU writes the integer count per frame.\n const uEmitCount = uniform(0, 'uint');\n const uNoiseStrength = uniform(float(0));\n const uNoisePower = uniform(float(0));\n const uNoiseFrequency = uniform(float(1));\n const uNoisePosAmount = uniform(float(0));\n const uNoiseRotAmount = uniform(float(0));\n const uNoiseSizeAmount = uniform(float(0));\n\n // ?? Shape / config scalar uniforms ??\n const shapeUniforms: Record<string, ShaderNodeObject<Node>> = {};\n const sh = (name: string, v: number) => {\n const u = uniform(float(v));\n shapeUniforms[name] = u;\n return u;\n };\n const uShape = sh('shapeKind', shapeParams.shapeKind);\n const uRadius = sh('radius', shapeParams.radius);\n const uRadiusThickness = sh('radiusThickness', shapeParams.radiusThickness);\n const uArcDeg = sh('arcDeg', shapeParams.arcDeg);\n const uConeAngleDeg = sh('coneAngleDeg', shapeParams.coneAngleDeg);\n const uRectRX = sh('rectangleRotXDeg', shapeParams.rectangleRotXDeg);\n const uRectRY = sh('rectangleRotYDeg', shapeParams.rectangleRotYDeg);\n const uRectSX = sh('rectangleScaleX', shapeParams.rectangleScaleX);\n const uRectSY = sh('rectangleScaleY', shapeParams.rectangleScaleY);\n const uBoxSX = sh('boxScaleX', shapeParams.boxScaleX);\n const uBoxSY = sh('boxScaleY', shapeParams.boxScaleY);\n const uBoxSZ = sh('boxScaleZ', shapeParams.boxScaleZ);\n const uBoxEmitFrom = sh('boxEmitFrom', shapeParams.boxEmitFrom);\n // ?? Emitter pose (written once per frame by the CPU, scalar only) ??\n // w = 1 for WORLD simulation (add translation + axis scale), 0 for LOCAL.\n const uEmitterPos = uniform(new Vector4(0, 0, 0, 0));\n // Wrapper quaternion (x, y, z, w). Identity in LOCAL space, emitter world\n // rotation in WORLD space ? mirrors generalData.wrapperQuaternion.\n const uWrapperQuat = uniform(new Vector4(0, 0, 0, 1));\n // Emitter world scale, applied to the rotated shape offset in WORLD space.\n const uWorldScale = uniform(new Vector3(1, 1, 1));\n\n const uSpeedMin = sh('speedMin', shapeParams.speedMin);\n const uSpeedMax = sh('speedMax', shapeParams.speedMax);\n const uSizeMin = sh('sizeMin', shapeParams.sizeMin);\n const uSizeMax = sh('sizeMax', shapeParams.sizeMax);\n const uRotMin = sh('rotMin', shapeParams.rotMin);\n const uRotMax = sh('rotMax', shapeParams.rotMax);\n // rotationOverLifetime has its OWN range (oracle: separate\n // lifetimeValues.rotationOverLifetime, never startRotation's min/max).\n const uRotOLMin = sh('rotOverLifeMin', shapeParams.rotOverLifeMin);\n const uRotOLMax = sh('rotOverLifeMax', shapeParams.rotOverLifeMax);\n const uOpMin = sh('opacityMin', shapeParams.opacityMin);\n const uOpMax = sh('opacityMax', shapeParams.opacityMax);\n const uLifeMin = sh('lifeMin', shapeParams.lifeMin);\n const uLifeMax = sh('lifeMax', shapeParams.lifeMax);\n const uCRR = sh('colorRMin', sRGBToLinear(shapeParams.colorRMin));\n const uCRX = sh('colorRMax', sRGBToLinear(shapeParams.colorRMax));\n const uCGR = sh('colorGMin', sRGBToLinear(shapeParams.colorGMin));\n const uCGX = sh('colorGMax', sRGBToLinear(shapeParams.colorGMax));\n const uCBR = sh('colorBMin', sRGBToLinear(shapeParams.colorBMin));\n const uCBX = sh('colorBMax', sRGBToLinear(shapeParams.colorBMax));\n const uFrMin = sh('startFrameMin', shapeParams.startFrameMin);\n const uFrMax = sh('startFrameMax', shapeParams.startFrameMax);\n\n // ?? Particle-state storage nodes (bindings 1-7) ??\n const sPos = storage(buffers.position, 'vec4', maxParticles);\n const sVel = storage(buffers.velocity, 'vec4', maxParticles);\n const sCol = storage(buffers.color, 'vec4', maxParticles);\n const sPS = storage(buffers.particleState, 'vec4', maxParticles);\n const sSV = storage(buffers.startValues, 'vec4', maxParticles);\n const sEx = storage(buffers.startColorsExt, 'vec4', maxParticles);\n const sOIA = storage(buffers.orbitalIsActive, 'vec4', maxParticles);\n\n // ?? Binding 8: integer ring-allocator counter ??\n // `array<atomic<u32>, 1>` (only index 0 is live): a monotonic birth counter,\n // slot = counter mod maxParticles, so allocation can never underflow.\n // With bindings 1-7 above this completes the guaranteed WebGPU budget of\n // exactly 8 storage buffers for the base pipeline (no optional binding 9).\n const allocatorCount = maxParticles + 1;\n const ringMod = float(maxParticles);\n // u32 ring modulus (§4): birthNo and slot modulo stay native integers.\n const ringModU = tuint(maxParticles);\n const sAllocator = storage(buffers.allocator, 'uint', Math.max(1, allocatorCount)).toAtomic();\n\n // ?? Read-mostly f32 tables: uniform buffer binding, non-atomic ??\n // Baked curve samples plus optional force-field / collision-plane records.\n // A plain uniform binding: it neither consumes a storage slot nor becomes\n // `atomic<f32>`, so curve sampling stays a straight `f32` load.\n const sCD = buffer(buffers.packedData, 'float', buffers.packedData.length);\n // Curve table sampler — must be in lexical scope BEFORE `simAxis`, the\n // emission/simulation kernels and every size/opacity/color/velocity\n // lifetime-curve lookup below.\n const lookupCurve = createCurveLookup(sCD);\n\n // ?? Sub-emitter FIFO channels: integer `atomic<u32>` counters + f32 payloads ??\n // The CPU writes the window index (0/1 frame parity) into uFifoBase; each\n // channel's payload window starts at `window * 6 * capacity`.\n const uFifoBase = uniform(float(0), 'uint');\n const fifoNodes = subFifos.map((f) => ({\n trigger: f.trigger,\n capacity: Math.max(1, f.capacity),\n windowSize: subEmitterWindowSize(Math.max(1, f.capacity)),\n count: storage(\n f.counter,\n 'uint',\n Math.max(1, (f.counter.array as Uint32Array).length)\n ).toAtomic(),\n payload: storage(\n f.payload,\n 'float',\n Math.max(1, (f.payload.array as Float32Array).length)\n ),\n }));\n // Per-trigger channel views: each event pass only binds its own channels,\n // which keeps both passes at <= 8 storage bindings (see pass builders below).\n const birthFifos = fifoNodes.filter((f) => f.trigger === 0);\n const deathFifos = fifoNodes.filter((f) => f.trigger === 1);\n const hasDeathFifo = deathFifos.length > 0;\n\n const writeFifoEvent = (\n f: {\n capacity: number;\n windowSize: number;\n count: ShaderNodeObject<Node>;\n payload: ShaderNodeObject<Node>;\n },\n x: ShaderNodeObject<Node>,\n y: ShaderNodeObject<Node>,\n z: ShaderNodeObject<Node>,\n vx: ShaderNodeObject<Node>,\n vy: ShaderNodeObject<Node>,\n vz: ShaderNodeObject<Node>\n ): void => {\n // `atomicAdd` on the integer counter gives the pre-increment event index;\n // indices beyond `capacity` are the explicitly dropped events.\n const winBase = uFifoBase.mul(float(f.windowSize)).toVar();\n const oldCount = float(\n atomicAdd(f.count.element(uFifoBase), tuint(1))\n ).toVar();\n If(oldCount.lessThan(float(f.capacity)), () => {\n const b = winBase.add(oldCount.mul(float(SUB_EMITTER_EVENT_STRIDE)));\n f.payload.element(b).assign(x);\n f.payload.element(b.add(float(1.0))).assign(y);\n f.payload.element(b.add(float(2.0))).assign(z);\n f.payload.element(b.add(float(3.0))).assign(vx);\n f.payload.element(b.add(float(4.0))).assign(vy);\n f.payload.element(b.add(float(5.0))).assign(vz);\n });\n };\n\n // ?? Trail history ring: plain vec4 f32 samples + integer atomic metadata ??\n const trailRows = trailDesc ? trailDesc.length + 1 : 0;\n const sTrail: ShaderNodeObject<Node> | null = trailDesc\n ? storage(trailDesc.attribute, 'vec4', trailRows * maxParticles)\n : null;\n const sTrailMeta: ShaderNodeObject<Node> | null =\n trailDesc && buffers.trailMeta\n ? storage(buffers.trailMeta, 'uint', maxParticles * 2).toAtomic()\n : null;\n\n const curveLen = Math.max(curveMap.data.length, 1);\n\n // ?? Force-field + collision-plane TSL readers ??\n const forceFieldOffset = curveLen;\n const collisionOffset = forceFieldOffset + (flags.forceFields ? FORCE_FIELD_DATA_SIZE : 0);\n\n const ffNodes = flags.forceFields\n ? createForceFieldTSL(sCD, forceFieldOffset, forceFieldCount) : null;\n const cpNodes = flags.collisionPlanes\n ? createCollisionPlaneTSL(sCD, collisionOffset, collisionPlaneCount) : null;\n\n // Per-axis raw velocity-over-lifetime values (constant / random-range /\n // curve) — oracle parity: random ranges are sampled PER PARTICLE from the\n // stable birth seed stored in `startColorsExt.w` (no extra storage buffer).\n // Destination contract:\n // startColorsExt.x = startColorG startColorsExt.y = startColorB\n // startColorsExt.z = rotationOverLifetime speed .w = particleSeed\n type AxisSpec = {\n /** -1 = not a lifetime curve; >= 0 = baked curve table index. */\n ci: number;\n min: number;\n max: number;\n /** true when the config value is a random-between-two range. */\n isRange: boolean;\n };\n const parseAxis = (\n rawAxis:\n | import('../types.js').Constant\n | import('../types.js').RandomBetweenTwoConstants\n | import('../types.js').LifetimeCurve\n | undefined,\n curveIdx: number\n ): AxisSpec => {\n if (curveIdx >= 0) {\n return { ci: curveIdx, min: 0, max: 0, isRange: false };\n }\n if (rawAxis && typeof rawAxis === 'object' && 'min' in rawAxis && 'max' in rawAxis) {\n const mn = Number(rawAxis.min) || 0;\n const mx = Number(rawAxis.max) || 0;\n return { ci: -1, min: mn, max: mx, isRange: mn !== mx };\n }\n const c = typeof rawAxis === 'number' ? rawAxis : 0;\n return { ci: -1, min: c, max: c, isRange: false };\n };\n const vv = velocityValues ?? {\n linear: [undefined, undefined, undefined],\n orbital: [undefined, undefined, undefined],\n };\n const linAxes: AxisSpec[] = [\n parseAxis(vv.linear[0], curveMap.linearVelX),\n parseAxis(vv.linear[1], curveMap.linearVelY),\n parseAxis(vv.linear[2], curveMap.linearVelZ),\n ];\n const orbAxes: AxisSpec[] = [\n parseAxis(vv.orbital[0], curveMap.orbitalVelX),\n parseAxis(vv.orbital[1], curveMap.orbitalVelY),\n parseAxis(vv.orbital[2], curveMap.orbitalVelZ),\n ];\n const axisUniforms = new Map<\n AxisSpec,\n [ShaderNodeObject<Node>, ShaderNodeObject<Node>]\n >();\n for (const a of [...linAxes, ...orbAxes]) {\n if (a.isRange) {\n axisUniforms.set(a, [uniform(float(a.min)), uniform(float(a.max))]);\n }\n }\n // Per-particle axis value for `startColorsExt.w = particleSeed`:\n // - lifetime curve -> `lookupCurve` on the baked table\n // - random range -> `mix(min, max, rand(seed + salt))` (stable per\n // particle; only the immutable birth seed is\n // used, NEVER the changing frame seed)\n // - constant -> direct passthrough\n // Six distinct fixed salts keep the six axis streams decorrelated.\n const simAxis = (\n a: AxisSpec,\n lifePct: ShaderNodeObject<Node>,\n particleSeed: ShaderNodeObject<Node>,\n salt: ShaderNodeObject<Node>\n ): ShaderNodeObject<Node> => {\n if (a.ci >= 0) {\n return lookupCurve({\n curveIndex: float(a.ci),\n t: lifePct,\n });\n }\n\n if (a.isRange) {\n const [mn, mx] = axisUniforms.get(a)!;\n return mix(\n mn,\n mx,\n pcg01(particleSeed.toUint().mul(tuint(2654435761)).bitXor(salt))\n );\n }\n\n return float(a.min);\n };\n\n //\n // `i` = invocation index (0 .. emitCount-1). Each invocation:\n // 1) atomically pops one uint slot id off the allocator stack,\n // 2) draws 14 independent randoms from `uSeed + 16*i + k`,\n // 3) builds the shape position + velocity (5 shape kinds, oracle math),\n // 4) rotates them by the emitter wrapper quaternion,\n // 5) writes vec4 slots on pos/vel/color/particleState/startValues/ext/orbital.\n // The random noise phase offset is derived from the stable birth seed by\n // the simulation pass (`useRandomOffset` honored there, §6 of the rescue).\n const emitKernel = Fn(() => {\n const i = instanceIndex;\n // Explicit count guard: the host dispatches max(1, emitCount) invocations, so the\n // kernel itself must skip the extra one when emitCount === 0.\n If(i.lessThan(uEmitCount), () => {\n // Race-safe ring allocation (never underflows), all in u32 (§4):\n // birthNo and the slot modulo use the native integer `%`.\n const birthNo = atomicAdd(sAllocator.element(0), tuint(1)).toVar();\n const slotIdx = birthNo.mod(ringModU).toVar();\n // Independent random channels: mix(birthNo, systemSeed, channelId) in\n // u32, PCG once per channel, single f32 conversion at the end.\n const rcA = randomChannel(birthNo, uSystemSeed, CH.SHAPE_A);\n const rcB = randomChannel(birthNo, uSystemSeed, CH.SHAPE_B);\n const rcC = randomChannel(birthNo, uSystemSeed, CH.SHAPE_C);\n const rcSpeed = randomChannel(birthNo, uSystemSeed, CH.SPEED);\n const rcSize = randomChannel(birthNo, uSystemSeed, CH.SIZE);\n const rcRot = randomChannel(birthNo, uSystemSeed, CH.ROTATION);\n const rcOpacity = randomChannel(birthNo, uSystemSeed, CH.OPACITY);\n // (shape kind A/B/C + speed, then sheet/size/rot/opacity/life/color/rotol)\n const rcSheet = randomChannel(birthNo, uSystemSeed, CH.START_FRAME);\n const rcLife = randomChannel(birthNo, uSystemSeed, CH.LIFETIME);\n const rcColor = randomChannel(birthNo, uSystemSeed, CH.COLOR);\n const rcRotOl = randomChannel(birthNo, uSystemSeed, CH.ROTOL);\n\n // ?? Shape emission (all 5 kinds, oracle math) in the emitter's local frame.\n const shE = shapeEmitNodes(\n {\n kind: uShape,\n radius: uRadius,\n thickness: uRadiusThickness,\n arcDeg: uArcDeg,\n coneAngleDeg: uConeAngleDeg,\n rectRX: uRectRX,\n rectRY: uRectRY,\n rectSX: uRectSX,\n rectSY: uRectSY,\n boxSX: uBoxSX,\n boxSY: uBoxSY,\n boxSZ: uBoxSZ,\n boxFrom: uBoxEmitFrom,\n speedMin: uSpeedMin,\n speedMax: uSpeedMax,\n },\n rcA,\n rcB,\n rcC,\n rcSpeed\n );\n const pxL = shE.px;\n const pyL = shE.py;\n const pzL = shE.pz;\n const vxL = shE.vx;\n const vyL = shE.vy;\n const vzL = shE.vz;\n\n // ?? Emitter pose: rotate by the wrapper quaternion, then (WORLD only)\n // apply the per-axis world scale and add the emitter translation.\n const [rotPX, rotPY, rotPZ] = quatRotateNodes(pxL, pyL, pzL, uWrapperQuat);\n const [rotVX, rotVY, rotVZ] = quatRotateNodes(vxL, vyL, vzL, uWrapperQuat);\n\n // LOCAL (w = 0): identity quaternion, no translation, no extra scale\n // (three applies matrixWorld at draw time). WORLD (w = 1): per-axis world\n // scale on the rotated offset, plus the emitter translation.\n const isWorld = uEmitterPos.w.greaterThan(0.5);\n const sxf = isWorld.select(uWorldScale.x, float(1.0));\n const syf = isWorld.select(uWorldScale.y, float(1.0));\n const szf = isWorld.select(uWorldScale.z, float(1.0));\n const ox = rotPX.mul(sxf).add(uEmitterPos.x);\n const oy = rotPY.mul(syf).add(uEmitterPos.y);\n const oz = rotPZ.mul(szf).add(uEmitterPos.z);\n\n // Start values (dedicated channels so no field aliases another).\n const opac = mix(uOpMin, uOpMax, rcOpacity);\n const clR = mix(uCRR, uCRX, rcColor);\n const clG = mix(uCGR, uCGX, rcColor);\n const clB = mix(uCBR, uCBX, rcColor);\n const slife = mix(uLifeMin, uLifeMax, rcLife).mul(float(1000.0));\n const ssize = mix(uSizeMin, uSizeMax, rcSize);\n const srot = mix(uRotMin, uRotMax, rcRot);\n const startFrame = floor(mix(uFrMin, uFrMax, rcSheet)).toVar();\n // Separate per-particle rotationOverLifetime speed (oracle keeps its own\n // min/max, distinct from startRotation's rotMin/rotMax).\n const rotSpeed = mix(uRotOLMin, uRotOLMax, rcRotOl);\n // 24-bit stable per-particle seed (§8): created ONCE at birth via the\n // RAW PCG mix (& 0xFFFFFF is exact in f32) and immutable for the whole\n // lifetime. sim derives every non-curve axis + noise phase from it.\n const stableSeedU = stableSeedU32(birthNo, uSystemSeed);\n\n sPos.element(slotIdx).assign(vec4(ox, oy, oz, float(0.0)));\n sVel.element(slotIdx).assign(vec4(rotVX, rotVY, rotVZ, float(0.0)));\n sCol.element(slotIdx).assign(vec4(clR, clG, clB, opac));\n // lifetime=0, size, rotation, startFrame\n sPS.element(slotIdx).assign(vec4(float(0.0), ssize, srot, startFrame));\n // startValues = (startLife, size, opacity, colorR)\n sSV.element(slotIdx).assign(vec4(slife, ssize, opac, clR));\n // ext = (colorG, colorB, rotSpeed, stableSeed 0..0xFFFFFF)\n sEx.element(slotIdx).assign(\n vec4(clG, clB, rotSpeed, stableSeedU.toFloat())\n );\n // Orbital pivot = rotated shape offset (oracle positionOffset), w=1.\n sOIA.element(slotIdx).assign(vec4(rotPX, rotPY, rotPZ, float(1.0)));\n\n // BIRTH events: written by the dedicated `sub-birth-events` pass below\n // (base emit keeps exactly its 8 storage bindings — no FIFO nodes here).\n });\n });\n\n const emitNode = compute(emitKernel(), maxParticles);\n\n // Simulation kernel — physics + modifier order mirrors the oracle CPU\n // `updateParticleSystems` inner loop exactly:\n // gravity -> force fields -> integrate -> collisions -> modifiers ->\n // lifetime += dt -> trail sample -> write back -> death.\n const noiseOctavesCount = Math.max(1, Math.round(shapeParams.noiseOctaves || 1));\n // three-noise FBm divides the accumulated octaves by\n // `max = 1 + 0.5 + ... + 0.5^octaves = 2 - 2^-octaves` (the sum includes\n // the trailing 0.5^n exactly like the oracle's `fbmMax` constant).\n const noiseFbmMax = 2 - Math.pow(2, -noiseOctavesCount);\n if (!Number.isFinite(noiseFbmMax) || noiseFbmMax <= 0) {\n throw new Error(\n `three-particles: invalid FBM normalization ${noiseFbmMax}`\n );\n }\n const simKernel = Fn(() => {\n const i = instanceIndex;\n If(float(i).lessThan(float(maxParticles)), () => {\n const oiaVec = sOIA.element(i).toVar();\n If(oiaVec.w.greaterThanEqual(float(0.5)), () => {\n const pos = sPos.element(i).xyz.toVar();\n const vel = sVel.element(i).xyz.toVar();\n const ps = sPS.element(i).toVar();\n const sv = sSV.element(i);\n const ex = sEx.element(i);\n const startLife = sv.x;\n const life = ps.x;\n const lifePct = tslMin(life.div(startLife), float(1.0));\n\n // 1. Gravity\n vel.assign(vel.sub(vec3(uGravityVelocity).mul(uDelta)));\n\n // 2. Force fields\n if (ffNodes) ffNodes.apply({ pos, vel, delta: uDelta });\n\n // 3. Integrate\n pos.assign(pos.add(vel.mul(uDelta)));\n\n // 4. Collisions\n if (cpNodes) cpNodes.apply({\n pos, vel, oiaVec,\n sColorNode: sCol, ps, startLife,\n particleIdx: i, sOrbitalIsActiveNode: sOIA,\n });\n\n // 5. Modifiers — oracle semantics.\n // 5a. Linear velocity over lifetime: per-axis value is either the\n // baked curve table (`lookupCurve`) or derived from the immutable\n // birth seed in `startColorsExt.w` (constant direct, range via a\n // fixed salt). position.w / velocity.w are plain padding 0.\n if (flags.linearVelocity) {\n const lvx = simAxis(linAxes[0], lifePct, stableSeedFromExt(ex.w), CH.LIN_X);\n const lvy = simAxis(linAxes[1], lifePct, stableSeedFromExt(ex.w), CH.LIN_Y);\n const lvz = simAxis(linAxes[2], lifePct, stableSeedFromExt(ex.w), CH.LIN_Z);\n pos.assign(pos.add(vec3(lvx, lvy, lvz).mul(uDelta)));\n }\n if (flags.orbitalVelocity) {\n // Pivot + offset mirror the oracle `positionOffset`: subtract it,\n // rotate the offset by the Euler, add it back (offset mutation is\n // stored in oia.xyz). Axis speeds derive from the birth seed.\n const offset = vec3(oiaVec.x, oiaVec.y, oiaVec.z).toVar();\n pos.assign(pos.sub(offset));\n const oX = simAxis(orbAxes[0], lifePct, stableSeedFromExt(ex.w), CH.ORB_X);\n const oY = simAxis(orbAxes[1], lifePct, stableSeedFromExt(ex.w), CH.ORB_Y);\n const oZ = simAxis(orbAxes[2], lifePct, stableSeedFromExt(ex.w), CH.ORB_Z);\n // Oracle: Euler(speedX*dt, speedZ*dt, speedY*dt) with order 'XYZ' —\n // intrinsic XYZ. Its matrix is Rx·Ry·Rz, so the vector product\n // applies Z FIRST, then Y, then X (extrinsic Z→Y→X). Keep the\n // per-axis mapping: Euler.x = oX, Euler.y = oZ, Euler.z = oY.\n const angX = oX.mul(uDelta);\n const angY = oZ.mul(uDelta);\n const angZ = oY.mul(uDelta);\n const c3 = cos(angZ), s3 = sin(angZ);\n const zx = offset.x.mul(c3).sub(offset.y.mul(s3));\n const zy = offset.x.mul(s3).add(offset.y.mul(c3));\n const zz = offset.z;\n const c2 = cos(angY), s2 = sin(angY);\n const yx = zx.mul(c2).add(zz.mul(s2));\n const yz = zx.mul(s2).negate().add(zz.mul(c2));\n const yy = zy;\n const c1 = cos(angX), s1 = sin(angX);\n const fx = yx;\n const fy = yy.mul(c1).sub(yz.mul(s1));\n const fz = yy.mul(s1).add(yz.mul(c1));\n pos.assign(pos.add(vec3(fx, fy, fz)));\n oiaVec.assign(vec4(fx, fy, fz, oiaVec.w));\n }\n // 5b. Size / opacity / color over lifetime — start value * multiplier.\n if (flags.sizeOverLifetime) {\n const s = lookupCurve({ curveIndex: float(curveMap.sizeOverLifetime), t: lifePct });\n ps.y.assign(s.mul(sv.y));\n }\n if (flags.opacityOverLifetime) {\n const op = lookupCurve({ curveIndex: float(curveMap.opacityOverLifetime), t: lifePct });\n const col = sCol.element(i).toVar();\n col.w.assign(op.mul(sv.z));\n sCol.element(i).assign(col);\n }\n if (flags.colorOverLifetime) {\n // Oracle: final = startChannel * curveMultiplier (NO mix\n // interpolation against the current color).\n const col = sCol.element(i).toVar();\n const sce = sEx.element(i);\n if (curveMap.colorR >= 0) {\n col.x.assign(sv.w.mul(lookupCurve({ curveIndex: float(curveMap.colorR), t: lifePct })));\n }\n if (curveMap.colorG >= 0) {\n col.y.assign(sce.x.mul(lookupCurve({ curveIndex: float(curveMap.colorG), t: lifePct })));\n }\n if (curveMap.colorB >= 0) {\n col.z.assign(sce.y.mul(lookupCurve({ curveIndex: float(curveMap.colorB), t: lifePct })));\n }\n sCol.element(i).assign(col);\n }\n // 5c. Rotation over lifetime: speed * delta * 0.02 (oracle factor).\n if (flags.rotationOverLifetime) {\n ps.z.assign(ps.z.add(ex.z.mul(uDelta).mul(float(0.02))));\n }\n // 5d. Noise — oracle FBM on a scalar input: per-axis coordinates\n // (t,0,0) / (t,t,0) / (t,t,t); per-octave input scaling\n // t -> t*frequency*2^k with amplitude 0.5^k, divided by\n // fbmMax = 2 - 2^-octaves. uNoisePower carries the single\n // 0.15*strength (per-channel amounts applied below). Random offset\n // comes from the STABLE birth seed (never the frame seed).\n if (flags.noise) {\n const noiseOffset = shapeParams.noiseUseRandomOffset\n ? pcg01(\n stableSeedFromExt(ex.w)\n .toUint()\n .mul(tuint(2654435761))\n .bitXor(CH.NOISE_PHASE)\n ).mul(float(100.0))\n : float(0.0);\n const np = lifePct\n .add(noiseOffset)\n .mul(float(10.0))\n .mul(uNoiseStrength)\n .mul(uNoiseFrequency);\n let noiseX = float(0.0).toVar();\n let noiseY = float(0.0).toVar();\n let noiseZ = float(0.0).toVar();\n let amp = 1.0;\n let lac = 1.0;\n for (let o = 0; o < noiseOctavesCount; o++) {\n const t = np.mul(float(lac));\n const sc = float(amp / noiseFbmMax);\n noiseX.assign(noiseX.add(snoise3D({ v: vec3(t, float(0), float(0)) }).mul(sc)));\n noiseY.assign(noiseY.add(snoise3D({ v: vec3(t, t, float(0)) }).mul(sc)));\n noiseZ.assign(noiseZ.add(snoise3D({ v: vec3(t, t, t) }).mul(sc)));\n amp *= 0.5;\n lac *= 2.0;\n }\n If(uNoisePosAmount.greaterThan(float(0.001)), () => {\n pos.assign(\n pos.add(vec3(noiseX, noiseY, noiseZ).mul(uNoisePower).mul(uNoisePosAmount))\n );\n });\n If(uNoiseRotAmount.greaterThan(float(0.001)), () => {\n ps.z.assign(ps.z.add(noiseX.mul(uNoisePower).mul(uNoiseRotAmount)));\n });\n If(uNoiseSizeAmount.greaterThan(float(0.001)), () => {\n ps.y.assign(ps.y.add(noiseX.mul(uNoisePower).mul(uNoiseSizeAmount)));\n });\n }\n\n ps.x.assign(ps.x.add(uDeltaMs));\n\n // Trail history is sampled by the dedicated `trail-history` pass\n // (see `trailHistoryNode` below), keeping this kernel at 8 bindings.\n\n // Position/velocity vec4 padding stays plain 0 (axes are seed-derived).\n sPos.element(i).assign(vec4(pos, float(0.0)));\n sVel.element(i).assign(vec4(vel, float(0.0)));\n sPS.element(i).assign(ps);\n sOIA.element(i).assign(oiaVec);\n\n // Death: ring allocator needs no push (the monotonically increasing\n // birth counter owns recycling); mark the slot inactive + zero color.\n // With DEATH-trigger sub-emitters the transient marker is -1; the\n // dedicated `sub-death-events` pass writes the FIFO then clears to 0.\n If(ps.x.greaterThan(startLife), () => {\n const inactive = sOIA.element(i).toVar();\n sOIA.element(i).assign(\n vec4(\n inactive.x,\n inactive.y,\n inactive.z,\n hasDeathFifo ? float(-1.0) : float(0.0)\n )\n );\n sCol.element(i).assign(vec4(float(0.0), float(0.0), float(0.0), float(0.0)));\n });\n });\n });\n });\n\n const simNode = compute(simKernel(), maxParticles);\n\n // ?? Dedicated trail-history pass (runs AFTER `simulate`) ??\n // Bindings: position, orbitalIsActive, trailHistory, trailMeta (= 4 <= 8).\n // Same adaptive ring sampling the inlined sim block used; reads the\n // post-simulation position straight back from the position pool.\n let trailHistoryNode: ReturnType<typeof compute> | null = null;\n if (sTrail && sTrailMeta && trailDesc) {\n const trailHistoryKernel = Fn(() => {\n const i = instanceIndex;\n If(float(i).lessThan(float(maxParticles)), () => {\n const oiaVec = sOIA.element(i).toVar();\n // active (1) or death-pending (-1, event pass not yet run) => sample.\n const activeNow = oiaVec.w.greaterThanEqual(float(0.5));\n const pendingDeath = oiaVec.w.lessThan(float(-0.5));\n If(activeNow.or(pendingDeath), () => {\n const pos = sPos.element(i).toVar();\n const L = float(trailDesc.length);\n const tr = float(trailRows);\n const curIdx = i.mul(tuint(2));\n const cursor = float(atomicLoad(sTrailMeta.element(curIdx))).toVar();\n const count = float(\n atomicLoad(sTrailMeta.element(curIdx.add(tuint(1))))\n ).toVar();\n const baseI = i.mul(float(trailRows));\n const prev = sTrail.element(baseI.add(cursor)).toVar();\n const ddx = pos.x.sub(prev.x);\n const ddy = pos.y.sub(prev.y);\n const ddz = pos.z.sub(prev.z);\n const dist = sqrt(\n ddx.mul(ddx).add(ddy.mul(ddy)).add(ddz.mul(ddz))\n );\n const firstSample = count.lessThan(float(0.5));\n const farEnough = dist.greaterThanEqual(\n float(Math.max(1e-6, trailDesc.minVertexDistance))\n );\n If(firstSample.or(farEnough), () => {\n // cursor indexes the LAST written sample; 0..L-1, wrapping.\n const newCursor = cursor\n .greaterThanEqual(L.sub(float(1)))\n .select(float(0), cursor.add(float(1)));\n sTrail.element(baseI.add(newCursor)).assign(\n vec4(pos.x, pos.y, pos.z, uNowMs)\n );\n atomicStore(\n sTrailMeta.element(curIdx),\n newCursor.toUint()\n );\n atomicStore(\n sTrailMeta.element(curIdx.add(tuint(1))),\n tslMin(count.add(float(1)), float(trailDesc.length)).toUint()\n );\n });\n });\n });\n });\n trailHistoryNode = compute(trailHistoryKernel(), maxParticles);\n }\n\n // ?? Dedicated sub-emitter event passes (never bound into base emit/sim) ??\n // BIRTH: born slots are recovered from the monotonic allocator counter\n // (counterAfter - emitCount + i, mod maxParticles); position/velocity are\n // read back from the parent pools the emit kernel just wrote.\n let subBirthEventsNode: ReturnType<typeof compute> | null = null;\n if (birthFifos.length > 0) {\n const subBirthKernel = Fn(() => {\n const i = instanceIndex;\n If(i.lessThan(uEmitCount), () => {\n const counterAfter = atomicLoad(sAllocator.element(0)).toVar();\n const birthNo = counterAfter.sub(uEmitCount).add(i).toVar();\n const slot = birthNo.mod(ringModU).toVar();\n const p = sPos.element(slot).toVar();\n const v = sVel.element(slot).toVar();\n for (const f of birthFifos) {\n writeFifoEvent(f, p.x, p.y, p.z, v.x, v.y, v.z);\n }\n });\n });\n subBirthEventsNode = compute(subBirthKernel(), maxParticles);\n }\n\n // DEATH: the sim kernel marks `orbitalIsActive.w = -1` for slots that died\n // this step; this pass appends the events, then clears the marker to 0.\n let subDeathEventsNode: ReturnType<typeof compute> | null = null;\n if (deathFifos.length > 0) {\n const subDeathKernel = Fn(() => {\n const i = instanceIndex;\n If(float(i).lessThan(float(maxParticles)), () => {\n const oiaVec = sOIA.element(i).toVar();\n If(oiaVec.w.equal(float(-1.0)), () => {\n const p = sPos.element(i).toVar();\n const v = sVel.element(i).toVar();\n for (const f of deathFifos) {\n writeFifoEvent(f, p.x, p.y, p.z, v.x, v.y, v.z);\n }\n sOIA.element(i).assign(\n vec4(oiaVec.x, oiaVec.y, oiaVec.z, float(0.0))\n );\n });\n });\n });\n subDeathEventsNode = compute(subDeathKernel(), maxParticles);\n }\n\n // ?? Real per-pass layouts (derived from each pass's actual resources) ??\n const layout = (\n name: string,\n storageNodes: Array<ShaderNodeObject<Node> | null>,\n uniformNodes: Array<ShaderNodeObject<Node> | null>\n ): PassLayout => ({\n name,\n storageBindings: new Set(storageNodes.filter((n) => n != null)).size,\n uniformBindings: new Set(uniformNodes.filter((n) => n != null)).size,\n });\n const basePool = [sPos, sVel, sCol, sPS, sSV, sEx, sOIA, sAllocator];\n const emitUniforms: Array<ShaderNodeObject<Node>> = [\n uEmitCount,\n uSeed,\n uShape,\n uRadius,\n uRadiusThickness,\n uArcDeg,\n uConeAngleDeg,\n uRectRX,\n uRectRY,\n uRectSX,\n uRectSY,\n uBoxSX,\n uBoxSY,\n uBoxSZ,\n uBoxEmitFrom,\n uSpeedMin,\n uSpeedMax,\n uSizeMin,\n uSizeMax,\n uRotMin,\n uRotMax,\n uOpMin,\n uOpMax,\n uLifeMin,\n uLifeMax,\n uCRR,\n uCRX,\n uCGR,\n uCGX,\n uCBR,\n uCBX,\n uFrMin,\n uFrMax,\n uRotOLMin,\n uRotOLMax,\n uWrapperQuat,\n uEmitterPos,\n uWorldScale,\n ];\n const simUniforms: Array<ShaderNodeObject<Node>> = [\n uDelta,\n uDeltaMs,\n uGravityVelocity,\n uNoiseStrength,\n uNoisePower,\n uNoiseFrequency,\n uNoisePosAmount,\n uNoiseRotAmount,\n uNoiseSizeAmount,\n sCD as ShaderNodeObject<Node>,\n ...Array.from(axisUniforms.values()).flat(),\n ];\n const passLayouts: PassLayout[] = [\n layout('emit', basePool, emitUniforms),\n layout('simulate', basePool, simUniforms),\n ];\n if (trailHistoryNode) {\n passLayouts.push(\n layout('trail-history', [sPos, sOIA, sTrail, sTrailMeta], [uNowMs])\n );\n }\n if (subBirthEventsNode) {\n passLayouts.push(\n layout(\n 'sub-birth-events',\n [\n sAllocator,\n sPos,\n sVel,\n ...birthFifos.flatMap((f) => [f.count, f.payload]),\n ],\n [uEmitCount, uFifoBase]\n )\n );\n }\n if (subDeathEventsNode) {\n passLayouts.push(\n layout(\n 'sub-death-events',\n [\n sPos,\n sVel,\n sOIA,\n ...deathFifos.flatMap((f) => [f.count, f.payload]),\n ],\n [uFifoBase]\n )\n );\n }\n\n return {\n emitNode,\n simNode,\n trailHistoryNode,\n subBirthEventsNode,\n subDeathEventsNode,\n computeNodes: [\n emitNode,\n ...(subBirthEventsNode ? [subBirthEventsNode] : []),\n simNode,\n ...(subDeathEventsNode ? [subDeathEventsNode] : []),\n ...(trailHistoryNode ? [trailHistoryNode] : []),\n ],\n passLayouts,\n uniforms: {\n delta: uDelta,\n deltaMs: uDeltaMs,\n nowMs: uNowMs,\n gravityVelocity: uGravityVelocity,\n noiseStrength: uNoiseStrength,\n noisePower: uNoisePower,\n noiseFrequency: uNoiseFrequency,\n noisePositionAmount: uNoisePosAmount,\n noiseRotationAmount: uNoiseRotAmount,\n noiseSizeAmount: uNoiseSizeAmount,\n emitCount: uEmitCount,\n seed: uSeed,\n /** Ping-pong FIFO window index for this frame (0 or 1). */\n fifoBase: uFifoBase,\n },\n shapeUniforms,\n buffers,\n allocatorCount,\n packedDataNode: sCD as ShaderNodeObject<Node>,\n passNames: [\n 'emit',\n ...(subBirthEventsNode ? ['sub-birth-events'] : []),\n 'simulate',\n ...(subDeathEventsNode ? ['sub-death-events'] : []),\n ...(trailHistoryNode ? ['trail-history'] : []),\n ],\n trailMeta: buffers.trailMeta,\n // Emitter-pose uniforms, refreshed once per frame by the CPU (scalar only).\n emitterPose: {\n positionW: uEmitterPos,\n wrapperQuat: uWrapperQuat,\n worldScale: uWorldScale,\n },\n forceFieldInfo: ffNodes\n ? { offset: forceFieldOffset, countUniform: ffNodes.countUniform }\n : null,\n collisionPlaneInfo: cpNodes\n ? { offset: collisionOffset, countUniform: cpNodes.countUniform }\n : null,\n };\n}\n\n// ─── Sub-emitter init kernel ─────────────────────────────────────────────────\n\n/** Compute pipeline for one sub-emitter child pool. */\nexport type SubEmitterInitPipeline = {\n /** Pass A: FIFO -> spawn commands (+ ring slot allocation). */\n commandBuildNode: unknown;\n /** Pass B: spawn commands -> child state (8 bindings, no allocator). */\n childInitNode: unknown;\n /** 1-invocation pass that zeroes the *other* ping-pong counter. */\n counterClearNode: unknown;\n /** CPU-owned vec4 command buffer (uploaded once, kernels own it after). */\n commandBuffer: StorageBufferAttribute;\n /** Real budgets for every pass this pipeline owns. */\n passLayouts: PassLayout[];\n passName: string;\n counterClearPassName: string;\n /** Per-frame scalar uniforms. */\n uniforms: {\n seed: ShaderNodeObject<Node>;\n fifoBase: ShaderNodeObject<Node>;\n inherit: ShaderNodeObject<Node>;\n /** Emitter pose, written like the main pipeline's `emitterPose`. */\n positionW: ShaderNodeObject<Node>;\n wrapperQuat: ShaderNodeObject<Node>;\n };\n buffers: ModifierStorageBuffers;\n};\n\n/**\n * Builds the sub-emitter init kernel: reads the parent event FIFO and, per\n * event, initializes `particlesPerEvent` slots in the child pool using the\n * child's own shape math (+ the inherited speed of the parent particle).\n *\n * Slot state layout is identical to {@link createModifierComputeUpdate}; the\n * child's *simulation* pass is a normal modifier pipeline created on the same\n * buffers (its emission node is unused because every child particle is created\n * by an event).\n */\nexport function createSubEmitterInitUpdate(\n child: ModifierStorageBuffers,\n childMax: number,\n childParams: ShapeEmitParams,\n parent: ModifierStorageBuffers,\n parentMax: number,\n fifo: SubEmitterFifo,\n inheritVelocity: number,\n particlesPerEvent: number,\n childVelValues?: VelocityAxisValues\n): SubEmitterInitPipeline {\n const capacity = Math.max(1, fifo.capacity);\n const perEvent = Math.max(1, particlesPerEvent);\n const windowSize = subEmitterWindowSize(capacity);\n\n // One-time system seed for this child init pipeline (§5): u32, written ONCE.\n const uSystemSeed = uniform(nextSystemSeed(), 'uint');\n const uSeed = uSystemSeed;\n const uInherit = uniform(float(Math.max(0, inheritVelocity)));\n const uFifoBase = uniform(float(0), 'uint');\n const uWrapperQuat = uniform(new Vector4(0, 0, 0, 1));\n const uEmitterPos = uniform(new Vector4(0, 0, 0, 0));\n const uWorldScale = uniform(new Vector3(1, 1, 1));\n\n // Child shape scalars (same flat table as the main pipeline).\n const cRadius = uniform(float(childParams.radius));\n const cThickness = uniform(float(childParams.radiusThickness));\n const cArc = uniform(float(childParams.arcDeg));\n const cAngle = uniform(float(childParams.coneAngleDeg));\n const cRRX = uniform(float(childParams.rectangleRotXDeg));\n const cRRY = uniform(float(childParams.rectangleRotYDeg));\n const cRSX = uniform(float(childParams.rectangleScaleX));\n const cRSY = uniform(float(childParams.rectangleScaleY));\n const cBSX = uniform(float(childParams.boxScaleX));\n const cBSY = uniform(float(childParams.boxScaleY));\n const cBSZ = uniform(float(childParams.boxScaleZ));\n const cBF = uniform(float(childParams.boxEmitFrom));\n const cKind = uniform(float(childParams.shapeKind));\n const cSpeedMin = uniform(float(childParams.speedMin));\n const cSpeedMax = uniform(float(childParams.speedMax));\n const cSizeMin = uniform(float(childParams.sizeMin));\n const cSizeMax = uniform(float(childParams.sizeMax));\n const cRotMin = uniform(float(childParams.rotMin));\n const cRotMax = uniform(float(childParams.rotMax));\n const cOpMin = uniform(float(childParams.opacityMin));\n const cOpMax = uniform(float(childParams.opacityMax));\n const cLifeMin = uniform(float(childParams.lifeMin));\n const cLifeMax = uniform(float(childParams.lifeMax));\n const cCRR = uniform(float(sRGBToLinear(childParams.colorRMin)));\n const cCRX = uniform(float(sRGBToLinear(childParams.colorRMax)));\n const cCGR = uniform(float(sRGBToLinear(childParams.colorGMin)));\n const cCGX = uniform(float(sRGBToLinear(childParams.colorGMax)));\n const cCBR = uniform(float(sRGBToLinear(childParams.colorBMin)));\n const cCBX = uniform(float(sRGBToLinear(childParams.colorBMax)));\n const cFrMin = uniform(float(childParams.startFrameMin));\n const cFrMax = uniform(float(childParams.startFrameMax));\n\n // Child pool (bindings 1..7) + its own ring allocator (binding 8). The\n // per-particle velocity axes are seed-derived (no per-axis table buffer).\n const cPos = storage(child.position, 'vec4', childMax);\n const cVel = storage(child.velocity, 'vec4', childMax);\n const cCol = storage(child.color, 'vec4', childMax);\n const cPS = storage(child.particleState, 'vec4', childMax);\n const cSV = storage(child.startValues, 'vec4', childMax);\n const cEx = storage(child.startColorsExt, 'vec4', childMax);\n const cOIA = storage(child.orbitalIsActive, 'vec4', childMax);\n const cAlloc = storage(\n child.allocator,\n 'uint',\n Math.max(1, childMax + 1)\n ).toAtomic();\n const cRingMod = float(childMax);\n // Uint ring modulus for the integer slot modulo in Pass A (§4).\n const cRingModU = tuint(childMax);\n void parent; void parentMax; // read through the FIFO payload only\n // Compact spawn-command buffer (vec4 stream). Command `m` = the child\n // particle with flat index `m` (event i, slot jj -> m = i*perEvent + jj):\n // vec4 1+2m : (ringSlot, eventX, eventY, eventZ)\n // vec4 2+2m : (velX, velY, velZ, 0)\n // vec4 slot 0 is the header (x = live event count written by Pass A).\n const commandBuffer = new StorageBufferAttribute(\n new Float32Array(4 * (1 + capacity * perEvent)),\n 4\n );\n const fifoCounter = storage(\n fifo.counter,\n 'uint',\n Math.max(1, (fifo.counter.array as Uint32Array).length)\n ).toAtomic();\n const fifoPayload = storage(\n fifo.payload,\n 'float',\n Math.max(1, (fifo.payload.array as Float32Array).length)\n );\n const sCmd = storage(commandBuffer, 'vec4', 1 + capacity * perEvent);\n\n // Child velocity-over-lifetime axes (parity with the main emit kernel).\n const cParseAxis = (\n rawAxis:\n | import('../types.js').Constant\n | import('../types.js').RandomBetweenTwoConstants\n | undefined,\n ci: number\n ): { min: number; max: number; isRange: boolean } => {\n if (rawAxis && typeof rawAxis === 'object' && 'min' in rawAxis) {\n const mn = Number(rawAxis.min) || 0;\n const mx = Number(rawAxis.max) || 0;\n return { min: mn, max: mx, isRange: mn !== mx };\n }\n const c = typeof rawAxis === 'number' ? rawAxis : 0;\n return { min: c, max: c, isRange: false };\n };\n const cVv = childVelValues ?? {\n linear: [undefined, undefined, undefined],\n orbital: [undefined, undefined, undefined],\n };\n const cLin = [0, 1, 2].map((k) => cParseAxis(cVv.linear[k], -1));\n const cOrb = [0, 1, 2].map((k) => cParseAxis(cVv.orbital[k], -1));\n void cLin; void cOrb; // seed-derived in the child sim kernel (no axis buffer)\n\n // The *other* window's counter is cleared by a dedicated 1-invocation\n // pass so the next frame's writers start from 0 (no race with this frame).\n const otherIdx = uFifoBase.equal(float(0)).select(tuint(1), tuint(0));\n const counterClearKernel = Fn(() => {\n atomicStore(fifoCounter.element(otherIdx), tuint(0));\n });\n const counterClearNode = compute(counterClearKernel(), 1);\n\n // ?? Pass A: events -> compact spawn commands (4 storage bindings) ??\n // fifoCounter + fifoPayload + child allocator + command buffer. Allocates\n // the ring slots here so Pass B needs no allocator (8-binding budget).\n const commandBuildKernel = Fn(() => {\n const i = instanceIndex;\n const winBase = uFifoBase.mul(float(windowSize)).toVar();\n const count = float(atomicLoad(fifoCounter.element(uFifoBase))).toVar();\n If(float(i).equal(float(0)), () => {\n // Header (vec4 slot 0): x = this frame's live event count.\n sCmd.element(float(0)).assign(vec4(count, float(0), float(0), float(0)));\n });\n If(float(i).lessThan(count), () => {\n const eb = winBase.add(float(i).mul(float(SUB_EMITTER_EVENT_STRIDE)));\n const eX = fifoPayload.element(eb).toVar();\n const eY = fifoPayload.element(eb.add(float(1))).toVar();\n const eZ = fifoPayload.element(eb.add(float(2))).toVar();\n const vX = fifoPayload.element(eb.add(float(3))).toVar();\n const vY = fifoPayload.element(eb.add(float(4))).toVar();\n const vZ = fifoPayload.element(eb.add(float(5))).toVar();\n // Unrolled per-event particle loop (particlesPerEvent is a host constant).\n for (let jj = 0; jj < perEvent; jj++) {\n // Ring slot: uint modulo with the native integer `%` (§4).\n const birthNo = atomicAdd(cAlloc.element(0), tuint(1)).toVar();\n const slot = birthNo.mod(cRingModU).toVar();\n const m = float(i.mul(float(perEvent)).add(float(jj)));\n sCmd\n .element(float(1).add(m.mul(float(2))))\n .assign(vec4(slot.toFloat(), eX, eY, eZ));\n sCmd\n .element(float(2).add(m.mul(float(2))))\n .assign(vec4(vX, vY, vZ, float(0)));\n }\n });\n });\n const commandBuildNode = compute(commandBuildKernel(), capacity);\n\n // ?? Pass B: spawn commands -> child state (exactly 8 storage bindings) ??\n // command buffer + the 7 child pools; no allocator, no FIFO nodes.\n const childInitKernel = Fn(() => {\n const i = instanceIndex;\n const header = sCmd.element(float(0)).toVar();\n If(float(i).lessThan(header.x.mul(float(perEvent))), () => {\n const m = float(i);\n // uint index for the integer channel mixes (§8).\n // `i` (instanceIndex) is already 'uint' in r186 — no extra conversion.\n const mU = i;\n const c0 = sCmd.element(float(1).add(m.mul(float(2)))).toVar();\n const c1 = sCmd.element(float(2).add(m.mul(float(2)))).toVar();\n const slot = c0.x;\n const eX = c0.y;\n const eY = c0.z;\n const eZ = c0.w;\n const vX = c1.x;\n const vY = c1.y;\n const vZ = c1.z;\n\n // Oracle: startSpeed += |parentVelocity| * inheritVelocity\n const parentSpeed = sqrt(\n vX.mul(vX).add(vY.mul(vY)).add(vZ.mul(vZ))\n ).toVar();\n const spAdd = parentSpeed.mul(uInherit);\n\n {\n // Integer channel mixes per child particle `m` (flat command index):\n // one dedicated channel id + one PCG draw each (u32, uint-first).\n const rcA = pcg01(mU.mul(tuint(2654435761)).bitXor(uSystemSeed).bitXor(CH.SHAPE_A));\n const rcB = pcg01(mU.mul(tuint(2654435761)).bitXor(uSystemSeed).bitXor(CH.SHAPE_B));\n const rcC = pcg01(mU.mul(tuint(2654435761)).bitXor(uSystemSeed).bitXor(CH.SHAPE_C));\n const rcSpeed = pcg01(mU.mul(tuint(2654435761)).bitXor(uSystemSeed).bitXor(CH.SPEED));\n const rcSize = pcg01(mU.mul(tuint(2654435761)).bitXor(uSystemSeed).bitXor(CH.SIZE));\n const rcRot = pcg01(mU.mul(tuint(2654435761)).bitXor(uSystemSeed).bitXor(CH.ROTATION));\n const rcOpacity = pcg01(mU.mul(tuint(2654435761)).bitXor(uSystemSeed).bitXor(CH.OPACITY));\n const rcSheet = pcg01(mU.mul(tuint(2654435761)).bitXor(uSystemSeed).bitXor(CH.START_FRAME));\n const rcLife = pcg01(mU.mul(tuint(2654435761)).bitXor(uSystemSeed).bitXor(CH.LIFETIME));\n const rcColor = pcg01(mU.mul(tuint(2654435761)).bitXor(uSystemSeed).bitXor(CH.COLOR));\n const rcRotOl = pcg01(mU.mul(tuint(2654435761)).bitXor(uSystemSeed).bitXor(CH.ROTOL));\n\n const shE = shapeEmitNodes(\n {\n kind: cKind,\n radius: cRadius,\n thickness: cThickness,\n arcDeg: cArc,\n coneAngleDeg: cAngle,\n rectRX: cRRX,\n rectRY: cRRY,\n rectSX: cRSX,\n rectSY: cRSY,\n boxSX: cBSX,\n boxSY: cBSY,\n boxSZ: cBSZ,\n boxFrom: cBF,\n speedMin: cSpeedMin.add(spAdd),\n speedMax: cSpeedMax.add(spAdd),\n },\n rcA,\n rcB,\n rcC,\n rcSpeed\n );\n\n // Child shape offset in the child's own frame, then the same\n // emitter-pose rules as the main kernel.\n const [rx, ry, rz] = quatRotateNodes(\n shE.px,\n shE.py,\n shE.pz,\n uWrapperQuat\n );\n const [rvx, rvy, rvz] = quatRotateNodes(\n shE.vx,\n shE.vy,\n shE.vz,\n uWrapperQuat\n );\n const isWorld = uEmitterPos.w.greaterThan(0.5);\n const sxf = isWorld.select(uWorldScale.x, float(1.0));\n const syf = isWorld.select(uWorldScale.y, float(1.0));\n const szf = isWorld.select(uWorldScale.z, float(1.0));\n const px = rx.mul(sxf).add(eX);\n const py = ry.mul(syf).add(eY);\n const pz = rz.mul(szf).add(eZ);\n\n const opac = mix(cOpMin, cOpMax, rcOpacity);\n const clR = mix(cCRR, cCRX, rcColor);\n const clG = mix(cCGR, cCGX, rcColor);\n const clB = mix(cCBR, cCBX, rcColor);\n const slife = mix(cLifeMin, cLifeMax, rcLife).mul(float(1000.0));\n const ssize = mix(cSizeMin, cSizeMax, rcSize);\n const srot = mix(cRotMin, cRotMax, rcRot);\n const startFrame = floor(mix(cFrMin, cFrMax, rcSheet)).toVar();\n // Separate rotationOverLifetime speed (own min/max, oracle parity).\n const rotSpeed = mix(\n float(childParams.rotOverLifeMin),\n float(childParams.rotOverLifeMax),\n rcRotOl\n );\n\n // 24-bit stable per-child-particle seed (§8), exact in f32, stored\n // in startColorsExt.w; the child sim recovers it with `toUint()`.\n const stableSeedU = pcgRawU32(\n mixBirthSeed(mU, uSystemSeed, CH.STABLE_SEED)\n )\n .bitAnd(tuint(0x00ffffff))\n .toVar();\n\n cPos.element(slot).assign(vec4(px, py, pz, float(0.0)));\n cVel.element(slot).assign(vec4(rvx, rvy, rvz, float(0.0)));\n cCol.element(slot).assign(vec4(clR, clG, clB, opac));\n cPS.element(slot).assign(\n vec4(float(0.0), ssize, srot, startFrame)\n );\n cSV.element(slot).assign(vec4(slife, ssize, opac, clR));\n // ext = (colorG, colorB, rotSpeed, stableSeed 0..0xFFFFFF)\n cEx.element(slot).assign(\n vec4(clG, clB, rotSpeed, stableSeedU.toFloat())\n );\n // Orbital pivot = rotated child shape offset (oracle parity).\n cOIA.element(slot).assign(vec4(rx, ry, rz, float(1.0)));\n }\n });\n });\n\n const childInitNode = compute(\n childInitKernel(),\n Math.max(1, capacity * perEvent)\n );\n\n const initPassLayouts: PassLayout[] = [\n {\n name: 'sub-command-build',\n storageBindings: 4, // fifoCounter, fifoPayload, allocator, commands\n uniformBindings: 1, // uFifoBase\n },\n {\n // command buffer + the 7 child pools; NO allocator here.\n name: 'sub-child-init',\n storageBindings: 8,\n uniformBindings: 35, // seed/inherit/pose + 30 child shape scalars\n },\n {\n name: 'sub-counter-clear',\n storageBindings: 1,\n uniformBindings: 1,\n },\n ];\n\n return {\n commandBuildNode,\n childInitNode,\n counterClearNode,\n commandBuffer,\n passLayouts: initPassLayouts,\n passName: fifo.trigger === 0 ? 'sub-birth' : 'sub-death',\n counterClearPassName: 'fifo-counter-clear',\n uniforms: {\n seed: uSeed,\n fifoBase: uFifoBase,\n inherit: uInherit,\n positionW: uEmitterPos,\n wrapperQuat: uWrapperQuat,\n },\n buffers: child,\n };\n}\n\n// ─── Trail ribbon build kernel ───────────────────────────────────────────────\n\n/** Compute pipeline that expands the trail history into ribbon vertices. */\nexport type TrailRibbonPipeline = {\n ribbonNode: unknown;\n /** Real budget for the single ribbon expansion pass. */\n passLayouts: PassLayout[];\n uniforms: { nowMs: ShaderNodeObject<Node> };\n buffers: Record<string, StorageBufferAttribute>;\n};\n\n/**\n * Expands the per-particle trail history ring into the ribbon vertex streams\n * consumed by `tsl-trail-ribbon-material` (position+halfWidth, next+alpha,\n * uv+color). Slot `s` maps to the history sample `cursor - s`, so the newest\n * sample is the head (t = 0) and older samples run toward the tail (t = 1),\n * exactly like the CPU oracle. Unused slots get half-width 0.\n */\nexport function createTrailRibbonUpdate(\n desc: TrailRibbonDesc\n): TrailRibbonPipeline {\n const L = desc.length;\n const rows = L + 1;\n const vertexCount = Math.max(1, desc.maxParticles) * Math.max(1, L);\n\n const uNowMs = uniform(float(0));\n\n // Bake the along-trail curves into one read-mostly f32 table; each curve\n // occupies exactly CURVE_RESOLUTION floats, inactive curves get identity.\n const activeFns = [\n desc.curveFns.width ?? ((t: number) => t),\n desc.curveFns.opacity ?? ((t: number) => t),\n desc.curveFns.colorR ?? ((t: number) => t),\n desc.curveFns.colorG ?? ((t: number) => t),\n desc.curveFns.colorB ?? ((t: number) => t),\n ];\n const curveData = new Float32Array(activeFns.length * CURVE_RESOLUTION);\n activeFns.forEach((fn, k) => {\n curveData.set(bakeCurve(fn, CURVE_RESOLUTION), k * CURVE_RESOLUTION);\n });\n const IDX_WIDTH = 0;\n const IDX_OPACITY = 1;\n const IDX_CR = 2;\n const IDX_CG = 3;\n const IDX_CB = 4;\n\n const aPos = storage(desc.position, 'vec4', vertexCount * 2);\n const aNext = storage(desc.next, 'vec4', vertexCount * 2);\n const aUVA = storage(desc.uvColorA, 'vec4', vertexCount * 2);\n const aColB = storage(desc.colorB, 'vec4', vertexCount * 2);\n const hist = storage(desc.history, 'vec4', rows * desc.maxParticles);\n const sMeta = storage(\n desc.meta,\n 'uint',\n Math.max(1, (desc.meta.array as Uint32Array).length)\n ).toAtomic();\n const pColor = storage(desc.particleColor, 'vec4', desc.maxParticles);\n const sCD = buffer(curveData, 'float', curveData.length);\n const lookupCurve = createCurveLookup(sCD);\n\n const halfWidthBase = float(desc.width * 0.5);\n\n const kernel = Fn(() => {\n const idx = instanceIndex;\n const lf = float(L);\n const rowF = float(rows);\n const i = floor(float(idx).div(lf));\n const s = float(idx).sub(i.mul(lf));\n\n If(i.lessThan(float(desc.maxParticles)), () => {\n const base = i.mul(rowF);\n const cursor = float(\n atomicLoad(sMeta.element(i.mul(float(2))))\n ).toVar();\n const count = float(\n atomicLoad(sMeta.element(i.mul(float(2)).add(float(1))))\n ).toVar();\n\n If(count.greaterThan(float(0.5)), () => {\n // Ring sample of slot s: (cursor - s) mod L, oldest -> newest order.\n const raw = cursor.sub(s).add(lf);\n const si = raw.sub(floor(raw.div(lf)).mul(lf));\n const sample = hist.element(base.add(si)).toVar();\n const nextRaw = si.add(float(1));\n const ni = nextRaw.sub(floor(nextRaw.div(lf)).mul(lf));\n const nextSample = hist.element(base.add(ni)).toVar();\n\n // Along-trail parameter: head (newest) = 0, tail = 1.\n const t = count\n .greaterThan(float(1.5))\n .select(s.div(tslMax(count.sub(float(1)), float(1))), float(0));\n\n // Curves along the trail (baked, identity when not supplied).\n const wScale = lookupCurve({\n curveIndex: float(IDX_WIDTH),\n t,\n });\n const oScale = lookupCurve({\n curveIndex: float(IDX_OPACITY),\n t,\n });\n const cr = lookupCurve({ curveIndex: float(IDX_CR), t });\n const cg = lookupCurve({ curveIndex: float(IDX_CG), t });\n const cb = lookupCurve({ curveIndex: float(IDX_CB), t });\n\n // Particle colour (RGBA, already modifier-shaped) modulated by the\n // along-trail colour curves; the current particle is slot `i`.\n const pcol = pColor.element(i).toVar();\n\n // Age expiry (trail.maxTime) and unused-slot masking.\n const inRange = s.lessThan(count);\n const ageOk = desc.maxTime > 0\n ? uNowMs.sub(sample.w).lessThanEqual(float(desc.maxTime))\n : inRange;\n const alive = inRange.and(ageOk);\n const hw = alive.select(halfWidthBase.mul(wScale), float(0));\n const alpha = alive.select(oScale.mul(pcol.w), float(0));\n\n const nPos = count\n .greaterThan(float(1.5))\n .select(nextSample.xyz, sample.xyz);\n\n // Two vertices per slot: side 0 (uv.x = 0) and side 1 (uv.x = 1).\n for (let side = 0; side < 2; side++) {\n const vi = float(idx).mul(float(2)).add(float(side));\n aPos.element(vi).assign(\n vec4(sample.x, sample.y, sample.z, hw)\n );\n aNext.element(vi).assign(\n vec4(nPos.x, nPos.y, nPos.z, alpha)\n );\n aUVA.element(vi).assign(\n vec4(float(side), t, cr.mul(pcol.x), cg.mul(pcol.y))\n );\n aColB.element(vi).assign(\n vec4(cb.mul(pcol.z), alpha, float(0), float(0))\n );\n }\n });\n });\n });\n\n const ribbonNode = compute(kernel(), vertexCount);\n\n return {\n ribbonNode,\n // 4 ribbon streams + history + meta + particle color = 7 storage bindings.\n passLayouts: [\n { name: 'trail-ribbon', storageBindings: 7, uniformBindings: 2 },\n ],\n uniforms: { nowMs: uNowMs },\n buffers: {\n position: desc.position,\n next: desc.next,\n uvColorA: desc.uvColorA,\n colorB: desc.colorB,\n history: desc.history,\n },\n };\n}\n\n\n","/**\n * Interleaved scalar buffer layout constants.\n *\n * All per-particle float attributes (except position and quat) are packed\n * into a single InterleavedBuffer to stay within the WebGPU vertex buffer\n * limit of 8.\n *\n * Buffer layout per particle (stride = 10 floats):\n * ```\n * [isActive, lifetime, startLifetime, startFrame, size, rotation, colorR, colorG, colorB, colorA]\n * ```\n */\n\n/** Number of float32 elements per particle in the interleaved scalar buffer. */\nexport const SCALAR_STRIDE = 10;\n\n/** Offset for the isActive flag (0 = inactive, 1 = active). */\nexport const S_IS_ACTIVE = 0;\n\n/** Offset for the current lifetime of the particle in milliseconds. */\nexport const S_LIFETIME = 1;\n\n/** Offset for the total lifetime of the particle in milliseconds. */\nexport const S_START_LIFETIME = 2;\n\n/** Offset for the texture sheet animation start frame index. */\nexport const S_START_FRAME = 3;\n\n/** Offset for the particle size. */\nexport const S_SIZE = 4;\n\n/** Offset for the particle rotation (radians). */\nexport const S_ROTATION = 5;\n\n/** Offset for the red color channel (0..1). */\nexport const S_COLOR_R = 6;\n\n/** Offset for the green color channel (0..1). */\nexport const S_COLOR_G = 7;\n\n/** Offset for the blue color channel (0..1). */\nexport const S_COLOR_B = 8;\n\n/** Offset for the alpha (opacity) channel (0..1). */\nexport const S_COLOR_A = 9;\n\n// ─── Shared rendering constants ─────────────────────────────────────────────\n\n/** Scale factor converting particle size to pixel-equivalent point size. */\nexport const POINT_SIZE_SCALE = 100.0;\n\n/** Minimum alpha below which fragments are discarded. */\nexport const ALPHA_DISCARD_THRESHOLD = 0.001;\n","/**\n * Shared TSL helper nodes used by multiple particle renderer materials.\n *\n * These functions create reusable shader node fragments for:\n * - Texture sheet animation (frame index + sprite-sheet UV calculation)\n * - Soft particle depth fade\n * - Background color discard\n */\nimport { DataTexture, Vector3, type Texture } from 'three';\nimport {\n Fn,\n vec2,\n vec3,\n float,\n uniform,\n texture,\n abs,\n floor,\n mod,\n max,\n min,\n round,\n smoothstep,\n screenUV,\n Discard,\n If,\n length,\n type ShaderNodeObject,\n type Node,\n} from 'three/tsl';\n\nimport type * as THREE from 'three';\n\n/** 1x1 white placeholder texture for null uniform slots. */\nlet _dummyTexture: DataTexture | null = null;\nexport function getDummyTexture(): DataTexture {\n if (!_dummyTexture) {\n _dummyTexture = new DataTexture(new Uint8Array([255, 255, 255, 255]), 1, 1);\n _dummyTexture.needsUpdate = true;\n }\n return _dummyTexture;\n}\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type SharedUniforms = {\n map: { value: THREE.Texture | null };\n elapsed: { value: number };\n fps: { value: number };\n useFPSForFrameIndex: { value: boolean };\n tiles: { value: THREE.Vector2 };\n discardBackgroundColor: { value: boolean };\n backgroundColor: { value: { r: number; g: number; b: number } };\n backgroundColorTolerance: { value: number };\n softParticlesEnabled: { value: boolean };\n softParticlesIntensity: { value: number };\n sceneDepthTexture: { value: THREE.Texture | null };\n cameraNearFar: { value: THREE.Vector2 };\n [key: string]: { value: unknown };\n};\n\n// ─── Uniform creators ────────────────────────────────────────────────────────\n\nexport function createParticleUniforms(sharedUniforms: SharedUniforms) {\n const dummy = getDummyTexture();\n\n // Particle color maps are treated as sRGB (standard three.js convention).\n // The renderer's output pass handles the final linear→sRGB conversion, so\n // we let three.js apply the hardware sRGB→linear decode on sample.\n const map = (sharedUniforms.map.value ?? dummy) as Texture;\n\n return {\n uMap: map,\n uElapsed: uniform(float(sharedUniforms.elapsed.value)),\n uFps: uniform(float(sharedUniforms.fps.value)),\n uUseFPSForFrameIndex: uniform(\n float(sharedUniforms.useFPSForFrameIndex.value ? 1 : 0)\n ),\n uTiles: uniform(sharedUniforms.tiles.value),\n uDiscardBg: uniform(\n float(sharedUniforms.discardBackgroundColor.value ? 1 : 0)\n ),\n uBgColor: uniform(\n new Vector3(\n sharedUniforms.backgroundColor.value.r,\n sharedUniforms.backgroundColor.value.g,\n sharedUniforms.backgroundColor.value.b\n )\n ),\n uBgTolerance: uniform(float(sharedUniforms.backgroundColorTolerance.value)),\n uSoftEnabled: uniform(\n float(sharedUniforms.softParticlesEnabled.value ? 1 : 0)\n ),\n uSoftIntensity: uniform(float(sharedUniforms.softParticlesIntensity.value)),\n uSceneDepthTex: sharedUniforms.sceneDepthTexture.value ?? dummy,\n uCameraNearFar: uniform(sharedUniforms.cameraNearFar.value),\n };\n}\n\n// ─── Texture sheet animation ─────────────────────────────────────────────────\n\n/**\n * Computes the frame index for texture sheet animation.\n *\n * Replicates the GLSL logic:\n * frameIndex = startFrame + (useFPS ? lifetime/1000 * fps : floor(lifePercent * totalFrames))\n */\nexport const computeFrameIndex = Fn(\n ({\n vLifetime,\n vStartLifetime,\n vStartFrame,\n uFps,\n uUseFPSForFrameIndex,\n uTiles,\n }: Record<string, ShaderNodeObject<Node>>) => {\n const totalFrames = uTiles.x.mul(uTiles.y);\n const lifePercent = min(vLifetime.div(vStartLifetime), float(1.0));\n\n // FPS-based: (lifetime / 1000) * fps\n const fpsBased = max(vLifetime.div(1000.0).mul(uFps), float(0.0));\n\n // Lifetime-based: floor(lifePercent * totalFrames), clamped\n const lifetimeBased = max(\n min(floor(lifePercent.mul(totalFrames)), totalFrames.sub(1.0)),\n float(0.0)\n );\n\n // Select based on mode (uUseFPSForFrameIndex: 1.0 = FPS, 0.0 = lifetime)\n // When fps == 0 in FPS mode, use 0\n const fpsResult = uFps.equal(0.0).select(float(0.0), fpsBased);\n const frameOffset = uUseFPSForFrameIndex\n .greaterThan(0.5)\n .select(fpsResult, lifetimeBased);\n\n return round(vStartFrame).add(frameOffset);\n }\n);\n\n/**\n * Computes sprite-sheet UV coordinates from a base UV and the frame index.\n *\n * Replicates:\n * spriteX = floor(mod(frameIndex, tiles.x))\n * spriteY = floor(mod(frameIndex / tiles.x, tiles.y))\n * uv = baseUV / tiles + sprite / tiles\n */\nexport const computeSpriteSheetUV = Fn(\n ({ baseUV, frameIndex, uTiles }: Record<string, ShaderNodeObject<Node>>) => {\n const spriteX = floor(mod(frameIndex, uTiles.x));\n const spriteY = floor(mod(frameIndex.div(uTiles.x), uTiles.y));\n\n return vec2(\n baseUV.x.div(uTiles.x).add(spriteX.div(uTiles.x)),\n baseUV.y.div(uTiles.y).add(spriteY.div(uTiles.y))\n );\n }\n);\n\n// ─── Soft particles ──────────────────────────────────────────────────────────\n\n/**\n * Linearizes a depth buffer sample from [0,1] NDC to view-space distance.\n */\nexport const linearizeDepth = Fn(\n ({ depthSample, near, far }: Record<string, ShaderNodeObject<Node>>) => {\n const zNdc = depthSample.mul(2.0).sub(1.0);\n return near\n .mul(2.0)\n .mul(far)\n .div(far.add(near).sub(zNdc.mul(far.sub(near))));\n }\n);\n\n/**\n * Computes the soft-particle alpha multiplier based on depth difference.\n * Returns 1.0 when soft particles are disabled.\n */\nexport const computeSoftParticleFade = Fn(\n ({\n viewZ,\n uSoftEnabled,\n uSoftIntensity,\n uSceneDepthTex,\n uCameraNearFar,\n }: Record<string, ShaderNodeObject<Node>>) => {\n const softFade = float(1.0).toVar();\n\n If(uSoftEnabled.greaterThan(0.5), () => {\n const depthSample = texture(uSceneDepthTex, screenUV).x;\n const sceneDepthLinear = linearizeDepth({\n depthSample,\n near: uCameraNearFar.x,\n far: uCameraNearFar.y,\n });\n const depthDiff = sceneDepthLinear.sub(viewZ);\n softFade.assign(smoothstep(float(0.0), uSoftIntensity, depthDiff));\n });\n\n return softFade;\n }\n);\n\n// ─── Background color discard ────────────────────────────────────────────────\n\n/**\n * Discards fragments whose texture color is close to the background color.\n *\n * Emitted inline (not wrapped in `Fn`) so the `Discard()` call reaches the\n * fragment main shader — `discard` is a fragment-specific statement and\n * wrapping it inside a TSL `Fn` helper prevents it from firing correctly.\n */\nexport function applyBackgroundDiscard({\n texColor,\n uDiscardBg,\n uBgColor,\n uBgTolerance,\n}: Record<string, ShaderNodeObject<Node>>): void {\n const diff = vec3(\n texColor.x.sub(uBgColor.x),\n texColor.y.sub(uBgColor.y),\n texColor.z.sub(uBgColor.z)\n );\n Discard(\n uDiscardBg.greaterThan(0.5).and(abs(length(diff)).lessThan(uBgTolerance))\n );\n}\n","/**\n * TSL (Three Shading Language) material for the INSTANCED billboard particle renderer.\n *\n * Replicates the behavior of instanced-particle-vertex-shader.glsl.ts and\n * instanced-particle-fragment-shader.glsl.ts using TSL node-based materials.\n *\n * Key differences from the POINTS TSL material ({@link createPointSpriteTSLMaterial}):\n * - Uses `instanceOffset` (vec3) attribute for particle world-space position instead\n * of the built-in `position` node.\n * - All per-particle attributes use the `instance` prefix\n * (`instanceSize`, `instanceColorR`, …).\n * - The base geometry is a -0.5…0.5 quad; UV is derived from the quad vertex position\n * rather than `pointUV` / `gl_PointCoord`.\n * - Perspective-correct size scaling uses `cameraProjectionMatrix[1][1]` and a\n * `viewportHeight` uniform so that billboard quads match POINTS renderer pixel sizes.\n * - The billboard offset is applied in view space:\n * `mvPosition.xy += position.xy * perspectiveSize`\n * - Uses {@link MeshBasicNodeMaterial} because the instanced quads are rendered as a\n * `THREE.Mesh`, not a `THREE.Points`.\n */\nimport {\n Fn,\n attribute,\n vec2,\n vec4,\n float,\n uniform,\n modelViewMatrix,\n positionLocal,\n cameraProjectionMatrix,\n texture,\n cos,\n sin,\n Discard,\n If,\n length,\n varyingProperty,\n type ShaderNodeObject,\n type Node,\n} from 'three/tsl';\nimport { MeshBasicNodeMaterial } from 'three/webgpu';\n\nimport {\n POINT_SIZE_SCALE,\n ALPHA_DISCARD_THRESHOLD,\n} from '../three-particles-constants.js';\nimport {\n type SharedUniforms,\n createParticleUniforms,\n computeFrameIndex,\n computeSpriteSheetUV,\n computeSoftParticleFade,\n applyBackgroundDiscard,\n} from './tsl-shared.js';\nimport type * as THREE from 'three';\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Creates a TSL-based {@link MeshBasicNodeMaterial} that replicates the GLSL instanced\n * billboard particle shaders. Works with both WebGPURenderer (WGSL output) and\n * WebGLRenderer (GLSL output) when using the node material system.\n *\n * The material is designed for use with an `InstancedBufferGeometry` whose base mesh\n * is a unit quad (vertices at ±0.5 in X and Y). Per-particle data is supplied via\n * `THREE.InstancedBufferAttribute` arrays with the following names:\n *\n * | Attribute name | Type | Description |\n * |----------------------|---------|------------------------------------------|\n * | `instanceOffset` | vec3 | Particle world-space position |\n * | `instanceSize` | float | Uniform scale factor |\n * | `instanceColorR/G/B/A` | float | Per-particle RGBA colour |\n * | `instanceLifetime` | float | Remaining lifetime (ms) |\n * | `instanceStartLifetime` | float | Initial lifetime (ms) |\n * | `instanceRotation` | float | 2-D billboard rotation (radians) |\n * | `instanceStartFrame` | float | Starting frame for texture sheet anim |\n *\n * Size scaling matches the POINTS renderer exactly:\n * ```\n * perspectiveSize = instanceSize * 100.0 / dist\n * * (-mvPosition.z)\n * / (projectionMatrix[1][1] * viewportHeight * 0.5)\n * ```\n *\n * @param sharedUniforms - Live uniform values shared with the particle system.\n * @param rendererConfig - Blending / depth / transparency settings.\n * @returns A configured {@link MeshBasicNodeMaterial}.\n */\nexport function createInstancedBillboardTSLMaterial(\n sharedUniforms: SharedUniforms,\n rendererConfig: {\n transparent: boolean;\n blending: THREE.Blending;\n depthTest: boolean;\n depthWrite: boolean;\n },\n gpuCompute = false\n): MeshBasicNodeMaterial {\n const u = createParticleUniforms(sharedUniforms);\n\n // ── viewportHeight uniform ─────────────────────────────────────────────────\n //\n // The particle system's onBeforeRender hook updates `sharedUniforms.viewportHeight.value`\n // each frame. To propagate those writes into the TSL shader graph without\n // modifying the caller, we create the TSL uniform node and then back-patch\n // `sharedUniforms.viewportHeight` to point at the same node. From that\n // point on, `sharedUniforms.viewportHeight.value = x` directly mutates\n // `uViewportHeight.value`, keeping both paths (GLSL fallback and TSL) in sync.\n const uViewportHeight = uniform(\n typeof (sharedUniforms.viewportHeight as { value?: number })?.value ===\n 'number'\n ? (sharedUniforms.viewportHeight as { value: number }).value\n : 1.0\n );\n\n // Back-patch the shared uniform so the caller's live updates are reflected\n // in the TSL uniform node automatically.\n sharedUniforms.viewportHeight = uViewportHeight as unknown as {\n value: unknown;\n };\n\n // ── Per-instance attributes ────────────────────────────────────────────────\n\n /** Particle world-space centre (vec3). */\n const aInstanceOffset = attribute('instanceOffset');\n /** Packed RGBA color (vec4). */\n const aColor = attribute('instanceColor');\n\n // GPU compute uses packed vec4 buffers; CPU uses individual attributes\n const aParticleState = gpuCompute ? attribute('instanceParticleState') : null;\n const aStartValues = gpuCompute ? attribute('instanceStartValues') : null;\n // CPU fallback: individual attributes\n const aSize = gpuCompute ? null : attribute('instanceSize');\n const aLifetime = gpuCompute ? null : attribute('instanceLifetime');\n const aStartLifetime = gpuCompute ? null : attribute('instanceStartLifetime');\n const aRotation = gpuCompute ? null : attribute('instanceRotation');\n const aStartFrame = gpuCompute ? null : attribute('instanceStartFrame');\n\n // ── Varyings ───────────────────────────────────────────────────────────────\n\n const vColor = varyingProperty('vec4', 'vColor');\n const vLifetime = varyingProperty('float', 'vLifetime');\n const vStartLifetime = varyingProperty('float', 'vStartLifetime');\n const vRotation = varyingProperty('float', 'vRotation');\n const vStartFrame = varyingProperty('float', 'vStartFrame');\n /** View-space UV coordinates derived from the quad vertex position. */\n const vUv = varyingProperty('vec2', 'vUv');\n /** Positive view-space depth for soft-particle depth comparison. */\n const vViewZ = varyingProperty('float', 'vViewZ');\n\n // ── Vertex stage ───────────────────────────────────────────────────────────\n\n /**\n * Replicates the GLSL instanced vertex shader:\n *\n * 1. Transform `instanceOffset` (particle world position) into view space.\n * 2. Compute distance-based perspective scale so the billboard matches POINTS\n * renderer pixel sizes exactly.\n * 3. Offset the quad vertices in view space (`mvPosition.xy += position.xy * scale`).\n * 4. Project to clip space.\n * 5. Derive UV from quad vertex position (flip Y to match `gl_PointCoord` convention).\n *\n * In TSL's `positionNode` the returned value is the local-space position, and the\n * renderer applies the full MVP transform automatically. For instanced billboards\n * we need to manipulate the view-space position directly (to add the billboard\n * offset), so we work in view space and then multiply by the projection matrix\n * ourselves before returning.\n *\n * Because `positionNode` is expected to return the *local-space* position that TSL\n * will then transform via MVP, and we have already applied the full MVP here, we\n * must also suppress the automatic MVP multiplication. The recommended pattern for\n * this in TSL is to assign the result to `vertexNode` (which replaces clip-space\n * output directly) rather than `positionNode`. We therefore store the computed\n * clip-space position and expose it via the material's `vertexNode` property.\n */\n const vertexNode = Fn((): ShaderNodeObject<Node> => {\n // Early-out for dead particles: push the vertex behind the camera\n // (negative w) so it is clipped before rasterisation. A degenerate\n // (0,0,0,0) position causes a NaN after perspective divide, which some\n // WebGPU drivers rasterise at an indeterminate location instead of\n // discarding cleanly — this was visible as rogue billboards snapping\n // to the scene origin when particles transitioned to a dead state.\n const clipPos = vec4(0.0, 0.0, 0.0, -1.0).toVar();\n\n If(aColor.w.greaterThan(0.0), () => {\n // Populate varyings\n vColor.assign(aColor.toVar());\n if (gpuCompute) {\n // particleState: x=lifetime, y=size, z=rotation, w=startFrame\n vLifetime.assign(aParticleState!.x);\n vStartLifetime.assign(aStartValues!.x);\n vRotation.assign(aParticleState!.z);\n vStartFrame.assign(aParticleState!.w);\n } else {\n vLifetime.assign(aLifetime!);\n vStartLifetime.assign(aStartLifetime!);\n vRotation.assign(aRotation!);\n vStartFrame.assign(aStartFrame!);\n }\n\n // UV: quad vertex ranges from -0.5..0.5; remap to 0..1 and flip Y so the\n // top-left of the texture corresponds to the top-left of the billboard.\n // This matches gl_PointCoord which has Y running top-to-bottom.\n // vUv.x = position.x + 0.5\n // vUv.y = 0.5 - position.y\n vUv.assign(\n vec2(positionLocal.x.add(0.5), float(0.5).sub(positionLocal.y))\n );\n\n // Transform the particle world position into view space\n // Use .xyz to handle vec3→vec4 padding by WebGPU storage buffer alignment\n const mvPosition = modelViewMatrix\n .mul(vec4(aInstanceOffset.xyz, 1.0))\n .toVar();\n\n // Match POINTS renderer pixel size:\n // gl_PointSize = instanceSize * 100.0 / distance\n // Equivalent view-space billboard half-extent (in view units):\n // perspectiveSize = pointSizePx * (-mvPosition.z)\n // / (projectionMatrix[1][1] * viewportHeight * 0.5)\n // projectionMatrix[1][1] == cameraProjectionMatrix.element(1).element(1)\n const dist = length(mvPosition.xyz);\n const sizeVal = gpuCompute ? aParticleState!.y : aSize!;\n const pointSizePx = sizeVal.mul(POINT_SIZE_SCALE).div(dist);\n const projY = cameraProjectionMatrix.element(1).element(1);\n const perspectiveSize = pointSizePx\n .mul(mvPosition.z.negate())\n .div(projY.mul(uViewportHeight).mul(0.5));\n\n // Billboard: expand the quad in view space (no rotation here; rotation is\n // applied to UVs in the fragment stage, identical to the POINTS approach)\n mvPosition.x.addAssign(positionLocal.x.mul(perspectiveSize));\n mvPosition.y.addAssign(positionLocal.y.mul(perspectiveSize));\n\n vViewZ.assign(mvPosition.z.negate());\n\n // Project to clip space\n clipPos.assign(cameraProjectionMatrix.mul(mvPosition));\n });\n\n return clipPos;\n })();\n\n // ── Fragment stage ─────────────────────────────────────────────────────────\n\n /**\n * Replicates the GLSL instanced fragment shader:\n *\n * 1. Apply 2-D rotation to the UV (identical to POINTS material).\n * 2. Discard pixels outside the inscribed circle (radius > 0.5).\n * 3. Compute texture sheet frame index.\n * 4. Sample the sprite-sheet texture at the rotated, tile-offset UV.\n * 5. Background colour discard.\n * 6. Soft-particle depth fade.\n */\n const fragmentColor = Fn((): ShaderNodeObject<Node> => {\n const outColor = vColor.toVar();\n\n // Rotate vUv around (0.5, 0.5) to match the POINTS renderer behaviour\n const center = vec2(0.5, 0.5);\n const centered = vUv.sub(center);\n const cosR = cos(vRotation);\n const sinR = sin(vRotation);\n const rotated = vec2(\n centered.x.mul(cosR).add(centered.y.mul(sinR)),\n centered.x.mul(sinR).negate().add(centered.y.mul(cosR))\n );\n const rotatedUV = rotated.add(center);\n\n // Discard pixels outside the inscribed circle (dist > 0.5 from centre)\n const dist = length(rotatedUV.sub(center));\n If(dist.greaterThan(0.5), () => {\n Discard();\n });\n\n // Texture sheet animation — compute frame index\n const frameIndex = computeFrameIndex({\n vLifetime,\n vStartLifetime,\n vStartFrame,\n uFps: u.uFps,\n uUseFPSForFrameIndex: u.uUseFPSForFrameIndex,\n uTiles: u.uTiles,\n });\n\n // Compute sprite-sheet UV from rotated UV + tile offset\n const uvPoint = computeSpriteSheetUV({\n baseUV: rotatedUV,\n frameIndex,\n uTiles: u.uTiles,\n });\n\n // Sample texture\n const texColor = texture(u.uMap, uvPoint);\n outColor.assign(outColor.mul(texColor));\n\n // Background colour discard\n applyBackgroundDiscard({\n texColor,\n uDiscardBg: u.uDiscardBg,\n uBgColor: u.uBgColor,\n uBgTolerance: u.uBgTolerance,\n });\n\n // Soft particles — fade out fragments close to opaque scene geometry\n const softFade = computeSoftParticleFade({\n viewZ: vViewZ,\n uSoftEnabled: u.uSoftEnabled,\n uSoftIntensity: u.uSoftIntensity,\n uSceneDepthTex: u.uSceneDepthTex,\n uCameraNearFar: u.uCameraNearFar,\n });\n outColor.assign(vec4(outColor.xyz, outColor.w.mul(softFade)));\n Discard(outColor.w.lessThan(ALPHA_DISCARD_THRESHOLD));\n\n return outColor;\n })();\n\n // ── Material assembly ──────────────────────────────────────────────────────\n\n const material = new MeshBasicNodeMaterial();\n material.transparent = rendererConfig.transparent;\n material.blending = rendererConfig.blending;\n material.depthTest = rendererConfig.depthTest;\n material.depthWrite = rendererConfig.depthWrite;\n material.toneMapped = false;\n material.fog = false;\n\n // vertexNode replaces the default clip-space position. For instanced\n // billboards we compute the full MVP ourselves (view-space billboard offset +\n // projection), so the result is already in clip space.\n material.vertexNode = vertexNode;\n material.colorNode = fragmentColor;\n\n return material;\n}\n","/**\n * TSL (Three Shading Language) material for the MESH particle renderer.\n *\n * Replicates the behavior of mesh-particle-vertex-shader.glsl.ts and\n * mesh-particle-fragment-shader.glsl.ts using TSL node-based materials.\n *\n * Key differences from the POINTS / INSTANCED TSL materials:\n * - Uses `instanceQuat` (vec4) for full 3D quaternion rotation of mesh vertices.\n * - Transforms normals by the same quaternion for per-fragment directional lighting.\n * - Uses real mesh UVs (`uv`) rather than a derived point-coord or billboard UV.\n * - No circle discard — mesh geometry defines the particle shape.\n * - Texture sheet animation is only applied when tiles > 1×1.\n * - Simple directional lighting: `0.5 + 0.5 * max(dot(vNormal, vec3(0,0,1)), 0.0)`.\n */\nimport {\n Fn,\n attribute,\n vec2,\n vec3,\n vec4,\n float,\n cameraProjectionMatrix,\n modelViewMatrix,\n positionLocal,\n normalLocal,\n texture,\n cos,\n sin,\n Discard,\n If,\n max,\n cross,\n dot,\n varyingProperty,\n uv,\n type ShaderNodeObject,\n type Node,\n} from 'three/tsl';\nimport { MeshBasicNodeMaterial } from 'three/webgpu';\n\nimport { ALPHA_DISCARD_THRESHOLD } from '../three-particles-constants.js';\nimport {\n type SharedUniforms,\n createParticleUniforms,\n computeFrameIndex,\n computeSpriteSheetUV,\n computeSoftParticleFade,\n applyBackgroundDiscard,\n} from './tsl-shared.js';\n\nimport type * as THREE from 'three';\n\n// ─── Quaternion helper ────────────────────────────────────────────────────────\n\n/**\n * Applies a unit quaternion `q` to vector `v`.\n *\n * Replicates the GLSL helper:\n * ```glsl\n * vec3 applyQuaternion(vec3 v, vec4 q) {\n * vec3 t = 2.0 * cross(q.xyz, v);\n * return v + q.w * t + cross(q.xyz, t);\n * }\n * ```\n */\nconst applyQuaternion = Fn(\n ({ v, q }: Record<string, ShaderNodeObject<Node>>) => {\n const t = cross(q.xyz, v).mul(2.0);\n return v.add(t.mul(q.w)).add(cross(q.xyz, t));\n }\n);\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Creates a TSL-based {@link MeshBasicNodeMaterial} that replicates the GLSL\n * mesh particle shaders. Works with both WebGPURenderer (WGSL output) and\n * WebGLRenderer (GLSL output) when using the node material system.\n *\n * @param sharedUniforms - Live uniform values shared with the particle system.\n * @param rendererConfig - Blending / depth / transparency settings.\n * @returns A configured {@link MeshBasicNodeMaterial}.\n */\nexport function createMeshParticleTSLMaterial(\n sharedUniforms: SharedUniforms,\n rendererConfig: {\n transparent: boolean;\n blending: THREE.Blending;\n depthTest: boolean;\n depthWrite: boolean;\n },\n gpuCompute = false\n): MeshBasicNodeMaterial {\n const u = createParticleUniforms(sharedUniforms);\n\n // ── Per-instance attributes ────────────────────────────────────────────────\n\n /** Particle world-space position (vec3). */\n const aInstanceOffset = attribute('instanceOffset');\n /** Packed RGBA color (vec4). */\n const aColor = attribute('instanceColor');\n\n // GPU compute uses packed vec4 buffers; CPU uses individual attributes\n const aParticleState = gpuCompute ? attribute('instanceParticleState') : null;\n const aStartValues = gpuCompute ? attribute('instanceStartValues') : null;\n /** Particle orientation as a unit quaternion (vec4: x, y, z, w). CPU path only. */\n const aInstanceQuat = gpuCompute ? null : attribute('instanceQuat');\n const aSize = gpuCompute ? null : attribute('instanceSize');\n const aLifetime = gpuCompute ? null : attribute('instanceLifetime');\n const aStartLifetime = gpuCompute ? null : attribute('instanceStartLifetime');\n const aRotation = gpuCompute ? null : attribute('instanceRotation');\n const aStartFrame = gpuCompute ? null : attribute('instanceStartFrame');\n\n // ── Varyings ───────────────────────────────────────────────────────────────\n\n const vColor = varyingProperty('vec4', 'vColor');\n const vLifetime = varyingProperty('float', 'vLifetime');\n const vStartLifetime = varyingProperty('float', 'vStartLifetime');\n const vStartFrame = varyingProperty('float', 'vStartFrame');\n const vRotation = varyingProperty('float', 'vRotation');\n /** View-space normal, transformed by the instance quaternion. */\n const vNormal = varyingProperty('vec3', 'vNormal');\n /** View-space depth (positive distance from camera). */\n const vViewZ = varyingProperty('float', 'vViewZ');\n\n // ── Vertex stage ───────────────────────────────────────────────────────────\n\n /**\n * Computes the world-space vertex position for each mesh vertex:\n * 1. Rotate the mesh vertex by the instance quaternion.\n * 2. Scale by instanceSize.\n * 3. Translate by instanceOffset.\n * Also populates all varyings for the fragment stage.\n */\n const vertexSetup = Fn(() => {\n // Early-out for dead particles: push the vertex behind the camera\n // (negative w) so it is clipped before rasterisation. A degenerate\n // (0,0,0,0) position causes a NaN after perspective divide, which some\n // WebGPU drivers rasterise at an indeterminate location instead of\n // discarding cleanly.\n const clipPos = vec4(0.0, 0.0, 0.0, -1.0).toVar();\n\n If(aColor.w.greaterThan(0.0), () => {\n // Populate varyings\n vColor.assign(aColor.toVar());\n if (gpuCompute) {\n vLifetime.assign(aParticleState!.x);\n vStartLifetime.assign(aStartValues!.x);\n vStartFrame.assign(aParticleState!.w);\n vRotation.assign(aParticleState!.z);\n } else {\n vLifetime.assign(aLifetime!);\n vStartLifetime.assign(aStartLifetime!);\n vStartFrame.assign(aStartFrame!);\n vRotation.assign(aRotation!);\n }\n\n // Build quaternion: GPU compute derives it from particleState.z (rotation\n // angle around Z); CPU path reads the pre-computed instanceQuat attribute.\n let quat: ShaderNodeObject<Node>;\n if (gpuCompute) {\n const halfZ = aParticleState!.z.mul(0.5);\n quat = vec4(0.0, 0.0, sin(halfZ), cos(halfZ));\n } else {\n quat = aInstanceQuat!;\n }\n\n // 1. Rotate mesh vertex position by instance quaternion\n const rotatedPos = applyQuaternion({\n v: positionLocal,\n q: quat,\n });\n\n // 2. Scale by particle size\n const scaledPos = rotatedPos.mul(gpuCompute ? aParticleState!.y : aSize!);\n\n // 3. Translate to particle world position\n // Use .xyz to handle vec3→vec4 padding by WebGPU storage buffer alignment\n const worldPos = scaledPos.add(aInstanceOffset.xyz);\n\n // Compute model-view position for depth and normal\n const mvPos = modelViewMatrix.mul(vec4(worldPos, 1.0));\n vViewZ.assign(mvPos.z.negate());\n\n // Transform normal: rotate by quaternion then into view space\n const rotatedNormal = applyQuaternion({\n v: normalLocal,\n q: quat,\n });\n const mvNormal = modelViewMatrix.mul(vec4(rotatedNormal, 0.0)).xyz;\n vNormal.assign(mvNormal.normalize());\n\n clipPos.assign(cameraProjectionMatrix.mul(mvPos));\n });\n\n // Return clip-space position (manual MVP to avoid double-transform)\n return clipPos;\n })();\n\n // ── Fragment stage ─────────────────────────────────────────────────────────\n\n const fragmentColor = Fn(() => {\n const outColor = vColor.toVar();\n\n // Use mesh UVs as the base for texture sampling\n const uvPoint = vec2(uv()).toVar();\n\n // Texture sheet animation — only applied when tiles > 1×1\n If(u.uTiles.x.greaterThan(1.0).or(u.uTiles.y.greaterThan(1.0)), () => {\n const frameIndex = computeFrameIndex({\n vLifetime,\n vStartLifetime,\n vStartFrame,\n uFps: u.uFps,\n uUseFPSForFrameIndex: u.uUseFPSForFrameIndex,\n uTiles: u.uTiles,\n });\n\n // Remap mesh UV into the selected tile\n uvPoint.assign(\n computeSpriteSheetUV({\n baseUV: uv(),\n frameIndex,\n uTiles: u.uTiles,\n })\n );\n });\n\n // Sample texture using the (possibly remapped) UV\n const texColor = texture(u.uMap, uvPoint);\n outColor.assign(outColor.mul(texColor));\n\n // Background color discard\n applyBackgroundDiscard({\n texColor,\n uDiscardBg: u.uDiscardBg,\n uBgColor: u.uBgColor,\n uBgTolerance: u.uBgTolerance,\n });\n\n // Simple directional lighting from camera direction (+Z in view space).\n // lightIntensity = 0.5 + 0.5 * max(dot(vNormal, vec3(0,0,1)), 0.0)\n const lightIntensity = float(0.5).add(\n float(0.5).mul(max(dot(vNormal, vec3(0.0, 0.0, 1.0)), float(0.0)))\n );\n outColor.assign(vec4(outColor.xyz.mul(lightIntensity), outColor.w));\n\n // Soft particles — fade out fragments that are close to opaque scene geometry\n const softFade = computeSoftParticleFade({\n viewZ: vViewZ,\n uSoftEnabled: u.uSoftEnabled,\n uSoftIntensity: u.uSoftIntensity,\n uSceneDepthTex: u.uSceneDepthTex,\n uCameraNearFar: u.uCameraNearFar,\n });\n outColor.assign(vec4(outColor.xyz, outColor.w.mul(softFade)));\n Discard(outColor.w.lessThan(ALPHA_DISCARD_THRESHOLD));\n\n return outColor;\n })();\n\n // ── Material assembly ──────────────────────────────────────────────────────\n\n const material = new MeshBasicNodeMaterial();\n material.transparent = rendererConfig.transparent;\n material.blending = rendererConfig.blending;\n material.depthTest = rendererConfig.depthTest;\n material.depthWrite = rendererConfig.depthWrite;\n material.toneMapped = false;\n material.fog = false;\n\n // vertexNode receives a clip-space vec4 (manual MVP to avoid double-transform)\n material.vertexNode = vertexSetup;\n material.colorNode = fragmentColor;\n\n return material;\n}\n","/**\n * TSL (Three Shading Language) material for the POINTS particle renderer.\n *\n * Replicates the behavior of particle-system-vertex-shader.glsl.ts and\n * particle-system-fragment-shader.glsl.ts using TSL node-based materials.\n */\nimport {\n Fn,\n attribute,\n vec2,\n vec4,\n float,\n modelViewMatrix,\n positionLocal,\n texture,\n cos,\n sin,\n Discard,\n If,\n length,\n varyingProperty,\n type ShaderNodeObject,\n type Node,\n} from 'three/tsl';\nimport { PointsNodeMaterial } from 'three/webgpu';\n\nimport {\n POINT_SIZE_SCALE,\n ALPHA_DISCARD_THRESHOLD,\n} from '../three-particles-constants.js';\nimport {\n type SharedUniforms,\n createParticleUniforms,\n computeFrameIndex,\n computeSpriteSheetUV,\n computeSoftParticleFade,\n applyBackgroundDiscard,\n} from './tsl-shared.js';\nimport type * as THREE from 'three';\n\n/**\n * Creates a TSL-based PointsNodeMaterial that replicates the GLSL point sprite\n * particle shaders. Works with both WebGPURenderer (WGSL output) and\n * WebGLRenderer (GLSL output) when using the node material system.\n */\nexport function createPointSpriteTSLMaterial(\n sharedUniforms: SharedUniforms,\n rendererConfig: {\n transparent: boolean;\n blending: THREE.Blending;\n depthTest: boolean;\n depthWrite: boolean;\n },\n gpuCompute = false\n): PointsNodeMaterial {\n const u = createParticleUniforms(sharedUniforms);\n\n // Read per-particle attributes\n const aColor = attribute('color');\n\n // GPU compute uses packed vec4 buffers; CPU uses individual attributes\n const aParticleState = gpuCompute ? attribute('particleState') : null;\n const aStartValues = gpuCompute ? attribute('startValues') : null;\n // CPU fallback: individual attributes\n const aSize = gpuCompute ? null : attribute('size');\n const aLifetime = gpuCompute ? null : attribute('lifetime');\n const aStartLifetime = gpuCompute ? null : attribute('startLifetime');\n const aRotation = gpuCompute ? null : attribute('rotation');\n const aStartFrame = gpuCompute ? null : attribute('startFrame');\n\n // ── Vertex stage ────────────────────────────────────────────────────────\n\n // Compute model-view position and distance-based point size\n const mvPos = modelViewMatrix.mul(vec4(positionLocal, 1.0));\n const sizeVal = gpuCompute ? aParticleState!.y : aSize!;\n const sizeNode = aColor.w\n .greaterThan(0.0)\n .select(sizeVal.mul(POINT_SIZE_SCALE).div(length(mvPos.xyz)), float(0.0));\n\n // Pass varyings to fragment\n const vColor = varyingProperty('vec4', 'vColor');\n const vLifetime = varyingProperty('float', 'vLifetime');\n const vStartLifetime = varyingProperty('float', 'vStartLifetime');\n const vRotation = varyingProperty('float', 'vRotation');\n const vStartFrame = varyingProperty('float', 'vStartFrame');\n const vViewZ = varyingProperty('float', 'vViewZ');\n\n // Assign varyings in vertex\n const vertexSetup = Fn(() => {\n // Early-out for dead particles: set size to 0 (produces zero-area points)\n // and skip all varying assignments to save vertex shader work.\n If(aColor.w.greaterThan(0.0), () => {\n vColor.assign(aColor.toVar());\n if (gpuCompute) {\n vLifetime.assign(aParticleState!.x);\n vStartLifetime.assign(aStartValues!.x);\n vRotation.assign(aParticleState!.z);\n vStartFrame.assign(aParticleState!.w);\n } else {\n vLifetime.assign(aLifetime!);\n vStartLifetime.assign(aStartLifetime!);\n vRotation.assign(aRotation!);\n vStartFrame.assign(aStartFrame!);\n }\n vViewZ.assign(mvPos.z.negate());\n });\n return positionLocal;\n })();\n\n // ── Fragment stage ──────────────────────────────────────────────────────\n\n const fragmentColor = Fn(() => {\n // Start with per-particle color\n const outColor = vColor.toVar();\n\n // Compute frame index (texture sheet animation)\n const frameIndex = computeFrameIndex({\n vLifetime,\n vStartLifetime,\n vStartFrame,\n uFps: u.uFps,\n uUseFPSForFrameIndex: u.uUseFPSForFrameIndex,\n uTiles: u.uTiles,\n });\n\n // Apply 2D rotation around the quad centre.\n //\n // r186 note: the `pointUV` node serialises as the raw GLSL snippet\n // `vec2(gl_PointCoord.x, 1.0 - gl_PointCoord.y)`, which the WGSL backend\n // emits verbatim but never declares - Naga reports it as an unresolved\n // value and the fragment pipeline fails to compile. WebGPU point\n // primitives are always a single pixel, so the point-coord of every\n // fragment is the centre of that pixel: `(0.5, 0.5)`. Use that constant,\n // which equals the WebGL `gl_PointCoord` value for 1-px points and keeps\n // the vertex/fragment pipeline identical on the GPU-only backend.\n const center = vec2(0.5, 0.5);\n const centered = vec2(0.0, 0.0); // `pointUV` (=0.5) minus its centre\n const cosR = cos(vRotation);\n const sinR = sin(vRotation);\n const rotated = vec2(\n centered.x.mul(cosR).add(centered.y.mul(sinR)),\n centered.x.mul(sinR).negate().add(centered.y.mul(cosR))\n );\n const rotatedUV = rotated.add(center);\n\n // Circle discard (inscribed circle in point quad)\n const dist = length(rotatedUV.sub(center));\n Discard(dist.greaterThan(0.5));\n\n // Compute sprite-sheet UV\n const uvPoint = computeSpriteSheetUV({\n baseUV: rotatedUV,\n frameIndex,\n uTiles: u.uTiles,\n });\n\n // Sample texture\n const texColor = texture(u.uMap, uvPoint);\n outColor.assign(outColor.mul(texColor));\n\n // Background color discard\n applyBackgroundDiscard({\n texColor,\n uDiscardBg: u.uDiscardBg,\n uBgColor: u.uBgColor,\n uBgTolerance: u.uBgTolerance,\n });\n\n // Soft particles\n const softFade = computeSoftParticleFade({\n viewZ: vViewZ,\n uSoftEnabled: u.uSoftEnabled,\n uSoftIntensity: u.uSoftIntensity,\n uSceneDepthTex: u.uSceneDepthTex,\n uCameraNearFar: u.uCameraNearFar,\n });\n outColor.assign(vec4(outColor.xyz, outColor.w.mul(softFade)));\n Discard(outColor.w.lessThan(ALPHA_DISCARD_THRESHOLD));\n\n return outColor;\n })();\n\n // ── Material assembly ───────────────────────────────────────────────────\n\n const material = new PointsNodeMaterial();\n material.transparent = rendererConfig.transparent;\n material.blending = rendererConfig.blending;\n material.depthTest = rendererConfig.depthTest;\n material.depthWrite = rendererConfig.depthWrite;\n material.toneMapped = false;\n material.fog = false;\n material.sizeNode = sizeNode;\n material.positionNode = vertexSetup;\n material.colorNode = fragmentColor;\n\n return material;\n}\n","/**\n * TSL (Three Shading Language) material for the trail ribbon renderer.\n *\n * Replicates the behavior of trail-vertex-shader.glsl.ts and\n * trail-fragment-shader.glsl.ts using TSL node-based materials.\n *\n * Key characteristics:\n * - Custom geometry with trail-specific per-vertex attributes\n * - Billboard ribbon: perp axis = cross(tangent, viewDir), with edge-on fallback\n * - Soft edge fade along the ribbon width (vUv.x axis)\n * - Optional texture modulation using luminance (dot-product brightness)\n * - DoubleSide rendering — no backface culling for ribbons\n * - NO texture sheet animation\n * - Trail uniforms are completely separate from the main particle uniforms\n */\nimport { DoubleSide } from 'three';\nimport {\n Fn,\n attribute,\n cameraPosition,\n cameraViewMatrix,\n vec2,\n vec3,\n vec4,\n float,\n modelViewMatrix,\n positionLocal,\n texture,\n normalize,\n cross,\n dot,\n abs,\n mix,\n smoothstep,\n screenUV,\n Discard,\n If,\n length,\n varyingProperty,\n uniform,\n type ShaderNodeObject,\n type Node,\n} from 'three/tsl';\nimport { MeshBasicNodeMaterial } from 'three/webgpu';\nimport { ALPHA_DISCARD_THRESHOLD } from '../three-particles-constants.js';\nimport { getDummyTexture, linearizeDepth } from './tsl-shared.js';\nimport type * as THREE from 'three';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/**\n * Uniforms consumed exclusively by the trail ribbon material.\n * These are managed separately from the main particle system's SharedUniforms.\n */\nexport type TrailUniforms = {\n /** Optional texture to modulate the ribbon color via luminance. */\n map: { value: THREE.Texture | null };\n /** Whether to apply texture modulation. */\n useMap: { value: boolean };\n /** Discard fragments whose color matches the background color. */\n discardBackgroundColor: { value: boolean };\n /** The background color to match for discard. */\n backgroundColor: { value: { r: number; g: number; b: number } };\n /** Tolerance radius in colour space for background discard. */\n backgroundColorTolerance: { value: number };\n /** Enable depth-difference soft-particle fading. */\n softParticlesEnabled: { value: boolean };\n /** Controls the fade distance for soft particles (view-space units). */\n softParticlesIntensity: { value: number };\n /** The pre-rendered scene depth texture, required for soft particles. */\n sceneDepthTexture: { value: THREE.Texture | null };\n /** Camera near/far planes packed as (near, far). */\n cameraNearFar: { value: THREE.Vector2 };\n};\n\n// ─── Internal uniform creators ───────────────────────────────────────────────\n\nfunction createTrailUniforms(trailUniforms: TrailUniforms) {\n const dummy = getDummyTexture();\n // Trail color maps are treated as sRGB (standard three.js convention);\n // the renderer's output pass handles the final linear→sRGB conversion.\n const map = (trailUniforms.map.value ?? dummy) as THREE.Texture;\n\n return {\n uMap: map,\n uUseMap: uniform(float(trailUniforms.useMap.value ? 1 : 0)),\n uDiscardBg: uniform(\n float(trailUniforms.discardBackgroundColor.value ? 1 : 0)\n ),\n uBgColor: uniform(\n new (trailUniforms.cameraNearFar.value.constructor as new (\n x: number,\n y: number,\n z: number\n ) => THREE.Vector3)(\n trailUniforms.backgroundColor.value.r,\n trailUniforms.backgroundColor.value.g,\n trailUniforms.backgroundColor.value.b\n )\n ),\n uBgTolerance: uniform(float(trailUniforms.backgroundColorTolerance.value)),\n uSoftEnabled: uniform(\n float(trailUniforms.softParticlesEnabled.value ? 1 : 0)\n ),\n uSoftIntensity: uniform(float(trailUniforms.softParticlesIntensity.value)),\n uSceneDepthTex: trailUniforms.sceneDepthTexture.value ?? dummy,\n uCameraNearFar: uniform(trailUniforms.cameraNearFar.value),\n };\n}\n\n// ─── Material factory ─────────────────────────────────────────────────────────\n\n/**\n * Creates a TSL-based MeshBasicNodeMaterial that replicates the GLSL trail\n * ribbon shaders. Works with both WebGPURenderer (WGSL output) and\n * WebGLRenderer (GLSL output) when using the node material system.\n *\n * The returned material expects geometry with these custom attributes:\n * - `trailAlpha` — per-vertex opacity along the trail\n * - `trailColor` — per-vertex RGBA colour\n * - `trailOffset` — ribbon edge side: −0.5 (left) or +0.5 (right)\n * - `trailHalfWidth` — half-width of the ribbon at this vertex\n * - `trailNext` — world-space position of the next trail sample\n * - `trailUV` — UV coordinates (x: along-trail, y: across-ribbon)\n *\n * @param trailUniforms - Per-trail uniform values (map, soft particles, bg discard, …).\n * @param rendererConfig - Blending / depth state forwarded to the material.\n * @returns Configured MeshBasicNodeMaterial ready for use with a trail mesh.\n */\nexport function createTrailRibbonTSLMaterial(\n trailUniforms: TrailUniforms,\n rendererConfig: {\n transparent: boolean;\n blending: THREE.Blending;\n depthTest: boolean;\n depthWrite: boolean;\n }\n): MeshBasicNodeMaterial {\n const u = createTrailUniforms(trailUniforms);\n\n // ── Per-vertex attributes ────────────────────────────────────────────────\n\n const aPosPacked = attribute('position', 'vec4');\n const aNextPacked = attribute('trailNext', 'vec4');\n const aUvColorA = attribute('trailUVColor', 'vec4');\n const aColorBA = attribute('trailColorBA', 'vec4');\n\n // Derived per-vertex values (see the contract above): the ribbon side offset\n // comes from uv.x (0 -> -0.5, 1 -> +0.5), so no extra attribute is needed.\n const aTrailAlpha = aNextPacked.w;\n const aTrailColor = vec4(aUvColorA.z, aUvColorA.w, aColorBA.x, aColorBA.y);\n const aTrailOffset = aUvColorA.x.sub(float(0.5));\n const aTrailHalfWidth = aPosPacked.w;\n const aTrailNext = vec3(aNextPacked.x, aNextPacked.y, aNextPacked.z);\n const aTrailUV = vec2(aUvColorA.x, aUvColorA.y);\n\n // ── Varyings ─────────────────────────────────────────────────────────────\n\n const vAlpha = varyingProperty('float', 'vAlpha');\n const vColor = varyingProperty('vec4', 'vColor');\n const vUv = varyingProperty('vec2', 'vUv');\n const vViewZ = varyingProperty('float', 'vViewZ');\n\n // ── Vertex stage ──────────────────────────────────────────────────────────\n //\n // Replicates trail-vertex-shader.glsl — billboard ribbon expansion:\n //\n // 1. Compute tangent from current → next position (with degenerate guard).\n // 2. Derive the camera-right fallback from viewMatrix column 0.\n // 3. Compute perp = cross(tangent, viewDir); blend toward fallback when\n // the cross product is near-zero (edge-on view).\n // 4. Offset position along perp by trailOffset * trailHalfWidth.\n // 5. Project and emit vViewZ for soft-particle depth test.\n\n const positionNode = Fn((): ShaderNodeObject<Node> => {\n // Pass varyings to fragment stage\n vAlpha.assign(aTrailAlpha);\n vColor.assign(aTrailColor);\n vUv.assign(aTrailUV);\n\n const current = vec3(aPosPacked.x, aPosPacked.y, aPosPacked.z);\n const next = vec3(aTrailNext);\n\n // Tangent: direction from current to next sample\n const rawTangent = next.sub(current);\n const tangentLen = length(rawTangent);\n // Degenerate guard: fall back to +Y when consecutive samples coincide\n const tangent = normalize(\n tangentLen.lessThan(0.0001).select(vec3(0.0, 1.0, 0.0), rawTangent)\n );\n\n // View-space position for depth (vViewZ)\n const mvCurrent = modelViewMatrix.mul(vec4(current, 1.0));\n\n // View direction in local/world space (tangent is in the same space)\n const viewDir = normalize(cameraPosition.sub(current));\n\n // Primary billboard perpendicular\n const rawPerp = cross(tangent, viewDir);\n const perpLen = length(rawPerp);\n\n // Camera right vector extracted from the view matrix (column 0)\n // Using cameraViewMatrix (view-only, no model transform)\n const camRight = vec3(\n cameraViewMatrix.element(0).element(0),\n cameraViewMatrix.element(1).element(0),\n cameraViewMatrix.element(2).element(0)\n );\n\n // Fallback perpendicular: project camRight onto the plane perpendicular to tangent\n const camRightDotTangent = dot(camRight, tangent);\n const fallbackPerp = normalize(\n camRight.sub(tangent.mul(camRightDotTangent))\n );\n\n // When perpLen is near zero the ribbon is edge-on; use fallback.\n // Otherwise blend smoothly toward fallback over a wide range (0 → 0.7)\n // to prevent abrupt flipping, matching the GLSL shader exactly.\n const perp = normalize(\n perpLen\n .lessThan(0.0001)\n .select(\n fallbackPerp,\n normalize(\n mix(\n fallbackPerp,\n normalize(rawPerp),\n smoothstep(float(0.0), float(0.7), perpLen)\n )\n )\n )\n );\n\n // Expand ribbon vertex by offset side and half-width\n const offsetPos = current.add(perp.mul(aTrailOffset).mul(aTrailHalfWidth));\n\n // Emit view-space depth for soft particles\n const mvOffset = modelViewMatrix.mul(vec4(offsetPos, 1.0));\n vViewZ.assign(mvOffset.z.negate());\n\n // Return the offset position in local space; TSL's positionNode feeds this\n // through the standard MVP transform automatically, so returning offsetPos\n // is sufficient — the engine reconstructs the clip-space position.\n return offsetPos;\n })();\n\n // ── Fragment stage ────────────────────────────────────────────────────────\n //\n // Replicates trail-fragment-shader.glsl:\n // 1. Soft edge fade along the ribbon width using vUv.x.\n // 2. Optional luminance-weighted texture modulation.\n // 3. Alpha = vColor.a * vAlpha * edgeFade (plus optional soft-particle fade).\n // 4. Background color discard.\n\n const colorNode = Fn((): ShaderNodeObject<Node> => {\n const outColor = vColor.toVar();\n\n // Soft edge fade: vUv.x runs [0, 1] across the ribbon width.\n // edgeDist = 1 − |2·x − 1| peaks at 0.5 (centre) and is 0 at edges.\n const edgeDist = float(1.0).sub(abs(vUv.x.mul(2.0).sub(1.0)));\n const edgeFade = smoothstep(float(0.0), float(0.4), edgeDist);\n\n // Optional texture: modulate colour by luminance (perceptual weighting)\n // and multiply alpha by texture alpha — matching the GLSL shader.\n If(u.uUseMap.greaterThan(0.5), () => {\n const texColor = texture(u.uMap, vUv);\n const texBrightness = dot(texColor.rgb, vec3(0.299, 0.587, 0.114));\n outColor.rgb.assign(\n outColor.rgb.mul(float(0.5).add(texBrightness.mul(0.5)))\n );\n outColor.a.assign(outColor.a.mul(texColor.a));\n });\n\n // Combine alpha: particle alpha × ribbon edge fade\n outColor.a.assign(outColor.a.mul(vAlpha).mul(edgeFade));\n\n // Early discard for fully transparent fragments\n Discard(outColor.a.lessThan(ALPHA_DISCARD_THRESHOLD));\n\n // Soft particles — depth-difference fade\n If(u.uSoftEnabled.greaterThan(0.5), () => {\n const depthSample = texture(u.uSceneDepthTex, screenUV).x;\n const sceneDepthLinear = linearizeDepth({\n depthSample,\n near: u.uCameraNearFar.x,\n far: u.uCameraNearFar.y,\n });\n const depthDiff = sceneDepthLinear.sub(vViewZ);\n const softFade = smoothstep(float(0.0), u.uSoftIntensity, depthDiff);\n outColor.a.assign(outColor.a.mul(softFade));\n });\n Discard(outColor.a.lessThan(ALPHA_DISCARD_THRESHOLD));\n\n // Background color discard\n const diff = vec3(\n outColor.r.sub(u.uBgColor.x),\n outColor.g.sub(u.uBgColor.y),\n outColor.b.sub(u.uBgColor.z)\n );\n Discard(\n u.uDiscardBg\n .greaterThan(0.5)\n .and(abs(length(diff)).lessThan(u.uBgTolerance))\n );\n\n return outColor;\n })();\n\n // ── Material assembly ─────────────────────────────────────────────────────\n\n const material = new MeshBasicNodeMaterial();\n material.transparent = rendererConfig.transparent;\n material.blending = rendererConfig.blending;\n material.depthTest = rendererConfig.depthTest;\n material.depthWrite = rendererConfig.depthWrite;\n material.toneMapped = false;\n material.fog = false;\n material.side = DoubleSide;\n\n // positionNode replaces the default local-space position fed into MVP\n material.positionNode = positionNode;\n material.colorNode = colorNode;\n\n return material;\n}\n","/**\n * TSL material factory for all particle renderer types + the GPU-only compute\n * pipeline (emission kernel + simulation kernel sharing one storage pool).\n *\n * @module\n */\nimport { RendererType } from '../three-particles-enums.js';\nimport { isLifeTimeCurve } from '../three-particles-utils.js';\nimport { sRGBToLinear } from '../color-utils.js';\nimport {\n createModifierStorageBuffers,\n createModifierComputeUpdate,\n createSubEmitterInitUpdate,\n createSubEmitterFifoAttribute,\n createTrailRibbonUpdate,\n SUB_EMITTER_EVENT_STRIDE,\n subEmitterWindowSize,\n type ModifierComputePipeline,\n type ModifierFlags,\n type ShapeEmitParams,\n type SubEmitterFifo,\n type SubEmitterInitPipeline,\n type TrailHistoryDesc,\n type TrailRibbonDesc,\n type TrailRibbonPipeline,\n} from './compute-modifiers.js';\n\nexport {\n createModifierStorageBuffers,\n createModifierComputeUpdate,\n createSubEmitterInitUpdate,\n createSubEmitterFifoAttribute,\n createTrailRibbonUpdate,\n SUB_EMITTER_EVENT_STRIDE,\n subEmitterWindowSize,\n};\nexport type {\n ModifierComputePipeline,\n ModifierFlags,\n ShapeEmitParams,\n SubEmitterFifo,\n SubEmitterInitPipeline,\n TrailHistoryDesc,\n TrailRibbonDesc,\n TrailRibbonPipeline,\n};\n\n\nimport { bakeParticleSystemCurves } from './curve-bake.js';\nimport { createInstancedBillboardTSLMaterial } from './tsl-instanced-billboard-material.js';\nimport { createMeshParticleTSLMaterial } from './tsl-mesh-particle-material.js';\nimport { createPointSpriteTSLMaterial } from './tsl-point-sprite-material.js';\nimport {\n createTrailRibbonTSLMaterial,\n type TrailUniforms,\n} from './tsl-trail-ribbon-material.js';\nimport type { SharedUniforms } from './tsl-shared.js';\nimport type {\n NormalizedParticleSystemConfig,\n ShapeConfig,\n} from '../types.js';\n\nimport type * as THREE from 'three';\nimport { StorageBufferAttribute } from 'three/webgpu';\n\nexport type { TrailUniforms };\n\nexport type RendererConfig = {\n transparent: boolean;\n blending: THREE.Blending;\n depthTest: boolean;\n depthWrite: boolean;\n};\n\n/**\n * Creates a TSL NodeMaterial for the main particle system (non-trail).\n */\nexport function createTSLParticleMaterial(\n rendererType: RendererType,\n sharedUniforms: SharedUniforms,\n rendererConfig: RendererConfig,\n gpuCompute = false\n): THREE.Material {\n switch (rendererType) {\n case RendererType.INSTANCED:\n return createInstancedBillboardTSLMaterial(sharedUniforms, rendererConfig, gpuCompute);\n case RendererType.MESH:\n return createMeshParticleTSLMaterial(sharedUniforms, rendererConfig, gpuCompute);\n case RendererType.POINTS:\n default:\n return createPointSpriteTSLMaterial(sharedUniforms, rendererConfig, gpuCompute);\n }\n}\n\nexport function createTSLTrailMaterial(\n trailUniforms: TrailUniforms,\n rendererConfig: RendererConfig\n): THREE.Material {\n return createTrailRibbonTSLMaterial(trailUniforms, rendererConfig);\n}\n\n/** Pull a scalar pair out of either a `number` or `{ min, max }` shape. */\nconst pair = (v: unknown): [number, number] => {\n if (typeof v === 'number') return [v, v];\n if (v && typeof v === 'object') {\n const o = v as Record<string, number>;\n return [Number(o.min) || 0, Number(o.max) || 0];\n }\n return [0, 0];\n};\n\n/** Map the public `Shape` string onto the GPU kernel kind. */\nconst shapeKindOf = (t: ShapeConfig['shape']): 0 | 1 | 2 | 3 | 4 => {\n switch (t) {\n case 'SPHERE': return 0;\n case 'CONE': return 1;\n case 'CIRCLE': return 2;\n case 'RECTANGLE': return 3;\n case 'BOX': return 4;\n default: return 0; // SPHERE, matching DEFAULT_PARTICLE_SYSTEM_CONFIG.shape.shape\n }\n};\n\n/** Map `EmitFrom` onto the box-emission kernel code. */\nconst boxEmitFromOf = (e: string | undefined): 0 | 1 | 2 =>\n e === 'SHELL' ? 1 : e === 'EDGE' ? 2 : 0;\n\n\n/**\n * Decodes the nested public `ShapeConfig` (+ start values / sheet frame) into\n * the flat scalar table consumed by the compute kernels. Exported so the\n * sub-emitter init kernel can reuse the identical encoding.\n */\nexport function encodeShapeEmitParams(\n normalizedConfig: NormalizedParticleSystemConfig,\n particleSystemId: number\n): ShapeEmitParams {\n const bakedCurves = bakeParticleSystemCurves(normalizedConfig, particleSystemId);\n const pairLocal = pair;\n const [lifeMin, lifeMax] = pairLocal(normalizedConfig.startLifetime);\n const [spdMin, spdMax] = pairLocal(normalizedConfig.startSpeed);\n const [szMin, szMax] = pairLocal(normalizedConfig.startSize);\n const [rotMin, rotMax] = pairLocal(normalizedConfig.startRotation);\n const [opMin, opMax] = pairLocal(normalizedConfig.startOpacity);\n const cMin =\n (\n normalizedConfig.startColor as {\n min?: { r: number; g: number; b: number };\n }\n ).min || { r: 1, g: 1, b: 1 };\n const cMax =\n (\n normalizedConfig.startColor as {\n max?: { r: number; g: number; b: number };\n }\n ).max || { r: 1, g: 1, b: 1 };\n const sf =\n (normalizedConfig.textureSheetAnimation &&\n (normalizedConfig.textureSheetAnimation as { startFrame?: unknown })\n .startFrame) ||\n 0;\n const sfPair = pairLocal(sf);\n const shp = normalizedConfig.shape;\n const sph = shp.sphere;\n const cone = shp.cone;\n const circ = shp.circle;\n const rect = shp.rectangle;\n const bx = shp.box;\n const num = (v: unknown, fallback: number): number =>\n typeof v === 'number' && Number.isFinite(v) ? v : fallback;\n const kind = shapeKindOf(shp.shape);\n return {\n shapeKind: kind,\n radius:\n shp.shape === 'CONE'\n ? num(cone?.radius, 1)\n : shp.shape === 'CIRCLE'\n ? num(circ?.radius, 1)\n : num(sph?.radius, 1),\n radiusThickness:\n shp.shape === 'CONE'\n ? num(cone?.radiusThickness, 1)\n : shp.shape === 'CIRCLE'\n ? num(circ?.radiusThickness, 1)\n : num(sph?.radiusThickness, 1),\n arcDeg:\n shp.shape === 'CONE'\n ? num(cone?.arc, 360)\n : shp.shape === 'CIRCLE'\n ? num(circ?.arc, 360)\n : num(sph?.arc, 360),\n coneAngleDeg: num(cone?.angle, 90),\n rectangleRotXDeg: num(rect?.rotation?.x, 0),\n rectangleRotYDeg: num(rect?.rotation?.y, 0),\n rectangleScaleX: num(rect?.scale?.x, 1),\n rectangleScaleY: num(rect?.scale?.y, 1),\n boxScaleX: num(bx?.scale?.x, 1),\n boxScaleY: num(bx?.scale?.y, 1),\n boxScaleZ: num(bx?.scale?.z, 1),\n boxEmitFrom: boxEmitFromOf(bx?.emitFrom),\n speedMin: spdMin,\n speedMax: spdMax,\n sizeMin: szMin,\n sizeMax: szMax,\n rotMin: rotMin,\n rotMax: rotMax,\n opacityMin: opMin,\n opacityMax: opMax,\n lifeMin: lifeMin,\n lifeMax: lifeMax,\n colorRMin: cMin.r,\n colorRMax: cMax.r,\n colorGMin: cMin.g,\n colorGMax: cMax.g,\n colorBMin: cMin.b,\n colorBMax: cMax.b,\n startFrameMin: sfPair[0],\n startFrameMax: sfPair[1],\n // Separate rotationOverLifetime range (never the startRotation pair).\n rotOverLifeMin: (() => {\n const rol = normalizedConfig.rotationOverLifetime as unknown as\n | { min?: number; max?: number }\n | undefined;\n return typeof rol?.min === 'number' && Number.isFinite(rol.min) ? rol.min : 0;\n })(),\n rotOverLifeMax: (() => {\n const rol = normalizedConfig.rotationOverLifetime as unknown as\n | { min?: number; max?: number }\n | undefined;\n return typeof rol?.max === 'number' && Number.isFinite(rol.max) ? rol.max : 0;\n })(),\n noiseOctaves: num(normalizedConfig.noise?.octaves, 1),\n noiseUseRandomOffset: !!normalizedConfig.noise?.useRandomOffset,\n rotationCurveActive: normalizedConfig.rotationOverLifetime.isActive,\n rotationalXCurve:\n (bakedCurves as unknown as Record<string, number>).orbitalVelX ?? -1,\n rotationalYCurve:\n (bakedCurves as unknown as Record<string, number>).orbitalVelY ?? -1,\n rotationalZCurve:\n (bakedCurves as unknown as Record<string, number>).orbitalVelZ ?? -1,\n linearXCurve:\n (bakedCurves as unknown as Record<string, number>).linearVelX ?? -1,\n linearYCurve:\n (bakedCurves as unknown as Record<string, number>).linearVelY ?? -1,\n linearZCurve:\n (bakedCurves as unknown as Record<string, number>).linearVelZ ?? -1,\n };\n}\n\nexport function createComputePipeline(\n\n maxParticles: number,\n instanced: boolean,\n normalizedConfig: NormalizedParticleSystemConfig,\n particleSystemId: number,\n forceFieldCount: number,\n collisionPlaneCount = 0,\n subFifos?: SubEmitterFifo[],\n trailDesc?: TrailHistoryDesc\n): ModifierComputePipeline {\n\n const bakedCurves = bakeParticleSystemCurves(normalizedConfig, particleSystemId);\n const v = normalizedConfig.velocityOverLifetime;\n\n const flags: ModifierFlags = {\n sizeOverLifetime: normalizedConfig.sizeOverLifetime.isActive,\n opacityOverLifetime: normalizedConfig.opacityOverLifetime.isActive,\n colorOverLifetime: normalizedConfig.colorOverLifetime.isActive,\n rotationOverLifetime: normalizedConfig.rotationOverLifetime.isActive,\n linearVelocity:\n v.isActive &&\n (isLifeTimeCurve(v.linear.x ?? 0) ||\n isLifeTimeCurve(v.linear.y ?? 0) ||\n isLifeTimeCurve(v.linear.z ?? 0) ||\n v.linear.x !== 0 ||\n v.linear.y !== 0 ||\n v.linear.z !== 0),\n orbitalVelocity:\n v.isActive &&\n (isLifeTimeCurve(v.orbital.x ?? 0) ||\n isLifeTimeCurve(v.orbital.y ?? 0) ||\n isLifeTimeCurve(v.orbital.z ?? 0) ||\n v.orbital.x !== 0 ||\n v.orbital.y !== 0 ||\n v.orbital.z !== 0),\n noise: normalizedConfig.noise.isActive,\n forceFields: forceFieldCount > 0,\n collisionPlanes: collisionPlaneCount > 0,\n };\n\n // Shared decoder (also used for sub-emitter children) - nested ShapeConfig\n // branches + start values, arcs / angles in degrees.\n const shapeParams: ShapeEmitParams = encodeShapeEmitParams(\n normalizedConfig,\n particleSystemId\n );\n\n // Raw axis values (constants / random ranges / curves) for the seed-based\n // per-particle axis derivation in the kernels (oracle-parity randomness).\n const velocityValues = {\n linear: [v.linear.x as never, v.linear.y as never, v.linear.z as never],\n orbital: [\n v.orbital.x as never,\n v.orbital.y as never,\n v.orbital.z as never,\n ],\n } as const;\n\n // Trail ring integer metadata (atomic<u32>): two cursor/count words.\n if (trailDesc && !trailDesc.meta) {\n trailDesc.meta = new StorageBufferAttribute(\n new Uint32Array(Math.max(1, maxParticles) * 2),\n 1\n );\n }\n\n const built = createModifierStorageBuffers(\n maxParticles,\n instanced,\n bakedCurves.data,\n flags.forceFields,\n flags.collisionPlanes,\n trailDesc ? trailDesc.length : 0\n );\n if (trailDesc && built.buffers.trailMeta) {\n trailDesc.meta = built.buffers.trailMeta;\n }\n\n return createModifierComputeUpdate(\n built.buffers,\n maxParticles,\n bakedCurves,\n flags,\n shapeParams,\n forceFieldCount,\n collisionPlaneCount,\n subFifos ?? [],\n trailDesc,\n velocityValues\n );\n}\n\n","import { registerTSLMaterialFactory } from '@cyberluke/three-particles';\nimport {\n assertNamed,\n normalizeVector2Value,\n normalizeTextureValue,\n normalizeDepthTextureValue,\n normalizeBackgroundToVector3,\n resolveWebGPUEffectiveRendererType,\n} from '@cyberluke/three-particles';\nimport { encodeCollisionPlanesForGPU } from './js/effects/three-particles/webgpu/compute-collision-planes.js';\nimport { encodeForceFieldsForGPU } from './js/effects/three-particles/webgpu/compute-force-fields.js';\nimport {\n pcgRawU32,\n pcg01,\n mixBirthSeed,\n randomChannel,\n nextSystemSeed,\n CH,\n} from './js/effects/three-particles/webgpu/compute-modifiers.js';\nimport {\n createTSLParticleMaterial,\n createTSLTrailMaterial,\n createComputePipeline,\n createModifierStorageBuffers,\n createSubEmitterInitUpdate,\n createSubEmitterFifoAttribute,\n createTrailRibbonUpdate,\n encodeShapeEmitParams,\n subEmitterWindowSize,\n} from './js/effects/three-particles/webgpu/tsl-materials.js';\n\n// Re-export individual functions for power users who do not want the factory.\nexport {\n createTSLParticleMaterial,\n createTSLTrailMaterial,\n createComputePipeline,\n createModifierStorageBuffers,\n createSubEmitterInitUpdate,\n createSubEmitterFifoAttribute,\n createTrailRibbonUpdate,\n encodeShapeEmitParams,\n subEmitterWindowSize,\n encodeForceFieldsForGPU,\n encodeCollisionPlanesForGPU,\n pcgRawU32,\n pcg01,\n mixBirthSeed,\n randomChannel,\n nextSystemSeed,\n CH,\n assertNamed,\n normalizeVector2Value,\n normalizeTextureValue,\n normalizeDepthTextureValue,\n normalizeBackgroundToVector3,\n resolveWebGPUEffectiveRendererType,\n};\n\n/**\n * Registers the TSL material + compute-pipeline factories against a specific\n * `WebGPURenderer` instance. Returns `true` when registration took place;\n * `false` when the supplied renderer is not compute-capable (e.g. WebGL2\n * fallback), in which case every subsequent `createParticleSystem(...)` call\n * throws a clear \"no CPU fallback\" error.\n */\nexport function enableWebGPU(renderer?: unknown): boolean {\n const factory: Parameters<typeof registerTSLMaterialFactory>[0] = {\n createTSLParticleMaterial: createTSLParticleMaterial as never,\n createTSLTrailMaterial: createTSLTrailMaterial as never,\n createComputePipeline: createComputePipeline as never,\n encodeForceFieldsForGPU,\n encodeCollisionPlanesForGPU,\n createSubEmitterFifoAttribute: createSubEmitterFifoAttribute as never,\n createSubEmitterInitUpdate: createSubEmitterInitUpdate as never,\n createTrailRibbonUpdate: createTrailRibbonUpdate as never,\n encodeShapeEmitParams: encodeShapeEmitParams as never,\n };\n return registerTSLMaterialFactory(\n factory,\n renderer !== undefined ? { renderer } : undefined\n );\n}\n"]}