@neutrinoparticles/js-v1.1-phaser 1.1.1 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -388,10 +388,16 @@ declare module '@neutrinoparticles/js-v1.1-phaser/NeutrinoRenderer' {
388
388
 
389
389
  declare module '@neutrinoparticles/js-v1.1-phaser/DataTextureManager' {
390
390
  /**
391
- * Manages a small ring of RGBA32F WebGL textures that hold the runtime's flat
391
+ * Manages a small ring of RGBA32UI WebGL textures that hold the runtime's flat
392
392
  * particle data buffer. Each frame the current texture is re-uploaded (zero-copy
393
- * from the runtime-owned Uint32Array via a Float32 view) and the ring advances,
394
- * which avoids GPU pipeline stalls from re-uploading into a texture still in use.
393
+ * from the runtime-owned Uint32Array) and the ring advances, which avoids GPU
394
+ * pipeline stalls from re-uploading into a texture still in use.
395
+ *
396
+ * Integer, not float: the record mixes f32 fields with u32-packed words (flags,
397
+ * color, grid config, strip neighbors). Fetched as floats those words are
398
+ * subnormal/NaN patterns a driver may flush or canonicalize — Mali does (issue
399
+ * #348). An integer fetch is bit-exact by spec; the shader reinterprets the f32
400
+ * fields with uintBitsToFloat.
395
401
  *
396
402
  * Unlike the pixi7 adapter this owns raw GL textures directly (no PIXI texture
397
403
  * system), so the exact same class works for both the PIXI v8 and Phaser
@@ -402,9 +408,7 @@ declare module '@neutrinoparticles/js-v1.1-phaser/DataTextureManager' {
402
408
  readonly textureHeight: number;
403
409
  /**
404
410
  * @param gl - WebGL2 context (from the host renderer)
405
- * @param data - Uint32Array from the runtime. A Float32Array view over the
406
- * same buffer is uploaded as RGBA32F — bit patterns (incl. NaN/Inf) pass
407
- * through unchanged.
411
+ * @param data - Uint32Array from the runtime, uploaded as-is as RGBA32UI.
408
412
  * @param textureWidth - from runtime (system.dataTextureWidth)
409
413
  * @param textureHeight - from runtime (system.dataTextureHeight)
410
414
  */
@@ -1,12 +1,20 @@
1
1
  var K = Object.defineProperty;
2
- var z = (s, e, t) => e in s ? K(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
3
- var n = (s, e, t) => z(s, typeof e != "symbol" ? e + "" : e, t);
2
+ var N = (s, e, t) => e in s ? K(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
3
+ var n = (s, e, t) => N(s, typeof e != "symbol" ? e + "" : e, t);
4
4
  import Phaser from "phaser";
5
5
  import * as Neutrino from "@neutrinoparticles/js-v1.1";
6
6
  const vertexShaderSource = `#version 300 es
7
7
  precision highp float;
8
-
9
- uniform sampler2D uDataTexture;
8
+ precision highp int;
9
+ precision highp usampler2D;
10
+
11
+ // RGBA32UI, not RGBA32F: the record mixes f32 fields with u32-packed words
12
+ // (flags, color, grid config, strip neighbor indices). Fetched as floats those
13
+ // words are subnormal/NaN patterns, which a driver may flush or canonicalize —
14
+ // Mali does (issue #348) — and a lowp/mediump float sampler may even return
15
+ // them through fp16. An integer fetch is bit-exact by spec; the f32 fields are
16
+ // reinterpreted with uintBitsToFloat, which is lossless for normal floats.
17
+ uniform usampler2D uDataTexture;
10
18
  uniform int uDataTextureWidth;
11
19
  uniform vec3 uCameraRight;
12
20
  uniform vec3 uCameraUp;
@@ -47,12 +55,16 @@ flat out int vBatchTextureIndex;
47
55
  flat out vec4 vAtlasRemap;
48
56
  flat out int vStripPath;
49
57
 
50
- vec4 fetchTexel(int globalTexelIndex) {
58
+ uvec4 fetchTexelU(int globalTexelIndex) {
51
59
  int x = globalTexelIndex % uDataTextureWidth;
52
60
  int y = globalTexelIndex / uDataTextureWidth;
53
61
  return texelFetch(uDataTexture, ivec2(x, y), 0);
54
62
  }
55
63
 
64
+ vec4 fetchTexel(int globalTexelIndex) {
65
+ return uintBitsToFloat(fetchTexelU(globalTexelIndex));
66
+ }
67
+
56
68
  // Strip geometry helpers (port of GPU33 makeScreenSpaceStrip).
57
69
  // 2D screen-space variant used by the Faced strip frame; world Z reaches
58
70
  // gl_Position only through uViewProjMatrix (ortho or v1.0-parity perspective).
@@ -66,13 +78,17 @@ void main() {
66
78
 
67
79
  int baseTexel = particleIndex * 4;
68
80
 
69
- vec4 t0 = fetchTexel(baseTexel + 0);
81
+ // Texels 0 and 3 carry the u32-packed words: keep their raw uvec4 next to
82
+ // the float view so the words never pass through a float.
83
+ uvec4 u0 = fetchTexelU(baseTexel + 0);
84
+ uvec4 u3 = fetchTexelU(baseTexel + 3);
85
+ vec4 t0 = uintBitsToFloat(u0);
70
86
  vec4 t1 = fetchTexel(baseTexel + 1);
71
87
  vec4 t2 = fetchTexel(baseTexel + 2);
72
- vec4 t3 = fetchTexel(baseTexel + 3);
88
+ vec4 t3 = uintBitsToFloat(u3);
73
89
 
74
- // Texel 0: flags (uint32 bits in float), posX, posY, posZ
75
- uint flags = floatBitsToUint(t0.r);
90
+ // Texel 0: flags (u32), posX, posY, posZ
91
+ uint flags = u0.r;
76
92
  vec3 position = t0.gba;
77
93
  uint rotationType = (flags >> 8u) & 3u;
78
94
  uint ctorType = (flags >> 10u) & 3u;
@@ -105,7 +121,8 @@ void main() {
105
121
  int siblingTexel = isCur ? (baseTexel + 4) : (baseTexel - 4);
106
122
  vec4 ts0 = fetchTexel(siblingTexel + 0);
107
123
  vec4 ts1 = fetchTexel(siblingTexel + 1);
108
- vec4 ts3 = fetchTexel(siblingTexel + 3);
124
+ uvec4 us3 = fetchTexelU(siblingTexel + 3);
125
+ vec4 ts3 = uintBitsToFloat(us3);
109
126
 
110
127
  // p1 always = position of the meta_cur end; p2 = meta_nex end.
111
128
  vec3 p1 = isCur ? t0.gba : ts0.gba;
@@ -117,8 +134,8 @@ void main() {
117
134
  float texU2 = isCur ? ts1.g : t1.g;
118
135
 
119
136
  // Color: meta_cur stores color of p1, meta_nex stores color of p2.
120
- uint packedColorCur = floatBitsToUint(isCur ? t3.r : ts3.r);
121
- uint packedColorNex = floatBitsToUint(isCur ? ts3.r : t3.r);
137
+ uint packedColorCur = isCur ? u3.r : us3.r;
138
+ uint packedColorNex = isCur ? us3.r : u3.r;
122
139
  vec4 color1 = vec4(
123
140
  float(packedColorCur & 0xFFu) / 255.0,
124
141
  float((packedColorCur >> 8u) & 0xFFu) / 255.0,
@@ -147,8 +164,8 @@ void main() {
147
164
  // Both are direct position-texel indices (NOT pair-cur indices that
148
165
  // would need a +1 offset for the nex slot). Boundary detection uses
149
166
  // selfPairCurTexel for both.
150
- uint neighborIdxP0 = floatBitsToUint(isCur ? t3.g : ts3.g);
151
- uint neighborIdxP3 = floatBitsToUint(isCur ? ts3.b : t3.b);
167
+ uint neighborIdxP0 = isCur ? u3.g : us3.g;
168
+ uint neighborIdxP3 = isCur ? us3.b : u3.b;
152
169
  uint selfPairCurTexel = uint(isCur ? baseTexel : siblingTexel) / 4u;
153
170
 
154
171
  vec3 p0 = (neighborIdxP0 == selfPairCurTexel)
@@ -521,8 +538,8 @@ void main() {
521
538
  vec2 origin = t1.rg;
522
539
  vec2 size = t1.ba;
523
540
 
524
- // Texel 3: packed colorRGBA (uint32 bits in float), packed gridConfig (uint32 bits), gridIndex
525
- uint packedColor = floatBitsToUint(t3.r);
541
+ // Texel 3: packed colorRGBA (u32), packed gridConfig (u32), gridIndex (f32)
542
+ uint packedColor = u3.r;
526
543
  vColor = vec4(
527
544
  float(packedColor & 0xFFu) / 255.0,
528
545
  float((packedColor >> 8u) & 0xFFu) / 255.0,
@@ -534,7 +551,7 @@ void main() {
534
551
  // here. S=1 for LDR colors (no-op). Alpha is untouched.
535
552
  vColor.rgb *= t3.a;
536
553
 
537
- uint gridConfig = floatBitsToUint(t3.g);
554
+ uint gridConfig = u3.g;
538
555
  float gridWidth = max(float(gridConfig & 0xFFFFu), 1.0);
539
556
  float gridHeight = max(float((gridConfig >> 16u) & 0xFFFFu), 1.0);
540
557
  // gridIndex must be truncated to an integer to pick a single cell —
@@ -1321,7 +1338,7 @@ void main() {
1321
1338
  // Mirror of the ES 3.00 shader.
1322
1339
  gl_FragColor.rgb *= vColor.a;
1323
1340
  }
1324
- `, A = class A {
1341
+ `, S = class S {
1325
1342
  constructor(e, t) {
1326
1343
  n(this, "neutrino");
1327
1344
  // On a WebGL1 context this actually holds a WebGLRenderingContext; the
@@ -1334,7 +1351,7 @@ void main() {
1334
1351
  n(this, "_vao", null);
1335
1352
  // WebGL1 render path state (TDD_js-v1.1-webgl1.md)
1336
1353
  n(this, "_isWebGL1", !1);
1337
- n(this, "_maxBatchTextures", A.MAX_BATCH_TEXTURES);
1354
+ n(this, "_maxBatchTextures", S.MAX_BATCH_TEXTURES);
1338
1355
  n(this, "_hasElementIndexUint", !1);
1339
1356
  n(this, "_vaoExt", null);
1340
1357
  n(this, "_aIdBuffer", null);
@@ -1439,12 +1456,12 @@ void main() {
1439
1456
  );
1440
1457
  const d = l ? new Uint32Array(e * 6) : new Uint16Array(e * 6);
1441
1458
  for (let i = 0; i < e; i++) {
1442
- const u = i * 4, _ = i * 6;
1443
- d[_ + 0] = u + 0, d[_ + 1] = u + 1, d[_ + 2] = u + 2, d[_ + 3] = u + 0, d[_ + 4] = u + 2, d[_ + 5] = u + 3;
1459
+ const c = i * 4, g = i * 6;
1460
+ d[g + 0] = c + 0, d[g + 1] = c + 1, d[g + 2] = c + 2, d[g + 3] = c + 0, d[g + 4] = c + 2, d[g + 5] = c + 3;
1444
1461
  }
1445
1462
  if (this._indexBuffer = t.createBuffer(), t.bindBuffer(t.ELEMENT_ARRAY_BUFFER, this._indexBuffer), t.bufferData(t.ELEMENT_ARRAY_BUFFER, d, t.STATIC_DRAW), this._isWebGL1) {
1446
1463
  const i = new Float32Array(e * 4);
1447
- for (let u = 0; u < i.length; u++) i[u] = u;
1464
+ for (let c = 0; c < i.length; c++) i[c] = c;
1448
1465
  this._aIdBuffer = t.createBuffer(), t.bindBuffer(t.ARRAY_BUFFER, this._aIdBuffer), t.bufferData(t.ARRAY_BUFFER, i, t.STATIC_DRAW);
1449
1466
  } else
1450
1467
  this._dummyVB = t.createBuffer(), t.bindBuffer(t.ARRAY_BUFFER, this._dummyVB), t.bufferData(t.ARRAY_BUFFER, e * 4, t.STATIC_DRAW), this._vao = t.createVertexArray(), t.bindVertexArray(this._vao), t.bindBuffer(t.ELEMENT_ARRAY_BUFFER, this._indexBuffer), t.bindBuffer(t.ARRAY_BUFFER, this._dummyVB), t.enableVertexAttribArray(0), t.vertexAttribPointer(0, 1, t.UNSIGNED_BYTE, !1, 0, 0), t.bindVertexArray(a);
@@ -1494,7 +1511,7 @@ void main() {
1494
1511
  const r = e.getParameter(e.MAX_COMBINED_TEXTURE_IMAGE_UNITS), o = e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS);
1495
1512
  this._maxBatchTextures = Math.max(
1496
1513
  1,
1497
- Math.min(A.MAX_BATCH_TEXTURES, r - 2, o)
1514
+ Math.min(S.MAX_BATCH_TEXTURES, r - 2, o)
1498
1515
  );
1499
1516
  }
1500
1517
  /**
@@ -1521,31 +1538,31 @@ varying vec4 vC;
1521
1538
  void main() { gl_FragColor = vC; }
1522
1539
  `, r = e.getParameter(e.VIEWPORT), o = e.getParameter(e.CURRENT_PROGRAM), l = e.getParameter(e.ARRAY_BUFFER_BINDING), d = e.getParameter(e.FRAMEBUFFER_BINDING), i = e.getParameter(e.ACTIVE_TEXTURE);
1523
1540
  e.activeTexture(e.TEXTURE0);
1524
- const u = e.getParameter(e.TEXTURE_BINDING_2D);
1541
+ const c = e.getParameter(e.TEXTURE_BINDING_2D);
1525
1542
  e.activeTexture(e.TEXTURE1);
1526
- const _ = e.getParameter(e.TEXTURE_BINDING_2D), y = e.isEnabled(e.BLEND), E = e.isEnabled(e.DEPTH_TEST), I = e.isEnabled(e.SCISSOR_TEST);
1527
- let m = null, w = null, U = null, f = null, v = null, g = null, c = -1, b = !1, x = null, h = 4, B = 0, p = 0, R = 0, D = !1, S = !1;
1528
- const T = new Uint8Array(4);
1543
+ const g = e.getParameter(e.TEXTURE_BINDING_2D), U = e.isEnabled(e.BLEND), P = e.isEnabled(e.DEPTH_TEST), A = e.isEnabled(e.SCISSOR_TEST);
1544
+ let v = null, b = null, R = null, y = null, x = null, m = null, u = -1, T = !1, E = null, p = 4, h = 0, f = 0, w = 0, C = !1, B = !1;
1545
+ const _ = new Uint8Array(4);
1529
1546
  try {
1530
- m = e.createProgram(), e.attachShader(m, this._compileShader(e.VERTEX_SHADER, t)), e.attachShader(m, this._compileShader(e.FRAGMENT_SHADER, a)), e.linkProgram(m);
1531
- const C = (P, F) => {
1547
+ v = e.createProgram(), e.attachShader(v, this._compileShader(e.VERTEX_SHADER, t)), e.attachShader(v, this._compileShader(e.FRAGMENT_SHADER, a)), e.linkProgram(v);
1548
+ const D = (I, F) => {
1532
1549
  const M = e.createTexture();
1533
- return e.bindTexture(e.TEXTURE_2D, M), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texImage2D(e.TEXTURE_2D, 0, e.RGBA, 1, 1, 0, e.RGBA, P, F), M;
1550
+ return e.bindTexture(e.TEXTURE_2D, M), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texImage2D(e.TEXTURE_2D, 0, e.RGBA, 1, 1, 0, e.RGBA, I, F), M;
1534
1551
  };
1535
- e.activeTexture(e.TEXTURE0), w = C(e.FLOAT, new Float32Array([1, 0.5, 0.25, 1])), U = C(e.UNSIGNED_BYTE, new Uint8Array([51, 102, 153, 255])), f = e.createTexture(), e.bindTexture(e.TEXTURE_2D, f), e.texImage2D(e.TEXTURE_2D, 0, e.RGBA, 1, 1, 0, e.RGBA, e.UNSIGNED_BYTE, null), v = e.createFramebuffer(), e.bindFramebuffer(e.FRAMEBUFFER, v), e.framebufferTexture2D(e.FRAMEBUFFER, e.COLOR_ATTACHMENT0, e.TEXTURE_2D, f, 0), g = e.createBuffer(), e.bindBuffer(e.ARRAY_BUFFER, g), e.bufferData(e.ARRAY_BUFFER, new Float32Array([0]), e.STATIC_DRAW), S = e.getProgramParameter(m, e.LINK_STATUS), S && (e.useProgram(m), e.activeTexture(e.TEXTURE0), e.bindTexture(e.TEXTURE_2D, w), e.activeTexture(e.TEXTURE1), e.bindTexture(e.TEXTURE_2D, U), e.uniform1i(e.getUniformLocation(m, "uF"), 0), e.uniform1i(e.getUniformLocation(m, "uB"), 1), c = e.getAttribLocation(m, "aId"), b = e.getVertexAttrib(c, e.VERTEX_ATTRIB_ARRAY_ENABLED), x = e.getVertexAttrib(c, e.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING), h = e.getVertexAttrib(c, e.VERTEX_ATTRIB_ARRAY_SIZE), B = e.getVertexAttrib(c, e.VERTEX_ATTRIB_ARRAY_TYPE), D = e.getVertexAttrib(c, e.VERTEX_ATTRIB_ARRAY_NORMALIZED), p = e.getVertexAttrib(c, e.VERTEX_ATTRIB_ARRAY_STRIDE), R = e.getVertexAttribOffset(c, e.VERTEX_ATTRIB_ARRAY_POINTER), e.enableVertexAttribArray(c), e.vertexAttribPointer(c, 1, e.FLOAT, !1, 0, 0), e.viewport(0, 0, 1, 1), e.disable(e.BLEND), e.disable(e.DEPTH_TEST), e.disable(e.SCISSOR_TEST), e.drawArrays(e.POINTS, 0, 1), e.readPixels(0, 0, 1, 1, e.RGBA, e.UNSIGNED_BYTE, T), S = Math.abs(T[0] - 51) <= 2 && Math.abs(T[1] - 51) <= 2 && Math.abs(T[2] - 38) <= 2);
1552
+ e.activeTexture(e.TEXTURE0), b = D(e.FLOAT, new Float32Array([1, 0.5, 0.25, 1])), R = D(e.UNSIGNED_BYTE, new Uint8Array([51, 102, 153, 255])), y = e.createTexture(), e.bindTexture(e.TEXTURE_2D, y), e.texImage2D(e.TEXTURE_2D, 0, e.RGBA, 1, 1, 0, e.RGBA, e.UNSIGNED_BYTE, null), x = e.createFramebuffer(), e.bindFramebuffer(e.FRAMEBUFFER, x), e.framebufferTexture2D(e.FRAMEBUFFER, e.COLOR_ATTACHMENT0, e.TEXTURE_2D, y, 0), m = e.createBuffer(), e.bindBuffer(e.ARRAY_BUFFER, m), e.bufferData(e.ARRAY_BUFFER, new Float32Array([0]), e.STATIC_DRAW), B = e.getProgramParameter(v, e.LINK_STATUS), B && (e.useProgram(v), e.activeTexture(e.TEXTURE0), e.bindTexture(e.TEXTURE_2D, b), e.activeTexture(e.TEXTURE1), e.bindTexture(e.TEXTURE_2D, R), e.uniform1i(e.getUniformLocation(v, "uF"), 0), e.uniform1i(e.getUniformLocation(v, "uB"), 1), u = e.getAttribLocation(v, "aId"), T = e.getVertexAttrib(u, e.VERTEX_ATTRIB_ARRAY_ENABLED), E = e.getVertexAttrib(u, e.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING), p = e.getVertexAttrib(u, e.VERTEX_ATTRIB_ARRAY_SIZE), h = e.getVertexAttrib(u, e.VERTEX_ATTRIB_ARRAY_TYPE), C = e.getVertexAttrib(u, e.VERTEX_ATTRIB_ARRAY_NORMALIZED), f = e.getVertexAttrib(u, e.VERTEX_ATTRIB_ARRAY_STRIDE), w = e.getVertexAttribOffset(u, e.VERTEX_ATTRIB_ARRAY_POINTER), e.enableVertexAttribArray(u), e.vertexAttribPointer(u, 1, e.FLOAT, !1, 0, 0), e.viewport(0, 0, 1, 1), e.disable(e.BLEND), e.disable(e.DEPTH_TEST), e.disable(e.SCISSOR_TEST), e.drawArrays(e.POINTS, 0, 1), e.readPixels(0, 0, 1, 1, e.RGBA, e.UNSIGNED_BYTE, _), B = Math.abs(_[0] - 51) <= 2 && Math.abs(_[1] - 51) <= 2 && Math.abs(_[2] - 38) <= 2);
1536
1553
  } finally {
1537
- c >= 0 && (x && (e.bindBuffer(e.ARRAY_BUFFER, x), e.vertexAttribPointer(
1538
- c,
1539
- h,
1540
- B,
1541
- D,
1554
+ u >= 0 && (E && (e.bindBuffer(e.ARRAY_BUFFER, E), e.vertexAttribPointer(
1555
+ u,
1542
1556
  p,
1543
- R
1544
- )), b ? e.enableVertexAttribArray(c) : e.disableVertexAttribArray(c)), v && e.deleteFramebuffer(v), f && e.deleteTexture(f), w && e.deleteTexture(w), U && e.deleteTexture(U), g && e.deleteBuffer(g), m && e.deleteProgram(m), e.bindFramebuffer(e.FRAMEBUFFER, d), e.bindBuffer(e.ARRAY_BUFFER, l), e.useProgram(o), e.activeTexture(e.TEXTURE0), e.bindTexture(e.TEXTURE_2D, u), e.activeTexture(e.TEXTURE1), e.bindTexture(e.TEXTURE_2D, _), e.activeTexture(i), y && e.enable(e.BLEND), E && e.enable(e.DEPTH_TEST), I && e.enable(e.SCISSOR_TEST), e.viewport(r[0], r[1], r[2], r[3]);
1557
+ h,
1558
+ C,
1559
+ f,
1560
+ w
1561
+ )), T ? e.enableVertexAttribArray(u) : e.disableVertexAttribArray(u)), x && e.deleteFramebuffer(x), y && e.deleteTexture(y), b && e.deleteTexture(b), R && e.deleteTexture(R), m && e.deleteBuffer(m), v && e.deleteProgram(v), e.bindFramebuffer(e.FRAMEBUFFER, d), e.bindBuffer(e.ARRAY_BUFFER, l), e.useProgram(o), e.activeTexture(e.TEXTURE0), e.bindTexture(e.TEXTURE_2D, c), e.activeTexture(e.TEXTURE1), e.bindTexture(e.TEXTURE_2D, g), e.activeTexture(i), U && e.enable(e.BLEND), P && e.enable(e.DEPTH_TEST), A && e.enable(e.SCISSOR_TEST), e.viewport(r[0], r[1], r[2], r[3]);
1545
1562
  }
1546
- if (!S)
1563
+ if (!B)
1547
1564
  throw new Error(
1548
- `NeutrinoParticles (js-v1.1): WebGL1 vertex texture fetch smoke test failed (got ${T[0]},${T[1]},${T[2]}); WebGL2 or WebGL1 with working vertex float textures is required.`
1565
+ `NeutrinoParticles (js-v1.1): WebGL1 vertex texture fetch smoke test failed (got ${_[0]},${_[1]},${_[2]}); WebGL2 or WebGL1 with working vertex float textures is required.`
1549
1566
  );
1550
1567
  }
1551
1568
  _initShader() {
@@ -1553,7 +1570,7 @@ void main() { gl_FragColor = vC; }
1553
1570
  if (this._shaderProgram = e.createProgram(), e.attachShader(this._shaderProgram, r), e.attachShader(this._shaderProgram, o), e.linkProgram(this._shaderProgram), !e.getProgramParameter(this._shaderProgram, e.LINK_STATUS))
1554
1571
  throw new Error("Shader link error: " + e.getProgramInfoLog(this._shaderProgram));
1555
1572
  e.deleteShader(r), e.deleteShader(o), this._uDataTexture = e.getUniformLocation(this._shaderProgram, "uDataTexture"), this._uCameraRight = e.getUniformLocation(this._shaderProgram, "uCameraRight"), this._uCameraUp = e.getUniformLocation(this._shaderProgram, "uCameraUp"), this._uCameraDir = e.getUniformLocation(this._shaderProgram, "uCameraDir"), this._uViewProjMatrix = e.getUniformLocation(this._shaderProgram, "uViewProjMatrix"), this._uModelMatrix = e.getUniformLocation(this._shaderProgram, "uModelMatrix"), this._uViewportAspect = e.getUniformLocation(this._shaderProgram, "uViewportAspect"), this._uWorldAlpha = e.getUniformLocation(this._shaderProgram, "uWorldAlpha"), this._isWebGL1 ? (this._uMetaTexture = e.getUniformLocation(this._shaderProgram, "uMetaTexture"), this._uDataTexSize = e.getUniformLocation(this._shaderProgram, "uDataTexSize"), this._aIdLocation = e.getAttribLocation(this._shaderProgram, "aId")) : this._uDataTextureWidth = e.getUniformLocation(this._shaderProgram, "uDataTextureWidth"), this._uTextures = [], this._uTexRemaps = [];
1556
- for (let l = 0; l < A.MAX_BATCH_TEXTURES; l++)
1573
+ for (let l = 0; l < S.MAX_BATCH_TEXTURES; l++)
1557
1574
  this._uTextures.push(e.getUniformLocation(this._shaderProgram, `uTextures[${l}]`)), this._uTexRemaps.push(e.getUniformLocation(this._shaderProgram, `uTexRemaps[${l}]`));
1558
1575
  }
1559
1576
  _compileShader(e, t) {
@@ -1565,8 +1582,8 @@ void main() { gl_FragColor = vC; }
1565
1582
  return r;
1566
1583
  }
1567
1584
  };
1568
- n(A, "MAX_BATCH_TEXTURES", 8);
1569
- let NeutrinoContext = A;
1585
+ n(S, "MAX_BATCH_TEXTURES", 8);
1586
+ let NeutrinoContext = S;
1570
1587
  class GamePlugin extends Phaser.Plugins.BasePlugin {
1571
1588
  constructor() {
1572
1589
  super(...arguments);
@@ -1640,8 +1657,8 @@ return new NeutrinoEffect(ctx);
1640
1657
  l ? this._onTextureLoaded(t, l) : (this.scene.load.once(
1641
1658
  "filecomplete-image-" + o,
1642
1659
  /* @__PURE__ */ ((d, i) => () => {
1643
- const u = this.scene.sys.textures.get(i);
1644
- this._onTextureLoaded(d, u.get(u.firstFrame));
1660
+ const c = this.scene.sys.textures.get(i);
1661
+ this._onTextureLoaded(d, c.get(c.firstFrame));
1645
1662
  })(t, o)
1646
1663
  ), this.scene.load.image(o, r));
1647
1664
  }
@@ -1707,9 +1724,7 @@ const RING_BUFFER_SIZE$1 = 3;
1707
1724
  class DataTextureManager {
1708
1725
  /**
1709
1726
  * @param gl - WebGL2 context (from the host renderer)
1710
- * @param data - Uint32Array from the runtime. A Float32Array view over the
1711
- * same buffer is uploaded as RGBA32F — bit patterns (incl. NaN/Inf) pass
1712
- * through unchanged.
1727
+ * @param data - Uint32Array from the runtime, uploaded as-is as RGBA32UI.
1713
1728
  * @param textureWidth - from runtime (system.dataTextureWidth)
1714
1729
  * @param textureHeight - from runtime (system.dataTextureHeight)
1715
1730
  */
@@ -1717,7 +1732,7 @@ class DataTextureManager {
1717
1732
  n(this, "textureWidth");
1718
1733
  n(this, "textureHeight");
1719
1734
  n(this, "_gl");
1720
- n(this, "_floatView");
1735
+ n(this, "_data");
1721
1736
  n(this, "_textures", []);
1722
1737
  n(this, "_currentIndex", 0);
1723
1738
  const o = e.getParameter(e.MAX_TEXTURE_SIZE);
@@ -1725,18 +1740,18 @@ class DataTextureManager {
1725
1740
  throw new Error(
1726
1741
  `NeutrinoParticles: data texture ${a}x${r} exceeds GL MAX_TEXTURE_SIZE (${o}). Reduce effect particle capacity.`
1727
1742
  );
1728
- this._gl = e, this.textureWidth = a, this.textureHeight = r, this._floatView = new Float32Array(t.buffer, t.byteOffset, t.length);
1743
+ this._gl = e, this.textureWidth = a, this.textureHeight = r, this._data = t;
1729
1744
  for (let l = 0; l < RING_BUFFER_SIZE$1; l++) {
1730
1745
  const d = e.createTexture();
1731
1746
  e.bindTexture(e.TEXTURE_2D, d), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texImage2D(
1732
1747
  e.TEXTURE_2D,
1733
1748
  0,
1734
- e.RGBA32F,
1749
+ e.RGBA32UI,
1735
1750
  a,
1736
1751
  r,
1737
1752
  0,
1738
- e.RGBA,
1739
- e.FLOAT,
1753
+ e.RGBA_INTEGER,
1754
+ e.UNSIGNED_INT,
1740
1755
  null
1741
1756
  ), this._textures.push(d);
1742
1757
  }
@@ -1755,9 +1770,9 @@ class DataTextureManager {
1755
1770
  0,
1756
1771
  this.textureWidth,
1757
1772
  this.textureHeight,
1758
- t.RGBA,
1759
- t.FLOAT,
1760
- this._floatView
1773
+ t.RGBA_INTEGER,
1774
+ t.UNSIGNED_INT,
1775
+ this._data
1761
1776
  );
1762
1777
  }
1763
1778
  advance() {
@@ -1905,82 +1920,87 @@ class NeutrinoRenderer {
1905
1920
  n(this, "_texSlotMap", /* @__PURE__ */ new Map());
1906
1921
  n(this, "_batchPool");
1907
1922
  n(this, "_batchCount", 0);
1923
+ n(this, "_samplerUnitsProgram", null);
1908
1924
  this._batchPool = [];
1909
1925
  for (let e = 0; e < MAX_BATCHES; e++)
1910
1926
  this._batchPool.push(new DrawBatch());
1911
1927
  }
1912
1928
  render(e, t, a, r, o, l, d) {
1913
1929
  if (l === 0) return;
1914
- const i = e.gl, u = e.isWebGL1, _ = e.maxBatchTextures, y = d.renderStyles, E = d.materials, I = u ? t.meta : null;
1915
- I && I.build(r, l), this._batchCount = 0;
1916
- const m = this._texSlotMap;
1930
+ const i = e.gl, c = e.isWebGL1, g = c ? PARTICLE_TEXTURE_START_UNIT_GL1 : PARTICLE_TEXTURE_START_UNIT, U = e.maxBatchTextures, P = d.renderStyles, A = d.materials, v = c ? t.meta : null;
1931
+ v && v.build(r, l), this._batchCount = 0;
1932
+ const b = this._texSlotMap;
1917
1933
  for (; this._batchPool.length < o.length; )
1918
1934
  this._batchPool.push(new DrawBatch());
1919
- let w = 0;
1920
- for (; w < o.length; ) {
1921
- const f = this._batchPool[this._batchCount];
1922
- f.reset(), f.blendMode = this._resolveBlend(o[w].blendMode, E), f.startParticle = o[w].startParticleIndex, m.clear();
1923
- let v = w;
1924
- for (; v < o.length && this._resolveBlend(o[v].blendMode, E) === f.blendMode; ) {
1925
- const g = y[o[v].renderStyleIndex].textureIndices[0];
1926
- if (!m.has(g)) {
1927
- if (m.size >= _) break;
1928
- const x = m.size;
1929
- m.set(g, x), f.glTextures[x] = d.glTextures[g] || null, f.remaps[x] = d.remaps[g] || null, f.numTextures = x + 1;
1935
+ let R = 0;
1936
+ for (; R < o.length; ) {
1937
+ const x = this._batchPool[this._batchCount];
1938
+ x.reset(), x.blendMode = this._resolveBlend(o[R].blendMode, A), x.startParticle = o[R].startParticleIndex, b.clear();
1939
+ let m = R;
1940
+ for (; m < o.length && this._resolveBlend(o[m].blendMode, A) === x.blendMode; ) {
1941
+ const u = P[o[m].renderStyleIndex].textureIndices[0];
1942
+ if (!b.has(u)) {
1943
+ if (b.size >= U) break;
1944
+ const p = b.size;
1945
+ b.set(u, p), x.glTextures[p] = d.glTextures[u] || null, x.remaps[p] = d.remaps[u] || null, x.numTextures = p + 1;
1930
1946
  }
1931
- const c = m.get(g), b = o[v];
1932
- if (I)
1933
- I.patchSlot(b.startParticleIndex, b.numParticles, c);
1934
- else if (c !== 0)
1935
- for (let x = 0; x < b.numParticles; x++) {
1936
- const h = (b.startParticleIndex + x) * BYTES_PER_PARTICLE, B = a.getUint32(h, !0);
1937
- a.setUint32(h, B & 4294967040 | c, !0);
1947
+ const T = b.get(u), E = o[m];
1948
+ if (v)
1949
+ v.patchSlot(E.startParticleIndex, E.numParticles, T);
1950
+ else if (T !== 0)
1951
+ for (let p = 0; p < E.numParticles; p++) {
1952
+ const h = (E.startParticleIndex + p) * BYTES_PER_PARTICLE, f = a.getUint32(h, !0);
1953
+ a.setUint32(h, f & 4294967040 | T, !0);
1938
1954
  }
1939
- f.numParticles += b.numParticles, v++;
1955
+ x.numParticles += E.numParticles, m++;
1940
1956
  }
1941
- this._batchCount++, w = v;
1957
+ this._batchCount++, R = m;
1942
1958
  }
1943
- const U = i.isEnabled(i.SCISSOR_TEST);
1959
+ const y = i.isEnabled(i.SCISSOR_TEST);
1944
1960
  try {
1945
- if (i.disable(i.DEPTH_TEST), i.disable(i.STENCIL_TEST), i.disable(i.SCISSOR_TEST), i.disable(i.CULL_FACE), i.depthMask(!1), i.colorMask(!0, !0, !0, !0), i.useProgram(e.shaderProgram), u) {
1946
- const p = t;
1947
- p.upload(l, DATA_TEXTURE_UNIT, META_TEXTURE_UNIT), i.uniform1i(e.uDataTexture, DATA_TEXTURE_UNIT), i.uniform1i(e.uMetaTexture, META_TEXTURE_UNIT), i.uniform2f(e.uDataTexSize, p.textureWidth, p.textureHeight);
1961
+ if (i.disable(i.DEPTH_TEST), i.disable(i.STENCIL_TEST), i.disable(i.SCISSOR_TEST), i.disable(i.CULL_FACE), i.depthMask(!1), i.colorMask(!0, !0, !0, !0), i.useProgram(e.shaderProgram), this._samplerUnitsProgram !== e.shaderProgram) {
1962
+ const f = c ? e.maxBatchTextures : NeutrinoContext.MAX_BATCH_TEXTURES;
1963
+ for (let w = 0; w < f; w++)
1964
+ i.uniform1i(e.uTextures[w], g + w);
1965
+ this._samplerUnitsProgram = e.shaderProgram;
1966
+ }
1967
+ if (c) {
1968
+ const f = t;
1969
+ f.upload(l, DATA_TEXTURE_UNIT, META_TEXTURE_UNIT), i.uniform1i(e.uDataTexture, DATA_TEXTURE_UNIT), i.uniform1i(e.uMetaTexture, META_TEXTURE_UNIT), i.uniform2f(e.uDataTexSize, f.textureWidth, f.textureHeight);
1948
1970
  } else {
1949
- const p = t;
1950
- p.uploadAndBind(DATA_TEXTURE_UNIT), i.uniform1i(e.uDataTexture, DATA_TEXTURE_UNIT), i.uniform1i(e.uDataTextureWidth, p.textureWidth);
1971
+ const f = t;
1972
+ f.uploadAndBind(DATA_TEXTURE_UNIT), i.uniform1i(e.uDataTexture, DATA_TEXTURE_UNIT), i.uniform1i(e.uDataTextureWidth, f.textureWidth);
1951
1973
  }
1952
1974
  i.uniform3f(e.uCameraRight, 1, 0, 0), i.uniform3f(e.uCameraUp, 0, -1, 0), i.uniform3f(e.uCameraDir, 0, 0, -1);
1953
- const f = d.viewportWidth, v = d.viewportHeight, g = d.zoom || 1, c = this._orthoMatrix;
1954
- if (c.fill(0), c[0] = 2 / f * g, c[5] = -2 / v * g, c[10] = 0, c[15] = 1, c[12] = -1 - 2 / f * g * d.scrollX, c[13] = 1 + 2 / v * g * d.scrollY, d.projection) {
1955
- const p = this._projFrame;
1956
- p.x = 0, p.y = 0, p.width = f, p.height = v, d.projection.setScreenFrame(p), d.projection.writeMatrix(this._perspMatrix), this._mulMatrix(this._vpMatrix, c, this._perspMatrix), i.uniformMatrix4fv(e.uViewProjMatrix, !1, this._vpMatrix);
1975
+ const x = d.viewportWidth, m = d.viewportHeight, u = d.zoom || 1, T = this._orthoMatrix;
1976
+ if (T.fill(0), T[0] = 2 / x * u, T[5] = -2 / m * u, T[10] = 0, T[15] = 1, T[12] = -1 - 2 / x * u * d.scrollX, T[13] = 1 + 2 / m * u * d.scrollY, d.projection) {
1977
+ const f = this._projFrame;
1978
+ f.x = 0, f.y = 0, f.width = x, f.height = m, d.projection.setScreenFrame(f), d.projection.writeMatrix(this._perspMatrix), this._mulMatrix(this._vpMatrix, T, this._perspMatrix), i.uniformMatrix4fv(e.uViewProjMatrix, !1, this._vpMatrix);
1957
1979
  } else
1958
- i.uniformMatrix4fv(e.uViewProjMatrix, !1, c);
1959
- const b = v > 0 ? f / v : 1;
1960
- e.uViewportAspect && i.uniform1f(e.uViewportAspect, b), e.uWorldAlpha && i.uniform1f(e.uWorldAlpha, d.worldAlpha);
1961
- const x = d.model, h = this._modelMatrix;
1962
- h[0] = x.a, h[1] = x.b, h[2] = 0, h[3] = 0, h[4] = x.c, h[5] = x.d, h[6] = 0, h[7] = 0, h[8] = 0, h[9] = 0, h[10] = 1, h[11] = 0, h[12] = x.tx, h[13] = x.ty, h[14] = 0, h[15] = 1, i.uniformMatrix4fv(e.uModelMatrix, !1, h), u ? (e.unbindVao(), i.bindBuffer(i.ARRAY_BUFFER, e.aIdBuffer), i.enableVertexAttribArray(e.aIdLocation), i.vertexAttribPointer(e.aIdLocation, 1, i.FLOAT, !1, 0, 0), i.bindBuffer(i.ELEMENT_ARRAY_BUFFER, e.indexBuffer)) : i.bindVertexArray(e.vao);
1963
- const B = u ? PARTICLE_TEXTURE_START_UNIT_GL1 : PARTICLE_TEXTURE_START_UNIT;
1964
- i.enable(i.BLEND);
1965
- for (let p = 0; p < this._batchCount; p++) {
1966
- const R = this._batchPool[p];
1967
- this._applyBlendMode(i, R.blendMode);
1968
- for (let T = 0; T < R.numTextures; T++) {
1969
- const C = B + T;
1970
- i.activeTexture(i.TEXTURE0 + C), i.bindTexture(i.TEXTURE_2D, R.glTextures[T]), i.uniform1i(e.uTextures[T], C);
1971
- const P = R.remaps[T];
1972
- P ? i.uniform4f(e.uTexRemaps[T], P.x, P.y, P.width, P.height) : i.uniform4f(e.uTexRemaps[T], 0, 0, 1, 1);
1980
+ i.uniformMatrix4fv(e.uViewProjMatrix, !1, T);
1981
+ const E = m > 0 ? x / m : 1;
1982
+ e.uViewportAspect && i.uniform1f(e.uViewportAspect, E), e.uWorldAlpha && i.uniform1f(e.uWorldAlpha, d.worldAlpha);
1983
+ const p = d.model, h = this._modelMatrix;
1984
+ h[0] = p.a, h[1] = p.b, h[2] = 0, h[3] = 0, h[4] = p.c, h[5] = p.d, h[6] = 0, h[7] = 0, h[8] = 0, h[9] = 0, h[10] = 1, h[11] = 0, h[12] = p.tx, h[13] = p.ty, h[14] = 0, h[15] = 1, i.uniformMatrix4fv(e.uModelMatrix, !1, h), c ? (e.unbindVao(), i.bindBuffer(i.ARRAY_BUFFER, e.aIdBuffer), i.enableVertexAttribArray(e.aIdLocation), i.vertexAttribPointer(e.aIdLocation, 1, i.FLOAT, !1, 0, 0), i.bindBuffer(i.ELEMENT_ARRAY_BUFFER, e.indexBuffer)) : i.bindVertexArray(e.vao), i.enable(i.BLEND);
1985
+ for (let f = 0; f < this._batchCount; f++) {
1986
+ const w = this._batchPool[f];
1987
+ this._applyBlendMode(i, w.blendMode);
1988
+ for (let _ = 0; _ < w.numTextures; _++) {
1989
+ const D = g + _;
1990
+ i.activeTexture(i.TEXTURE0 + D), i.bindTexture(i.TEXTURE_2D, w.glTextures[_]);
1991
+ const I = w.remaps[_];
1992
+ I ? i.uniform4f(e.uTexRemaps[_], I.x, I.y, I.width, I.height) : i.uniform4f(e.uTexRemaps[_], 0, 0, 1, 1);
1973
1993
  }
1974
- const D = R.startParticle * 6, S = R.numParticles * 6;
1994
+ const C = w.startParticle * 6, B = w.numParticles * 6;
1975
1995
  i.drawElements(
1976
1996
  i.TRIANGLES,
1977
- S,
1997
+ B,
1978
1998
  e.indexType,
1979
- D * (e.indexType === i.UNSIGNED_INT ? 4 : 2)
1999
+ C * (e.indexType === i.UNSIGNED_INT ? 4 : 2)
1980
2000
  );
1981
2001
  }
1982
2002
  } finally {
1983
- u ? (i.disableVertexAttribArray(e.aIdLocation), i.bindBuffer(i.ARRAY_BUFFER, null), i.bindBuffer(i.ELEMENT_ARRAY_BUFFER, null)) : i.bindVertexArray(null), i.useProgram(null), U && i.enable(i.SCISSOR_TEST);
2003
+ c ? (i.disableVertexAttribArray(e.aIdLocation), i.bindBuffer(i.ARRAY_BUFFER, null), i.bindBuffer(i.ELEMENT_ARRAY_BUFFER, null)) : i.bindVertexArray(null), i.useProgram(null), i.activeTexture(i.TEXTURE0 + DATA_TEXTURE_UNIT), i.bindTexture(i.TEXTURE_2D, null), y && i.enable(i.SCISSOR_TEST);
1984
2004
  }
1985
2005
  }
1986
2006
  // Resolve a renderStyle's compacted material INDEX to the real blend enum (0=Normal/
@@ -2087,11 +2107,11 @@ class Effect extends Phaser.GameObjects.GameObject {
2087
2107
  const d = this.effect.renderInstructions, i = d._totalParticles;
2088
2108
  if (i === 0) return;
2089
2109
  t.flush();
2090
- const u = this.effectModel.effectModel.textures.length, _ = this._glTexturesScratch;
2091
- _.length = u;
2092
- for (let E = 0; E < u; ++E)
2093
- _[E] = this.effectModel.glTexture(E);
2094
- const y = this._worldScale;
2110
+ const c = this.effectModel.effectModel.textures.length, g = this._glTexturesScratch;
2111
+ g.length = c;
2112
+ for (let P = 0; P < c; ++P)
2113
+ g[P] = this.effectModel.glTexture(P);
2114
+ const U = this._worldScale;
2095
2115
  try {
2096
2116
  sharedRenderer.render(
2097
2117
  o,
@@ -2101,7 +2121,7 @@ class Effect extends Phaser.GameObjects.GameObject {
2101
2121
  d,
2102
2122
  i,
2103
2123
  {
2104
- model: { a: y, b: 0, c: 0, d: y, tx: 0, ty: 0 },
2124
+ model: { a: U, b: 0, c: 0, d: U, tx: 0, ty: 0 },
2105
2125
  viewportWidth: t.width,
2106
2126
  viewportHeight: t.height,
2107
2127
  scrollX: r.scrollX * this.scrollFactorX,
@@ -2109,7 +2129,7 @@ class Effect extends Phaser.GameObjects.GameObject {
2109
2129
  zoom: r.zoom,
2110
2130
  worldAlpha: this.alpha,
2111
2131
  projection: this.projection,
2112
- glTextures: _,
2132
+ glTextures: g,
2113
2133
  remaps: this.effectModel.texturesRemap,
2114
2134
  renderStyles: this.effect.model.renderStyles,
2115
2135
  materials: this.effect.model.materials