@neutrinoparticles/js-v1.1-pixi8 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 +9 -0
- package/README.md +231 -0
- package/dist/AplicationPlugin.d.ts +9 -0
- package/dist/Context.d.ts +92 -0
- package/dist/DataTextureManager.d.ts +32 -0
- package/dist/Effect.d.ts +104 -0
- package/dist/EffectModel.d.ts +20 -0
- package/dist/EffectModelLoader.d.ts +13 -0
- package/dist/EffectPipe.d.ts +25 -0
- package/dist/NeutrinoRenderer.d.ts +31 -0
- package/dist/PerspectiveProjection.d.ts +70 -0
- package/dist/TexturesLoader.d.ts +17 -0
- package/dist/gl1/DataTextureManagerGL1.d.ts +23 -0
- package/dist/gl1/MetaTextureManager.d.ts +9 -0
- package/dist/index.d.ts +22 -0
- package/dist/neutrinoparticles.js-v1.1-pixi8.cjs.js +1214 -0
- package/dist/neutrinoparticles.js-v1.1-pixi8.cjs.js.map +1 -0
- package/dist/neutrinoparticles.js-v1.1-pixi8.d.ts +482 -0
- package/dist/neutrinoparticles.js-v1.1-pixi8.es.js +2211 -0
- package/dist/neutrinoparticles.js-v1.1-pixi8.es.js.map +1 -0
- package/dist/neutrinoparticles.js-v1.1-pixi8.umd.js +1214 -0
- package/dist/neutrinoparticles.js-v1.1-pixi8.umd.js.map +1 -0
- package/dist/types.d.ts +59 -0
- package/package.json +56 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neutrinoparticles.js-v1.1-pixi8.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/Context.ts","../src/AplicationPlugin.ts","../src/EffectModel.ts","../src/TexturesLoader.ts","../src/EffectModelLoader.ts","../src/NeutrinoRenderer.ts","../src/EffectPipe.ts","../src/DataTextureManager.ts","../src/gl1/MetaTextureManager.ts","../src/gl1/DataTextureManagerGL1.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 used by the Faced strip frame; world Z reaches\\n// gl_Position only through uViewProjMatrix (ortho or v1.0-parity perspective).\\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 PIXI7 renderer has no true 3D camera\\n // (uViewProjMatrix is ortho or the v1.0-parity perspective),\\n // so 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 ndc1 = (sp1.xy / sp1.w) * aspectMul;\\n vec2 ndc2 = (sp2.xy / sp2.w) * aspectMul;\\n // Neighbor anchors behind the near plane produce garbage NDC after\\n // the perspective divide (possible only with Projection3D, where w\\n // varies); collapse them onto their segment anchor so the existing\\n // zero-length degeneracy path (dir01 = dir12 / dir23 = dir12)\\n // handles the knee instead of a poisoned miter. spU1/spU2 need no\\n // guard: uCameraUp has zero Z, so their w equals sp1.w / sp2.w.\\n vec2 ndc0 = (sp0.w < 1e-3) ? ndc1 : (sp0.xy / sp0.w) * aspectMul;\\n vec2 ndc3 = (sp3.w < 1e-3) ? ndc2 : (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, 1.0);\\n\\n // v1.0-parity near-plane culling for the perspective projection: the\\n // whole quad is discarded when ANY of its 4 corners is behind the near\\n // plane (w < 0.01 == pos.z > 0.99 * z_cam in PerspectiveProjection\\n // terms). w is linear in position, so the corner minimum comes from the\\n // w-row and the corner offsets (x in {-ox, 1-ox}, y in {-oy, 1-oy}).\\n // Without a projection every w is 1.0 and this is a no-op.\\n vec4 wRow = vec4(mvpMatrix[0].w, mvpMatrix[1].w, mvpMatrix[2].w, mvpMatrix[3].w);\\n float wx = dot(wRow.xyz, xaxis);\\n float wy = dot(wRow.xyz, yaxis);\\n float minW = dot(wRow.xyz, position) + wRow.w\\n - origin.x * wx + min(wx, 0.0)\\n - origin.y * wy + min(wy, 0.0);\\n if (minW < 0.01) {\\n gl_Position = vec4(2.0, 2.0, 2.0, 1.0);\\n }\\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 ndc1 = (sp1.xy / sp1.w) * aspectMul;\\n vec2 ndc2 = (sp2.xy / sp2.w) * aspectMul;\\n // Neighbor anchors behind the near plane produce garbage NDC after\\n // the perspective divide (possible only with Projection3D, where w\\n // varies); collapse them onto their segment anchor so the existing\\n // zero-length degeneracy path (dir01 = dir12 / dir23 = dir12)\\n // handles the knee instead of a poisoned miter. spU1/spU2 need no\\n // guard: uCameraUp has zero Z, so their w equals sp1.w / sp2.w.\\n vec2 ndc0 = (sp0.w < 1e-3) ? ndc1 : (sp0.xy / sp0.w) * aspectMul;\\n vec2 ndc3 = (sp3.w < 1e-3) ? ndc2 : (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, 1.0);\\n\\n // v1.0-parity near-plane culling for the perspective projection: the\\n // whole quad is discarded when ANY of its 4 corners is behind the near\\n // plane (w < 0.01 == pos.z > 0.99 * z_cam in PerspectiveProjection\\n // terms). w is linear in position, so the corner minimum comes from the\\n // w-row and the corner offsets (x in {-ox, 1-ox}, y in {-oy, 1-oy}).\\n // Without a projection every w is 1.0 and this is a no-op.\\n vec4 wRow = vec4(mvpMatrix[0].w, mvpMatrix[1].w, mvpMatrix[2].w, mvpMatrix[3].w);\\n float wx = dot(wRow.xyz, xaxis);\\n float wy = dot(wRow.xyz, yaxis);\\n float minW = dot(wRow.xyz, position) + wRow.w\\n - origin.x * wx + min(wx, 0.0)\\n - origin.y * wy + min(wy, 0.0);\\n if (minW < 0.01) {\\n gl_Position = vec4(2.0, 2.0, 2.0, 1.0);\\n }\\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 { Renderer } from 'pixi.js';\nimport { NeutrinoContext } 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\nexport interface ContextOptions {\n texturesBasePath?: string;\n trimmedExtensionsLookupFirst?: boolean;\n}\n\nexport interface ContextLoadData {\n __neutrinoContext__: Context;\n}\n\n/**\n * Shared GL state for the PIXI v8 NeutrinoParticles integration: the shader\n * program (WebGL2 data-texture path, or the WebGL1 meta-texture path — see\n * docs/tdd/TDD_js-v1.1-webgl1.md), a static quad index buffer (+ VAO on\n * WebGL2 / aId attribute stream on WebGL1), and all uniform locations.\n * Created once per application and reused by every {@link Effect}.\n */\nexport class Context {\n public readonly neutrino: NeutrinoContext;\n public readonly renderer: Renderer;\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 public readonly options: ContextOptions;\n public readonly loadData: ContextLoadData;\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 = Context.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 // Uniform locations\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 constructor(renderer: Renderer, options?: ContextOptions) {\n this.renderer = renderer;\n this.gl = (renderer as any).gl as WebGL2RenderingContext;\n if (!this.gl) {\n throw new Error('NeutrinoParticles (js-v1.1): a WebGL renderer is required.');\n }\n this.options = Object.assign({\n texturesBasePath: \"\",\n trimmedExtensionsLookupFirst: true\n }, options);\n\n this.neutrino = new Neutrino.Context();\n this.loadData = { __neutrinoContext__: this };\n this._noiseInitialized = false;\n\n const webGLVersion = (renderer as any).context?.webGLVersion\n ?? (typeof (this.gl as any).createVertexArray === 'function' ? 2 : 1);\n this._isWebGL1 = webGLVersion === 1;\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 private _noiseInitialized: boolean;\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.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(): WebGLUniformLocation | null { return this._uDataTexture; }\n get uDataTextureWidth(): WebGLUniformLocation | null { return this._uDataTextureWidth; }\n get uMetaTexture(): WebGLUniformLocation | null { return this._uMetaTexture; }\n get uDataTexSize(): WebGLUniformLocation | null { return this._uDataTexSize; }\n get uCameraRight(): WebGLUniformLocation | null { return this._uCameraRight; }\n get uCameraUp(): WebGLUniformLocation | null { return this._uCameraUp; }\n get uCameraDir(): WebGLUniformLocation | null { return this._uCameraDir; }\n get uViewProjMatrix(): WebGLUniformLocation | null { return this._uViewProjMatrix; }\n get uModelMatrix(): WebGLUniformLocation | null { return this._uModelMatrix; }\n get uViewportAspect(): WebGLUniformLocation | null { return this._uViewportAspect; }\n get uWorldAlpha(): WebGLUniformLocation | null { return this._uWorldAlpha; }\n get uTextures(): (WebGLUniformLocation | null)[] { return this._uTextures; }\n get uTexRemaps(): (WebGLUniformLocation | null)[] { return this._uTexRemaps; }\n\n ensureIndexBuffer(maxParticles: number): void {\n if (maxParticles <= this._indexBufferCapacity) return;\n\n const gl = this.gl;\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);\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 gl.bindBuffer(gl.ARRAY_BUFFER, null);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n } else {\n // Dummy vertex buffer — WebGL2 requires at least one vertex buffer for\n // drawElements even though we use gl_VertexID. Size = maxParticles * 4\n // vertices * 1 byte.\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 gl.bindVertexArray(null);\n }\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(Context.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. PIXI's\n // batch 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 < Context.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 { Application, ExtensionType, Renderer } from \"pixi.js\";\nimport { Context } from \"./Context\";\n\n/**\n * Creates the shared {@link Context} and assigns it to app.neutrino on init.\n */\nexport class ApplicationPlugin {\n static get extension(): any {\n return {\n name: 'neutrino',\n type: ExtensionType.Application,\n };\n }\n\n static init(this: Application, options: any): void {\n (this as any).neutrino = new Context(this.renderer as Renderer, options.neutrino);\n }\n\n static destroy(this: Application): void {\n if ((this as any).neutrino) {\n (this as any).neutrino.destroy();\n (this as any).neutrino = undefined;\n }\n }\n}\n","import { Cache, EventEmitter, Texture } from \"pixi.js\";\nimport { Context } from \"./Context\";\nimport { AbstractTexturesLoader } from \"./TexturesLoader\";\nimport { NeutrinoEffectModel, NeutrinoSubRect } from \"./types\";\n\n/**\n * Wraps a neutrinoparticles.js v1.1 effect model and loads its textures via the\n * PIXI v8 asset cache. Computes atlas UV remaps (as plain {x,y,width,height}\n * objects — the v1.1 renderer reads them directly, no SubRect wrapper).\n */\nexport class EffectModel extends EventEmitter {\n public readonly ctx: Context;\n public readonly effectModel: NeutrinoEffectModel;\n\n public texturesRemap: Array<NeutrinoSubRect | null> = [];\n public readonly textures: Array<Texture> = [];\n\n private _numTexturesToLoadLeft: number;\n\n constructor(context: Context, neutrinoModel: string | NeutrinoEffectModel, texturesLoader: AbstractTexturesLoader) {\n super();\n\n this.ctx = context;\n\n if (typeof neutrinoModel === \"string\") {\n const evalScript = \"(function(ctx) {\\n\" + neutrinoModel +\n \"\\nreturn new NeutrinoEffect(ctx);\\n})(context.neutrino);\";\n this.effectModel = eval(evalScript);\n } else {\n this.effectModel = neutrinoModel;\n }\n\n const numTextures = this.effectModel.textures.length;\n this._numTexturesToLoadLeft = numTextures;\n\n for (let texIndex = 0; texIndex < numTextures; ++texIndex) {\n const texturePath = this.effectModel.textures[texIndex];\n let texture: Texture | null = null;\n\n if (this.ctx.options.trimmedExtensionsLookupFirst) {\n const trimmedTexturePath = texturePath.replace(/\\.[^/.]+$/, \"\");\n if (Cache.has(trimmedTexturePath))\n texture = Cache.get(trimmedTexturePath);\n }\n\n if (!texture && Cache.has(texturePath))\n texture = Cache.get(texturePath);\n\n if (texture) {\n this._onTextureLoaded(texIndex, texture, true);\n } else {\n texturesLoader.load(this.ctx.options.texturesBasePath + texturePath).then(\n ((self: EffectModel, imageIndex: number) => {\n return (tex: Texture) => { self._onTextureLoaded(imageIndex, tex, false); };\n })(this, texIndex));\n }\n }\n }\n\n public ready(): boolean {\n return this._numTexturesToLoadLeft === 0;\n }\n\n private _onTextureLoaded(index: number, texture: Texture, defer: boolean): void {\n this.textures[index] = texture;\n this._numTexturesToLoadLeft--;\n\n if (this._numTexturesToLoadLeft === 0) {\n this._initTexturesRemapIfNeeded();\n if (!defer) {\n this.emit('ready', this);\n } else {\n setTimeout(() => { this.emit('ready', this); }, 0);\n }\n }\n }\n\n private _initTexturesRemapIfNeeded(): void {\n let remapNeeded = false;\n\n for (let texIdx = 0; texIdx < this.textures.length; ++texIdx) {\n const texture = this.textures[texIdx];\n if (texture.frame.x != 0 || texture.frame.y != 0\n || texture.frame.width != texture.source.pixelWidth\n || texture.frame.height != texture.source.pixelHeight) {\n remapNeeded = true;\n break;\n }\n }\n\n if (!remapNeeded) return;\n\n for (let texIdx = 0; texIdx < this.textures.length; ++texIdx) {\n const texture = this.textures[texIdx];\n this.texturesRemap[texIdx] = {\n x: texture.frame.x / texture.source.pixelWidth,\n y: 1.0 - (texture.frame.y + texture.frame.height) / texture.source.pixelHeight,\n width: texture.frame.width / texture.source.pixelWidth,\n height: texture.frame.height / texture.source.pixelHeight\n };\n }\n }\n}\n","import { Assets, Loader, Texture } from 'pixi.js'\n\n/**\n * Texture loader interface used by {@link EffectModel} to load required textures.\n */\nexport abstract class AbstractTexturesLoader {\n constructor() {}\n\n abstract load(texturePath: string): Promise<Texture>;\n}\n\nexport class AssetsTexturesLoader extends AbstractTexturesLoader {\n private loader: Loader;\n\n constructor(loader: Loader) {\n super();\n this.loader = loader;\n }\n\n async load(texturePath: string): Promise<Texture> {\n return await this.loader.load(texturePath);\n }\n}\n\nexport class DefaultAssetsTexturesLoader extends AssetsTexturesLoader {\n public static readonly instance: DefaultAssetsTexturesLoader = new DefaultAssetsTexturesLoader();\n\n private constructor() {\n super(Assets.loader);\n }\n}\n","import { DOMAdapter, ExtensionType, Loader, LoaderParserPriority, ResolvedAsset } from 'pixi.js';\nimport { EffectModel } from './EffectModel';\nimport { Context } from './Context';\nimport { AssetsTexturesLoader } from './TexturesLoader';\n\nexport const effectModelLoader = {\n extension: {\n type: ExtensionType.LoadParser,\n priority: LoaderParserPriority.Normal,\n },\n\n test(_url: string, loadAsset: ResolvedAsset, _loader: Loader) {\n return loadAsset.data && loadAsset.data.__neutrinoContext__\n && (loadAsset.data.__neutrinoContext__ instanceof Context);\n },\n\n async load(url: string, _loadAsset: ResolvedAsset, _loader: Loader) {\n const response = await DOMAdapter.get().fetch(url);\n const sourceCode = await response.text();\n return sourceCode;\n },\n\n async testParse(this: Loader, _asset: any, options: ResolvedAsset) {\n return options.data && options.data.__neutrinoContext__\n && (options.data.__neutrinoContext__ instanceof Context);\n },\n\n async parse(asset: string, options: ResolvedAsset, loader: Loader) {\n return new Promise((resolve) => {\n const context = options.data.__neutrinoContext__;\n\n const effectModel = new EffectModel(context, asset, new AssetsTexturesLoader(loader));\n if (effectModel.ready()) {\n resolve(effectModel);\n } else {\n effectModel.once('ready', () => {\n resolve(effectModel);\n });\n }\n });\n },\n\n unload(_effectModel: EffectModel) {\n // destroy?\n }\n};\n","import { Rectangle, WebGLRenderer } from \"pixi.js\";\nimport { Context } from \"./Context\";\nimport { Effect } from \"./Effect\";\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; // preallocated batch pool size\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(Context.MAX_BATCH_TEXTURES).fill(null);\n remaps: (NeutrinoSubRect | null)[] = new Array(Context.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\n/**\n * Raw WebGL2 data-texture renderer for the PIXI v8 integration.\n *\n * Mirrors the pixi7 RendererPlugin: builds draw batches (grouped by blend mode,\n * up to 8 textures each), patches the per-particle texture-slot byte into the\n * runtime data buffer, uploads the data texture, sets camera/projection/model\n * uniforms, and issues one drawElements per batch. Particle textures are bound\n * by their raw WebGL handle (resolved from PIXI via the texture system).\n */\nexport class NeutrinoRenderer {\n private _orthoMatrix = new Float32Array(16);\n private _perspMatrix = new Float32Array(16);\n private _vpMatrix = new Float32Array(16);\n private _modelMatrix = new Float32Array(16);\n private _projFrame = new Rectangle();\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 renderEffect(\n renderer: WebGLRenderer,\n ctx: Context,\n effect: Effect,\n dtm: DataTextureManager | DataTextureManagerGL1,\n instructions: any[],\n numParticles: number\n ): void {\n if (numParticles === 0) return;\n\n const gl = ctx.gl;\n const isGL1 = ctx.isWebGL1;\n const textureSystem: any = (renderer as any).texture;\n const maxBatch = ctx.maxBatchTextures;\n const renderStyles = effect.effect!.model.renderStyles;\n const materials = effect.effect!.model.materials;\n const textures = effect.effectModel.textures;\n const texturesRemap = effect.effectModel.texturesRemap;\n const dataView = effect.effect!.particleDataView;\n\n // WebGL1: repack the u32 fields into the meta texture BEFORE slot\n // patching (the runtime's float buffer is never mutated on this path).\n const metaManager = isGL1 ? (dtm as DataTextureManagerGL1).meta : null;\n if (metaManager) {\n metaManager.build(effect.effect!.particleDataUint32, numParticles);\n }\n\n // Phase 1: Build draw batches and patch flags (single pass over instructions)\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 const tex = textures[texIndex];\n // Resolve raw GL texture handle (this also lazily uploads the source).\n batch.glTextures[slot] = tex ? textureSystem.getGlSource(tex.source).texture : null;\n batch.remaps[slot] = texturesRemap[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: Setup GL state. Reset PIXI's shader/geometry/state tracking so\n // our raw calls don't desync its cache, then drive the GL directly.\n renderer.shader.resetState();\n renderer.geometry.resetState();\n renderer.state.resetState();\n\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 // Upload + bind the data (unit 0) and meta (unit 1) ring textures.\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 // Upload + bind the data texture into unit 0.\n (dtm as DataTextureManager).uploadAndBind(DATA_TEXTURE_UNIT);\n gl.uniform1i(ctx.uDataTexture, DATA_TEXTURE_UNIT);\n gl.uniform1i(ctx.uDataTextureWidth, dtm.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 // Active viewport — PIXI v8 builds renderTarget.projectionMatrix from\n // the current viewport (in logical units: pixels / resolution), which\n // can be a sub-rect of the render target. The projection screen frame\n // and the strip viewport aspect must describe that same region, so both\n // derive from it (renderer.screen / the full target would be wrong for\n // render-to-texture and sub-rect frames).\n const viewport = renderer.renderTarget.viewport;\n const resolution = renderer.renderTarget.renderTarget.resolution;\n\n this._fillProjMatrix(this._orthoMatrix, renderer);\n if (effect.projection) {\n // v1.0-parity perspective: uViewProjMatrix = ortho * perspective,\n // both acting in screen space (see TDD_157-js11-pixi-projection3d.md).\n const frame = this._projFrame;\n frame.x = 0;\n frame.y = 0;\n frame.width = viewport.width / resolution;\n frame.height = viewport.height / resolution;\n effect.projection.setScreenFrame(frame);\n effect.projection.writeMatrix(this._perspMatrix);\n this._mulMatrix(this._vpMatrix, this._orthoMatrix, this._perspMatrix);\n gl.uniformMatrix4fv(ctx.uViewProjMatrix, false, this._vpMatrix);\n } else {\n gl.uniformMatrix4fv(ctx.uViewProjMatrix, false, this._orthoMatrix);\n }\n\n // Viewport aspect (width / height) — only used by strip path for\n // aspect-corrected NDC math. Quads ignore it.\n const aspect = viewport.height > 0 ? (viewport.width / viewport.height) : 1.0;\n if (ctx.uViewportAspect) gl.uniform1f(ctx.uViewportAspect, aspect);\n\n if (ctx.uWorldAlpha) gl.uniform1f(ctx.uWorldAlpha, effect.worldAlpha);\n\n this._fillModelMatrix(this._modelMatrix, effect);\n gl.uniformMatrix4fv(ctx.uModelMatrix, false, this._modelMatrix);\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 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\n // Invalidate PIXI's texture binding cache for the units we touched, so it\n // re-binds correctly on its next draw.\n const boundTextures = textureSystem._boundTextures;\n if (boundTextures) {\n for (let u = 0; u < particleStartUnit + Context.MAX_BATCH_TEXTURES; u++) {\n boundTextures[u] = null;\n }\n }\n\n renderer.shader.resetState();\n renderer.geometry.resetState();\n renderer.state.resetState();\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 private _fillProjMatrix(out: Float32Array, renderer: WebGLRenderer): void {\n // PIXI v8 keeps the active projection matrix on the renderTarget system.\n // z row is zeroed: clip z is always 0 on this path (depth test/write\n // are disabled) and sim-space Z, which quads now feed into the matrix\n // for the perspective case, must never be clipped by the ortho part.\n const pm = renderer.renderTarget.projectionMatrix;\n out[0] = pm.a; out[1] = pm.b; out[2] = 0; out[3] = 0;\n out[4] = pm.c; out[5] = pm.d; out[6] = 0; out[7] = 0;\n out[8] = 0; out[9] = 0; out[10] = 0; out[11] = 0;\n out[12] = pm.tx; out[13] = pm.ty; out[14] = 0; out[15] = 1;\n }\n\n // Column-major 4x4 multiply: out = a * b. Preallocated outputs only.\n private _mulMatrix(out: Float32Array, a: Float32Array, b: Float32Array): void {\n for (let c = 0; c < 16; c += 4) {\n const b0 = b[c], b1 = b[c + 1], b2 = b[c + 2], b3 = b[c + 3];\n out[c] = a[0] * b0 + a[4] * b1 + a[8] * b2 + a[12] * b3;\n out[c + 1] = a[1] * b0 + a[5] * b1 + a[9] * b2 + a[13] * b3;\n out[c + 2] = a[2] * b0 + a[6] * b1 + a[10] * b2 + a[14] * b3;\n out[c + 3] = a[3] * b0 + a[7] * b1 + a[11] * b2 + a[15] * b3;\n }\n }\n\n private _fillModelMatrix(mm: Float32Array, effect: Effect): void {\n const wt = effect.worldRenderMatrix;\n mm[0] = wt.a; mm[1] = wt.b;\n mm[4] = wt.c; mm[5] = wt.d;\n mm[12] = wt.tx; mm[13] = wt.ty;\n mm[2] = 0; mm[3] = 0; mm[6] = 0; mm[7] = 0;\n mm[8] = 0; mm[9] = 0; mm[10] = 1; mm[11] = 0;\n mm[14] = 0; mm[15] = 1;\n }\n}\n","import { ExtensionType, InstructionSet, RenderPipe, WebGLRenderer } from \"pixi.js\";\nimport { Effect } from \"./Effect\";\nimport { NeutrinoRenderer } from \"./NeutrinoRenderer\";\n\n/**\n * PIXI v8 render pipe for NeutrinoParticles effects.\n *\n * Each effect is its own instruction (Effect.batched = false). The actual draw\n * happens in {@link execute}, which runs inside the v8 render pass where PIXI\n * owns the GL state — there we construct the frame's geometry and issue the raw\n * WebGL2 data-texture draw via {@link NeutrinoRenderer}.\n */\nexport class EffectPipe implements RenderPipe<Effect> {\n public static extension = {\n type: [ExtensionType.WebGLPipes],\n name: 'neutrino',\n } as const;\n\n public readonly renderer: WebGLRenderer;\n private readonly _neutrinoRenderer = new NeutrinoRenderer();\n\n constructor(renderer: WebGLRenderer) {\n this.renderer = renderer;\n }\n\n public validateRenderable(_effect: Effect): boolean {\n return true;\n }\n\n public addRenderable(effect: Effect, instructionSet: InstructionSet): void {\n instructionSet.add(effect);\n }\n\n public updateRenderable(_effect: Effect): void {}\n\n public destroyRenderable(_effect: Effect): void {}\n\n public execute(effect: Effect): void {\n if (!effect.ready()) return;\n // Fully transparent → nothing to draw. A custom v8 render pipe's execute()\n // runs even for a zero-alpha container (unlike the classic scene-graph\n // cull), so the alpha gate is explicit here (mirrors the phaser adapter).\n if (effect._isInvisible()) return;\n\n const ctx = effect.ctx;\n const dtm = effect._dtm();\n if (!ctx || !dtm) return;\n\n // Auto-unpause on first-render and refresh the world transform from the\n // live scene graph (mirrors pixi7 _render / phaser renderWebGL).\n effect._prepareRender();\n\n effect.effect!.construct([0, 0, -1]);\n\n const instructions = effect.effect!.renderInstructions;\n const numParticles = instructions._totalParticles;\n if (numParticles === 0) return;\n\n this._neutrinoRenderer.renderEffect(\n this.renderer, ctx, effect, dtm, instructions, numParticles);\n\n dtm.advance();\n }\n\n public destroy(): void {}\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 { Bounds, Container, Instruction, Point, ViewContainer } from 'pixi.js';\nimport { EffectModel } from './EffectModel';\nimport { Context } from './Context';\nimport { DataTextureManager } from './DataTextureManager';\nimport { DataTextureManagerGL1 } from './gl1/DataTextureManagerGL1';\nimport { PerspectiveProjection } from './PerspectiveProjection';\nimport { NeutrinoSystem, Vec2, Vec3 } from './types';\n\nexport enum Pause {\n NO = 0,\n BEFORE_UPDATE_OR_RENDER = 1,\n YES = 2\n}\n\nexport interface EffectOptions {\n position?: Vec3;\n rotation?: number;\n scale?: Vec3;\n pause?: Pause;\n generatorsPaused?: boolean;\n baseParent?: Container;\n projection?: PerspectiveProjection;\n autoInit?: boolean;\n}\n\ninterface EffectStartupOptions {\n paused: boolean;\n generatorsPaused: boolean;\n}\n\nexport interface RenderMatrix {\n a: number; b: number; c: number; d: number; tx: number; ty: number;\n}\n\nconst emptyBounds = new Bounds(0, 0, 0, 0);\n\n/**\n * A NeutrinoParticles effect instance on a PIXI v8 scene.\n *\n * Extends ViewContainer and plugs into the v8 render graph as a custom render\n * pipe ('neutrino'). Simulation runs on the CPU (neutrinoparticles.js v1.1);\n * geometry is constructed on the GPU from a data texture by {@link NeutrinoRenderer}.\n */\nexport class Effect extends ViewContainer implements Instruction {\n\n public override readonly renderPipeId: string = 'neutrino';\n public override batched: boolean = false;\n\n public readonly ctx: Context;\n public readonly effectModel: EffectModel;\n public effect?: NeutrinoSystem;\n public readonly baseParent?: Container;\n public readonly projection?: PerspectiveProjection;\n public positionZ: number;\n public scaleZ: number;\n\n /** World transform actually fed to the renderer's model matrix (2x3). */\n public worldRenderMatrix: RenderMatrix = { a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 };\n\n private _worldPosition: Point = new Point(0, 0);\n private _worldRotationDegree: number = 0;\n private _worldScale: Point = new Point(1, 1);\n private _dataTextureManager?: DataTextureManager | DataTextureManagerGL1;\n private _unpauseOnUpdateRender: boolean;\n private _startupOptions: EffectStartupOptions;\n private _inited: boolean = false;\n private _ready: boolean = false;\n\n constructor(effectModel: EffectModel, options?: EffectOptions) {\n super({});\n\n const opts = Object.assign({\n position: [0, 0, 0] as Vec3,\n rotation: 0,\n scale: [1, 1, 1] as Vec3,\n pause: Pause.BEFORE_UPDATE_OR_RENDER,\n generatorsPaused: false,\n baseParent: undefined,\n projection: undefined,\n autoInit: true\n }, options);\n\n this.ctx = effectModel.ctx;\n this.effectModel = effectModel;\n this.baseParent = opts.baseParent;\n this.projection = opts.projection;\n\n this.position.set(opts.position[0], opts.position[1]);\n this.positionZ = opts.position[2];\n this.rotation = opts.rotation;\n this.scale.x = opts.scale[0];\n this.scale.y = opts.scale[1];\n this.scaleZ = opts.scale[2];\n\n this._startupOptions = {\n paused: opts.pause !== Pause.NO,\n generatorsPaused: opts.generatorsPaused\n };\n this._unpauseOnUpdateRender = (opts.pause === Pause.BEFORE_UPDATE_OR_RENDER);\n\n if (opts.autoInit) this.init();\n\n this._updateWorldTransform();\n }\n\n public get bounds() { return emptyBounds; }\n protected override updateBounds(): void {}\n\n init(): void {\n if (this._inited) return;\n this._inited = true;\n\n if (this.effectModel.ready()) {\n this._onEffectReady();\n } else {\n this.effectModel.once('ready', this._onEffectReady, this);\n }\n }\n\n ready(): boolean { return this._ready; }\n\n update(seconds: number): void {\n if (!this.ready()) return;\n this._checkUnpauseOnUpdateRender();\n this._updateWorldTransform();\n\n if (this.effect) {\n this.effect.update(seconds, this._scaledPosition(),\n this.ctx.neutrino.axisangle2quat_([0, 0, 1], this._worldRotationDegree));\n this.onViewUpdate();\n }\n }\n\n restart(position?: Vec3, rotation?: number): void {\n if (position) {\n this.position.x = position[0];\n this.position.y = position[1];\n this.positionZ = position[2];\n }\n if (rotation) this.rotation = rotation;\n this._updateWorldTransform();\n\n this.effect!.restart(this._scaledPosition(),\n rotation ? this.ctx.neutrino.axisangle2quat_([0, 0, 1], this._worldRotationDegree) : undefined);\n this.onViewUpdate();\n }\n\n resetPosition(position?: Vec3, rotation?: number): void {\n if (position) {\n this.position.x = position[0];\n this.position.y = position[1];\n this.positionZ = position[2];\n }\n if (rotation) this.rotation = rotation;\n this._updateWorldTransform();\n\n this.effect!.resetPosition(this._scaledPosition(),\n rotation ? this.ctx.neutrino.axisangle2quat_([0, 0, 1], this._worldRotationDegree) : undefined);\n this.onViewUpdate();\n }\n\n pause(): void {\n if (this.ready()) this.effect!.pauseAllEmitters();\n else this._startupOptions.paused = true;\n }\n\n unpause(): void {\n if (this.ready()) this.effect!.unpauseAllEmitters();\n else this._startupOptions.paused = false;\n }\n\n pauseGenerators(): void {\n if (this.ready()) this.effect!.pauseGeneratorsInAllEmitters();\n else this._startupOptions.generatorsPaused = true;\n }\n\n unpauseGenerators(): void {\n if (this.ready()) this.effect!.unpauseGeneratorsInAllEmitters();\n else this._startupOptions.generatorsPaused = false;\n }\n\n setPropertyInAllEmitters(name: string, value: Vec3 | Vec2 | number): void {\n this.effect!.setPropertyInAllEmitters(name, value);\n this.onViewUpdate();\n }\n\n getNumParticles(): number {\n return this.effect ? this.effect.getNumParticles() : 0;\n }\n\n /** @internal — called by EffectPipe during the render pass. */\n _dtm(): DataTextureManager | DataTextureManagerGL1 | undefined { return this._dataTextureManager; }\n\n /**\n * @internal — called by EffectPipe before constructing the frame.\n * Auto-unpauses an effect whose first interaction is a render rather than an\n * update (Pause.BEFORE_UPDATE_OR_RENDER), then refreshes the world transform\n * from the live scene graph so a parent transform change since the last\n * update() is reflected this frame (mirrors pixi7, which reads\n * baseParent.worldTransform live in its render plugin).\n */\n _prepareRender(): void {\n this._checkUnpauseOnUpdateRender();\n this._updateWorldTransform();\n }\n\n /**\n * @internal — resolved world alpha fed to the renderer (uWorldAlpha).\n * groupAlpha only accumulates alpha WITHIN the effect's render group; the\n * cross-group factor lives on parentRenderGroup.worldAlpha, so multiply both\n * to honour transparency set on a render-group ancestor.\n */\n get worldAlpha(): number {\n return this.groupAlpha * (this.parentRenderGroup?.worldAlpha ?? 1);\n }\n\n /**\n * @internal — called by EffectPipe. True when the effect is fully\n * transparent, in which case the draw is skipped entirely (mirrors the phaser\n * adapter and PIXI's scene-graph cull of a zero-alpha container). Partial\n * alpha is applied in the shader via uWorldAlpha (see {@link worldAlpha}).\n */\n _isInvisible(): boolean { return this.worldAlpha <= 0; }\n\n override destroy(options?: any): void {\n if (!this.effect) {\n this.effectModel.removeListener('ready', this._onEffectReady, this);\n }\n if (this._dataTextureManager) {\n this._dataTextureManager.destroy();\n this._dataTextureManager = undefined;\n }\n super.destroy(options);\n }\n\n private _onEffectReady(): void {\n this._updateWorldTransform();\n\n this.effect = this.effectModel.effectModel.createInstance(\n this._scaledPosition(),\n this.ctx.neutrino.axisangle2quat_([0, 0, 1], this._worldRotationDegree),\n this._startupOptions);\n\n // WebGL2 uses the RGBA32F ring; WebGL1 the float+meta ring pair\n // (docs/tdd/TDD_js-v1.1-webgl1.md §4.4).\n this._dataTextureManager = this.ctx.isWebGL1\n ? new DataTextureManagerGL1(\n this.ctx.gl,\n this.effect.particleDataUint32,\n this.effect.dataTextureWidth,\n this.effect.dataTextureHeight)\n : new DataTextureManager(\n this.ctx.gl,\n this.effect.particleDataUint32,\n this.effect.dataTextureWidth,\n this.effect.dataTextureHeight);\n\n this.ctx.ensureIndexBuffer(this.effectModel.effectModel.totalParticles);\n\n this._ready = true;\n this.emit('ready', this);\n }\n\n private _scaledPosition(): Vec3 {\n // Guard against zero scale (degenerate parent/self scale): a NaN/Infinity\n // position would poison the simulation for every subsequent frame.\n return [\n this._worldScale.x !== 0 ? this._worldPosition.x / this._worldScale.x : 0,\n this._worldScale.y !== 0 ? this._worldPosition.y / this._worldScale.y : 0,\n this.scaleZ !== 0 ? this.positionZ / this.scaleZ : 0\n ];\n }\n\n private _getRenderGroupContainer(container: Container): Container {\n if (container.renderGroup || !container.parent) return container;\n return this._getRenderGroupContainer(container.parent);\n }\n\n private _updateWorldTransform(): void {\n const localPosition = new Point(0, 0);\n const localXAxis = new Point(1, 0);\n const localYAxis = new Point(0, 1);\n\n const baseParent = this.baseParent || this._getRenderGroupContainer(this);\n\n this._worldPosition = baseParent.toLocal(localPosition, this);\n const worldXAxis = baseParent.toLocal(localXAxis, this);\n const worldYAxis = baseParent.toLocal(localYAxis, this);\n\n worldXAxis.x -= this._worldPosition.x;\n worldXAxis.y -= this._worldPosition.y;\n worldYAxis.x -= this._worldPosition.x;\n worldYAxis.y -= this._worldPosition.y;\n\n this._worldScale = new Point(\n Math.sqrt(worldXAxis.x * worldXAxis.x + worldXAxis.y * worldXAxis.y),\n Math.sqrt(worldYAxis.x * worldYAxis.x + worldYAxis.y * worldYAxis.y)\n );\n\n this._worldRotationDegree = (this._calcWorldRotation(this) / Math.PI * 180) % 360;\n\n // Model matrix mirrors pixi7 RendererPlugin: with a baseParent the raw\n // baseParent world transform is used (per-particle world placement is\n // baked into the scaled simulation position/rotation); otherwise a pure\n // world-scale diagonal.\n if (this.baseParent) {\n const m = this.baseParent.worldTransform;\n this.worldRenderMatrix = { a: m.a, b: m.b, c: m.c, d: m.d, tx: m.tx, ty: m.ty };\n } else {\n this.worldRenderMatrix = {\n a: this._worldScale.x, b: 0, c: 0, d: this._worldScale.y, tx: 0, ty: 0\n };\n }\n }\n\n private _calcWorldRotation(obj: Container): number {\n if (obj.parent && obj.parent != this.baseParent)\n return obj.rotation + this._calcWorldRotation(obj.parent);\n else\n return obj.rotation;\n }\n\n private _checkUnpauseOnUpdateRender(): void {\n if (this._unpauseOnUpdateRender) {\n this.resetPosition();\n this.unpause();\n this._unpauseOnUpdateRender = false;\n }\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 { Rectangle } from \"pixi.js\";\nimport { Vec2, Vec3 } from \"./types\";\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 {PIXI.Rectangle} frame Rendering frame.\n */\n setScreenFrame(frame: Rectangle) {\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\n /**\n * Writes the projection as a 4x4 column-major matrix operating in screen\n * space, for the GPU render path. Homogeneous equivalent of\n * transformPosition(): clip.xy = p.xy - center * (p.z / z),\n * clip.w = 1 - p.z / z; the z row is zeroed (no depth on this path).\n * setScreenFrame() must have been called before.\n *\n * @param {Float32Array} out 16-element column-major output matrix.\n */\n writeMatrix(out: Float32Array): void {\n // Degenerate camera distance (zero-width frame or non-finite FOV math)\n // falls back to an orthographic (identity) projection.\n const z = this._z;\n const invZ = (Number.isFinite(z) && z > 0) ? 1.0 / z : 0.0;\n out.fill(0);\n out[0] = 1;\n out[5] = 1;\n out[8] = -this._screenPosX * invZ;\n out[9] = -this._screenPosY * invZ;\n out[11] = -invZ;\n out[15] = 1;\n }\n}","import { ApplicationPlugin } from './AplicationPlugin';\nimport { Context, ContextOptions } from './Context';\nimport { effectModelLoader } from './EffectModelLoader';\nimport { EffectPipe } from './EffectPipe';\nimport { extensions } from 'pixi.js';\n\nexport * from './types';\nexport * from './AplicationPlugin';\nexport * from './Context';\nexport * from './Effect';\nexport * from './EffectModel';\nexport * from './DataTextureManager';\nexport * from './NeutrinoRenderer';\nexport * from './EffectPipe';\nexport * from './TexturesLoader';\nexport * from './PerspectiveProjection';\nexport * from './EffectModelLoader';\n\nexport function registerPlugins() {\n extensions.add(ApplicationPlugin);\n extensions.add(effectModelLoader);\n extensions.add(EffectPipe);\n}\n\nexport function unregisterPlugins() {\n extensions.remove(ApplicationPlugin);\n extensions.remove(effectModelLoader);\n extensions.remove(EffectPipe);\n}\n\ndeclare module 'pixi.js' {\n interface ApplicationOptions {\n neutrino?: ContextOptions;\n }\n\n interface Application {\n neutrino?: Context;\n }\n}\n\nregisterPlugins();\n"],"names":["_Context","renderer","options","__publicField","Neutrino","webGLVersion","_a","path","success","fail","noiseGenerator","maxParticles","gl","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","ExtensionType","EventEmitter","texIndex","texturePath","texture","trimmedTexturePath","Cache","self","imageIndex","tex","index","defer","remapNeeded","texIdx","loader","_DefaultAssetsTexturesLoader","Assets","LoaderParserPriority","_url","loadAsset","_loader","url","_loadAsset","DOMAdapter","_asset","asset","resolve","context","effectModel","_effectModel","Rectangle","ctx","effect","dtm","instructions","numParticles","isGL1","textureSystem","maxBatch","renderStyles","materials","textures","texturesRemap","dataView","metaManager","texSlotMap","batch","j","slot","instr","flagOffset","flags","dtmGL1","viewport","resolution","frame","aspect","particleStartUnit","b","s","unit","remap","indexOffset","indexCount","boundTextures","u","materialIndex","blendMode","out","pm","a","c","b0","b1","b2","b3","mm","wt","_effect","instructionSet","RING_BUFFER_SIZE","data","textureWidth","textureHeight","maxSize","dataUint32","dst","d","startParticle","count","bytes","dataUnit","metaUnit","w","rows","Pause","Bounds","ViewContainer","Point","opts","seconds","position","rotation","name","value","container","localPosition","localXAxis","localYAxis","baseParent","worldXAxis","worldYAxis","m","obj","horizontalAngle","pos","scale","outSize","size","z","invZ","extensions"],"mappings":"qqBAAA,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;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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,wBAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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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"}
|