@neutrinoparticles/js-v1.1-phaser 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +212 -0
- package/dist/DataTextureManager.d.ts +32 -0
- package/dist/Effect.d.ts +76 -0
- package/dist/EffectModel.d.ts +27 -0
- package/dist/File.d.ts +18 -0
- package/dist/GamePlugin.d.ts +27 -0
- package/dist/NeutrinoContext.d.ts +88 -0
- package/dist/NeutrinoRenderer.d.ts +54 -0
- package/dist/PerspectiveProjection.d.ts +65 -0
- package/dist/gl1/DataTextureManagerGL1.d.ts +23 -0
- package/dist/gl1/MetaTextureManager.d.ts +9 -0
- package/dist/index.d.ts +43 -0
- package/dist/neutrinoparticles.js-v1.1-phaser.cjs.js +1169 -0
- package/dist/neutrinoparticles.js-v1.1-phaser.cjs.js.map +1 -0
- package/dist/neutrinoparticles.js-v1.1-phaser.d.ts +481 -0
- package/dist/neutrinoparticles.js-v1.1-phaser.es.js +2105 -0
- package/dist/neutrinoparticles.js-v1.1-phaser.es.js.map +1 -0
- package/dist/neutrinoparticles.js-v1.1-phaser.umd.js +1169 -0
- package/dist/neutrinoparticles.js-v1.1-phaser.umd.js.map +1 -0
- package/dist/types.d.ts +64 -0
- package/package.json +56 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neutrinoparticles.js-v1.1-phaser.cjs.js","sources":["../src/shaders/particle.vert?raw","../src/shaders/particle.frag?raw","../src/shaders/particle_gl1.vert?raw","../src/shaders/particle_gl1.frag?raw","../src/NeutrinoContext.ts","../src/GamePlugin.ts","../src/EffectModel.ts","../src/File.ts","../src/types.ts","../src/DataTextureManager.ts","../src/gl1/MetaTextureManager.ts","../src/gl1/DataTextureManagerGL1.ts","../src/NeutrinoRenderer.ts","../src/Effect.ts","../src/PerspectiveProjection.ts","../src/index.ts"],"sourcesContent":["export default \"#version 300 es\\nprecision highp float;\\n\\nuniform sampler2D uDataTexture;\\nuniform int uDataTextureWidth;\\nuniform vec3 uCameraRight;\\nuniform vec3 uCameraUp;\\nuniform vec3 uCameraDir;\\nuniform mat4 uViewProjMatrix;\\nuniform mat4 uModelMatrix;\\nuniform float uViewportAspect; // viewport width / height — strip-only\\nuniform vec4 uTexRemaps[8];\\n\\nconst vec2 ORIGIN_MUL[4] = vec2[4](\\n vec2(-1.0, 0.0),\\n vec2(-1.0, -1.0),\\n vec2(0.0, -1.0),\\n vec2(0.0, 0.0)\\n);\\n\\nconst vec2 INV_ORIGIN_MUL[4] = vec2[4](\\n vec2(0.0, 1.0),\\n vec2(0.0, 0.0),\\n vec2(1.0, 0.0),\\n vec2(1.0, 1.0)\\n);\\n\\nconst vec2 TEX_COORD[4] = vec2[4](\\n vec2(0.0, 0.0),\\n vec2(0.0, 1.0),\\n vec2(1.0, 1.0),\\n vec2(1.0, 0.0)\\n);\\n\\nout vec2 vTexCoord;\\nout vec4 vColor;\\nflat out int vBatchTextureIndex;\\n// Atlas slot rect (origin.xy, extent.zw) used by the strip path to wrap\\n// U inside its own slot at the fragment stage. Quad path keeps the old\\n// vertex-side remap so quad sampling stays bit-perfect with prior IBCT\\n// snapshots. The flag distinguishes the two paths in the fragment.\\nflat out vec4 vAtlasRemap;\\nflat out int vStripPath;\\n\\nvec4 fetchTexel(int globalTexelIndex) {\\n int x = globalTexelIndex % uDataTextureWidth;\\n int y = globalTexelIndex / uDataTextureWidth;\\n return texelFetch(uDataTexture, ivec2(x, y), 0);\\n}\\n\\n// Strip geometry helpers (port of GPU33 makeScreenSpaceStrip).\\n// 2D screen-space variant — PIXI7 renderer is 2D, world Z is dropped at gl_Position.\\nvec2 stripOrtho(vec2 v) {\\n return vec2(-v.y, v.x);\\n}\\n\\nvoid main() {\\n int vertexIndex = gl_VertexID % 4;\\n int particleIndex = gl_VertexID / 4;\\n\\n int baseTexel = particleIndex * 4;\\n\\n vec4 t0 = fetchTexel(baseTexel + 0);\\n vec4 t1 = fetchTexel(baseTexel + 1);\\n vec4 t2 = fetchTexel(baseTexel + 2);\\n vec4 t3 = fetchTexel(baseTexel + 3);\\n\\n // Texel 0: flags (uint32 bits in float), posX, posY, posZ\\n uint flags = floatBitsToUint(t0.r);\\n vec3 position = t0.gba;\\n uint rotationType = (flags >> 8u) & 3u;\\n uint ctorType = (flags >> 10u) & 3u;\\n int batchTexIdx = int(flags & 0xFFu);\\n vBatchTextureIndex = batchTexIdx;\\n\\n // ─── Strip path ───────────────────────────────────────────────────────\\n // ctorType: 0 = Quad, 1 = StripCur, 2 = StripNex.\\n // Strip meta records come in pairs: meta_cur describes the \\\"p1\\\" end and\\n // meta_nex describes the \\\"p2\\\" end of one segment. Sibling meta is at the\\n // adjacent texel base (cur + 4 = nex; nex - 4 = cur). p0 (= prev pair's\\n // p1) and p3 (= next pair's p2) are reached via neighborIdxP0 / P3 stored\\n // as uint32 in t3.g / t3.b. Boundary particles use self-reference: when\\n // p0==p1 the shader sets dir01=dir12 and the knee degenerates.\\n //\\n // rotationType handling in the strip path:\\n // 0 (Faced): screen-space ortho to dir12 — equivalent to camera-faced\\n // billboard normal in a 2D camera setup.\\n // 1 (Free): the quaternion stored in texel 2 nominally encodes a 3D\\n // orientation. The current PIXI7 renderer is fundamentally\\n // 2D (worldPos.z is dropped at gl_Position for quads), so\\n // the quat is read but its 3D y-axis is projected to screen\\n // and used as the section normal. When the projection\\n // degenerates (looking along the y-axis) we fall back to\\n // the screen-space ortho. Real 3D free-rotation requires a\\n // future 3D pipeline; this is documented as a deviation in\\n // docs/tdd/TDD_80-js-v1.1-constructor-strip.md.\\n if (ctorType >= 1u) {\\n bool isCur = (ctorType == 1u);\\n int siblingTexel = isCur ? (baseTexel + 4) : (baseTexel - 4);\\n vec4 ts0 = fetchTexel(siblingTexel + 0);\\n vec4 ts1 = fetchTexel(siblingTexel + 1);\\n vec4 ts3 = fetchTexel(siblingTexel + 3);\\n\\n // p1 always = position of the meta_cur end; p2 = meta_nex end.\\n vec3 p1 = isCur ? t0.gba : ts0.gba;\\n vec3 p2 = isCur ? ts0.gba : t0.gba;\\n\\n float halfSize1 = isCur ? t1.r : ts1.r;\\n float halfSize2 = isCur ? ts1.r : t1.r;\\n float texU1 = isCur ? t1.g : ts1.g;\\n float texU2 = isCur ? ts1.g : t1.g;\\n\\n // Color: meta_cur stores color of p1, meta_nex stores color of p2.\\n uint packedColorCur = floatBitsToUint(isCur ? t3.r : ts3.r);\\n uint packedColorNex = floatBitsToUint(isCur ? ts3.r : t3.r);\\n vec4 color1 = vec4(\\n float(packedColorCur & 0xFFu) / 255.0,\\n float((packedColorCur >> 8u) & 0xFFu) / 255.0,\\n float((packedColorCur >> 16u) & 0xFFu) / 255.0,\\n float((packedColorCur >> 24u) & 0xFFu) / 255.0);\\n vec4 color2 = vec4(\\n float(packedColorNex & 0xFFu) / 255.0,\\n float((packedColorNex >> 8u) & 0xFFu) / 255.0,\\n float((packedColorNex >> 16u) & 0xFFu) / 255.0,\\n float((packedColorNex >> 24u) & 0xFFu) / 255.0);\\n\\n // neighborIdxP0 / neighborIdxP3 are stored on every meta of a pair\\n // (both meta_cur and meta_nex hold the same pair of indices), so we\\n // can read them from either self or sibling.\\n //\\n // Runtime convention (`_constructStripParticles` in system.js):\\n // neighborIdxP0 = global texel index of the position of W\\n // (= lnkdPrev(X)); boundary sentinel = curTexIdx\\n // (the pair's meta_cur texel index).\\n // neighborIdxP3 = global texel index of the position of Z\\n // (= lnkdNext(Y)); boundary sentinel = curTexIdx.\\n // Both are direct position-texel indices (NOT pair-cur indices that\\n // would need a +1 offset for the nex slot). Boundary detection uses\\n // selfPairCurTexel for both.\\n uint neighborIdxP0 = floatBitsToUint(isCur ? t3.g : ts3.g);\\n uint neighborIdxP3 = floatBitsToUint(isCur ? ts3.b : t3.b);\\n uint selfPairCurTexel = uint(isCur ? baseTexel : siblingTexel) / 4u;\\n\\n vec3 p0 = (neighborIdxP0 == selfPairCurTexel)\\n ? p1\\n : fetchTexel(int(neighborIdxP0) * 4 + 0).gba;\\n vec3 p3 = (neighborIdxP3 == selfPairCurTexel)\\n ? p2\\n : fetchTexel(int(neighborIdxP3) * 4 + 0).gba;\\n\\n // Segment frame. Two completely separate frames depending on\\n // rotationType — MIRROR of preview3 DataTextureRenderer3 (the editor's\\n // own JS1.1 renderer) so all data-texture renderers stay identical:\\n // Faced (rotationType 0/2): screen-space NDC frame around dir12.\\n // Free (rotationType 1): FULL world-space 3D frame (make3DStrip);\\n // the ribbon keeps its 3D orientation from the quat and Z collapses\\n // naturally only at projection (front-planar is a camera artifact,\\n // not a shader simplification). Mixing world-space section into a\\n // screen-space miter distorts sharp bends and makes geometry track\\n // the camera even with a static quat — Free stays camera-independent.\\n mat4 mvpMatrix = uViewProjMatrix * uModelMatrix;\\n bool isFreeRotation = (rotationType == 1u);\\n\\n // Anchor projections — both branches use them for gl_Position.\\n vec4 sp1 = mvpMatrix * vec4(p1, 1.0);\\n vec4 sp2 = mvpMatrix * vec4(p2, 1.0);\\n\\n // Near-plane guard (Faced only; the world-space Free frame is unaffected\\n // by the sign of w). Forces a discard outside the [-w,w] cube at the end.\\n bool nearPlaneClipped = (sp1.w < 1e-3) || (sp2.w < 1e-3);\\n\\n // Aspect correction so the 2D Faced ortho gives visually-perpendicular\\n // dirs on non-square viewports (inverted before gl_Position).\\n vec2 aspectMul = vec2(1.0, 1.0 / max(uViewportAspect, 1e-6));\\n\\n vec4 ts2 = fetchTexel(siblingTexel + 2);\\n vec4 q1 = isCur ? t2 : ts2;\\n vec4 q2 = isCur ? ts2 : t2;\\n\\n // Frame outputs: Faced fills the 2D (k/b/IK), Free fills the 3D\\n // (worldK/B/IK); the vertex ladder picks the right one per gl_Position.\\n vec3 worldK1, worldB1, worldIK1, worldK2, worldB2, worldIK2;\\n vec2 k1, b1, IK1, k2, b2, IK2;\\n float Bmul1, Bmul2, kb1, kb2;\\n bool noKnee1, noKnee2;\\n float pathLen12; // len12 in the active frame's units (NDC for Faced, world for Free)\\n\\n if (isFreeRotation) {\\n // World-space frame (mirror of GPU33 make3DStrip). Section normal\\n // n = quat z-axis (local Z ⟂ ribbon plane); ribbon lies in local XY\\n // (travel along local X, width along local Y). B = cross(dir12, n).\\n float xz1 = 2.0 * q1.x * q1.z;\\n float wy1 = 2.0 * q1.w * q1.y;\\n float yz1 = 2.0 * q1.y * q1.z;\\n float wx1 = 2.0 * q1.w * q1.x;\\n vec3 n1 = vec3(xz1 + wy1, yz1 - wx1, 1.0 - 2.0 * (q1.x * q1.x + q1.y * q1.y));\\n float xz2 = 2.0 * q2.x * q2.z;\\n float wy2 = 2.0 * q2.w * q2.y;\\n float yz2 = 2.0 * q2.y * q2.z;\\n float wx2 = 2.0 * q2.w * q2.x;\\n vec3 n2 = vec3(xz2 + wy2, yz2 - wx2, 1.0 - 2.0 * (q2.x * q2.x + q2.y * q2.y));\\n\\n vec3 wp01 = p1 - p0;\\n vec3 wp12 = p2 - p1;\\n vec3 wp23 = p3 - p2;\\n float wlen01 = length(wp01);\\n float wlen12 = length(wp12);\\n float wlen23 = length(wp23);\\n vec3 wdir12 = (wlen12 > 1e-6) ? (wp12 / wlen12) : vec3(1.0, 0.0, 0.0);\\n vec3 wdir01 = (wlen01 > 1e-6) ? (wp01 / wlen01) : wdir12;\\n vec3 wdir23 = (wlen23 > 1e-6) ? (wp23 / wlen23) : wdir12;\\n noKnee1 = dot(wdir01, wdir12) > 0.999;\\n noKnee2 = dot(wdir12, wdir23) > 0.999;\\n pathLen12 = wlen12;\\n\\n if (!noKnee1) {\\n vec3 B1raw = normalize(cross(wdir12, n1));\\n vec3 c1 = normalize(cross(wdir01, wdir12));\\n float Kmul1 = sign(dot(c1, n1));\\n vec3 K1 = Kmul1 * normalize(cross(wdir01 + wdir12, n1));\\n Bmul1 = sign(dot(B1raw, K1));\\n vec3 B1 = B1raw * Bmul1;\\n float ik1 = halfSize1 / max(dot(B1, K1), 1e-6);\\n if (dot(-wdir01, ik1 * -K1) > wlen01) ik1 = wlen01;\\n if (dot( wdir12, ik1 * -K1) > wlen12) ik1 = wlen12;\\n worldK1 = p1 + K1 * halfSize1;\\n worldB1 = p1 + B1 * halfSize1;\\n worldIK1 = p1 - K1 * ik1;\\n kb1 = distance(worldK1, worldB1);\\n } else {\\n Bmul1 = 1.0;\\n vec3 B1 = normalize(cross(wdir01 + wdir12, n1));\\n worldK1 = p1 + B1 * halfSize1;\\n worldB1 = worldK1;\\n worldIK1 = p1 - B1 * halfSize1;\\n kb1 = 0.0;\\n }\\n\\n if (!noKnee2) {\\n vec3 B2raw = normalize(cross(wdir12, n2));\\n vec3 c2 = normalize(cross(wdir12, wdir23));\\n float Kmul2 = sign(dot(c2, n2));\\n vec3 K2 = Kmul2 * normalize(cross(wdir12 + wdir23, n2));\\n Bmul2 = sign(dot(B2raw, K2));\\n vec3 B2 = B2raw * Bmul2;\\n float ik2 = halfSize2 / max(dot(B2, K2), 1e-6);\\n if (dot(-wdir12, ik2 * -K2) > wlen12) ik2 = wlen12;\\n if (dot( wdir23, ik2 * -K2) > wlen23) ik2 = wlen23;\\n worldK2 = p2 + K2 * halfSize2;\\n worldB2 = p2 + B2 * halfSize2;\\n worldIK2 = p2 - K2 * ik2;\\n kb2 = distance(worldK2, worldB2);\\n } else {\\n Bmul2 = 1.0;\\n vec3 B2 = normalize(cross(wdir12 + wdir23, n2));\\n worldK2 = p2 + B2 * halfSize2;\\n worldB2 = worldK2;\\n worldIK2 = p2 - B2 * halfSize2;\\n kb2 = 0.0;\\n }\\n } else {\\n // Faced: screen-space NDC frame around dir12.\\n vec4 sp0 = mvpMatrix * vec4(p0, 1.0);\\n vec4 sp3 = mvpMatrix * vec4(p3, 1.0);\\n vec2 ndc0 = (sp0.xy / sp0.w) * aspectMul;\\n vec2 ndc1 = (sp1.xy / sp1.w) * aspectMul;\\n vec2 ndc2 = (sp2.xy / sp2.w) * aspectMul;\\n vec2 ndc3 = (sp3.xy / sp3.w) * aspectMul;\\n\\n vec2 d01 = ndc1 - ndc0;\\n vec2 d12 = ndc2 - ndc1;\\n vec2 d23 = ndc3 - ndc2;\\n float len01 = length(d01);\\n float len12 = length(d12);\\n float len23 = length(d23);\\n vec2 dir12 = (len12 > 1e-6) ? (d12 / len12) : vec2(1.0, 0.0);\\n vec2 dir01 = (len01 > 1e-6) ? (d01 / len01) : dir12;\\n vec2 dir23 = (len23 > 1e-6) ? (d23 / len23) : dir12;\\n noKnee1 = dot(dir01, dir12) > 0.999;\\n noKnee2 = dot(dir12, dir23) > 0.999;\\n pathLen12 = len12;\\n\\n // Section magnitude: project camera_up*halfSize per anchor into NDC.\\n vec4 spU1 = mvpMatrix * vec4(p1 + uCameraUp * halfSize1, 1.0);\\n vec4 spU2 = mvpMatrix * vec4(p2 + uCameraUp * halfSize2, 1.0);\\n float ndcHalfSize1 = length((spU1.xy / spU1.w) * aspectMul - ndc1);\\n float ndcHalfSize2 = length((spU2.xy / spU2.w) * aspectMul - ndc2);\\n\\n vec2 B = stripOrtho(dir12);\\n if (!noKnee1) {\\n float Kmul1 = -sign(dot(stripOrtho(dir01), dir12));\\n vec2 K1 = Kmul1 * normalize(stripOrtho(dir01 + dir12));\\n Bmul1 = sign(dot(B, K1));\\n vec2 B1 = B * Bmul1;\\n float ik1 = ndcHalfSize1 / max(dot(B1, K1), 1e-6);\\n if (dot(-dir01, ik1 * -K1) > len01) ik1 = len01;\\n if (dot(dir12, ik1 * -K1) > len12) ik1 = len12;\\n k1 = ndc1 + K1 * ndcHalfSize1;\\n b1 = ndc1 + B1 * ndcHalfSize1;\\n IK1 = ndc1 - K1 * ik1;\\n kb1 = distance(k1, b1);\\n } else {\\n vec2 B1 = normalize(stripOrtho(dir01 + dir12));\\n Bmul1 = 1.0;\\n k1 = ndc1 + B1 * ndcHalfSize1;\\n b1 = k1;\\n IK1 = ndc1 - B1 * ndcHalfSize1;\\n kb1 = 0.0;\\n }\\n if (!noKnee2) {\\n float Kmul2 = -sign(dot(stripOrtho(dir12), dir23));\\n vec2 K2 = Kmul2 * normalize(stripOrtho(dir12 + dir23));\\n Bmul2 = sign(dot(B, K2));\\n vec2 B2 = B * Bmul2;\\n float ik2 = ndcHalfSize2 / max(dot(B2, K2), 1e-6);\\n if (dot(-dir12, ik2 * -K2) > len12) ik2 = len12;\\n if (dot(dir23, ik2 * -K2) > len23) ik2 = len23;\\n k2 = ndc2 + K2 * ndcHalfSize2;\\n b2 = ndc2 + B2 * ndcHalfSize2;\\n IK2 = ndc2 - K2 * ik2;\\n kb2 = distance(k2, b2);\\n } else {\\n vec2 B2 = normalize(stripOrtho(dir12 + dir23));\\n Bmul2 = 1.0;\\n k2 = ndc2 + B2 * ndcHalfSize2;\\n b2 = k2;\\n IK2 = ndc2 - B2 * ndcHalfSize2;\\n kb2 = 0.0;\\n }\\n }\\n\\n // V coords (mirror of preview3 / GPU33 make*Strip):\\n // V at outer knee (k) = (Bmul + 1) * 0.5\\n // V at inner knee (IK) = 1 - V_outer ; bend (b) = outer\\n float Vtop1 = (Bmul1 + 1.0) * 0.5;\\n float Vbot1 = 1.0 - Vtop1;\\n float Vtop2 = (Bmul2 + 1.0) * 0.5;\\n float Vbot2 = 1.0 - Vtop2;\\n\\n // Vertex layout per meta (4 vertices × IBO [0,1,2, 0,2,3] = 2 tris):\\n //\\n // Bmul1*Bmul2 ≥ 0 (knees same side):\\n // meta_cur: v0=b1, v1=k1, v2=IK1, v3=b2\\n // T1=(b1,k1,IK1) — knee at p1 ✓\\n // T2=(b1,IK1,b2) — top half segment ✓\\n // meta_nex: v0=b2, v1=IK1, v2=IK2, v3=k2\\n // T1=(b2,IK1,IK2) — bottom half segment ✓\\n // T2=(b2,IK2,k2) — knee at p2 ✓\\n //\\n // Bmul1*Bmul2 < 0 (knees opposite sides):\\n // meta_cur: v0=b1, v1=k1, v2=IK1, v3=IK2\\n // T1=(b1,k1,IK1) ✓\\n // T2=(b1,IK1,IK2) — diagonal cross ✓\\n // meta_nex: v0=IK2, v1=IK1, v2=b2, v3=k2\\n // T1=(IK2,IK1,b2) — diagonal cross ✓\\n // T2=(IK2,b2,k2) — knee at p2 ✓\\n //\\n // The shader picks v0..v3 based on (isCur, vertexIndex, sign(Bmul1*Bmul2)).\\n bool sameSide = (Bmul1 * Bmul2 >= 0.0);\\n // Distance for U interpolation along the bend point. Clamped to a\\n // small epsilon to avoid NaN on fully degenerate segments (p1≈p2 or\\n // 1-particle \\\"strip\\\" reached through self-references).\\n float dPath = max(sameSide ? (kb1 + pathLen12 + kb2) : (kb1 + pathLen12), 1e-6);\\n float dPathNex = max(sameSide ? dPath : (kb2 + pathLen12), 1e-6);\\n\\n // Per-vertex colour follows the same kb / dPath ratio as texU.\\n // Knee corners (k1/IK1, k2/IK2) are anchored to their own particle;\\n // bend points (b1/b2) blend between color1 and color2 by the same\\n // fraction the U coord uses. Opposite-side bend uses the shorter\\n // denominator (kb*+len12) and IK on the far end is the other colour.\\n float bUcur = kb1 / dPath;\\n float bUnex = sameSide ? (kb2 / dPath) : (kb2 / dPathNex);\\n vec4 colorB1 = mix(color1, color2, bUcur);\\n vec4 colorB2 = mix(color2, color1, bUnex);\\n\\n // vertPos holds the picked vertex in the 2D Faced frame (NDC);\\n // vertPos3D holds it in world space for Free. A single ladder over the\\n // IBO layout picks both, then gl_Position chooses by isFreeRotation.\\n vec2 vertPos;\\n vec3 vertPos3D = vec3(0.0);\\n vec2 vertUV;\\n vec4 vertColor;\\n if (isCur) {\\n // meta_cur vertices\\n if (vertexIndex == 0) {\\n vertPos = b1; vertPos3D = worldB1;\\n vertUV = vec2(mix(texU1, texU2, kb1 / dPath), Vtop1);\\n vertColor = colorB1;\\n } else if (vertexIndex == 1) {\\n vertPos = k1; vertPos3D = worldK1;\\n vertUV = vec2(texU1, Vtop1);\\n vertColor = color1;\\n } else if (vertexIndex == 2) {\\n vertPos = IK1; vertPos3D = worldIK1;\\n vertUV = vec2(texU1, Vbot1);\\n vertColor = color1;\\n } else {\\n // v3 = b2 (sameSide) or IK2 (different side)\\n if (sameSide) {\\n vertPos = b2; vertPos3D = worldB2;\\n vertUV = vec2(mix(texU2, texU1, kb2 / dPath), Vtop2);\\n vertColor = colorB2;\\n } else {\\n vertPos = IK2; vertPos3D = worldIK2;\\n vertUV = vec2(texU2, Vbot2);\\n vertColor = color2;\\n }\\n }\\n // noKnee fallback: collapse to k1/IK1 to produce degenerate segments.\\n if (noKnee1) {\\n if (vertexIndex == 0) { vertPos = k1; vertPos3D = worldK1; vertUV = vec2(texU1, Vtop1); vertColor = color1; }\\n }\\n } else {\\n // meta_nex vertices\\n if (sameSide) {\\n if (vertexIndex == 0) { vertPos = b2; vertPos3D = worldB2; vertUV = vec2(mix(texU2, texU1, kb2 / dPath), Vtop2); vertColor = colorB2; }\\n else if (vertexIndex == 1) { vertPos = IK1; vertPos3D = worldIK1; vertUV = vec2(texU1, Vbot1); vertColor = color1; }\\n else if (vertexIndex == 2) { vertPos = IK2; vertPos3D = worldIK2; vertUV = vec2(texU2, Vbot2); vertColor = color2; }\\n else { vertPos = k2; vertPos3D = worldK2; vertUV = vec2(texU2, Vtop2); vertColor = color2; }\\n } else {\\n if (vertexIndex == 0) { vertPos = IK2; vertPos3D = worldIK2; vertUV = vec2(texU2, Vbot2); vertColor = color2; }\\n else if (vertexIndex == 1) { vertPos = IK1; vertPos3D = worldIK1; vertUV = vec2(texU1, Vbot1); vertColor = color1; }\\n else if (vertexIndex == 2) { vertPos = b2; vertPos3D = worldB2; vertUV = vec2(mix(texU2, texU1, kb2 / dPathNex), Vtop2); vertColor = colorB2; }\\n else { vertPos = k2; vertPos3D = worldK2; vertUV = vec2(texU2, Vtop2); vertColor = color2; }\\n }\\n if (noKnee2) {\\n if (vertexIndex == 3) { vertPos = IK2; vertPos3D = worldIK2; vertUV = vec2(texU2, Vbot2); vertColor = color2; }\\n }\\n }\\n\\n // Free projects the world-space vertex through MVP directly; Faced\\n // reconstructs clip space from aspect-corrected NDC (mirror of preview3).\\n if (isFreeRotation) {\\n gl_Position = mvpMatrix * vec4(vertPos3D, 1.0);\\n } else if (nearPlaneClipped) {\\n // At least one anchor is at / behind the near plane → the NDC math\\n // is garbage; emit a point outside the [-w,w] cube to discard.\\n gl_Position = vec4(2.0, 2.0, 2.0, 1.0);\\n } else {\\n // Inverse aspect, × anchor w; reuse anchor z/w for a consistent\\n // perspective divide within a pair-half.\\n vec4 anchorProj = isCur ? sp1 : sp2;\\n vec2 vertPosClip = vertPos / aspectMul;\\n gl_Position = vec4(vertPosClip * anchorProj.w, anchorProj.zw);\\n }\\n vColor = vertColor;\\n\\n // Strip emits *raw* (U, V) — fragment wraps U via fract() before\\n // scaling into the atlas slot. Otherwise a Distance/PerSegment U\\n // > 1 would step into the neighbouring atlas tile.\\n vTexCoord = vertUV;\\n vAtlasRemap = uTexRemaps[batchTexIdx];\\n vStripPath = 1;\\n return;\\n }\\n // ─── End strip path ───────────────────────────────────────────────────\\n\\n // Texel 1: originX, originY, sizeX, sizeY\\n vec2 origin = t1.rg;\\n vec2 size = t1.ba;\\n\\n // Texel 3: packed colorRGBA (uint32 bits in float), packed gridConfig (uint32 bits), gridIndex\\n uint packedColor = floatBitsToUint(t3.r);\\n vColor = vec4(\\n float(packedColor & 0xFFu) / 255.0,\\n float((packedColor >> 8u) & 0xFFu) / 255.0,\\n float((packedColor >> 16u) & 0xFFu) / 255.0,\\n float((packedColor >> 24u) & 0xFFu) / 255.0\\n );\\n\\n uint gridConfig = floatBitsToUint(t3.g);\\n float gridWidth = max(float(gridConfig & 0xFFFFu), 1.0);\\n float gridHeight = max(float((gridConfig >> 16u) & 0xFFFFu), 1.0);\\n // gridIndex must be truncated to an integer to pick a single cell —\\n // otherwise a fractional index (animated frames) blends UVs from two\\n // adjacent cells horizontally (gx = mod(frac, W) leaks the fractional\\n // part into the column offset). Matches the original int(*data.inIndex_) cast.\\n float gridIndex = floor(t3.b);\\n\\n // Texel 2: rotation\\n vec3 xaxis, yaxis;\\n\\n if (rotationType == 0u) {\\n float angle = t2.r;\\n float rad = angle * 3.14159265 / 180.0;\\n float s = -sin(rad);\\n float c = cos(rad);\\n xaxis = uCameraRight * c + uCameraUp * s;\\n yaxis = -uCameraRight * s + uCameraUp * c;\\n } else if (rotationType == 1u) {\\n vec4 q = t2;\\n float z2 = 2.0 * q.z * q.z;\\n float xy = 2.0 * q.x * q.y;\\n float wz = 2.0 * q.w * q.z;\\n xaxis = vec3(\\n 1.0 - 2.0 * q.y * q.y - z2,\\n xy + wz,\\n 2.0 * q.x * q.z - 2.0 * q.w * q.y);\\n yaxis = vec3(\\n xy - wz,\\n 1.0 - 2.0 * q.x * q.x - z2,\\n 2.0 * q.y * q.z + 2.0 * q.w * q.x);\\n } else {\\n xaxis = cross(uCameraUp, uCameraDir);\\n yaxis = uCameraUp;\\n }\\n\\n xaxis *= size.x;\\n yaxis *= size.y;\\n\\n vec2 vOrigin = ORIGIN_MUL[vertexIndex] * origin\\n + INV_ORIGIN_MUL[vertexIndex] * (vec2(1.0) - origin);\\n vec3 posDisp = vOrigin.x * xaxis + vOrigin.y * yaxis;\\n\\n mat4 mvpMatrix = uViewProjMatrix * uModelMatrix;\\n vec3 worldPos = position + posDisp;\\n gl_Position = mvpMatrix * vec4(worldPos.xy, 0.0, 1.0);\\n\\n // Texture coordinates with grid + atlas remap\\n vec2 baseTexCoord = TEX_COORD[vertexIndex];\\n\\n float gx = mod(gridIndex, gridWidth);\\n float gy = floor(gridIndex / gridWidth);\\n float cellW = 1.0 / gridWidth;\\n float cellH = 1.0 / gridHeight;\\n\\n vec2 gridTexCoord = vec2(\\n (gx + baseTexCoord.x) * cellW,\\n 1.0 - (gy + 1.0 - baseTexCoord.y) * cellH\\n );\\n\\n // Quad keeps the old vertex-side atlas remap so existing IBCT\\n // snapshots (interpolated vTexCoord = final atlas UV) stay bit-\\n // perfect identical. Strip uses the fragment-side wrap path\\n // (vStripPath = 1) for atlas-aware tiling of accumulated U.\\n vec4 remap = uTexRemaps[batchTexIdx];\\n vTexCoord = remap.xy + gridTexCoord * remap.zw;\\n vAtlasRemap = remap; // unused by fragment when vStripPath == 0\\n vStripPath = 0;\\n}\\n\"","export default \"#version 300 es\\nprecision highp float;\\n\\nuniform sampler2D uTextures[8];\\n// Host scene-graph container/world alpha. The particle already carries its own\\n// per-particle alpha in vColor; this is the global multiplier (e.g. a faded\\n// parent). Mirrors JS1.0, which scaled vertex.color[3] by worldAlpha.\\nuniform float uWorldAlpha;\\n\\nin vec2 vTexCoord;\\nin vec4 vColor;\\nflat in int vBatchTextureIndex;\\nflat in vec4 vAtlasRemap;\\nflat in int vStripPath;\\n\\nout vec4 fragColor;\\n\\nvoid main() {\\n // Quad path (vStripPath == 0): vTexCoord is already the final atlas\\n // UV multiplied through in the vertex stage — kept bit-perfect with\\n // the original quad shader so IBCT snapshots remain identical.\\n //\\n // Strip path (vStripPath == 1): vTexCoord is a raw [0;..]-domain UV\\n // because the strip's accumulated U can exceed 1 (Distance mode\\n // accumulates dist / repeat, PerSegment counts up by 1 per segment).\\n // We wrap U via mod-style fract per-pixel before scaling into the\\n // emitter's atlas slot, so it tiles inside the slot instead of\\n // bleeding into a neighbouring atlas tile. fract(1.0) == 0.0, so a\\n // plain fract() would collapse U == 1.0 to U == 0.0 — we leave\\n // exact-[0;1] U values alone and only wrap outside that range.\\n // Atlas-space gradients of the RAW (un-wrapped) strip U. Hoisted above the\\n // strip/quad branch so the derivatives are taken in uniform control flow.\\n // For the affine atlas remap, d(vec2(u,y)*remap.zw+remap.xy) == d(u,y)*remap.zw,\\n // so differentiate the incoming varying (branch-invariant) and scale.\\n vec2 tcDx = dFdx(vTexCoord);\\n vec2 tcDy = dFdy(vTexCoord);\\n vec2 gradX = tcDx * vAtlasRemap.zw;\\n vec2 gradY = tcDy * vAtlasRemap.zw;\\n\\n vec2 atlasUV;\\n // useGrad: strip atlas slot → sample with the un-wrapped-U gradients so the\\n // frac(u) discontinuity at a tile junction no longer poisons the mip/aniso\\n // LOD (the \\\"chewed\\\" column). Non-atlas strips (identity remap) and quads\\n // keep the implicit-LOD texture() sample so their baselines stay identical.\\n bool useGrad = false;\\n if (vStripPath == 0) {\\n atlasUV = vTexCoord;\\n } else {\\n float u = vTexCoord.x;\\n float wrappedU = u - floor(u);\\n if (u >= 0.0 && u <= 1.0) wrappedU = u;\\n atlasUV = vec2(wrappedU, vTexCoord.y) * vAtlasRemap.zw + vAtlasRemap.xy;\\n bool isAtlas = vAtlasRemap != vec4(0.0, 0.0, 1.0, 1.0);\\n useGrad = isAtlas;\\n }\\n\\n vec4 texColor;\\n // WebGL2 requires static indexing for sampler arrays.\\n if (vBatchTextureIndex == 0) texColor = useGrad ? textureGrad(uTextures[0], atlasUV, gradX, gradY) : texture(uTextures[0], atlasUV);\\n else if (vBatchTextureIndex == 1) texColor = useGrad ? textureGrad(uTextures[1], atlasUV, gradX, gradY) : texture(uTextures[1], atlasUV);\\n else if (vBatchTextureIndex == 2) texColor = useGrad ? textureGrad(uTextures[2], atlasUV, gradX, gradY) : texture(uTextures[2], atlasUV);\\n else if (vBatchTextureIndex == 3) texColor = useGrad ? textureGrad(uTextures[3], atlasUV, gradX, gradY) : texture(uTextures[3], atlasUV);\\n else if (vBatchTextureIndex == 4) texColor = useGrad ? textureGrad(uTextures[4], atlasUV, gradX, gradY) : texture(uTextures[4], atlasUV);\\n else if (vBatchTextureIndex == 5) texColor = useGrad ? textureGrad(uTextures[5], atlasUV, gradX, gradY) : texture(uTextures[5], atlasUV);\\n else if (vBatchTextureIndex == 6) texColor = useGrad ? textureGrad(uTextures[6], atlasUV, gradX, gradY) : texture(uTextures[6], atlasUV);\\n else texColor = useGrad ? textureGrad(uTextures[7], atlasUV, gradX, gradY) : texture(uTextures[7], atlasUV);\\n\\n fragColor = texColor * vColor;\\n // Apply host world alpha. texColor is premultiplied and the blend funcs use\\n // a src factor of ONE (NORMAL) / ONE,ONE (ADD), so the whole RGBA must be\\n // scaled — fading RGB, not just the alpha channel — to dim correctly in both\\n // alpha-blended and additive modes.\\n fragColor *= uWorldAlpha;\\n}\\n\"","export default \"// WebGL1 (GLSL ES 1.00) port of particle.vert — variant C: the RGBA32F data\\n// texture is sampled with texture2DLod + computed UV, the u32-bit-packed\\n// fields come from the RGBA8 meta texture (ES 1.00 has no floatBitsToUint),\\n// and vertex identity comes from the static aId attribute (no gl_VertexID).\\n// Design: docs/tdd/TDD_js-v1.1-webgl1.md §4.5.\\nprecision highp float;\\n\\nattribute float aId; // particleIndex * 4 + corner\\n\\nuniform sampler2D uDataTexture; // RGBA/FLOAT, 4 texels per particle\\nuniform sampler2D uMetaTexture; // RGBA8, same dimensions (meta texel i ~ data texel i)\\nuniform vec2 uDataTexSize;\\nuniform vec3 uCameraRight;\\nuniform vec3 uCameraUp;\\nuniform vec3 uCameraDir;\\nuniform mat4 uViewProjMatrix;\\nuniform mat4 uModelMatrix;\\nuniform float uViewportAspect; // viewport width / height — strip-only\\nuniform vec4 uTexRemaps[8];\\n\\nvarying vec2 vTexCoord;\\nvarying vec4 vColor;\\n// Constant across the 4 vertices of a particle, so plain (smooth) varyings\\n// interpolate to the same value — ES 1.00 has no `flat`. The fragment stage\\n// re-quantizes vBatchTextureIndex via floor(x + 0.5).\\nvarying float vBatchTextureIndex;\\nvarying vec4 vAtlasRemap;\\nvarying float vStripPath;\\n\\n// idx -> row/column with the x-range fix-up: floor(idx/W) is exact on an\\n// IEEE-correct driver for idx < 2^24 (TDD §4.7), the fix-up defends against\\n// the division imprecision GLSL ES 1.00 permits.\\nvec2 texelUv(float idx) {\\n float y = floor(idx / uDataTexSize.x);\\n float x = idx - y * uDataTexSize.x;\\n if (x < 0.0) { y -= 1.0; x += uDataTexSize.x; }\\n if (x >= uDataTexSize.x) { y += 1.0; x -= uDataTexSize.x; }\\n return (vec2(x, y) + 0.5) / uDataTexSize;\\n}\\n\\nvec4 fetchData(float idx) { return texture2DLod(uDataTexture, texelUv(idx), 0.0); }\\nvec4 fetchMeta(float idx) { return texture2DLod(uMetaTexture, texelUv(idx), 0.0); }\\n\\n// Exact byte recovery from an RGBA8 UNORM sample (b/255 is spec-exact).\\nfloat byteOf(float v) { return floor(v * 255.0 + 0.5); }\\n\\n// Strip geometry helper (port of GPU33 makeScreenSpaceStrip).\\nvec2 stripOrtho(vec2 v) {\\n return vec2(-v.y, v.x);\\n}\\n\\n// Corner tables (ES 1.00 has no const-array initializers — if-ladder like\\n// the CS1.2 GL cornerTables()).\\nvec2 originMul(float corner) {\\n if (corner < 0.5) return vec2(-1.0, 0.0);\\n if (corner < 1.5) return vec2(-1.0, -1.0);\\n if (corner < 2.5) return vec2(0.0, -1.0);\\n return vec2(0.0, 0.0);\\n}\\nvec2 invOriginMul(float corner) {\\n if (corner < 0.5) return vec2(0.0, 1.0);\\n if (corner < 1.5) return vec2(0.0, 0.0);\\n if (corner < 2.5) return vec2(1.0, 0.0);\\n return vec2(1.0, 1.0);\\n}\\nvec2 texCoordOf(float corner) {\\n if (corner < 0.5) return vec2(0.0, 0.0);\\n if (corner < 1.5) return vec2(0.0, 1.0);\\n if (corner < 2.5) return vec2(1.0, 1.0);\\n return vec2(1.0, 0.0);\\n}\\n\\nvoid main() {\\n // Canonical aId decomposition (exact for aId < 2^24, TDD §4.5).\\n float corner = mod(aId, 4.0);\\n float particleIndex = (aId - corner) * 0.25;\\n float baseTexel = particleIndex * 4.0;\\n\\n vec4 t0 = fetchData(baseTexel);\\n vec4 t1 = fetchData(baseTexel + 1.0);\\n vec4 t2 = fetchData(baseTexel + 2.0);\\n vec4 t3 = fetchData(baseTexel + 3.0);\\n\\n // Meta M0: flags bytes — [batchTexIdx, rotationType|ctorType bits, -, -].\\n vec4 m0 = fetchMeta(baseTexel);\\n float batchTexIdx = byteOf(m0.r);\\n float flagsByte1 = byteOf(m0.g);\\n float rotationType = mod(flagsByte1, 4.0); // bits 1:0\\n float ctorType = mod(floor(flagsByte1 * 0.25), 4.0); // bits 3:2\\n vBatchTextureIndex = batchTexIdx;\\n\\n vec3 position = t0.gba;\\n\\n // ─── Strip path ───────────────────────────────────────────────────────\\n // Port of the ES 3.00 strip branch (particle.vert). Same algorithm and\\n // record conventions; deltas are purely mechanical: texel fetches via\\n // texture2DLod, packed colors read directly from meta M1 (the sample IS\\n // the color), neighbor RECORD indices decoded from 3 meta bytes\\n // (M2 @ pair-cur = neighborIdxP0, M3 @ pair-nex = neighborIdxP3), and\\n // the corner/int ladders in float math.\\n if (ctorType >= 0.5) {\\n bool isCur = (ctorType < 1.5);\\n float siblingTexel = isCur ? (baseTexel + 4.0) : (baseTexel - 4.0);\\n vec4 ts0 = fetchData(siblingTexel);\\n vec4 ts1 = fetchData(siblingTexel + 1.0);\\n\\n // Pair bases: cur = the \\\"p1\\\" end, nex = the \\\"p2\\\" end.\\n float curBase = isCur ? baseTexel : siblingTexel;\\n float nexBase = isCur ? siblingTexel : baseTexel;\\n\\n // p1 always = position of the meta_cur end; p2 = meta_nex end.\\n vec3 p1 = isCur ? t0.gba : ts0.gba;\\n vec3 p2 = isCur ? ts0.gba : t0.gba;\\n\\n float halfSize1 = isCur ? t1.r : ts1.r;\\n float halfSize2 = isCur ? ts1.r : t1.r;\\n float texU1 = isCur ? t1.g : ts1.g;\\n float texU2 = isCur ? ts1.g : t1.g;\\n\\n // Colors: the meta M1 sample is the normalized RGBA directly.\\n vec4 color1 = fetchMeta(curBase + 1.0);\\n vec4 color2 = fetchMeta(nexBase + 1.0);\\n\\n // Neighbor RECORD indices (system.js convention: neighborIdxP0 on the\\n // pair-cur meta, neighborIdxP3 on the pair-nex meta; boundary\\n // sentinel = the pair's cur record index).\\n vec4 mNp0 = fetchMeta(curBase + 2.0);\\n vec4 mNp3 = fetchMeta(nexBase + 3.0);\\n float np0 = byteOf(mNp0.r) + byteOf(mNp0.g) * 256.0 + byteOf(mNp0.b) * 65536.0;\\n float np3 = byteOf(mNp3.r) + byteOf(mNp3.g) * 256.0 + byteOf(mNp3.b) * 65536.0;\\n float selfPairCurRecord = curBase * 0.25;\\n\\n vec3 p0 = (abs(np0 - selfPairCurRecord) < 0.5)\\n ? p1\\n : fetchData(np0 * 4.0).gba;\\n vec3 p3 = (abs(np3 - selfPairCurRecord) < 0.5)\\n ? p2\\n : fetchData(np3 * 4.0).gba;\\n\\n // Segment frame: Faced (rotationType 0/2) = screen-space NDC frame;\\n // Free (rotationType 1) = full world-space 3D frame. Mirror of the\\n // ES 3.00 shader / preview3 DataTextureRenderer3.\\n mat4 mvpMatrix = uViewProjMatrix * uModelMatrix;\\n bool isFreeRotation = (rotationType > 0.5 && rotationType < 1.5);\\n\\n // Anchor projections — both branches use them for gl_Position.\\n vec4 sp1 = mvpMatrix * vec4(p1, 1.0);\\n vec4 sp2 = mvpMatrix * vec4(p2, 1.0);\\n\\n // Near-plane guard (Faced only; the world-space Free frame is\\n // unaffected by the sign of w).\\n bool nearPlaneClipped = (sp1.w < 1e-3) || (sp2.w < 1e-3);\\n\\n // Aspect correction for the 2D Faced ortho on non-square viewports.\\n vec2 aspectMul = vec2(1.0, 1.0 / max(uViewportAspect, 1e-6));\\n\\n vec4 ts2 = fetchData(siblingTexel + 2.0);\\n vec4 q1 = isCur ? t2 : ts2;\\n vec4 q2 = isCur ? ts2 : t2;\\n\\n // Frame outputs: Faced fills the 2D (k/b/IK), Free the 3D\\n // (worldK/B/IK); the vertex ladder picks by isFreeRotation.\\n vec3 worldK1, worldB1, worldIK1, worldK2, worldB2, worldIK2;\\n vec2 k1, b1, IK1, k2, b2, IK2;\\n float Bmul1, Bmul2, kb1, kb2;\\n bool noKnee1, noKnee2;\\n float pathLen12; // len12 in the active frame's units\\n\\n // Initialize both frames (ES 1.00 warns on possibly-uninitialized\\n // locals across the branch below on some compilers).\\n worldK1 = vec3(0.0); worldB1 = vec3(0.0); worldIK1 = vec3(0.0);\\n worldK2 = vec3(0.0); worldB2 = vec3(0.0); worldIK2 = vec3(0.0);\\n k1 = vec2(0.0); b1 = vec2(0.0); IK1 = vec2(0.0);\\n k2 = vec2(0.0); b2 = vec2(0.0); IK2 = vec2(0.0);\\n\\n if (isFreeRotation) {\\n // World-space frame (mirror of GPU33 make3DStrip). Section normal\\n // n = quat z-axis; B = cross(dir12, n).\\n float xz1 = 2.0 * q1.x * q1.z;\\n float wy1 = 2.0 * q1.w * q1.y;\\n float yz1 = 2.0 * q1.y * q1.z;\\n float wx1 = 2.0 * q1.w * q1.x;\\n vec3 n1 = vec3(xz1 + wy1, yz1 - wx1, 1.0 - 2.0 * (q1.x * q1.x + q1.y * q1.y));\\n float xz2 = 2.0 * q2.x * q2.z;\\n float wy2 = 2.0 * q2.w * q2.y;\\n float yz2 = 2.0 * q2.y * q2.z;\\n float wx2 = 2.0 * q2.w * q2.x;\\n vec3 n2 = vec3(xz2 + wy2, yz2 - wx2, 1.0 - 2.0 * (q2.x * q2.x + q2.y * q2.y));\\n\\n vec3 wp01 = p1 - p0;\\n vec3 wp12 = p2 - p1;\\n vec3 wp23 = p3 - p2;\\n float wlen01 = length(wp01);\\n float wlen12 = length(wp12);\\n float wlen23 = length(wp23);\\n vec3 wdir12 = (wlen12 > 1e-6) ? (wp12 / wlen12) : vec3(1.0, 0.0, 0.0);\\n vec3 wdir01 = (wlen01 > 1e-6) ? (wp01 / wlen01) : wdir12;\\n vec3 wdir23 = (wlen23 > 1e-6) ? (wp23 / wlen23) : wdir12;\\n noKnee1 = dot(wdir01, wdir12) > 0.999;\\n noKnee2 = dot(wdir12, wdir23) > 0.999;\\n pathLen12 = wlen12;\\n\\n if (!noKnee1) {\\n vec3 B1raw = normalize(cross(wdir12, n1));\\n vec3 c1 = normalize(cross(wdir01, wdir12));\\n float Kmul1 = sign(dot(c1, n1));\\n vec3 K1 = Kmul1 * normalize(cross(wdir01 + wdir12, n1));\\n Bmul1 = sign(dot(B1raw, K1));\\n vec3 B1 = B1raw * Bmul1;\\n float ik1 = halfSize1 / max(dot(B1, K1), 1e-6);\\n if (dot(-wdir01, ik1 * -K1) > wlen01) ik1 = wlen01;\\n if (dot( wdir12, ik1 * -K1) > wlen12) ik1 = wlen12;\\n worldK1 = p1 + K1 * halfSize1;\\n worldB1 = p1 + B1 * halfSize1;\\n worldIK1 = p1 - K1 * ik1;\\n kb1 = distance(worldK1, worldB1);\\n } else {\\n Bmul1 = 1.0;\\n vec3 B1 = normalize(cross(wdir01 + wdir12, n1));\\n worldK1 = p1 + B1 * halfSize1;\\n worldB1 = worldK1;\\n worldIK1 = p1 - B1 * halfSize1;\\n kb1 = 0.0;\\n }\\n\\n if (!noKnee2) {\\n vec3 B2raw = normalize(cross(wdir12, n2));\\n vec3 c2 = normalize(cross(wdir12, wdir23));\\n float Kmul2 = sign(dot(c2, n2));\\n vec3 K2 = Kmul2 * normalize(cross(wdir12 + wdir23, n2));\\n Bmul2 = sign(dot(B2raw, K2));\\n vec3 B2 = B2raw * Bmul2;\\n float ik2 = halfSize2 / max(dot(B2, K2), 1e-6);\\n if (dot(-wdir12, ik2 * -K2) > wlen12) ik2 = wlen12;\\n if (dot( wdir23, ik2 * -K2) > wlen23) ik2 = wlen23;\\n worldK2 = p2 + K2 * halfSize2;\\n worldB2 = p2 + B2 * halfSize2;\\n worldIK2 = p2 - K2 * ik2;\\n kb2 = distance(worldK2, worldB2);\\n } else {\\n Bmul2 = 1.0;\\n vec3 B2 = normalize(cross(wdir12 + wdir23, n2));\\n worldK2 = p2 + B2 * halfSize2;\\n worldB2 = worldK2;\\n worldIK2 = p2 - B2 * halfSize2;\\n kb2 = 0.0;\\n }\\n } else {\\n // Faced: screen-space NDC frame around dir12.\\n vec4 sp0 = mvpMatrix * vec4(p0, 1.0);\\n vec4 sp3 = mvpMatrix * vec4(p3, 1.0);\\n vec2 ndc0 = (sp0.xy / sp0.w) * aspectMul;\\n vec2 ndc1 = (sp1.xy / sp1.w) * aspectMul;\\n vec2 ndc2 = (sp2.xy / sp2.w) * aspectMul;\\n vec2 ndc3 = (sp3.xy / sp3.w) * aspectMul;\\n\\n vec2 d01 = ndc1 - ndc0;\\n vec2 d12 = ndc2 - ndc1;\\n vec2 d23 = ndc3 - ndc2;\\n float len01 = length(d01);\\n float len12 = length(d12);\\n float len23 = length(d23);\\n vec2 dir12 = (len12 > 1e-6) ? (d12 / len12) : vec2(1.0, 0.0);\\n vec2 dir01 = (len01 > 1e-6) ? (d01 / len01) : dir12;\\n vec2 dir23 = (len23 > 1e-6) ? (d23 / len23) : dir12;\\n noKnee1 = dot(dir01, dir12) > 0.999;\\n noKnee2 = dot(dir12, dir23) > 0.999;\\n pathLen12 = len12;\\n\\n // Section magnitude: project camera_up*halfSize per anchor into NDC.\\n vec4 spU1 = mvpMatrix * vec4(p1 + uCameraUp * halfSize1, 1.0);\\n vec4 spU2 = mvpMatrix * vec4(p2 + uCameraUp * halfSize2, 1.0);\\n float ndcHalfSize1 = length((spU1.xy / spU1.w) * aspectMul - ndc1);\\n float ndcHalfSize2 = length((spU2.xy / spU2.w) * aspectMul - ndc2);\\n\\n vec2 B = stripOrtho(dir12);\\n if (!noKnee1) {\\n float Kmul1 = -sign(dot(stripOrtho(dir01), dir12));\\n vec2 K1 = Kmul1 * normalize(stripOrtho(dir01 + dir12));\\n Bmul1 = sign(dot(B, K1));\\n vec2 B1 = B * Bmul1;\\n float ik1 = ndcHalfSize1 / max(dot(B1, K1), 1e-6);\\n if (dot(-dir01, ik1 * -K1) > len01) ik1 = len01;\\n if (dot(dir12, ik1 * -K1) > len12) ik1 = len12;\\n k1 = ndc1 + K1 * ndcHalfSize1;\\n b1 = ndc1 + B1 * ndcHalfSize1;\\n IK1 = ndc1 - K1 * ik1;\\n kb1 = distance(k1, b1);\\n } else {\\n vec2 B1 = normalize(stripOrtho(dir01 + dir12));\\n Bmul1 = 1.0;\\n k1 = ndc1 + B1 * ndcHalfSize1;\\n b1 = k1;\\n IK1 = ndc1 - B1 * ndcHalfSize1;\\n kb1 = 0.0;\\n }\\n if (!noKnee2) {\\n float Kmul2 = -sign(dot(stripOrtho(dir12), dir23));\\n vec2 K2 = Kmul2 * normalize(stripOrtho(dir12 + dir23));\\n Bmul2 = sign(dot(B, K2));\\n vec2 B2 = B * Bmul2;\\n float ik2 = ndcHalfSize2 / max(dot(B2, K2), 1e-6);\\n if (dot(-dir12, ik2 * -K2) > len12) ik2 = len12;\\n if (dot(dir23, ik2 * -K2) > len23) ik2 = len23;\\n k2 = ndc2 + K2 * ndcHalfSize2;\\n b2 = ndc2 + B2 * ndcHalfSize2;\\n IK2 = ndc2 - K2 * ik2;\\n kb2 = distance(k2, b2);\\n } else {\\n vec2 B2 = normalize(stripOrtho(dir12 + dir23));\\n Bmul2 = 1.0;\\n k2 = ndc2 + B2 * ndcHalfSize2;\\n b2 = k2;\\n IK2 = ndc2 - B2 * ndcHalfSize2;\\n kb2 = 0.0;\\n }\\n }\\n\\n // V coords: V at outer knee (k) = (Bmul + 1) * 0.5; inner = 1 - outer.\\n float Vtop1 = (Bmul1 + 1.0) * 0.5;\\n float Vbot1 = 1.0 - Vtop1;\\n float Vtop2 = (Bmul2 + 1.0) * 0.5;\\n float Vbot2 = 1.0 - Vtop2;\\n\\n // Vertex layout per meta over the IBO [0,1,2, 0,2,3] — same ladder as\\n // the ES 3.00 shader (see its comment block for the geometry).\\n bool sameSide = (Bmul1 * Bmul2 >= 0.0);\\n float dPath = max(sameSide ? (kb1 + pathLen12 + kb2) : (kb1 + pathLen12), 1e-6);\\n float dPathNex = max(sameSide ? dPath : (kb2 + pathLen12), 1e-6);\\n\\n float bUcur = kb1 / dPath;\\n float bUnex = sameSide ? (kb2 / dPath) : (kb2 / dPathNex);\\n vec4 colorB1 = mix(color1, color2, bUcur);\\n vec4 colorB2 = mix(color2, color1, bUnex);\\n\\n vec2 vertPos;\\n vec3 vertPos3D = vec3(0.0);\\n vec2 vertUV;\\n vec4 vertColor;\\n if (isCur) {\\n // meta_cur vertices\\n if (corner < 0.5) {\\n vertPos = b1; vertPos3D = worldB1;\\n vertUV = vec2(mix(texU1, texU2, kb1 / dPath), Vtop1);\\n vertColor = colorB1;\\n } else if (corner < 1.5) {\\n vertPos = k1; vertPos3D = worldK1;\\n vertUV = vec2(texU1, Vtop1);\\n vertColor = color1;\\n } else if (corner < 2.5) {\\n vertPos = IK1; vertPos3D = worldIK1;\\n vertUV = vec2(texU1, Vbot1);\\n vertColor = color1;\\n } else {\\n // v3 = b2 (sameSide) or IK2 (different side)\\n if (sameSide) {\\n vertPos = b2; vertPos3D = worldB2;\\n vertUV = vec2(mix(texU2, texU1, kb2 / dPath), Vtop2);\\n vertColor = colorB2;\\n } else {\\n vertPos = IK2; vertPos3D = worldIK2;\\n vertUV = vec2(texU2, Vbot2);\\n vertColor = color2;\\n }\\n }\\n // noKnee fallback: collapse to k1/IK1 to produce degenerate segments.\\n if (noKnee1) {\\n if (corner < 0.5) { vertPos = k1; vertPos3D = worldK1; vertUV = vec2(texU1, Vtop1); vertColor = color1; }\\n }\\n } else {\\n // meta_nex vertices\\n if (sameSide) {\\n if (corner < 0.5) { vertPos = b2; vertPos3D = worldB2; vertUV = vec2(mix(texU2, texU1, kb2 / dPath), Vtop2); vertColor = colorB2; }\\n else if (corner < 1.5) { vertPos = IK1; vertPos3D = worldIK1; vertUV = vec2(texU1, Vbot1); vertColor = color1; }\\n else if (corner < 2.5) { vertPos = IK2; vertPos3D = worldIK2; vertUV = vec2(texU2, Vbot2); vertColor = color2; }\\n else { vertPos = k2; vertPos3D = worldK2; vertUV = vec2(texU2, Vtop2); vertColor = color2; }\\n } else {\\n if (corner < 0.5) { vertPos = IK2; vertPos3D = worldIK2; vertUV = vec2(texU2, Vbot2); vertColor = color2; }\\n else if (corner < 1.5) { vertPos = IK1; vertPos3D = worldIK1; vertUV = vec2(texU1, Vbot1); vertColor = color1; }\\n else if (corner < 2.5) { vertPos = b2; vertPos3D = worldB2; vertUV = vec2(mix(texU2, texU1, kb2 / dPathNex), Vtop2); vertColor = colorB2; }\\n else { vertPos = k2; vertPos3D = worldK2; vertUV = vec2(texU2, Vtop2); vertColor = color2; }\\n }\\n if (noKnee2) {\\n if (corner > 2.5) { vertPos = IK2; vertPos3D = worldIK2; vertUV = vec2(texU2, Vbot2); vertColor = color2; }\\n }\\n }\\n\\n // Free projects the world-space vertex through MVP directly; Faced\\n // reconstructs clip space from aspect-corrected NDC.\\n if (isFreeRotation) {\\n gl_Position = mvpMatrix * vec4(vertPos3D, 1.0);\\n } else if (nearPlaneClipped) {\\n gl_Position = vec4(2.0, 2.0, 2.0, 1.0);\\n } else {\\n vec4 anchorProj = isCur ? sp1 : sp2;\\n vec2 vertPosClip = vertPos / aspectMul;\\n gl_Position = vec4(vertPosClip * anchorProj.w, anchorProj.zw);\\n }\\n vColor = vertColor;\\n\\n // Strip emits raw (U, V) — fragment wraps U into the atlas slot.\\n vTexCoord = vertUV;\\n vAtlasRemap = uTexRemaps[int(batchTexIdx)];\\n vStripPath = 1.0;\\n return;\\n }\\n // ─── End strip path ─────────────────────────────────────────────────────\\n\\n // Texel 1: originX, originY, sizeX, sizeY\\n vec2 origin = t1.rg;\\n vec2 size = t1.ba;\\n\\n // Meta M1: the packedColor u32 LE bytes ARE the normalized RGBA sample.\\n vColor = fetchMeta(baseTexel + 1.0);\\n\\n // Meta M2: gridConfig — [gridW lo, gridW hi, gridH lo, gridH hi].\\n vec4 m2 = fetchMeta(baseTexel + 2.0);\\n float gridWidth = max(byteOf(m2.r) + byteOf(m2.g) * 256.0, 1.0);\\n float gridHeight = max(byteOf(m2.b) + byteOf(m2.a) * 256.0, 1.0);\\n // gridIndex is a plain float — read from the float texture (mirror of the\\n // ES 3.00 shader: truncate so animated frames pick a single cell).\\n float gridIndex = floor(t3.b);\\n\\n // Texel 2: rotation\\n vec3 xaxis, yaxis;\\n\\n if (rotationType < 0.5) {\\n float angle = t2.r;\\n float rad = angle * 3.14159265 / 180.0;\\n float s = -sin(rad);\\n float c = cos(rad);\\n xaxis = uCameraRight * c + uCameraUp * s;\\n yaxis = -uCameraRight * s + uCameraUp * c;\\n } else if (rotationType < 1.5) {\\n vec4 q = t2;\\n float z2 = 2.0 * q.z * q.z;\\n float xy = 2.0 * q.x * q.y;\\n float wz = 2.0 * q.w * q.z;\\n xaxis = vec3(\\n 1.0 - 2.0 * q.y * q.y - z2,\\n xy + wz,\\n 2.0 * q.x * q.z - 2.0 * q.w * q.y);\\n yaxis = vec3(\\n xy - wz,\\n 1.0 - 2.0 * q.x * q.x - z2,\\n 2.0 * q.y * q.z + 2.0 * q.w * q.x);\\n } else {\\n xaxis = cross(uCameraUp, uCameraDir);\\n yaxis = uCameraUp;\\n }\\n\\n xaxis *= size.x;\\n yaxis *= size.y;\\n\\n vec2 vOrigin = originMul(corner) * origin\\n + invOriginMul(corner) * (vec2(1.0) - origin);\\n vec3 posDisp = vOrigin.x * xaxis + vOrigin.y * yaxis;\\n\\n mat4 mvpMatrix = uViewProjMatrix * uModelMatrix;\\n vec3 worldPos = position + posDisp;\\n gl_Position = mvpMatrix * vec4(worldPos.xy, 0.0, 1.0);\\n\\n // Texture coordinates with grid + atlas remap\\n vec2 baseTexCoord = texCoordOf(corner);\\n\\n float gx = mod(gridIndex, gridWidth);\\n float gy = floor(gridIndex / gridWidth);\\n float cellW = 1.0 / gridWidth;\\n float cellH = 1.0 / gridHeight;\\n\\n vec2 gridTexCoord = vec2(\\n (gx + baseTexCoord.x) * cellW,\\n 1.0 - (gy + 1.0 - baseTexCoord.y) * cellH\\n );\\n\\n // Dynamic indexing of a uniform array is legal in ES 1.00 VERTEX shaders\\n // (only fragment shaders are constant-index restricted).\\n vec4 remap = uTexRemaps[int(batchTexIdx)];\\n vTexCoord = remap.xy + gridTexCoord * remap.zw;\\n vAtlasRemap = remap; // unused by fragment when vStripPath == 0\\n vStripPath = 0.0;\\n}\\n\"","export default \"// WebGL1 (GLSL ES 1.00) port of particle.frag. Fragment highp is a REQUIRED\\n// capability of the GL1 path (probed at Context creation) — the strip U-wrap\\n// does floor/fract on accumulated texU which mediump would corrupt; the\\n// #else branch only keeps the shader compilable on probe-rejected devices.\\n#ifdef GL_FRAGMENT_PRECISION_HIGH\\nprecision highp float;\\n#else\\nprecision mediump float;\\n#endif\\n\\nuniform sampler2D uTextures[8];\\n// Host scene-graph container/world alpha (same semantics as the ES 3.00\\n// shader: scales the whole premultiplied RGBA).\\nuniform float uWorldAlpha;\\n\\nvarying vec2 vTexCoord;\\nvarying vec4 vColor;\\nvarying float vBatchTextureIndex; // constant across the quad; re-quantized below\\nvarying vec4 vAtlasRemap;\\nvarying float vStripPath;\\n\\nvoid main() {\\n // Quad path (vStripPath == 0): vTexCoord is the final atlas UV from the\\n // vertex stage. Strip path (vStripPath == 1): raw U wrapped per-pixel\\n // into the atlas slot; exact-[0;1] U is left alone (fract(1.0) == 0.0\\n // would collapse the strip end) — mirror of the ES 3.00 shader.\\n vec2 atlasUV;\\n if (vStripPath < 0.5) {\\n atlasUV = vTexCoord;\\n } else {\\n float u = vTexCoord.x;\\n float wrappedU = u - floor(u);\\n if (u >= 0.0 && u <= 1.0) wrappedU = u;\\n atlasUV = vec2(wrappedU, vTexCoord.y) * vAtlasRemap.zw + vAtlasRemap.xy;\\n }\\n\\n // ES 1.00 fragment shaders require constant sampler indexing — the same\\n // if-ladder as WebGL2, driven by the re-quantized float varying.\\n float texIdx = floor(vBatchTextureIndex + 0.5);\\n vec4 texColor;\\n if (texIdx < 0.5) texColor = texture2D(uTextures[0], atlasUV);\\n else if (texIdx < 1.5) texColor = texture2D(uTextures[1], atlasUV);\\n else if (texIdx < 2.5) texColor = texture2D(uTextures[2], atlasUV);\\n else if (texIdx < 3.5) texColor = texture2D(uTextures[3], atlasUV);\\n else if (texIdx < 4.5) texColor = texture2D(uTextures[4], atlasUV);\\n else if (texIdx < 5.5) texColor = texture2D(uTextures[5], atlasUV);\\n else if (texIdx < 6.5) texColor = texture2D(uTextures[6], atlasUV);\\n else texColor = texture2D(uTextures[7], atlasUV);\\n\\n // texColor is premultiplied and blend src factors are ONE-based, so the\\n // world alpha scales the whole RGBA (mirror of the ES 3.00 shader).\\n gl_FragColor = texColor * vColor * uWorldAlpha;\\n}\\n\"","// @ts-ignore\nimport * as Neutrino from '@neutrinoparticles/js-v1.1';\nimport { NeutrinoRuntimeContext as INeutrinoContext } from './types';\nimport vertexShaderSource from './shaders/particle.vert?raw';\nimport fragmentShaderSource from './shaders/particle.frag?raw';\nimport vertexShaderSourceGL1 from './shaders/particle_gl1.vert?raw';\nimport fragmentShaderSourceGL1 from './shaders/particle_gl1.frag?raw';\n\n/**\n * Engine-agnostic WebGL state for the NeutrinoParticles data-texture renderer:\n * the shader program, a static quad index buffer + VAO (WebGL2) or aId vertex\n * stream (WebGL1), and uniform locations.\n *\n * This is the Phaser counterpart of the pixi adapters' Context, but it holds no\n * reference to a host renderer — it works purely off a WebGL context. Owned by\n * {@link GamePlugin} and shared by every effect in the game.\n *\n * The render path is selected automatically (TDD_js-v1.1-webgl1.md): a WebGL2\n * context uses the texelFetch/gl_VertexID renderer unchanged; a WebGL1 context\n * with the required capabilities (probed here, §4.2) uses the two-texture +\n * static-aId variant; anything else throws a capability-specific Error.\n */\nexport class NeutrinoContext {\n public readonly neutrino: INeutrinoContext;\n // On a WebGL1 context this actually holds a WebGLRenderingContext; the\n // GL2-only members are never touched on the GL1 path.\n public readonly gl: WebGL2RenderingContext;\n\n private _shaderProgram: WebGLProgram | null = null;\n private _indexBuffer: WebGLBuffer | null = null;\n private _dummyVB: WebGLBuffer | null = null;\n private _indexBufferCapacity: number = 0;\n private _vao: WebGLVertexArrayObject | null = null;\n\n // WebGL1 render path state (TDD_js-v1.1-webgl1.md)\n private _isWebGL1: boolean = false;\n private _maxBatchTextures: number = NeutrinoContext.MAX_BATCH_TEXTURES;\n private _hasElementIndexUint: boolean = false;\n private _vaoExt: OES_vertex_array_object | null = null;\n private _aIdBuffer: WebGLBuffer | null = null;\n private _aIdLocation: number = -1;\n\n static readonly MAX_BATCH_TEXTURES = 8;\n\n private _uDataTexture: WebGLUniformLocation | null = null;\n private _uDataTextureWidth: WebGLUniformLocation | null = null;\n private _uMetaTexture: WebGLUniformLocation | null = null;\n private _uDataTexSize: WebGLUniformLocation | null = null;\n private _uCameraRight: WebGLUniformLocation | null = null;\n private _uCameraUp: WebGLUniformLocation | null = null;\n private _uCameraDir: WebGLUniformLocation | null = null;\n private _uViewProjMatrix: WebGLUniformLocation | null = null;\n private _uModelMatrix: WebGLUniformLocation | null = null;\n private _uViewportAspect: WebGLUniformLocation | null = null;\n private _uWorldAlpha: WebGLUniformLocation | null = null;\n private _uTextures: (WebGLUniformLocation | null)[] = [];\n private _uTexRemaps: (WebGLUniformLocation | null)[] = [];\n\n private _noiseInitialized: boolean = false;\n\n constructor(gl: WebGL2RenderingContext, neutrino: INeutrinoContext) {\n this.gl = gl;\n this.neutrino = neutrino;\n\n this._isWebGL1 = typeof (gl as any).createVertexArray !== 'function';\n\n if (this._isWebGL1) {\n this._probeWebGL1Capabilities();\n }\n\n this._initShader();\n\n if (this._isWebGL1) {\n this._smokeTestVertexTextureFetch();\n }\n }\n\n public initializeNoise(path: string, success: () => void, fail: () => void): void {\n if (this._noiseInitialized) { if (success) success(); return; }\n this.neutrino.initializeNoise(path,\n () => { this._noiseInitialized = true; if (success) success(); }, fail);\n }\n\n public generateNoise(): void {\n if (this._noiseInitialized) return;\n const noiseGenerator = new (this.neutrino as any).NoiseGenerator();\n while (!noiseGenerator.step()) { /* ~5000 steps */ }\n this._noiseInitialized = true;\n }\n\n get shaderProgram(): WebGLProgram { return this._shaderProgram!; }\n get isWebGL1(): boolean { return this._isWebGL1; }\n /**\n * Textures usable in one batch. 8 on WebGL2; on WebGL1 reduced when the\n * combined texture-unit budget is tight (the vertex stage takes 2 units).\n * A lower cap only produces more batches, never wrong output.\n */\n get maxBatchTextures(): number { return this._maxBatchTextures; }\n get uDataTexture() { return this._uDataTexture; }\n get uDataTextureWidth() { return this._uDataTextureWidth; }\n get uMetaTexture() { return this._uMetaTexture; }\n get uDataTexSize() { return this._uDataTexSize; }\n get uCameraRight() { return this._uCameraRight; }\n get uCameraUp() { return this._uCameraUp; }\n get uCameraDir() { return this._uCameraDir; }\n get uViewProjMatrix() { return this._uViewProjMatrix; }\n get uModelMatrix() { return this._uModelMatrix; }\n get uViewportAspect() { return this._uViewportAspect; }\n get uWorldAlpha() { return this._uWorldAlpha; }\n get uTextures() { return this._uTextures; }\n get uTexRemaps() { return this._uTexRemaps; }\n\n ensureIndexBuffer(maxParticles: number): void {\n if (maxParticles <= this._indexBufferCapacity) return;\n\n const gl = this.gl;\n\n // This may be called after the host renderer has set up its own bindings\n // (e.g. a second effect created once the scene is running). Snapshot the\n // bindings we touch and restore them so we don't desync the host's state.\n // (VERTEX_ARRAY_BINDING is not a valid pname on a WebGL1 context.)\n const prevVao = this._isWebGL1 ? null\n : gl.getParameter(gl.VERTEX_ARRAY_BINDING) as WebGLVertexArrayObject | null;\n const prevArrayBuf = gl.getParameter(gl.ARRAY_BUFFER_BINDING) as WebGLBuffer | null;\n const prevElemBuf = gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING) as WebGLBuffer | null;\n\n if (this._indexBuffer) gl.deleteBuffer(this._indexBuffer);\n if (this._dummyVB) { gl.deleteBuffer(this._dummyVB); this._dummyVB = null; }\n if (this._vao) { gl.deleteVertexArray(this._vao); this._vao = null; }\n if (this._aIdBuffer) { gl.deleteBuffer(this._aIdBuffer); this._aIdBuffer = null; }\n\n const use32bit = maxParticles > 16383; // 65535 / 4\n if (use32bit && this._isWebGL1 && !this._hasElementIndexUint) {\n throw new Error(\n 'NeutrinoParticles (js-v1.1): the effect needs 32-bit indices ' +\n `(${maxParticles} particles) but this WebGL1 context lacks ` +\n 'OES_element_index_uint.');\n }\n const indices = use32bit\n ? new Uint32Array(maxParticles * 6)\n : new Uint16Array(maxParticles * 6);\n\n for (let p = 0; p < maxParticles; p++) {\n const v = p * 4;\n const i = p * 6;\n indices[i + 0] = v + 0;\n indices[i + 1] = v + 1;\n indices[i + 2] = v + 2;\n indices[i + 3] = v + 0;\n indices[i + 4] = v + 2;\n indices[i + 5] = v + 3;\n }\n\n this._indexBuffer = gl.createBuffer()!;\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);\n gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);\n\n if (this._isWebGL1) {\n // Static aId stream: particleIndex * 4 + corner per vertex — the\n // gl_VertexID substitute (TDD §4.4). No VAO on the GL1 path; the\n // renderer binds buffers + attribute pointer per render.\n const ids = new Float32Array(maxParticles * 4);\n for (let v = 0; v < ids.length; v++) ids[v] = v;\n this._aIdBuffer = gl.createBuffer()!;\n gl.bindBuffer(gl.ARRAY_BUFFER, this._aIdBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, ids, gl.STATIC_DRAW);\n } else {\n // Dummy vertex buffer — WebGL2 requires at least one vertex buffer for\n // drawElements even though we address particle data via gl_VertexID.\n this._dummyVB = gl.createBuffer()!;\n gl.bindBuffer(gl.ARRAY_BUFFER, this._dummyVB);\n gl.bufferData(gl.ARRAY_BUFFER, maxParticles * 4, gl.STATIC_DRAW);\n\n this._vao = gl.createVertexArray()!;\n gl.bindVertexArray(this._vao);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);\n gl.bindBuffer(gl.ARRAY_BUFFER, this._dummyVB);\n gl.enableVertexAttribArray(0);\n gl.vertexAttribPointer(0, 1, gl.UNSIGNED_BYTE, false, 0, 0);\n\n gl.bindVertexArray(prevVao);\n }\n\n gl.bindBuffer(gl.ARRAY_BUFFER, prevArrayBuf);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, prevElemBuf);\n\n this._indexBufferCapacity = maxParticles;\n }\n\n get vao(): WebGLVertexArrayObject { return this._vao!; }\n get indexBuffer(): WebGLBuffer { return this._indexBuffer!; }\n get aIdBuffer(): WebGLBuffer { return this._aIdBuffer!; }\n get aIdLocation(): number { return this._aIdLocation; }\n get indexType(): number {\n return this._indexBufferCapacity > 16383\n ? this.gl.UNSIGNED_INT\n : this.gl.UNSIGNED_SHORT;\n }\n\n /** Unbind any VAO (incl. OES on WebGL1) before raw attribute setup. */\n unbindVao(): void {\n if (this._isWebGL1) {\n if (this._vaoExt) this._vaoExt.bindVertexArrayOES(null);\n } else {\n this.gl.bindVertexArray(null);\n }\n }\n\n destroy(): void {\n const gl = this.gl;\n if (this._shaderProgram) gl.deleteProgram(this._shaderProgram);\n if (this._indexBuffer) gl.deleteBuffer(this._indexBuffer);\n if (this._dummyVB) gl.deleteBuffer(this._dummyVB);\n if (this._vao) gl.deleteVertexArray(this._vao);\n if (this._aIdBuffer) gl.deleteBuffer(this._aIdBuffer);\n }\n\n // ── WebGL1 capability probe (TDD §4.2) ─────────────────────────────────\n\n private _probeWebGL1Capabilities(): void {\n const gl = this.gl as unknown as WebGLRenderingContext;\n\n if (!gl.getExtension('OES_texture_float')) {\n throw new Error(\n 'NeutrinoParticles (js-v1.1): WebGL1 context lacks OES_texture_float; ' +\n 'WebGL2 or WebGL1 with vertex float textures is required.');\n }\n\n const vtfUnits = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS) as number;\n if (vtfUnits < 2) {\n throw new Error(\n 'NeutrinoParticles (js-v1.1): WebGL1 context has ' + vtfUnits +\n ' vertex texture units (2 required); WebGL2 or WebGL1 with ' +\n 'vertex float textures is required.');\n }\n\n const fragHigh = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);\n if (!fragHigh || fragHigh.precision === 0) {\n throw new Error(\n 'NeutrinoParticles (js-v1.1): WebGL1 context lacks highp float ' +\n 'in fragment shaders; WebGL2 or WebGL1 with fragment highp is required.');\n }\n\n this._hasElementIndexUint = !!gl.getExtension('OES_element_index_uint');\n this._vaoExt = gl.getExtension('OES_vertex_array_object');\n\n // The vertex stage takes units 0 (data) + 1 (meta); particle textures\n // get the rest, capped at the WebGL2 batching width.\n const combined = gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS) as number;\n const fragment = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS) as number;\n this._maxBatchTextures = Math.max(1,\n Math.min(NeutrinoContext.MAX_BATCH_TEXTURES, combined - 2, fragment));\n }\n\n /**\n * Compile/link alone does not prove vertex texture fetch works on a\n * driver — some fail only at draw time. One-time 1×1 smoke draw: a point\n * whose color is produced by sampling a float and a byte texture in the\n * vertex shader, rendered into a 1×1 RGBA8 FBO and read back.\n */\n private _smokeTestVertexTextureFetch(): void {\n const gl = this.gl as unknown as WebGLRenderingContext;\n\n const vs =\n 'precision highp float;\\n' +\n 'attribute float aId;\\n' +\n 'uniform sampler2D uF;\\n' +\n 'uniform sampler2D uB;\\n' +\n 'varying vec4 vC;\\n' +\n 'void main() {\\n' +\n ' vec4 f = texture2DLod(uF, vec2(0.5, 0.5), 0.0);\\n' +\n ' vec4 b = texture2DLod(uB, vec2(0.5, 0.5), 0.0);\\n' +\n ' vC = vec4(f.r * b.r, f.g * b.g, f.b * b.b, 1.0);\\n' +\n ' gl_Position = vec4(aId, 0.0, 0.0, 1.0);\\n' +\n ' gl_PointSize = 1.0;\\n' +\n '}\\n';\n const fs =\n 'precision mediump float;\\n' +\n 'varying vec4 vC;\\n' +\n 'void main() { gl_FragColor = vC; }\\n';\n\n // Full save/restore of every state the smoke draw touches, applied in\n // finally so early shader-compile throws cannot leak state either.\n const prevViewport = gl.getParameter(gl.VIEWPORT) as Int32Array;\n const prevProgram = gl.getParameter(gl.CURRENT_PROGRAM) as WebGLProgram | null;\n const prevArrayBuffer = gl.getParameter(gl.ARRAY_BUFFER_BINDING) as WebGLBuffer | null;\n const prevFbo = gl.getParameter(gl.FRAMEBUFFER_BINDING) as WebGLFramebuffer | null;\n const prevActiveTexture = gl.getParameter(gl.ACTIVE_TEXTURE) as number;\n gl.activeTexture(gl.TEXTURE0);\n const prevTex0 = gl.getParameter(gl.TEXTURE_BINDING_2D) as WebGLTexture | null;\n gl.activeTexture(gl.TEXTURE1);\n const prevTex1 = gl.getParameter(gl.TEXTURE_BINDING_2D) as WebGLTexture | null;\n const prevBlend = gl.isEnabled(gl.BLEND);\n const prevDepthTest = gl.isEnabled(gl.DEPTH_TEST);\n const prevScissorTest = gl.isEnabled(gl.SCISSOR_TEST);\n\n let program: WebGLProgram | null = null;\n let floatTex: WebGLTexture | null = null;\n let byteTex: WebGLTexture | null = null;\n let target: WebGLTexture | null = null;\n let fbo: WebGLFramebuffer | null = null;\n let vbo: WebGLBuffer | null = null;\n let attribLoc = -1;\n let prevAttribEnabled = false;\n let prevAttribBuffer: WebGLBuffer | null = null;\n let prevAttribSize = 4, prevAttribType = 0, prevAttribStride = 0, prevAttribOffset = 0;\n let prevAttribNormalized = false;\n\n let ok = false;\n const pixel = new Uint8Array(4);\n try {\n program = gl.createProgram()!;\n gl.attachShader(program, this._compileShader(gl.VERTEX_SHADER, vs));\n gl.attachShader(program, this._compileShader(gl.FRAGMENT_SHADER, fs));\n gl.linkProgram(program);\n\n const makeTex = (type: number, pixels: ArrayBufferView) => {\n const t = gl.createTexture()!;\n gl.bindTexture(gl.TEXTURE_2D, t);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, type, pixels);\n return t;\n };\n\n gl.activeTexture(gl.TEXTURE0);\n floatTex = makeTex(gl.FLOAT, new Float32Array([1.0, 0.5, 0.25, 1.0]));\n byteTex = makeTex(gl.UNSIGNED_BYTE, new Uint8Array([51, 102, 153, 255]));\n\n target = gl.createTexture()!;\n gl.bindTexture(gl.TEXTURE_2D, target);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n fbo = gl.createFramebuffer()!;\n gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, target, 0);\n\n vbo = gl.createBuffer()!;\n gl.bindBuffer(gl.ARRAY_BUFFER, vbo);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0]), gl.STATIC_DRAW);\n\n ok = gl.getProgramParameter(program, gl.LINK_STATUS) as boolean;\n if (ok) {\n gl.useProgram(program);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, floatTex);\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, byteTex);\n gl.uniform1i(gl.getUniformLocation(program, 'uF'), 0);\n gl.uniform1i(gl.getUniformLocation(program, 'uB'), 1);\n attribLoc = gl.getAttribLocation(program, 'aId');\n // The slot may already be in use by the host (e.g. Phaser's\n // pipeline attributes) — capture its full state for restore.\n prevAttribEnabled = gl.getVertexAttrib(attribLoc, gl.VERTEX_ATTRIB_ARRAY_ENABLED) as boolean;\n prevAttribBuffer = gl.getVertexAttrib(attribLoc, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) as WebGLBuffer | null;\n prevAttribSize = gl.getVertexAttrib(attribLoc, gl.VERTEX_ATTRIB_ARRAY_SIZE) as number;\n prevAttribType = gl.getVertexAttrib(attribLoc, gl.VERTEX_ATTRIB_ARRAY_TYPE) as number;\n prevAttribNormalized = gl.getVertexAttrib(attribLoc, gl.VERTEX_ATTRIB_ARRAY_NORMALIZED) as boolean;\n prevAttribStride = gl.getVertexAttrib(attribLoc, gl.VERTEX_ATTRIB_ARRAY_STRIDE) as number;\n prevAttribOffset = gl.getVertexAttribOffset(attribLoc, gl.VERTEX_ATTRIB_ARRAY_POINTER) as number;\n gl.enableVertexAttribArray(attribLoc);\n gl.vertexAttribPointer(attribLoc, 1, gl.FLOAT, false, 0, 0);\n gl.viewport(0, 0, 1, 1);\n gl.disable(gl.BLEND);\n gl.disable(gl.DEPTH_TEST);\n gl.disable(gl.SCISSOR_TEST);\n gl.drawArrays(gl.POINTS, 0, 1);\n gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);\n // Expected: (1*0.2, 0.5*0.4, 0.25*0.6) * 255 = (51, 51, 38).\n ok = Math.abs(pixel[0] - 51) <= 2\n && Math.abs(pixel[1] - 51) <= 2\n && Math.abs(pixel[2] - 38) <= 2;\n }\n } finally {\n if (attribLoc >= 0) {\n // Restore the slot's pointer first (vertexAttribPointer reads\n // the CURRENT ARRAY_BUFFER binding), then its enable state;\n // a null previous buffer means the slot had no pointer set —\n // nothing to restore beyond the enable bit.\n if (prevAttribBuffer) {\n gl.bindBuffer(gl.ARRAY_BUFFER, prevAttribBuffer);\n gl.vertexAttribPointer(attribLoc, prevAttribSize, prevAttribType,\n prevAttribNormalized, prevAttribStride, prevAttribOffset);\n }\n if (prevAttribEnabled) gl.enableVertexAttribArray(attribLoc);\n else gl.disableVertexAttribArray(attribLoc);\n }\n if (fbo) gl.deleteFramebuffer(fbo);\n if (target) gl.deleteTexture(target);\n if (floatTex) gl.deleteTexture(floatTex);\n if (byteTex) gl.deleteTexture(byteTex);\n if (vbo) gl.deleteBuffer(vbo);\n if (program) gl.deleteProgram(program);\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, prevFbo);\n gl.bindBuffer(gl.ARRAY_BUFFER, prevArrayBuffer);\n gl.useProgram(prevProgram);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, prevTex0);\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, prevTex1);\n gl.activeTexture(prevActiveTexture);\n if (prevBlend) gl.enable(gl.BLEND);\n if (prevDepthTest) gl.enable(gl.DEPTH_TEST);\n if (prevScissorTest) gl.enable(gl.SCISSOR_TEST);\n gl.viewport(prevViewport[0], prevViewport[1], prevViewport[2], prevViewport[3]);\n }\n\n if (!ok) {\n throw new Error(\n 'NeutrinoParticles (js-v1.1): WebGL1 vertex texture fetch smoke ' +\n `test failed (got ${pixel[0]},${pixel[1]},${pixel[2]}); WebGL2 or ` +\n 'WebGL1 with working vertex float textures is required.');\n }\n }\n\n private _initShader(): void {\n const gl = this.gl;\n\n const vsSource = this._isWebGL1 ? vertexShaderSourceGL1 : vertexShaderSource;\n const fsSource = this._isWebGL1 ? fragmentShaderSourceGL1 : fragmentShaderSource;\n\n const vs = this._compileShader(gl.VERTEX_SHADER, vsSource);\n const fs = this._compileShader(gl.FRAGMENT_SHADER, fsSource);\n\n this._shaderProgram = gl.createProgram()!;\n gl.attachShader(this._shaderProgram, vs);\n gl.attachShader(this._shaderProgram, fs);\n gl.linkProgram(this._shaderProgram);\n\n if (!gl.getProgramParameter(this._shaderProgram, gl.LINK_STATUS)) {\n throw new Error('Shader link error: ' + gl.getProgramInfoLog(this._shaderProgram));\n }\n\n gl.deleteShader(vs);\n gl.deleteShader(fs);\n\n this._uDataTexture = gl.getUniformLocation(this._shaderProgram, 'uDataTexture');\n this._uCameraRight = gl.getUniformLocation(this._shaderProgram, 'uCameraRight');\n this._uCameraUp = gl.getUniformLocation(this._shaderProgram, 'uCameraUp');\n this._uCameraDir = gl.getUniformLocation(this._shaderProgram, 'uCameraDir');\n this._uViewProjMatrix = gl.getUniformLocation(this._shaderProgram, 'uViewProjMatrix');\n this._uModelMatrix = gl.getUniformLocation(this._shaderProgram, 'uModelMatrix');\n this._uViewportAspect = gl.getUniformLocation(this._shaderProgram, 'uViewportAspect');\n this._uWorldAlpha = gl.getUniformLocation(this._shaderProgram, 'uWorldAlpha');\n\n if (this._isWebGL1) {\n this._uMetaTexture = gl.getUniformLocation(this._shaderProgram, 'uMetaTexture');\n this._uDataTexSize = gl.getUniformLocation(this._shaderProgram, 'uDataTexSize');\n this._aIdLocation = gl.getAttribLocation(this._shaderProgram, 'aId');\n } else {\n this._uDataTextureWidth = gl.getUniformLocation(this._shaderProgram, 'uDataTextureWidth');\n }\n\n this._uTextures = [];\n this._uTexRemaps = [];\n for (let i = 0; i < NeutrinoContext.MAX_BATCH_TEXTURES; i++) {\n this._uTextures.push(gl.getUniformLocation(this._shaderProgram, `uTextures[${i}]`));\n this._uTexRemaps.push(gl.getUniformLocation(this._shaderProgram, `uTexRemaps[${i}]`));\n }\n }\n\n private _compileShader(type: number, source: string): WebGLShader {\n const gl = this.gl;\n const shader = gl.createShader(type)!;\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(shader);\n gl.deleteShader(shader);\n throw new Error('Shader compile error: ' + info);\n }\n\n return shader;\n }\n}\n","import Phaser from 'phaser';\n// @ts-ignore\nimport * as Neutrino from '@neutrinoparticles/js-v1.1';\nimport { NeutrinoContext } from './NeutrinoContext';\n\nexport interface GamePluginOptions {\n texturesBasePath?: string;\n generateNoise?: boolean;\n}\n\n/**\n * Main NeutrinoParticles plugin for Phaser (JS v1.1 runtime).\n *\n * Owns the shared {@link NeutrinoContext} (shader/index-buffer GL state) and\n * the neutrino simulation context, and manages noise generation. A WebGL\n * renderer is required — the v1.1 data-texture renderer has no Canvas\n * fallback. Both WebGL2 and WebGL1 contexts are supported; the render path is\n * selected automatically by {@link NeutrinoContext}.\n */\nexport class GamePlugin extends Phaser.Plugins.BasePlugin {\n declare public game: Phaser.Game;\n public neutrino!: any; // neutrinoparticles.js context\n public ctx!: NeutrinoContext; // shared WebGL render context\n public texturesBasePath: string = \"\";\n\n init(options?: GamePluginOptions) {\n options = Object.assign({\n texturesBasePath: \"\",\n generateNoise: false\n }, options);\n\n if (this.game.renderer.type !== Phaser.WEBGL) {\n throw new Error('NeutrinoParticles (js-v1.1): a WebGL renderer is required (Canvas not supported).');\n }\n\n // WebGL2 vs WebGL1 is detected (and WebGL1 capabilities are probed) by\n // NeutrinoContext itself — no hard WebGL2 gate here anymore.\n const renderer = this.game.renderer as Phaser.Renderer.WebGL.WebGLRenderer;\n const gl = renderer.gl as WebGL2RenderingContext;\n\n this.texturesBasePath = options.texturesBasePath!;\n this.neutrino = new Neutrino.Context();\n this.ctx = new NeutrinoContext(gl, this.neutrino);\n\n if (options.generateNoise)\n this.generateNoise();\n }\n\n start() {}\n stop() {}\n\n destroy() {\n if (this.ctx) this.ctx.destroy();\n this.neutrino = null!;\n super.destroy();\n }\n\n loadNoise(path: string, success?: () => void, fail?: () => void) {\n this.ctx.initializeNoise(path, success || (() => {}), fail || (() => {}));\n }\n\n generateNoise() {\n this.ctx.generateNoise();\n }\n}\n","import Phaser from 'phaser';\nimport { GamePlugin } from './GamePlugin';\nimport { NeutrinoEffectModel, NeutrinoSubRect } from './types';\n\nfunction noext(path: string): string {\n return path.replace(/\\.[^/.]+$/, \"\");\n}\n\n/**\n * Wraps a neutrinoparticles.js v1.1 effect model for Phaser. Loads textures from\n * standalone files or atlases via Phaser's loader, and computes atlas UV remaps\n * as plain {x,y,width,height} objects (the v1.1 renderer reads them directly).\n */\nexport class EffectModel {\n public readonly gamePlugin: GamePlugin;\n public readonly scene: Phaser.Scene;\n public readonly effectModel: NeutrinoEffectModel;\n\n public textureFrames: Array<Phaser.Textures.Frame | null> = [];\n public texturesRemap: Array<NeutrinoSubRect | null> = [];\n\n private _numTexturesToLoadLeft: number = 0;\n\n constructor(scene: Phaser.Scene, scriptText: string, options?: { atlases?: string[] }) {\n options = Object.assign({ atlases: [] }, options);\n\n this.gamePlugin = scene.plugins.get('neutrino') as GamePlugin;\n this.scene = scene;\n\n const evalScript = \"(function(ctx) {\\n\" + scriptText +\n \"\\nreturn new NeutrinoEffect(ctx);\\n})(this.gamePlugin.neutrino);\";\n this.effectModel = eval(evalScript) as NeutrinoEffectModel;\n\n this._startLoadTextures(options.atlases!);\n }\n\n get ready(): boolean {\n return this._numTexturesToLoadLeft === 0;\n }\n\n /** Raw WebGL texture handle for a given texture index (or null). */\n glTexture(index: number): WebGLTexture | null {\n const frame = this.textureFrames[index];\n return frame ? (frame.glTexture as any).webGLTexture : null;\n }\n\n private _startLoadTextures(atlases: string[]) {\n const numTextures = this.effectModel.textures.length;\n this._numTexturesToLoadLeft = numTextures;\n\n for (let imageIndex = 0; imageIndex < numTextures; ++imageIndex) {\n const textureName = this.effectModel.textures[imageIndex];\n const texturePath = this.gamePlugin.texturesBasePath + textureName;\n const texturePathNoExt = noext(texturePath);\n\n let frame = this._findFrameInAtlases(atlases, textureName);\n if (!frame)\n frame = this._findFrameInAtlases(atlases, noext(textureName));\n\n if (!frame && this.scene.sys.textures.exists(texturePathNoExt)) {\n const texture = this.scene.sys.textures.get(texturePathNoExt);\n frame = texture.get(texture.firstFrame);\n }\n\n if (frame) {\n this._onTextureLoaded(imageIndex, frame);\n } else {\n this.scene.load.once('filecomplete-image-' + texturePathNoExt,\n ((idx: number, key: string) => {\n return () => {\n const texture = this.scene.sys.textures.get(key);\n this._onTextureLoaded(idx, texture.get(texture.firstFrame));\n }\n })(imageIndex, texturePathNoExt));\n\n this.scene.load.image(texturePathNoExt, texturePath);\n }\n }\n }\n\n private _findFrameInAtlases(atlases: string[], frameName: string): Phaser.Textures.Frame | null {\n for (let i = 0; i < atlases.length; ++i) {\n const key = atlases[i];\n if (!this.scene.sys.textures.exists(key))\n continue;\n\n const texture = this.scene.sys.textures.get(key);\n if (texture.has(frameName))\n return texture.get(frameName);\n }\n\n return null;\n }\n\n private _onTextureLoaded(index: number, frame: Phaser.Textures.Frame) {\n this.textureFrames[index] = frame;\n this._numTexturesToLoadLeft--;\n\n if (this._numTexturesToLoadLeft === 0) {\n this._initTexturesRemapIfNeeded();\n }\n }\n\n private _fullCover(frame: Phaser.Textures.Frame): boolean {\n return frame.width === frame.source.width && frame.height === frame.source.height;\n }\n\n private _initTexturesRemapIfNeeded() {\n let remapNeeded = false;\n\n for (let texIdx = 0; texIdx < this.textureFrames.length; ++texIdx) {\n if (!this._fullCover(this.textureFrames[texIdx]!)) {\n remapNeeded = true;\n break;\n }\n }\n\n if (!remapNeeded) return;\n\n for (let texIdx = 0; texIdx < this.textureFrames.length; ++texIdx) {\n const frame = this.textureFrames[texIdx]!;\n // Phaser frame UVs are already top-left-origin normalized; the shader\n // expects y measured from the bottom, hence 1 - v1.\n this.texturesRemap[texIdx] = {\n x: frame.u0,\n y: 1.0 - frame.v1,\n width: frame.u1 - frame.u0,\n height: frame.v1 - frame.v0\n };\n }\n }\n}\n","import Phaser from 'phaser';\nimport { EffectModel } from './EffectModel';\n\nexport interface NeutrinoFileConfig {\n key: string;\n url: string;\n options?: { atlases?: string[] };\n xhrSettings?: Phaser.Types.Loader.XHRSettingsObject;\n}\n\n/**\n * Custom Phaser loader file type for NeutrinoParticles effects (.js export).\n * Parses the exported source into an {@link EffectModel} stored in the binary cache.\n */\nexport class NeutrinoFile extends Phaser.Loader.File {\n private _options?: { atlases?: string[] };\n\n constructor(loader: Phaser.Loader.LoaderPlugin, config: NeutrinoFileConfig) {\n const { key, url, options, xhrSettings } = config;\n\n super(loader, {\n type: 'binary',\n extension: 'js',\n responseType: 'text',\n key,\n url,\n xhrSettings\n });\n\n this.cache = loader.cacheManager.binary;\n this._options = options;\n }\n\n onProcess() {\n this.state = Phaser.Loader.FILE_PROCESSING;\n const text = this.xhrLoader!.response as string;\n this.data = new EffectModel(this.loader.scene, text, this._options);\n this.onProcessComplete();\n }\n}\n","export type Vec2 = [number, number];\nexport type Vec3 = [number, number, number];\nexport type Vec4 = [number, number, number, number];\nexport type Quat = [number, number, number, number];\nexport type Mat3x2 = [number, number, number, number, number, number];\n\nexport enum Pause {\n NO = 0,\n BEFORE_UPDATE_OR_RENDER = 1,\n YES = 2\n}\n\nexport interface RenderInstruction {\n startParticleIndex: number;\n numParticles: number;\n renderStyleIndex: number;\n blendMode: number;\n}\n\nexport interface RenderStyle {\n materialIndex: number;\n textureIndices: number[];\n}\n\nexport interface NeutrinoEffectModel {\n textures: string[];\n materials: number[];\n renderStyles: RenderStyle[];\n totalParticles: number;\n createInstance(position: Vec3, rotation: Quat, options: object): NeutrinoSystem;\n}\n\nexport interface NeutrinoSystem {\n model: NeutrinoEffectModel;\n particleDataUint32: Uint32Array;\n particleDataBuffer: ArrayBuffer;\n particleDataView: DataView;\n dataTextureWidth: number;\n dataTextureHeight: number;\n renderInstructions: RenderInstruction[] & { _totalParticles: number };\n update(dt: number, position?: Vec3 | null, rotation?: Quat | null): void;\n construct(cameraDir?: Vec3): void;\n restart(position?: Vec3, rotation?: Quat, options?: object): void;\n resetPosition(position?: Vec3, rotation?: Quat): void;\n pauseAllEmitters(): void;\n unpauseAllEmitters(): void;\n areAllEmittersPaused(): boolean;\n pauseGeneratorsInAllEmitters(): void;\n unpauseGeneratorsInAllEmitters(): void;\n areGeneratorsInAllEmittersPaused(): boolean;\n getNumParticles(): number;\n setPropertyInAllEmitters(name: string, value: number | Vec2 | Vec3): void;\n}\n\nexport interface NeutrinoRuntimeContext {\n initializeNoise(path: string, success: () => void, fail: () => void): void;\n NoiseGenerator: new () => { step(): boolean; progress: number };\n axisangle2quat_(axis: Vec3, angleDeg: number): Quat;\n}\n\nexport interface NeutrinoSubRect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n","const RING_BUFFER_SIZE = 3;\n\n/**\n * Manages a small ring of RGBA32F WebGL textures that hold the runtime's flat\n * particle data buffer. Each frame the current texture is re-uploaded (zero-copy\n * from the runtime-owned Uint32Array via a Float32 view) and the ring advances,\n * which avoids GPU pipeline stalls from re-uploading into a texture still in use.\n *\n * Unlike the pixi7 adapter this owns raw GL textures directly (no PIXI texture\n * system), so the exact same class works for both the PIXI v8 and Phaser\n * integrations, which both do their own raw WebGL2 draw.\n */\nexport class DataTextureManager {\n public readonly textureWidth: number;\n public readonly textureHeight: number;\n\n private readonly _gl: WebGL2RenderingContext;\n private readonly _floatView: Float32Array;\n private _textures: (WebGLTexture | null)[] = [];\n private _currentIndex: number = 0;\n\n /**\n * @param gl - WebGL2 context (from the host renderer)\n * @param data - Uint32Array from the runtime. A Float32Array view over the\n * same buffer is uploaded as RGBA32F — bit patterns (incl. NaN/Inf) pass\n * through unchanged.\n * @param textureWidth - from runtime (system.dataTextureWidth)\n * @param textureHeight - from runtime (system.dataTextureHeight)\n */\n constructor(gl: WebGL2RenderingContext, data: Uint32Array, textureWidth: number, textureHeight: number) {\n const maxSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) as number;\n if (textureWidth > maxSize || textureHeight > maxSize) {\n throw new Error(\n `NeutrinoParticles: data texture ${textureWidth}x${textureHeight} exceeds ` +\n `GL MAX_TEXTURE_SIZE (${maxSize}). Reduce effect particle capacity.`);\n }\n\n this._gl = gl;\n this.textureWidth = textureWidth;\n this.textureHeight = textureHeight;\n\n // Same underlying ArrayBuffer — bit patterns pass through unchanged.\n this._floatView = new Float32Array(data.buffer, data.byteOffset, data.length);\n\n for (let i = 0; i < RING_BUFFER_SIZE; i++) {\n const tex = gl.createTexture();\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, textureWidth, textureHeight, 0,\n gl.RGBA, gl.FLOAT, null);\n this._textures.push(tex);\n }\n gl.bindTexture(gl.TEXTURE_2D, null);\n }\n\n get currentTexture(): WebGLTexture {\n return this._textures[this._currentIndex]!;\n }\n\n /** Bind the current texture to a unit and upload the latest particle data. */\n uploadAndBind(unit: number): void {\n const gl = this._gl;\n gl.activeTexture(gl.TEXTURE0 + unit);\n gl.bindTexture(gl.TEXTURE_2D, this._textures[this._currentIndex]);\n gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);\n // The particle data is raw floats (positions/sizes/flags), NOT colour.\n // The host engine (PIXI/Phaser) may leave UNPACK_PREMULTIPLY_ALPHA /\n // UNPACK_FLIP_Y enabled from its own texture uploads, which would\n // corrupt our data (each RGB scaled by A, rows flipped). Force them off.\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);\n gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, this.textureWidth, this.textureHeight,\n gl.RGBA, gl.FLOAT, this._floatView);\n }\n\n advance(): void {\n this._currentIndex = (this._currentIndex + 1) % RING_BUFFER_SIZE;\n }\n\n destroy(): void {\n const gl = this._gl;\n for (const tex of this._textures) {\n if (tex) gl.deleteTexture(tex);\n }\n this._textures = [];\n }\n}\n","// CPU packing of the RGBA8 meta texture for the WebGL1 render path\n// (TDD §4.3). GLSL ES 1.00 cannot bit-reinterpret floats, so the u32-packed\n// record fields travel as raw bytes in a texture the same size as the data\n// texture: meta texel `baseTexel + k` pairs with data texel `baseTexel + k`.\n//\n// Per particle (4 meta texels, 16 bytes):\n// M0 = flags u32 (byte0 = batchTexIdx, patched by the renderer;\n// byte1 bits 1:0 = rotationType, bits 3:2 = ctorType)\n// M1 = packedColor u32 (the LE bytes ARE the normalized RGBA color)\n// M2 = u32 @ record offset 52 (gridConfig for quads / neighborIdxP0 for strips)\n// M3 = u32 @ record offset 56 (neighborIdxP3 for strips; for quads these are\n// the raw bits of the float gridIndex — never read by the quad path)\n//\n// Byte order note: the whole v1.1 pipeline already assumes a little-endian\n// platform (the runtime writes fields via little-endian DataView and reads\n// them back through Uint32Array) — the Uint32Array fast path below relies on\n// the same assumption.\nexport class MetaTextureManager {\n public readonly bytes: Uint8Array;\n\n private readonly _u32: Uint32Array;\n\n constructor(textureWidth: number, textureHeight: number) {\n this.bytes = new Uint8Array(textureWidth * textureHeight * 4);\n this._u32 = new Uint32Array(this.bytes.buffer);\n }\n\n /** Repack the packed-u32 record fields for the first `numParticles` records. */\n build(dataUint32: Uint32Array, numParticles: number): void {\n const dst = this._u32;\n for (let p = 0; p < numParticles; p++) {\n const s = p * 16; // 16 uint32 per 64-byte record\n const d = p * 4; // 4 meta texels per particle\n dst[d] = dataUint32[s]; // flags (record offset 0)\n dst[d + 1] = dataUint32[s + 12]; // packedColor (record offset 48)\n dst[d + 2] = dataUint32[s + 13]; // gridConfig / neighborIdxP0 (52)\n dst[d + 3] = dataUint32[s + 14]; // gridIndex bits / neighborIdxP3 (56)\n }\n }\n\n /** Write the batch texture slot into byte0 of M0 (flags) per particle. */\n patchSlot(startParticle: number, count: number, slot: number): void {\n const bytes = this.bytes;\n let o = startParticle * 16;\n for (let p = 0; p < count; p++) {\n bytes[o] = slot;\n o += 16;\n }\n }\n}\n","import { MetaTextureManager } from \"./MetaTextureManager\";\n\nconst RING_BUFFER_SIZE = 3;\n\n// WebGL1 counterpart of DataTextureManager (TDD §4.4): raw-GL managed — NOT\n// routed through PIXI BaseTexture — so the float-texture handling does not\n// depend on PIXI's WebGL1 code paths and the same module works in pixi7 and\n// pixi8. Owns two 3-deep texture rings over the same W×H:\n// - RGBA/FLOAT data texture wrapping the runtime's particle buffer (zero-copy);\n// - RGBA8 meta texture built per frame by MetaTextureManager.\n// NEAREST + CLAMP_TO_EDGE (NPOT-safe on WebGL1). Uploads only the rows\n// covering the live particles via texSubImage2D.\nexport class DataTextureManagerGL1 {\n public readonly textureWidth: number;\n public readonly textureHeight: number;\n public readonly meta: MetaTextureManager;\n\n private readonly _gl: WebGLRenderingContext;\n private readonly _floatView: Float32Array;\n private _dataTextures: WebGLTexture[] = [];\n private _metaTextures: WebGLTexture[] = [];\n private _currentIndex: number = 0;\n\n constructor(gl: WebGLRenderingContext, data: Uint32Array, textureWidth: number, textureHeight: number) {\n const maxSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) as number;\n if (textureWidth > maxSize || textureHeight > maxSize) {\n throw new Error(\n `NeutrinoParticles: data texture ${textureWidth}x${textureHeight} exceeds ` +\n `GL MAX_TEXTURE_SIZE (${maxSize}). Reduce effect particle capacity.`);\n }\n // Texel indices (aId, neighbor-record*4) must stay exact in fp32\n // (TDD §4.7) — cap the texel count at 2^24 on the WebGL1 path.\n if (textureWidth * textureHeight > 16777216) {\n throw new Error(\n `NeutrinoParticles: data texture ${textureWidth}x${textureHeight} exceeds ` +\n `the WebGL1 render path texel cap (2^24). Reduce effect particle capacity.`);\n }\n\n this._gl = gl;\n this.textureWidth = textureWidth;\n this.textureHeight = textureHeight;\n\n // Bits pass through unchanged — same zero-copy Float32Array view over\n // the runtime buffer the WebGL2 path uses.\n this._floatView = new Float32Array(data.buffer, data.byteOffset, data.length);\n this.meta = new MetaTextureManager(textureWidth, textureHeight);\n\n // Texture creation binds raw; construction can run mid-frame (effect\n // 'ready' fires from texture-load callbacks), so restore the active\n // unit's previous binding to keep the host's (PIXI's) texture-state\n // cache valid. upload() does not need this — the renderer plugin\n // resets the host cache right after it.\n const prevActiveTexture = gl.getParameter(gl.ACTIVE_TEXTURE) as number;\n gl.activeTexture(gl.TEXTURE0);\n const prevTex0 = gl.getParameter(gl.TEXTURE_BINDING_2D) as WebGLTexture | null;\n for (let i = 0; i < RING_BUFFER_SIZE; i++) {\n this._dataTextures.push(this._createTexture(gl.FLOAT));\n this._metaTextures.push(this._createTexture(gl.UNSIGNED_BYTE));\n }\n gl.bindTexture(gl.TEXTURE_2D, prevTex0);\n gl.activeTexture(prevActiveTexture);\n }\n\n get currentDataTexture(): WebGLTexture { return this._dataTextures[this._currentIndex]; }\n get currentMetaTexture(): WebGLTexture { return this._metaTextures[this._currentIndex]; }\n\n /**\n * Upload the rows covering `numParticles` into the current ring textures,\n * leaving them bound to `dataUnit` / `metaUnit`. The caller invalidates\n * PIXI's bound-texture bookkeeping for those units.\n */\n upload(numParticles: number, dataUnit: number, metaUnit: number): void {\n const gl = this._gl;\n const w = this.textureWidth;\n const rows = Math.min(this.textureHeight, Math.ceil((numParticles * 4) / w));\n if (rows === 0) return;\n const count = rows * w * 4;\n\n // PIXI leaves UNPACK_PREMULTIPLY_ALPHA/FLIP_Y set from its own lazy\n // texture uploads (they apply to typed-array uploads on WebGL1!).\n // Premultiply would multiply each texel's rgb by its alpha — for data\n // texel 0 alpha is posZ (0 in 2D), zeroing flags/posX/posY. Force the\n // raw pass-through state before every upload; PIXI re-sets these per\n // upload itself, so no restore is needed.\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\n gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);\n\n gl.activeTexture(gl.TEXTURE0 + dataUnit);\n gl.bindTexture(gl.TEXTURE_2D, this.currentDataTexture);\n gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, w, rows, gl.RGBA, gl.FLOAT,\n this._floatView.subarray(0, count));\n\n gl.activeTexture(gl.TEXTURE0 + metaUnit);\n gl.bindTexture(gl.TEXTURE_2D, this.currentMetaTexture);\n gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, w, rows, gl.RGBA, gl.UNSIGNED_BYTE,\n this.meta.bytes.subarray(0, count));\n }\n\n advance(): void {\n this._currentIndex = (this._currentIndex + 1) % RING_BUFFER_SIZE;\n }\n\n destroy(): void {\n const gl = this._gl;\n for (const t of this._dataTextures) gl.deleteTexture(t);\n for (const t of this._metaTextures) gl.deleteTexture(t);\n this._dataTextures = [];\n this._metaTextures = [];\n }\n\n private _createTexture(type: number): WebGLTexture {\n const gl = this._gl;\n const tex = gl.createTexture()!;\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n // Full-size allocation once; per-frame updates go through texSubImage2D.\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.textureWidth, this.textureHeight,\n 0, gl.RGBA, type, null);\n return tex;\n }\n}\n","import { NeutrinoContext } from \"./NeutrinoContext\";\nimport { DataTextureManager } from \"./DataTextureManager\";\nimport { DataTextureManagerGL1 } from \"./gl1/DataTextureManagerGL1\";\nimport { NeutrinoSubRect } from \"./types\";\n\nconst DATA_TEXTURE_UNIT = 0;\nconst META_TEXTURE_UNIT = 1; // WebGL1 path only\nconst PARTICLE_TEXTURE_START_UNIT = 1; // WebGL2: units 1..8\nconst PARTICLE_TEXTURE_START_UNIT_GL1 = 2; // WebGL1: meta takes unit 1\nconst FLOATS_PER_PARTICLE = 16; // 4 texels × 4 RGBA\nconst BYTES_PER_PARTICLE = FLOATS_PER_PARTICLE * 4;\nconst MAX_BATCHES = 64;\n\nclass DrawBatch {\n blendMode: number = 0;\n startParticle: number = 0;\n numParticles: number = 0;\n numTextures: number = 0;\n glTextures: (WebGLTexture | null)[] = new Array(NeutrinoContext.MAX_BATCH_TEXTURES).fill(null);\n remaps: (NeutrinoSubRect | null)[] = new Array(NeutrinoContext.MAX_BATCH_TEXTURES).fill(null);\n\n reset(): void {\n this.blendMode = 0;\n this.startParticle = 0;\n this.numParticles = 0;\n this.numTextures = 0;\n }\n}\n\nexport interface RenderParams {\n /** Effect world transform (2x3) already including world scale. */\n model: { a: number, b: number, c: number, d: number, tx: number, ty: number };\n /** Canvas pixel dimensions, for the ortho projection. */\n viewportWidth: number;\n viewportHeight: number;\n /** Camera scroll (subtracted in pixel space) and zoom. */\n scrollX: number;\n scrollY: number;\n zoom: number;\n /** Host scene-graph world alpha, multiplied into each particle's alpha. */\n worldAlpha: number;\n /** Per-particle GL textures (one per render-style texture index). */\n glTextures: (WebGLTexture | null)[];\n remaps: Array<NeutrinoSubRect | null>;\n renderStyles: Array<{ materialIndex: number; textureIndices: number[] }>;\n materials: number[];\n}\n\n/**\n * Raw WebGL data-texture renderer for the Phaser integration.\n *\n * Mirrors the pixi adapters: builds blend-mode batches (≤maxBatchTextures each),\n * patches the per-particle texture-slot byte, uploads the data texture and draws\n * each batch with gl.drawElements. On WebGL1 the u32-packed fields travel via an\n * RGBA8 meta texture and the slot patch goes there instead of the float buffer\n * (TDD_js-v1.1-webgl1.md §4.3/§4.6). Because Phaser owns the GL state machine,\n * the caller is responsible for flushing Phaser's batch and restoring pipeline\n * state around a render() call (see Effect.renderWebGL).\n */\nexport class NeutrinoRenderer {\n private _orthoMatrix = new Float32Array(16);\n private _modelMatrix = new Float32Array(16);\n private _texSlotMap = new Map<number, number>();\n private _batchPool: DrawBatch[];\n private _batchCount: number = 0;\n\n constructor() {\n this._batchPool = [];\n for (let i = 0; i < MAX_BATCHES; i++) {\n this._batchPool.push(new DrawBatch());\n }\n }\n\n render(\n ctx: NeutrinoContext,\n dtm: DataTextureManager | DataTextureManagerGL1,\n dataView: DataView,\n dataUint32: Uint32Array,\n instructions: any[],\n numParticles: number,\n params: RenderParams\n ): void {\n if (numParticles === 0) return;\n\n const gl = ctx.gl;\n const isGL1 = ctx.isWebGL1;\n const maxBatch = ctx.maxBatchTextures;\n const renderStyles = params.renderStyles;\n const materials = params.materials;\n\n // WebGL1: repack the u32 fields into the meta texture BEFORE slot\n // patching (build overwrites the whole meta region from the runtime\n // buffer; the runtime's float buffer itself is never mutated).\n const metaManager = isGL1 ? (dtm as DataTextureManagerGL1).meta : null;\n if (metaManager) {\n metaManager.build(dataUint32, numParticles);\n }\n\n // Phase 1: Build draw batches and patch flags.\n this._batchCount = 0;\n const texSlotMap = this._texSlotMap;\n\n while (this._batchPool.length < instructions.length) {\n this._batchPool.push(new DrawBatch());\n }\n\n let i = 0;\n while (i < instructions.length) {\n const batch = this._batchPool[this._batchCount];\n batch.reset();\n // instruction.blendMode is the per-effect COMPACTED material INDEX, not the blend\n // enum — resolve it through materials[] (see _resolveBlend). Resolving before the\n // coalescing comparison is correct: indices mapping to the same enum share a batch.\n batch.blendMode = this._resolveBlend(instructions[i].blendMode, materials);\n batch.startParticle = instructions[i].startParticleIndex;\n texSlotMap.clear();\n\n let j = i;\n while (j < instructions.length && this._resolveBlend(instructions[j].blendMode, materials) === batch.blendMode) {\n const texIndex = renderStyles[instructions[j].renderStyleIndex].textureIndices[0];\n\n if (!texSlotMap.has(texIndex)) {\n if (texSlotMap.size >= maxBatch) break;\n const slot = texSlotMap.size;\n texSlotMap.set(texIndex, slot);\n batch.glTextures[slot] = params.glTextures[texIndex] || null;\n batch.remaps[slot] = params.remaps[texIndex] || null;\n batch.numTextures = slot + 1;\n }\n\n const slot = texSlotMap.get(texIndex)!;\n const instr = instructions[j];\n if (metaManager) {\n // WebGL1: the slot lives in the meta texture (byte0 of M0).\n metaManager.patchSlot(instr.startParticleIndex, instr.numParticles, slot);\n } else {\n for (let p = 0; p < instr.numParticles; p++) {\n const flagOffset = (instr.startParticleIndex + p) * BYTES_PER_PARTICLE;\n const flags = dataView.getUint32(flagOffset, true);\n dataView.setUint32(flagOffset, (flags & 0xFFFFFF00) | slot, true);\n }\n }\n\n batch.numParticles += instr.numParticles;\n j++;\n }\n\n this._batchCount++;\n i = j;\n }\n\n // Phase 2: GL state + uniforms.\n // Scissor is the one piece of state neither this renderer's own\n // unconditional setup nor Phaser's pipelines.rebind() re-establishes\n // (rebind touches viewport/blend/program but not scissor) — restore\n // its enable bit after the draws so a camera scissor region survives.\n // The restore (and the buffer/program cleanup) runs in finally so an\n // exception mid-render cannot leak the disabled state either.\n const prevScissorTest = gl.isEnabled(gl.SCISSOR_TEST);\n try {\n gl.disable(gl.DEPTH_TEST);\n gl.disable(gl.STENCIL_TEST);\n gl.disable(gl.SCISSOR_TEST);\n gl.disable(gl.CULL_FACE);\n gl.depthMask(false);\n gl.colorMask(true, true, true, true);\n\n gl.useProgram(ctx.shaderProgram);\n\n if (isGL1) {\n const dtmGL1 = dtm as DataTextureManagerGL1;\n // Single upload of both ring textures (after all slot patches),\n // left bound to their units. Raw binds are safe here: Phaser\n // consults no texture cache between the caller's flush() and\n // pipelines.rebind(), and rebind() re-establishes its own state.\n dtmGL1.upload(numParticles, DATA_TEXTURE_UNIT, META_TEXTURE_UNIT);\n gl.uniform1i(ctx.uDataTexture, DATA_TEXTURE_UNIT);\n gl.uniform1i(ctx.uMetaTexture, META_TEXTURE_UNIT);\n gl.uniform2f(ctx.uDataTexSize, dtmGL1.textureWidth, dtmGL1.textureHeight);\n } else {\n const dtmGL2 = dtm as DataTextureManager;\n dtmGL2.uploadAndBind(DATA_TEXTURE_UNIT);\n gl.uniform1i(ctx.uDataTexture, DATA_TEXTURE_UNIT);\n gl.uniform1i(ctx.uDataTextureWidth, dtmGL2.textureWidth);\n }\n\n gl.uniform3f(ctx.uCameraRight, 1, 0, 0);\n gl.uniform3f(ctx.uCameraUp, 0, -1, 0);\n gl.uniform3f(ctx.uCameraDir, 0, 0, -1);\n\n // Top-left ortho: pixel [0..w]x[0..h] -> NDC, y flipped. Camera zoom scales,\n // scroll translates (in pixel space, applied before projection via tx/ty).\n const w = params.viewportWidth;\n const h = params.viewportHeight;\n const zoom = params.zoom || 1;\n const om = this._orthoMatrix;\n om.fill(0);\n om[0] = (2 / w) * zoom;\n om[5] = (-2 / h) * zoom;\n om[10] = 1;\n om[15] = 1;\n om[12] = -1 - (2 / w) * zoom * params.scrollX;\n om[13] = 1 + (2 / h) * zoom * params.scrollY;\n gl.uniformMatrix4fv(ctx.uViewProjMatrix, false, om);\n\n const aspect = h > 0 ? (w / h) : 1.0;\n if (ctx.uViewportAspect) gl.uniform1f(ctx.uViewportAspect, aspect);\n\n if (ctx.uWorldAlpha) gl.uniform1f(ctx.uWorldAlpha, params.worldAlpha);\n\n const m = params.model;\n const mm = this._modelMatrix;\n mm[0] = m.a; mm[1] = m.b; mm[2] = 0; mm[3] = 0;\n mm[4] = m.c; mm[5] = m.d; mm[6] = 0; mm[7] = 0;\n mm[8] = 0; mm[9] = 0; mm[10] = 1; mm[11] = 0;\n mm[12] = m.tx; mm[13] = m.ty; mm[14] = 0; mm[15] = 1;\n gl.uniformMatrix4fv(ctx.uModelMatrix, false, mm);\n\n if (isGL1) {\n // No VAO on the GL1 path: raw buffer binds + the aId pointer.\n ctx.unbindVao();\n gl.bindBuffer(gl.ARRAY_BUFFER, ctx.aIdBuffer);\n gl.enableVertexAttribArray(ctx.aIdLocation);\n gl.vertexAttribPointer(ctx.aIdLocation, 1, gl.FLOAT, false, 0, 0);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ctx.indexBuffer);\n } else {\n gl.bindVertexArray(ctx.vao);\n }\n\n const particleStartUnit = isGL1 ? PARTICLE_TEXTURE_START_UNIT_GL1 : PARTICLE_TEXTURE_START_UNIT;\n\n // Phase 3: Draw batches.\n gl.enable(gl.BLEND);\n for (let b = 0; b < this._batchCount; b++) {\n const batch = this._batchPool[b];\n\n this._applyBlendMode(gl, batch.blendMode);\n\n for (let s = 0; s < batch.numTextures; s++) {\n const unit = particleStartUnit + s;\n gl.activeTexture(gl.TEXTURE0 + unit);\n gl.bindTexture(gl.TEXTURE_2D, batch.glTextures[s]);\n gl.uniform1i(ctx.uTextures[s], unit);\n\n const remap = batch.remaps[s];\n if (remap) {\n gl.uniform4f(ctx.uTexRemaps[s], remap.x, remap.y, remap.width, remap.height);\n } else {\n gl.uniform4f(ctx.uTexRemaps[s], 0, 0, 1, 1);\n }\n }\n\n const indexOffset = batch.startParticle * 6;\n const indexCount = batch.numParticles * 6;\n gl.drawElements(\n gl.TRIANGLES,\n indexCount,\n ctx.indexType,\n indexOffset * (ctx.indexType === gl.UNSIGNED_INT ? 4 : 2)\n );\n }\n\n } finally {\n // Harmless when the exception hit before the aId/VAO setup:\n // disabling a not-enabled attribute and null-binds are no-ops.\n if (isGL1) {\n gl.disableVertexAttribArray(ctx.aIdLocation);\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n } else {\n gl.bindVertexArray(null);\n }\n gl.useProgram(null);\n if (prevScissorTest) gl.enable(gl.SCISSOR_TEST);\n }\n // Note: the particle texture units we bound are left as-is; the caller\n // re-establishes Phaser's pipeline texture state via pipelines.rebind(),\n // which re-binds the active pipeline's own sampler textures.\n }\n\n // Resolve a renderStyle's compacted material INDEX to the real blend enum (0=Normal/\n // 1=Add/2=Multiply) via materials[]. The runtime sets instruction.blendMode =\n // renderStyles[rsi].materialIndex (system.js _renderStyleBlendModes), an INDEX into\n // materials[], NOT the blend itself — without this deref a single-material effect\n // (materialIndex 0) would always render as materials[0]'s slot 0 (Normal). Falls back to\n // the raw value if materials is missing/out of range (mirror of cocos _resolveBlendMode).\n private _resolveBlend(materialIndex: number, materials: number[]): number {\n if (materials && materialIndex >= 0 && materialIndex < materials.length) {\n return materials[materialIndex];\n }\n return materialIndex;\n }\n\n private _applyBlendMode(gl: WebGL2RenderingContext, blendMode: number): void {\n switch (blendMode) {\n default:\n case 0:\n gl.blendFuncSeparate(gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n break;\n case 1:\n gl.blendFunc(gl.ONE, gl.ONE);\n break;\n case 2:\n gl.blendFunc(gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA);\n break;\n }\n }\n}\n","import Phaser from 'phaser';\nimport { Pause, Vec2, Vec3, Quat } from './types';\nimport { GamePlugin } from './GamePlugin';\nimport { EffectModel } from './EffectModel';\nimport { DataTextureManager } from './DataTextureManager';\nimport { DataTextureManagerGL1 } from './gl1/DataTextureManagerGL1';\nimport { NeutrinoRenderer } from './NeutrinoRenderer';\nimport { NeutrinoSystem } from './types';\n\nexport interface EffectOptions {\n position?: Vec3;\n angle?: number;\n scale?: number;\n pause?: Pause;\n generatorsPaused?: boolean;\n}\n\ninterface EffectStartupOptions {\n paused: boolean;\n generatorsPaused: boolean;\n}\n\nconst sharedRenderer = new NeutrinoRenderer();\n\n/**\n * A NeutrinoParticles effect on a Phaser scene (JS v1.1 runtime).\n *\n * Simulation runs in preUpdate(); rendering happens in renderWebGL() via a raw\n * WebGL data-texture draw (WebGL2 or the WebGL1 variant, chosen by the shared\n * NeutrinoContext). Phaser's active pipeline is flushed before and rebound\n * after the draw so its state machine stays consistent.\n */\nexport class Effect extends Phaser.GameObjects.GameObject {\n public gamePlugin: GamePlugin;\n public effectModel: EffectModel;\n public effect: NeutrinoSystem | null = null;\n\n // Transform (manually managed, not via Phaser component mixins).\n public x: number = 0;\n public y: number = 0;\n public z: number = 0;\n public angle: number = 0;\n public rotation: number = 0;\n public scaleX: number = 1;\n public scaleY: number = 1;\n public scrollFactorX: number = 1;\n public scrollFactorY: number = 1;\n public alpha: number = 1;\n public depth: number = 0;\n public blendMode: number = Phaser.BlendModes.NORMAL;\n\n private _dataTextureManager: DataTextureManager | DataTextureManagerGL1 | null = null;\n private _worldPosition: Phaser.Math.Vector2;\n private _worldScaledPosition: Vec3;\n private _worldRotation: Quat = [0, 0, 0, 1];\n private _worldScale: number;\n private _tempMatrix1: Phaser.GameObjects.Components.TransformMatrix;\n private _tempMatrix2: Phaser.GameObjects.Components.TransformMatrix;\n private _unpauseOnUpdateRender: boolean;\n private _glTexturesScratch: (WebGLTexture | null)[] = [];\n\n constructor(effectModel: EffectModel, scene: Phaser.Scene, options?: EffectOptions) {\n options = Object.assign({\n position: [0, 0, 0] as Vec3,\n angle: 0,\n scale: 1,\n pause: Pause.BEFORE_UPDATE_OR_RENDER,\n generatorsPaused: false\n }, options || {});\n\n super(scene, 'Neutrino');\n\n this.gamePlugin = scene.plugins.get('neutrino') as GamePlugin;\n this.effectModel = effectModel;\n\n this.x = options.position![0];\n this.y = options.position![1];\n this.z = options.position![2];\n\n this.angle = options.angle!;\n this.scaleX = options.scale!;\n this.scaleY = options.scale!;\n\n this._worldPosition = new Phaser.Math.Vector2();\n this._worldScaledPosition = [0, 0, 0];\n this._worldScale = 1;\n this._tempMatrix1 = new Phaser.GameObjects.Components.TransformMatrix();\n this._tempMatrix2 = new Phaser.GameObjects.Components.TransformMatrix();\n this._unpauseOnUpdateRender = (options.pause === Pause.BEFORE_UPDATE_OR_RENDER);\n\n this._updateWorldTransform();\n\n const startupOptions: EffectStartupOptions = {\n paused: options.pause !== Pause.NO,\n generatorsPaused: options.generatorsPaused!\n };\n\n if (this.effectModel) {\n this.effect = this.effectModel.effectModel.createInstance(\n this._renderPosition(), this._renderRotation(), startupOptions);\n\n // WebGL1 uses the raw-GL float+meta ring manager (TDD §4.4).\n this._dataTextureManager = this.gamePlugin.ctx.isWebGL1\n ? new DataTextureManagerGL1(\n this.gamePlugin.ctx.gl,\n this.effect.particleDataUint32,\n this.effect.dataTextureWidth,\n this.effect.dataTextureHeight)\n : new DataTextureManager(\n this.gamePlugin.ctx.gl,\n this.effect.particleDataUint32,\n this.effect.dataTextureWidth,\n this.effect.dataTextureHeight);\n\n this.gamePlugin.ctx.ensureIndexBuffer(this.effectModel.effectModel.totalParticles);\n }\n }\n\n get ready(): boolean {\n return this.effectModel != null && this.effectModel.ready && this.effect != null;\n }\n\n preUpdate(_time: number, ms: number) {\n if (!this.ready) return;\n\n if (!this._checkUnpauseOnUpdateRender())\n this._updateWorldTransform();\n\n this.effect!.update(ms / 1000.0, this._renderPosition(), this._renderRotation());\n }\n\n renderWebGL(renderer: Phaser.Renderer.WebGL.WebGLRenderer, _src: Effect,\n camera: Phaser.Cameras.Scene2D.Camera) {\n if (!this.ready) return;\n // Fully transparent → nothing to draw (mirrors the pixi adapters, where a\n // zero worldAlpha container is skipped by the scene graph). Partial alpha\n // is not applied per-particle in the v1.1 data-texture path.\n if (this.alpha <= 0) return;\n\n this._checkUnpauseOnUpdateRender();\n\n const ctx = this.gamePlugin.ctx;\n const dtm = this._dataTextureManager!;\n\n this.effect!.construct([0, 0, -1]);\n const instructions = this.effect!.renderInstructions;\n const numParticles = instructions._totalParticles;\n if (numParticles === 0) return;\n\n // Flush Phaser's current batch so our raw draw doesn't interleave with it.\n renderer.flush();\n\n // Resolve per-texture GL handles for this frame.\n const textureCount = this.effectModel.effectModel.textures.length;\n const glTextures = this._glTexturesScratch;\n glTextures.length = textureCount;\n for (let t = 0; t < textureCount; ++t) {\n glTextures[t] = this.effectModel.glTexture(t);\n }\n\n const s = this._worldScale;\n try {\n sharedRenderer.render(ctx, dtm, this.effect!.particleDataView,\n this.effect!.particleDataUint32, instructions, numParticles, {\n model: { a: s, b: 0, c: 0, d: s, tx: 0, ty: 0 },\n viewportWidth: renderer.width,\n viewportHeight: renderer.height,\n scrollX: camera.scrollX * this.scrollFactorX,\n scrollY: camera.scrollY * this.scrollFactorY,\n zoom: camera.zoom,\n worldAlpha: this.alpha,\n glTextures,\n remaps: this.effectModel.texturesRemap,\n renderStyles: this.effect!.model.renderStyles as any,\n materials: this.effect!.model.materials\n });\n\n dtm.advance();\n } finally {\n // Restore Phaser's pipeline/GL state for subsequent game objects —\n // in finally so a raw-draw exception cannot leave Phaser's state\n // machine desynced. The raw draw already unbound every texture unit\n // it touched (see NeutrinoRenderer), and rebind() re-establishes\n // the active pipeline's program, VAO, textures and uniforms — which\n // re-binds the pipeline's own sampler textures, so Phaser's texture\n // state is consistent again on the next draw.\n renderer.pipelines.rebind();\n }\n }\n\n restart(options?: { position?: Vec3, angle?: number, rotation?: number }) {\n if (!this.ready) return;\n this._applyTransformOptions(options);\n this._updateWorldTransform();\n this.effect!.restart(this._renderPosition(), this._renderRotation());\n }\n\n resetPosition(options?: { position?: Vec3, angle?: number, rotation?: number }) {\n if (!this.ready) return;\n this._applyTransformOptions(options);\n this._updateWorldTransform();\n this.effect!.resetPosition(this._renderPosition(), this._renderRotation());\n }\n\n pause() {\n if (this.ready) this.effect!.pauseAllEmitters();\n }\n\n unpause() {\n if (this.ready) this.effect!.unpauseAllEmitters();\n }\n\n get paused(): boolean {\n return (this.ready) ? this.effect!.areAllEmittersPaused() : false;\n }\n\n pauseGenerators() {\n if (this.ready) this.effect!.pauseGeneratorsInAllEmitters();\n }\n\n unpauseGenerators() {\n if (this.ready) this.effect!.unpauseGeneratorsInAllEmitters();\n }\n\n get generatorsPaused(): boolean {\n return (this.ready) ? this.effect!.areGeneratorsInAllEmittersPaused() : false;\n }\n\n setPropertyInAllEmitters(name: string, value: Vec3 | Vec2 | number) {\n if (this.ready) this.effect!.setPropertyInAllEmitters(name, value);\n }\n\n getNumParticles(): number {\n return (this.ready) ? this.effect!.getNumParticles() : 0;\n }\n\n // --- Minimal Phaser GameObject component shims ---\n // The effect manages its own transform/alpha, but a parent Container's\n // renderer calls these on its children during the render pass.\n setScrollFactor(x: number, y?: number): this {\n this.scrollFactorX = x;\n this.scrollFactorY = (y === undefined) ? x : y;\n return this;\n }\n\n setAlpha(topLeft?: number, _topRight?: number, _bottomLeft?: number, _bottomRight?: number): this {\n this.alpha = (topLeft === undefined) ? 1 : topLeft;\n return this;\n }\n\n override destroy(fromScene?: boolean) {\n if (this._dataTextureManager) {\n this._dataTextureManager.destroy();\n this._dataTextureManager = null;\n }\n super.destroy(fromScene);\n }\n\n private _applyTransformOptions(options?: { position?: Vec3, angle?: number, rotation?: number }) {\n if (!options) return;\n if (options.position) {\n this.x = options.position[0];\n this.y = options.position[1];\n this.z = options.position[2];\n }\n if (options.angle !== undefined) {\n this.angle = options.angle;\n this.rotation = Phaser.Math.DegToRad(options.angle);\n } else if (options.rotation !== undefined) {\n this.rotation = options.rotation;\n this.angle = Phaser.Math.RadToDeg(options.rotation);\n }\n }\n\n private _updateWorldTransform() {\n const computeWorldTransform = (parent: Phaser.GameObjects.Container | null,\n result: { matrix: Phaser.GameObjects.Components.TransformMatrix, angle: number, scale: number }) => {\n if (!parent) return;\n const parentLocalMatrix = this._tempMatrix2;\n parentLocalMatrix.applyITRS(parent.x, parent.y, parent.rotation, parent.scaleX, parent.scaleY);\n parentLocalMatrix.multiply(result.matrix, result.matrix);\n result.angle += parent.angle;\n result.scale *= (parent.scaleX + parent.scaleY) * 0.5;\n computeWorldTransform(parent.parentContainer, result);\n }\n\n const transform = {\n matrix: this._tempMatrix1.loadIdentity(),\n angle: this.angle,\n scale: (this.scaleX + this.scaleY) * 0.5\n };\n computeWorldTransform(this.parentContainer as Phaser.GameObjects.Container | null, transform);\n\n transform.matrix.transformPoint(this.x, this.y, this._worldPosition);\n this._worldRotation = this.gamePlugin.neutrino.axisangle2quat_([0, 0, 1], transform.angle);\n this._worldScale = transform.scale;\n // Guard against a zero world scale (degenerate parent/self scale): a NaN\n // position would poison the simulation for every subsequent frame.\n const invScale = this._worldScale !== 0 ? 1 / this._worldScale : 0;\n this._worldScaledPosition[0] = this._worldPosition.x * invScale;\n this._worldScaledPosition[1] = this._worldPosition.y * invScale;\n this._worldScaledPosition[2] = this.z * invScale;\n }\n\n private _renderPosition(): Vec3 {\n return this._worldScaledPosition;\n }\n\n private _renderRotation(): Quat {\n return this._worldRotation;\n }\n\n private _checkUnpauseOnUpdateRender(): boolean {\n if (!this._unpauseOnUpdateRender) return false;\n\n this.resetPosition();\n this.unpause();\n this._unpauseOnUpdateRender = false;\n return true;\n }\n}\n","\n/**\n * The class implements perspective projection transformation.\n * \n * @example\n * // Create effect instance using loaded model\n * let effect = new PIXINeutrino.Effect(resources.effectModel, {\n * position: [400, 300, 0],\n * projection: new PIXINeutrino.PerspectiveProjection(60.0)\n * });\n * \n * @param {number} [horizontalAngle] Horizontal angle of the perspective projection in degrees.\n */\n\nimport { Vec2, Vec3 } from \"./types\";\n\nexport interface ScreenFrame { x: number; y: number; width: number; height: number; }\n\nexport class PerspectiveProjection\n{\n private _angleTan: number = 0;\n private _screenWidth: number = 0;\n private _screenPosX: number = 0;\n private _screenPosY: number = 0;\n private _z: number = 0;\n private _near: number = 0;\n\n set horizontalAngle(value: number) {\n this._angleTan = Math.tan((value * 0.5) / 180.0 * Math.PI);\n }\n\n constructor(horizontalAngle: number) {\n this.horizontalAngle = horizontalAngle;\n }\n\n /**\n\t * Changes horizontal angle of the projection.\n\t * \n\t * @param {number} value Angle in degrees.\n\t */\n \n\n /**\n * Sets rendering frame for the projection.\n * \n * This method shouldn't be called manually when the class is used with effects. It is called\n * on every render call for each effect automatically.\n * @param {ScreenFrame} frame Rendering frame.\n */\n setScreenFrame(frame: ScreenFrame) {\n this._screenWidth = frame.width;\n this._screenPosX = frame.x + frame.width * 0.5;\n this._screenPosY = frame.y + frame.height * 0.5;\n this._z = this._screenWidth * 0.5 / this._angleTan;\n this._near = this._z * 0.99;\n }\n\n /**\n * Transforms 3D point accordingly to the projection.\n * \n * Basically, point's position X and Y components are simply scaled dependently on Z position. The method\n * is used in WebGL and Canvas rendering.\n * \n * @param {Array} out [x, y] Transformed position.\n * @param {Array} pos [x, y, z] Untransformed input vertex position.\n * @returns false, if a particle is on the back side of the camera and should be discarded. Otherwise - true.\n */\n transformPosition(out: Vec2, pos: Vec3): boolean {\n if (pos[2] > this._near) {\n return false;\n }\n\n const scale = this._getScale(pos);\n out[0] = (pos[0] - this._screenPosX) * scale + this._screenPosX;\n out[1] = (pos[1] - this._screenPosY) * scale + this._screenPosY;\n\n return true;\n }\n\n /**\n * Transforms 2D size of a particle accordingly to the projection.\n * \n * Basically, size is simply scaled dependently on Z position of a particle. The method is used\n * only in Canvas rendering.\n * \n * @param {Array} outSize [width, height] Transformed size.\n * @param {Array} pos [x, y, z] Untransformed particle position.\n * @param {Array} size [width, height] Untransformed size.\n */\n transformSize(outSize: Vec2, pos: Vec3, size: Vec2) {\n const scale = this._getScale(pos);\n outSize[0] = size[0] * scale;\n outSize[1] = size[1] * scale;\n }\n\n _getScale(pos: Vec3) {\n return this._z / (this._z - pos[2]);\n }\n}","import Phaser from 'phaser';\nimport { GamePlugin } from './GamePlugin';\nimport { NeutrinoFile, NeutrinoFileConfig } from './File';\nimport { Effect, EffectOptions } from './Effect';\nimport { EffectModel } from './EffectModel';\n\nexport * from './types';\nexport * from './GamePlugin';\nexport * from './NeutrinoContext';\nexport * from './NeutrinoRenderer';\nexport * from './DataTextureManager';\nexport * from './Effect';\nexport * from './EffectModel';\nexport * from './File';\nexport * from './PerspectiveProjection';\n\ndeclare module 'phaser' {\n namespace Loader {\n interface LoaderPlugin {\n neutrino(key: string | NeutrinoFileConfig | NeutrinoFileConfig[],\n url?: string, options?: { atlases?: string[] },\n xhrSettings?: Phaser.Types.Loader.XHRSettingsObject): this;\n }\n }\n namespace GameObjects {\n interface GameObjectFactory {\n neutrino(effectModel: EffectModel, options?: EffectOptions): Effect;\n }\n interface GameObjectCreator {\n neutrino(config: { effectModel: EffectModel } & EffectOptions & { add?: boolean }): Effect;\n }\n }\n}\n\nlet _installed = false;\n\n/**\n * Installs the NeutrinoParticles plugin into Phaser's global registries:\n * - Loader file type: scene.load.neutrino(key, url, options)\n * - GameObjectFactory: scene.add.neutrino(effectModel, options)\n * - GameObjectCreator: scene.make.neutrino(config)\n */\nexport function installPlugin() {\n if (_installed) return;\n _installed = true;\n\n Phaser.Loader.FileTypesManager.register('neutrino',\n function (this: Phaser.Loader.LoaderPlugin,\n key: string | NeutrinoFileConfig | NeutrinoFileConfig[],\n url?: string,\n options?: { atlases?: string[] },\n xhrSettings?: Phaser.Types.Loader.XHRSettingsObject) {\n\n if (Array.isArray(key)) {\n for (const item of key) {\n this.addFile(new NeutrinoFile(this, item));\n }\n } else if (typeof key === 'object') {\n this.addFile(new NeutrinoFile(this, key));\n } else {\n this.addFile(new NeutrinoFile(this, { key, url: url!, options, xhrSettings }));\n }\n\n return this;\n });\n\n Phaser.GameObjects.GameObjectFactory.register('neutrino',\n function (this: Phaser.GameObjects.GameObjectFactory,\n effectModel: EffectModel, options?: EffectOptions) {\n const effect = new Effect(effectModel, this.scene, options);\n this.displayList.add(effect);\n this.updateList.add(effect);\n return effect;\n });\n\n Phaser.GameObjects.GameObjectCreator.register('neutrino',\n function (this: Phaser.GameObjects.GameObjectCreator,\n config: { effectModel: EffectModel } & EffectOptions & { add?: boolean }) {\n const effect = new Effect(config.effectModel, this.scene, config);\n if (config.add !== false) {\n this.scene.sys.displayList.add(effect);\n this.scene.sys.updateList.add(effect);\n }\n return effect;\n });\n}\n\ninstallPlugin();\n\nexport { GamePlugin };\n"],"names":["_NeutrinoContext","gl","neutrino","__publicField","path","success","fail","noiseGenerator","maxParticles","prevVao","prevArrayBuf","prevElemBuf","use32bit","indices","p","v","i","ids","vtfUnits","fragHigh","combined","fragment","vs","fs","prevViewport","prevProgram","prevArrayBuffer","prevFbo","prevActiveTexture","prevTex0","prevTex1","prevBlend","prevDepthTest","prevScissorTest","program","floatTex","byteTex","target","fbo","vbo","attribLoc","prevAttribEnabled","prevAttribBuffer","prevAttribSize","prevAttribType","prevAttribStride","prevAttribOffset","prevAttribNormalized","ok","pixel","makeTex","type","pixels","t","vsSource","fsSource","source","shader","info","options","Neutrino","index","frame","atlases","numTextures","imageIndex","textureName","texturePath","texturePathNoExt","texture","idx","key","frameName","remapNeeded","texIdx","loader","config","url","xhrSettings","text","Pause","RING_BUFFER_SIZE","data","textureWidth","textureHeight","maxSize","tex","unit","dataUint32","numParticles","dst","s","d","startParticle","count","slot","bytes","dataUnit","metaUnit","w","rows","ctx","dtm","dataView","instructions","params","isGL1","maxBatch","renderStyles","materials","metaManager","texSlotMap","batch","j","texIndex","instr","flagOffset","flags","dtmGL1","dtmGL2","h","zoom","om","aspect","m","mm","particleStartUnit","b","remap","indexOffset","indexCount","materialIndex","blendMode","effectModel","scene","startupOptions","_time","ms","renderer","_src","camera","textureCount","glTextures","name","value","x","y","topLeft","_topRight","_bottomLeft","_bottomRight","fromScene","computeWorldTransform","parent","result","parentLocalMatrix","transform","invScale","horizontalAngle","out","pos","scale","outSize","size","item","effect"],"mappings":"mqBAAA,mBAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,ECAf,qBAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,ECAf,sBAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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"}
|