@neutrinoparticles/js-v1.1-phaser 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -1
- package/dist/neutrinoparticles.js-v1.1-phaser.cjs.js +129 -46
- package/dist/neutrinoparticles.js-v1.1-phaser.cjs.js.map +1 -1
- package/dist/neutrinoparticles.js-v1.1-phaser.es.js +195 -112
- package/dist/neutrinoparticles.js-v1.1-phaser.es.js.map +1 -1
- package/dist/neutrinoparticles.js-v1.1-phaser.umd.js +129 -46
- package/dist/neutrinoparticles.js-v1.1-phaser.umd.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## [1.0.1] - 2026-07-25
|
|
4
4
|
|
|
5
5
|
- Initial Phaser 3 integration for the JS v1.1 export format (GPU geometry construction, data-texture renderer). Works on WebGL2 and, automatically, on WebGL1 contexts with float vertex textures — Phaser's default WebGL1 context works out of the box.
|
|
6
6
|
- Fixed strip texture seams: a ribbon whose atlas texture repeats along its length no longer shows a muddy "chewed" column at tile junctions when the texture has mipmaps (WebGL2).
|
|
7
|
+
- Emitter-anchored strips no longer show a brief mis-oriented sliver at the emitter end right after a new particle spawns.
|
|
8
|
+
- Fixed broken ribbon (Strip) geometry on sharp bends: a dark wedge was cut out of the ribbon wherever the path bent sharper than the ribbon's own width, and the segments next to the ribbon's ends (near the emitter and at the tail) could render as a twisted, mostly-invisible band or a stray misoriented quad — most visible right where the ribbon is being created when the head particle sits close to the emitter (issue #236).
|
|
9
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var F=Object.defineProperty;var N=(s,e,t)=>e in s?F(s,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):s[e]=t;var n=(s,e,t)=>N(s,typeof e!="symbol"?e+"":e,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Phaser=require("phaser"),Neutrino=require("@neutrinoparticles/js-v1.1");function _interopNamespaceDefault(s){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(s){for(const t in s)if(t!=="default"){const a=Object.getOwnPropertyDescriptor(s,t);Object.defineProperty(e,t,a.get?a:{enumerable:!0,get:()=>s[t]})}}return e.default=s,Object.freeze(e)}const Neutrino__namespace=_interopNamespaceDefault(Neutrino),vertexShaderSource=`#version 300 es
|
|
2
2
|
precision highp float;
|
|
3
3
|
|
|
4
4
|
uniform sampler2D uDataTexture;
|
|
@@ -169,6 +169,10 @@ void main() {
|
|
|
169
169
|
// by the sign of w). Forces a discard outside the [-w,w] cube at the end.
|
|
170
170
|
bool nearPlaneClipped = (sp1.w < 1e-3) || (sp2.w < 1e-3);
|
|
171
171
|
|
|
172
|
+
// #236: set when the segment itself is degenerate (much shorter than
|
|
173
|
+
// the ribbon half-width) - the pair is discarded like nearPlaneClipped.
|
|
174
|
+
bool stripDegenerate = false;
|
|
175
|
+
|
|
172
176
|
// Aspect correction so the 2D Faced ortho gives visually-perpendicular
|
|
173
177
|
// dirs on non-square viewports (inverted before gl_Position).
|
|
174
178
|
vec2 aspectMul = vec2(1.0, 1.0 / max(uViewportAspect, 1e-6));
|
|
@@ -206,9 +210,15 @@ void main() {
|
|
|
206
210
|
float wlen01 = length(wp01);
|
|
207
211
|
float wlen12 = length(wp12);
|
|
208
212
|
float wlen23 = length(wp23);
|
|
213
|
+
// #236: degeneracy guards at visual scale (mirror of GPU33).
|
|
214
|
+
// A segment much shorter than the ribbon half-width cannot define
|
|
215
|
+
// a visually meaningful direction; a degenerate neighbour falls
|
|
216
|
+
// back to the straight cap instead of a noise knee.
|
|
217
|
+
float wDegenEps = max(max(abs(halfSize1), abs(halfSize2)) * 0.02, 1e-6);
|
|
218
|
+
if (wlen12 < wDegenEps) stripDegenerate = true;
|
|
209
219
|
vec3 wdir12 = (wlen12 > 1e-6) ? (wp12 / wlen12) : vec3(1.0, 0.0, 0.0);
|
|
210
|
-
vec3 wdir01 = (wlen01 >
|
|
211
|
-
vec3 wdir23 = (wlen23 >
|
|
220
|
+
vec3 wdir01 = (wlen01 > wDegenEps) ? (wp01 / wlen01) : wdir12;
|
|
221
|
+
vec3 wdir23 = (wlen23 > wDegenEps) ? (wp23 / wlen23) : wdir12;
|
|
212
222
|
noKnee1 = dot(wdir01, wdir12) > 0.999;
|
|
213
223
|
noKnee2 = dot(wdir12, wdir23) > 0.999;
|
|
214
224
|
pathLen12 = wlen12;
|
|
@@ -220,9 +230,12 @@ void main() {
|
|
|
220
230
|
vec3 K1 = Kmul1 * normalize(cross(wdir01 + wdir12, n1));
|
|
221
231
|
Bmul1 = sign(dot(B1raw, K1));
|
|
222
232
|
vec3 B1 = B1raw * Bmul1;
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
233
|
+
// #236: inner vertex at the ribbon half-width along the
|
|
234
|
+
// bisector, symmetric to the outer vertex (mirror of GPU33).
|
|
235
|
+
// The old true-miter-with-neighbour-length-clamp cut an
|
|
236
|
+
// uncovered wedge out of sharp bends whenever halfSize
|
|
237
|
+
// exceeded the particle spacing.
|
|
238
|
+
float ik1 = halfSize1;
|
|
226
239
|
worldK1 = p1 + K1 * halfSize1;
|
|
227
240
|
worldB1 = p1 + B1 * halfSize1;
|
|
228
241
|
worldIK1 = p1 - K1 * ik1;
|
|
@@ -243,9 +256,8 @@ void main() {
|
|
|
243
256
|
vec3 K2 = Kmul2 * normalize(cross(wdir12 + wdir23, n2));
|
|
244
257
|
Bmul2 = sign(dot(B2raw, K2));
|
|
245
258
|
vec3 B2 = B2raw * Bmul2;
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (dot( wdir23, ik2 * -K2) > wlen23) ik2 = wlen23;
|
|
259
|
+
// #236: see ik1 - inner vertex at the ribbon half-width.
|
|
260
|
+
float ik2 = halfSize2;
|
|
249
261
|
worldK2 = p2 + K2 * halfSize2;
|
|
250
262
|
worldB2 = p2 + B2 * halfSize2;
|
|
251
263
|
worldIK2 = p2 - K2 * ik2;
|
|
@@ -273,12 +285,6 @@ void main() {
|
|
|
273
285
|
float len01 = length(d01);
|
|
274
286
|
float len12 = length(d12);
|
|
275
287
|
float len23 = length(d23);
|
|
276
|
-
vec2 dir12 = (len12 > 1e-6) ? (d12 / len12) : vec2(1.0, 0.0);
|
|
277
|
-
vec2 dir01 = (len01 > 1e-6) ? (d01 / len01) : dir12;
|
|
278
|
-
vec2 dir23 = (len23 > 1e-6) ? (d23 / len23) : dir12;
|
|
279
|
-
noKnee1 = dot(dir01, dir12) > 0.999;
|
|
280
|
-
noKnee2 = dot(dir12, dir23) > 0.999;
|
|
281
|
-
pathLen12 = len12;
|
|
282
288
|
|
|
283
289
|
// Section magnitude: project camera_up*halfSize per anchor into NDC.
|
|
284
290
|
vec4 spU1 = mvpMatrix * vec4(p1 + uCameraUp * halfSize1, 1.0);
|
|
@@ -286,15 +292,25 @@ void main() {
|
|
|
286
292
|
float ndcHalfSize1 = length((spU1.xy / spU1.w) * aspectMul - ndc1);
|
|
287
293
|
float ndcHalfSize2 = length((spU2.xy / spU2.w) * aspectMul - ndc2);
|
|
288
294
|
|
|
295
|
+
// #236: degeneracy guards at visual scale (mirror of GPU33).
|
|
296
|
+
float degenEps = max(max(ndcHalfSize1, ndcHalfSize2) * 0.02, 1e-6);
|
|
297
|
+
if (len12 < degenEps) stripDegenerate = true;
|
|
298
|
+
vec2 dir12 = (len12 > 1e-6) ? (d12 / len12) : vec2(1.0, 0.0);
|
|
299
|
+
vec2 dir01 = (len01 > degenEps) ? (d01 / len01) : dir12;
|
|
300
|
+
vec2 dir23 = (len23 > degenEps) ? (d23 / len23) : dir12;
|
|
301
|
+
noKnee1 = dot(dir01, dir12) > 0.999;
|
|
302
|
+
noKnee2 = dot(dir12, dir23) > 0.999;
|
|
303
|
+
pathLen12 = len12;
|
|
304
|
+
|
|
289
305
|
vec2 B = stripOrtho(dir12);
|
|
290
306
|
if (!noKnee1) {
|
|
291
307
|
float Kmul1 = -sign(dot(stripOrtho(dir01), dir12));
|
|
292
308
|
vec2 K1 = Kmul1 * normalize(stripOrtho(dir01 + dir12));
|
|
293
309
|
Bmul1 = sign(dot(B, K1));
|
|
294
310
|
vec2 B1 = B * Bmul1;
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
311
|
+
// #236: inner vertex at the ribbon half-width (see the Free
|
|
312
|
+
// branch comment above).
|
|
313
|
+
float ik1 = ndcHalfSize1;
|
|
298
314
|
k1 = ndc1 + K1 * ndcHalfSize1;
|
|
299
315
|
b1 = ndc1 + B1 * ndcHalfSize1;
|
|
300
316
|
IK1 = ndc1 - K1 * ik1;
|
|
@@ -312,9 +328,8 @@ void main() {
|
|
|
312
328
|
vec2 K2 = Kmul2 * normalize(stripOrtho(dir12 + dir23));
|
|
313
329
|
Bmul2 = sign(dot(B, K2));
|
|
314
330
|
vec2 B2 = B * Bmul2;
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if (dot(dir23, ik2 * -K2) > len23) ik2 = len23;
|
|
331
|
+
// #236: see ik1 - inner vertex at the ribbon half-width.
|
|
332
|
+
float ik2 = ndcHalfSize2;
|
|
318
333
|
k2 = ndc2 + K2 * ndcHalfSize2;
|
|
319
334
|
b2 = ndc2 + B2 * ndcHalfSize2;
|
|
320
335
|
IK2 = ndc2 - K2 * ik2;
|
|
@@ -329,6 +344,33 @@ void main() {
|
|
|
329
344
|
}
|
|
330
345
|
}
|
|
331
346
|
|
|
347
|
+
// #236: a noKnee (straight-cap) end carries no bend side of its own -
|
|
348
|
+
// its raw side label is always the +B side. If the segment's other
|
|
349
|
+
// end is a real knee on the -B side, the mismatched labels would send
|
|
350
|
+
// the ladder into the opposite-sides (twist) branch and flip the
|
|
351
|
+
// texture V across a segment that does not actually change bend side.
|
|
352
|
+
// Relabel the straight end to the knee end's side (swap its k/IK and
|
|
353
|
+
// re-collapse b onto the new k) so the ladder stays untwisted. Both
|
|
354
|
+
// frames are swapped; only the active one is meaningful.
|
|
355
|
+
if (noKnee1 && !noKnee2 && Bmul2 < 0.0) {
|
|
356
|
+
// Swap only the ACTIVE frame's variables - the inactive frame's
|
|
357
|
+
// are uninitialized and must not be read.
|
|
358
|
+
if (isFreeRotation) {
|
|
359
|
+
vec3 tRw1 = worldK1; worldK1 = worldIK1; worldIK1 = tRw1; worldB1 = worldK1;
|
|
360
|
+
} else {
|
|
361
|
+
vec2 tRl1 = k1; k1 = IK1; IK1 = tRl1; b1 = k1;
|
|
362
|
+
}
|
|
363
|
+
Bmul1 = Bmul2;
|
|
364
|
+
}
|
|
365
|
+
if (noKnee2 && !noKnee1 && Bmul1 < 0.0) {
|
|
366
|
+
if (isFreeRotation) {
|
|
367
|
+
vec3 tRw2 = worldK2; worldK2 = worldIK2; worldIK2 = tRw2; worldB2 = worldK2;
|
|
368
|
+
} else {
|
|
369
|
+
vec2 tRl2 = k2; k2 = IK2; IK2 = tRl2; b2 = k2;
|
|
370
|
+
}
|
|
371
|
+
Bmul2 = Bmul1;
|
|
372
|
+
}
|
|
373
|
+
|
|
332
374
|
// V coords (mirror of preview3 / GPU33 make*Strip):
|
|
333
375
|
// V at outer knee (k) = (Bmul + 1) * 0.5
|
|
334
376
|
// V at inner knee (IK) = 1 - V_outer ; bend (b) = outer
|
|
@@ -430,7 +472,10 @@ void main() {
|
|
|
430
472
|
|
|
431
473
|
// Free projects the world-space vertex through MVP directly; Faced
|
|
432
474
|
// reconstructs clip space from aspect-corrected NDC (mirror of preview3).
|
|
433
|
-
if (
|
|
475
|
+
if (stripDegenerate) {
|
|
476
|
+
// #236: sub-visual segment - discard the pair entirely.
|
|
477
|
+
gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
|
|
478
|
+
} else if (isFreeRotation) {
|
|
434
479
|
gl_Position = mvpMatrix * vec4(vertPos3D, 1.0);
|
|
435
480
|
} else if (nearPlaneClipped) {
|
|
436
481
|
// At least one anchor is at / behind the near plane → the NDC math
|
|
@@ -765,6 +810,10 @@ void main() {
|
|
|
765
810
|
// unaffected by the sign of w).
|
|
766
811
|
bool nearPlaneClipped = (sp1.w < 1e-3) || (sp2.w < 1e-3);
|
|
767
812
|
|
|
813
|
+
// #236: set when the segment itself is degenerate (much shorter than
|
|
814
|
+
// the ribbon half-width) - the pair is discarded like nearPlaneClipped.
|
|
815
|
+
bool stripDegenerate = false;
|
|
816
|
+
|
|
768
817
|
// Aspect correction for the 2D Faced ortho on non-square viewports.
|
|
769
818
|
vec2 aspectMul = vec2(1.0, 1.0 / max(uViewportAspect, 1e-6));
|
|
770
819
|
|
|
@@ -807,9 +856,12 @@ void main() {
|
|
|
807
856
|
float wlen01 = length(wp01);
|
|
808
857
|
float wlen12 = length(wp12);
|
|
809
858
|
float wlen23 = length(wp23);
|
|
859
|
+
// #236: degeneracy guards at visual scale (mirror of GPU33).
|
|
860
|
+
float wDegenEps = max(max(abs(halfSize1), abs(halfSize2)) * 0.02, 1e-6);
|
|
861
|
+
if (wlen12 < wDegenEps) stripDegenerate = true;
|
|
810
862
|
vec3 wdir12 = (wlen12 > 1e-6) ? (wp12 / wlen12) : vec3(1.0, 0.0, 0.0);
|
|
811
|
-
vec3 wdir01 = (wlen01 >
|
|
812
|
-
vec3 wdir23 = (wlen23 >
|
|
863
|
+
vec3 wdir01 = (wlen01 > wDegenEps) ? (wp01 / wlen01) : wdir12;
|
|
864
|
+
vec3 wdir23 = (wlen23 > wDegenEps) ? (wp23 / wlen23) : wdir12;
|
|
813
865
|
noKnee1 = dot(wdir01, wdir12) > 0.999;
|
|
814
866
|
noKnee2 = dot(wdir12, wdir23) > 0.999;
|
|
815
867
|
pathLen12 = wlen12;
|
|
@@ -821,9 +873,9 @@ void main() {
|
|
|
821
873
|
vec3 K1 = Kmul1 * normalize(cross(wdir01 + wdir12, n1));
|
|
822
874
|
Bmul1 = sign(dot(B1raw, K1));
|
|
823
875
|
vec3 B1 = B1raw * Bmul1;
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
876
|
+
// #236: inner vertex at the ribbon half-width (mirror of
|
|
877
|
+
// GPU33; see the ES 3.00 shader for the rationale).
|
|
878
|
+
float ik1 = halfSize1;
|
|
827
879
|
worldK1 = p1 + K1 * halfSize1;
|
|
828
880
|
worldB1 = p1 + B1 * halfSize1;
|
|
829
881
|
worldIK1 = p1 - K1 * ik1;
|
|
@@ -844,9 +896,8 @@ void main() {
|
|
|
844
896
|
vec3 K2 = Kmul2 * normalize(cross(wdir12 + wdir23, n2));
|
|
845
897
|
Bmul2 = sign(dot(B2raw, K2));
|
|
846
898
|
vec3 B2 = B2raw * Bmul2;
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
if (dot( wdir23, ik2 * -K2) > wlen23) ik2 = wlen23;
|
|
899
|
+
// #236: see ik1 - inner vertex at the ribbon half-width.
|
|
900
|
+
float ik2 = halfSize2;
|
|
850
901
|
worldK2 = p2 + K2 * halfSize2;
|
|
851
902
|
worldB2 = p2 + B2 * halfSize2;
|
|
852
903
|
worldIK2 = p2 - K2 * ik2;
|
|
@@ -874,12 +925,6 @@ void main() {
|
|
|
874
925
|
float len01 = length(d01);
|
|
875
926
|
float len12 = length(d12);
|
|
876
927
|
float len23 = length(d23);
|
|
877
|
-
vec2 dir12 = (len12 > 1e-6) ? (d12 / len12) : vec2(1.0, 0.0);
|
|
878
|
-
vec2 dir01 = (len01 > 1e-6) ? (d01 / len01) : dir12;
|
|
879
|
-
vec2 dir23 = (len23 > 1e-6) ? (d23 / len23) : dir12;
|
|
880
|
-
noKnee1 = dot(dir01, dir12) > 0.999;
|
|
881
|
-
noKnee2 = dot(dir12, dir23) > 0.999;
|
|
882
|
-
pathLen12 = len12;
|
|
883
928
|
|
|
884
929
|
// Section magnitude: project camera_up*halfSize per anchor into NDC.
|
|
885
930
|
vec4 spU1 = mvpMatrix * vec4(p1 + uCameraUp * halfSize1, 1.0);
|
|
@@ -887,15 +932,24 @@ void main() {
|
|
|
887
932
|
float ndcHalfSize1 = length((spU1.xy / spU1.w) * aspectMul - ndc1);
|
|
888
933
|
float ndcHalfSize2 = length((spU2.xy / spU2.w) * aspectMul - ndc2);
|
|
889
934
|
|
|
935
|
+
// #236: degeneracy guards at visual scale (mirror of GPU33).
|
|
936
|
+
float degenEps = max(max(ndcHalfSize1, ndcHalfSize2) * 0.02, 1e-6);
|
|
937
|
+
if (len12 < degenEps) stripDegenerate = true;
|
|
938
|
+
vec2 dir12 = (len12 > 1e-6) ? (d12 / len12) : vec2(1.0, 0.0);
|
|
939
|
+
vec2 dir01 = (len01 > degenEps) ? (d01 / len01) : dir12;
|
|
940
|
+
vec2 dir23 = (len23 > degenEps) ? (d23 / len23) : dir12;
|
|
941
|
+
noKnee1 = dot(dir01, dir12) > 0.999;
|
|
942
|
+
noKnee2 = dot(dir12, dir23) > 0.999;
|
|
943
|
+
pathLen12 = len12;
|
|
944
|
+
|
|
890
945
|
vec2 B = stripOrtho(dir12);
|
|
891
946
|
if (!noKnee1) {
|
|
892
947
|
float Kmul1 = -sign(dot(stripOrtho(dir01), dir12));
|
|
893
948
|
vec2 K1 = Kmul1 * normalize(stripOrtho(dir01 + dir12));
|
|
894
949
|
Bmul1 = sign(dot(B, K1));
|
|
895
950
|
vec2 B1 = B * Bmul1;
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
if (dot(dir12, ik1 * -K1) > len12) ik1 = len12;
|
|
951
|
+
// #236: inner vertex at the ribbon half-width.
|
|
952
|
+
float ik1 = ndcHalfSize1;
|
|
899
953
|
k1 = ndc1 + K1 * ndcHalfSize1;
|
|
900
954
|
b1 = ndc1 + B1 * ndcHalfSize1;
|
|
901
955
|
IK1 = ndc1 - K1 * ik1;
|
|
@@ -913,9 +967,8 @@ void main() {
|
|
|
913
967
|
vec2 K2 = Kmul2 * normalize(stripOrtho(dir12 + dir23));
|
|
914
968
|
Bmul2 = sign(dot(B, K2));
|
|
915
969
|
vec2 B2 = B * Bmul2;
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
if (dot(dir23, ik2 * -K2) > len23) ik2 = len23;
|
|
970
|
+
// #236: see ik1 - inner vertex at the ribbon half-width.
|
|
971
|
+
float ik2 = ndcHalfSize2;
|
|
919
972
|
k2 = ndc2 + K2 * ndcHalfSize2;
|
|
920
973
|
b2 = ndc2 + B2 * ndcHalfSize2;
|
|
921
974
|
IK2 = ndc2 - K2 * ik2;
|
|
@@ -930,6 +983,33 @@ void main() {
|
|
|
930
983
|
}
|
|
931
984
|
}
|
|
932
985
|
|
|
986
|
+
// #236: a noKnee (straight-cap) end carries no bend side of its own -
|
|
987
|
+
// its raw side label is always the +B side. If the segment's other
|
|
988
|
+
// end is a real knee on the -B side, the mismatched labels would send
|
|
989
|
+
// the ladder into the opposite-sides (twist) branch and flip the
|
|
990
|
+
// texture V across a segment that does not actually change bend side.
|
|
991
|
+
// Relabel the straight end to the knee end's side (swap its k/IK and
|
|
992
|
+
// re-collapse b onto the new k) so the ladder stays untwisted. Both
|
|
993
|
+
// frames are swapped; only the active one is meaningful.
|
|
994
|
+
if (noKnee1 && !noKnee2 && Bmul2 < 0.0) {
|
|
995
|
+
// Swap only the ACTIVE frame's variables - the inactive frame's
|
|
996
|
+
// are uninitialized and must not be read.
|
|
997
|
+
if (isFreeRotation) {
|
|
998
|
+
vec3 tRw1 = worldK1; worldK1 = worldIK1; worldIK1 = tRw1; worldB1 = worldK1;
|
|
999
|
+
} else {
|
|
1000
|
+
vec2 tRl1 = k1; k1 = IK1; IK1 = tRl1; b1 = k1;
|
|
1001
|
+
}
|
|
1002
|
+
Bmul1 = Bmul2;
|
|
1003
|
+
}
|
|
1004
|
+
if (noKnee2 && !noKnee1 && Bmul1 < 0.0) {
|
|
1005
|
+
if (isFreeRotation) {
|
|
1006
|
+
vec3 tRw2 = worldK2; worldK2 = worldIK2; worldIK2 = tRw2; worldB2 = worldK2;
|
|
1007
|
+
} else {
|
|
1008
|
+
vec2 tRl2 = k2; k2 = IK2; IK2 = tRl2; b2 = k2;
|
|
1009
|
+
}
|
|
1010
|
+
Bmul2 = Bmul1;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
933
1013
|
// V coords: V at outer knee (k) = (Bmul + 1) * 0.5; inner = 1 - outer.
|
|
934
1014
|
float Vtop1 = (Bmul1 + 1.0) * 0.5;
|
|
935
1015
|
float Vbot1 = 1.0 - Vtop1;
|
|
@@ -1001,7 +1081,10 @@ void main() {
|
|
|
1001
1081
|
|
|
1002
1082
|
// Free projects the world-space vertex through MVP directly; Faced
|
|
1003
1083
|
// reconstructs clip space from aspect-corrected NDC.
|
|
1004
|
-
if (
|
|
1084
|
+
if (stripDegenerate) {
|
|
1085
|
+
// #236: sub-visual segment - discard the pair entirely.
|
|
1086
|
+
gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
|
|
1087
|
+
} else if (isFreeRotation) {
|
|
1005
1088
|
gl_Position = mvpMatrix * vec4(vertPos3D, 1.0);
|
|
1006
1089
|
} else if (nearPlaneClipped) {
|
|
1007
1090
|
gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
|
|
@@ -1147,7 +1230,7 @@ void main() {
|
|
|
1147
1230
|
// world alpha scales the whole RGBA (mirror of the ES 3.00 shader).
|
|
1148
1231
|
gl_FragColor = texColor * vColor * uWorldAlpha;
|
|
1149
1232
|
}
|
|
1150
|
-
`,A=class A{constructor(e,t){n(this,"neutrino");n(this,"gl");n(this,"_shaderProgram",null);n(this,"_indexBuffer",null);n(this,"_dummyVB",null);n(this,"_indexBufferCapacity",0);n(this,"_vao",null);n(this,"_isWebGL1",!1);n(this,"_maxBatchTextures",A.MAX_BATCH_TEXTURES);n(this,"_hasElementIndexUint",!1);n(this,"_vaoExt",null);n(this,"_aIdBuffer",null);n(this,"_aIdLocation",-1);n(this,"_uDataTexture",null);n(this,"_uDataTextureWidth",null);n(this,"_uMetaTexture",null);n(this,"_uDataTexSize",null);n(this,"_uCameraRight",null);n(this,"_uCameraUp",null);n(this,"_uCameraDir",null);n(this,"_uViewProjMatrix",null);n(this,"_uModelMatrix",null);n(this,"_uViewportAspect",null);n(this,"_uWorldAlpha",null);n(this,"_uTextures",[]);n(this,"_uTexRemaps",[]);n(this,"_noiseInitialized",!1);this.gl=e,this.neutrino=t,this._isWebGL1=typeof e.createVertexArray!="function",this._isWebGL1&&this._probeWebGL1Capabilities(),this._initShader(),this._isWebGL1&&this._smokeTestVertexTextureFetch()}initializeNoise(e,t,a){if(this._noiseInitialized){t&&t();return}this.neutrino.initializeNoise(e,()=>{this._noiseInitialized=!0,t&&t()},a)}generateNoise(){if(this._noiseInitialized)return;const e=new this.neutrino.NoiseGenerator;for(;!e.step(););this._noiseInitialized=!0}get shaderProgram(){return this._shaderProgram}get isWebGL1(){return this._isWebGL1}get maxBatchTextures(){return this._maxBatchTextures}get uDataTexture(){return this._uDataTexture}get uDataTextureWidth(){return this._uDataTextureWidth}get uMetaTexture(){return this._uMetaTexture}get uDataTexSize(){return this._uDataTexSize}get uCameraRight(){return this._uCameraRight}get uCameraUp(){return this._uCameraUp}get uCameraDir(){return this._uCameraDir}get uViewProjMatrix(){return this._uViewProjMatrix}get uModelMatrix(){return this._uModelMatrix}get uViewportAspect(){return this._uViewportAspect}get uWorldAlpha(){return this._uWorldAlpha}get uTextures(){return this._uTextures}get uTexRemaps(){return this._uTexRemaps}ensureIndexBuffer(e){if(e<=this._indexBufferCapacity)return;const t=this.gl,a=this._isWebGL1?null:t.getParameter(t.VERTEX_ARRAY_BINDING),r=t.getParameter(t.ARRAY_BUFFER_BINDING),o=t.getParameter(t.ELEMENT_ARRAY_BUFFER_BINDING);this._indexBuffer&&t.deleteBuffer(this._indexBuffer),this._dummyVB&&(t.deleteBuffer(this._dummyVB),this._dummyVB=null),this._vao&&(t.deleteVertexArray(this._vao),this._vao=null),this._aIdBuffer&&(t.deleteBuffer(this._aIdBuffer),this._aIdBuffer=null);const l=e>16383;if(l&&this._isWebGL1&&!this._hasElementIndexUint)throw new Error(`NeutrinoParticles (js-v1.1): the effect needs 32-bit indices (${e} particles) but this WebGL1 context lacks OES_element_index_uint.`);const
|
|
1233
|
+
`,A=class A{constructor(e,t){n(this,"neutrino");n(this,"gl");n(this,"_shaderProgram",null);n(this,"_indexBuffer",null);n(this,"_dummyVB",null);n(this,"_indexBufferCapacity",0);n(this,"_vao",null);n(this,"_isWebGL1",!1);n(this,"_maxBatchTextures",A.MAX_BATCH_TEXTURES);n(this,"_hasElementIndexUint",!1);n(this,"_vaoExt",null);n(this,"_aIdBuffer",null);n(this,"_aIdLocation",-1);n(this,"_uDataTexture",null);n(this,"_uDataTextureWidth",null);n(this,"_uMetaTexture",null);n(this,"_uDataTexSize",null);n(this,"_uCameraRight",null);n(this,"_uCameraUp",null);n(this,"_uCameraDir",null);n(this,"_uViewProjMatrix",null);n(this,"_uModelMatrix",null);n(this,"_uViewportAspect",null);n(this,"_uWorldAlpha",null);n(this,"_uTextures",[]);n(this,"_uTexRemaps",[]);n(this,"_noiseInitialized",!1);this.gl=e,this.neutrino=t,this._isWebGL1=typeof e.createVertexArray!="function",this._isWebGL1&&this._probeWebGL1Capabilities(),this._initShader(),this._isWebGL1&&this._smokeTestVertexTextureFetch()}initializeNoise(e,t,a){if(this._noiseInitialized){t&&t();return}this.neutrino.initializeNoise(e,()=>{this._noiseInitialized=!0,t&&t()},a)}generateNoise(){if(this._noiseInitialized)return;const e=new this.neutrino.NoiseGenerator;for(;!e.step(););this._noiseInitialized=!0}get shaderProgram(){return this._shaderProgram}get isWebGL1(){return this._isWebGL1}get maxBatchTextures(){return this._maxBatchTextures}get uDataTexture(){return this._uDataTexture}get uDataTextureWidth(){return this._uDataTextureWidth}get uMetaTexture(){return this._uMetaTexture}get uDataTexSize(){return this._uDataTexSize}get uCameraRight(){return this._uCameraRight}get uCameraUp(){return this._uCameraUp}get uCameraDir(){return this._uCameraDir}get uViewProjMatrix(){return this._uViewProjMatrix}get uModelMatrix(){return this._uModelMatrix}get uViewportAspect(){return this._uViewportAspect}get uWorldAlpha(){return this._uWorldAlpha}get uTextures(){return this._uTextures}get uTexRemaps(){return this._uTexRemaps}ensureIndexBuffer(e){if(e<=this._indexBufferCapacity)return;const t=this.gl,a=this._isWebGL1?null:t.getParameter(t.VERTEX_ARRAY_BINDING),r=t.getParameter(t.ARRAY_BUFFER_BINDING),o=t.getParameter(t.ELEMENT_ARRAY_BUFFER_BINDING);this._indexBuffer&&t.deleteBuffer(this._indexBuffer),this._dummyVB&&(t.deleteBuffer(this._dummyVB),this._dummyVB=null),this._vao&&(t.deleteVertexArray(this._vao),this._vao=null),this._aIdBuffer&&(t.deleteBuffer(this._aIdBuffer),this._aIdBuffer=null);const l=e>16383;if(l&&this._isWebGL1&&!this._hasElementIndexUint)throw new Error(`NeutrinoParticles (js-v1.1): the effect needs 32-bit indices (${e} particles) but this WebGL1 context lacks OES_element_index_uint.`);const d=l?new Uint32Array(e*6):new Uint16Array(e*6);for(let i=0;i<e;i++){const u=i*4,g=i*6;d[g+0]=u+0,d[g+1]=u+1,d[g+2]=u+2,d[g+3]=u+0,d[g+4]=u+2,d[g+5]=u+3}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){const i=new Float32Array(e*4);for(let u=0;u<i.length;u++)i[u]=u;this._aIdBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this._aIdBuffer),t.bufferData(t.ARRAY_BUFFER,i,t.STATIC_DRAW)}else 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);t.bindBuffer(t.ARRAY_BUFFER,r),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,o),this._indexBufferCapacity=e}get vao(){return this._vao}get indexBuffer(){return this._indexBuffer}get aIdBuffer(){return this._aIdBuffer}get aIdLocation(){return this._aIdLocation}get indexType(){return this._indexBufferCapacity>16383?this.gl.UNSIGNED_INT:this.gl.UNSIGNED_SHORT}unbindVao(){this._isWebGL1?this._vaoExt&&this._vaoExt.bindVertexArrayOES(null):this.gl.bindVertexArray(null)}destroy(){const e=this.gl;this._shaderProgram&&e.deleteProgram(this._shaderProgram),this._indexBuffer&&e.deleteBuffer(this._indexBuffer),this._dummyVB&&e.deleteBuffer(this._dummyVB),this._vao&&e.deleteVertexArray(this._vao),this._aIdBuffer&&e.deleteBuffer(this._aIdBuffer)}_probeWebGL1Capabilities(){const e=this.gl;if(!e.getExtension("OES_texture_float"))throw new Error("NeutrinoParticles (js-v1.1): WebGL1 context lacks OES_texture_float; WebGL2 or WebGL1 with vertex float textures is required.");const t=e.getParameter(e.MAX_VERTEX_TEXTURE_IMAGE_UNITS);if(t<2)throw new Error("NeutrinoParticles (js-v1.1): WebGL1 context has "+t+" vertex texture units (2 required); WebGL2 or WebGL1 with vertex float textures is required.");const a=e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT);if(!a||a.precision===0)throw new Error("NeutrinoParticles (js-v1.1): WebGL1 context lacks highp float in fragment shaders; WebGL2 or WebGL1 with fragment highp is required.");this._hasElementIndexUint=!!e.getExtension("OES_element_index_uint"),this._vaoExt=e.getExtension("OES_vertex_array_object");const r=e.getParameter(e.MAX_COMBINED_TEXTURE_IMAGE_UNITS),o=e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS);this._maxBatchTextures=Math.max(1,Math.min(A.MAX_BATCH_TEXTURES,r-2,o))}_smokeTestVertexTextureFetch(){const e=this.gl,t=`precision highp float;
|
|
1151
1234
|
attribute float aId;
|
|
1152
1235
|
uniform sampler2D uF;
|
|
1153
1236
|
uniform sampler2D uB;
|
|
@@ -1162,8 +1245,8 @@ void main() {
|
|
|
1162
1245
|
`,a=`precision mediump float;
|
|
1163
1246
|
varying vec4 vC;
|
|
1164
1247
|
void main() { gl_FragColor = vC; }
|
|
1165
|
-
`,r=e.getParameter(e.VIEWPORT),o=e.getParameter(e.CURRENT_PROGRAM),l=e.getParameter(e.ARRAY_BUFFER_BINDING),
|
|
1248
|
+
`,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);e.activeTexture(e.TEXTURE0);const u=e.getParameter(e.TEXTURE_BINDING_2D);e.activeTexture(e.TEXTURE1);const g=e.getParameter(e.TEXTURE_BINDING_2D),I=e.isEnabled(e.BLEND),E=e.isEnabled(e.DEPTH_TEST),U=e.isEnabled(e.SCISSOR_TEST);let x=null,b=null,B=null,p=null,v=null,T=null,c=-1,w=!1,f=null,h=4,y=0,_=0,P=0,D=!1,S=!1;const m=new Uint8Array(4);try{x=e.createProgram(),e.attachShader(x,this._compileShader(e.VERTEX_SHADER,t)),e.attachShader(x,this._compileShader(e.FRAGMENT_SHADER,a)),e.linkProgram(x);const C=(R,K)=>{const M=e.createTexture();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,R,K),M};e.activeTexture(e.TEXTURE0),b=C(e.FLOAT,new Float32Array([1,.5,.25,1])),B=C(e.UNSIGNED_BYTE,new Uint8Array([51,102,153,255])),p=e.createTexture(),e.bindTexture(e.TEXTURE_2D,p),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,p,0),T=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,T),e.bufferData(e.ARRAY_BUFFER,new Float32Array([0]),e.STATIC_DRAW),S=e.getProgramParameter(x,e.LINK_STATUS),S&&(e.useProgram(x),e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,b),e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,B),e.uniform1i(e.getUniformLocation(x,"uF"),0),e.uniform1i(e.getUniformLocation(x,"uB"),1),c=e.getAttribLocation(x,"aId"),w=e.getVertexAttrib(c,e.VERTEX_ATTRIB_ARRAY_ENABLED),f=e.getVertexAttrib(c,e.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING),h=e.getVertexAttrib(c,e.VERTEX_ATTRIB_ARRAY_SIZE),y=e.getVertexAttrib(c,e.VERTEX_ATTRIB_ARRAY_TYPE),D=e.getVertexAttrib(c,e.VERTEX_ATTRIB_ARRAY_NORMALIZED),_=e.getVertexAttrib(c,e.VERTEX_ATTRIB_ARRAY_STRIDE),P=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,m),S=Math.abs(m[0]-51)<=2&&Math.abs(m[1]-51)<=2&&Math.abs(m[2]-38)<=2)}finally{c>=0&&(f&&(e.bindBuffer(e.ARRAY_BUFFER,f),e.vertexAttribPointer(c,h,y,D,_,P)),w?e.enableVertexAttribArray(c):e.disableVertexAttribArray(c)),v&&e.deleteFramebuffer(v),p&&e.deleteTexture(p),b&&e.deleteTexture(b),B&&e.deleteTexture(B),T&&e.deleteBuffer(T),x&&e.deleteProgram(x),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,g),e.activeTexture(i),I&&e.enable(e.BLEND),E&&e.enable(e.DEPTH_TEST),U&&e.enable(e.SCISSOR_TEST),e.viewport(r[0],r[1],r[2],r[3])}if(!S)throw new Error(`NeutrinoParticles (js-v1.1): WebGL1 vertex texture fetch smoke test failed (got ${m[0]},${m[1]},${m[2]}); WebGL2 or WebGL1 with working vertex float textures is required.`)}_initShader(){const e=this.gl,t=this._isWebGL1?vertexShaderSourceGL1:vertexShaderSource,a=this._isWebGL1?fragmentShaderSourceGL1:fragmentShaderSource,r=this._compileShader(e.VERTEX_SHADER,t),o=this._compileShader(e.FRAGMENT_SHADER,a);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))throw new Error("Shader link error: "+e.getProgramInfoLog(this._shaderProgram));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=[];for(let l=0;l<A.MAX_BATCH_TEXTURES;l++)this._uTextures.push(e.getUniformLocation(this._shaderProgram,`uTextures[${l}]`)),this._uTexRemaps.push(e.getUniformLocation(this._shaderProgram,`uTexRemaps[${l}]`))}_compileShader(e,t){const a=this.gl,r=a.createShader(e);if(a.shaderSource(r,t),a.compileShader(r),!a.getShaderParameter(r,a.COMPILE_STATUS)){const o=a.getShaderInfoLog(r);throw a.deleteShader(r),new Error("Shader compile error: "+o)}return r}};n(A,"MAX_BATCH_TEXTURES",8);let NeutrinoContext=A;class GamePlugin extends Phaser.Plugins.BasePlugin{constructor(){super(...arguments);n(this,"neutrino");n(this,"ctx");n(this,"texturesBasePath","")}init(t){if(t=Object.assign({texturesBasePath:"",generateNoise:!1},t),this.game.renderer.type!==Phaser.WEBGL)throw new Error("NeutrinoParticles (js-v1.1): a WebGL renderer is required (Canvas not supported).");const r=this.game.renderer.gl;this.texturesBasePath=t.texturesBasePath,this.neutrino=new Neutrino__namespace.Context,this.ctx=new NeutrinoContext(r,this.neutrino),t.generateNoise&&this.generateNoise()}start(){}stop(){}destroy(){this.ctx&&this.ctx.destroy(),this.neutrino=null,super.destroy()}loadNoise(t,a,r){this.ctx.initializeNoise(t,a||(()=>{}),r||(()=>{}))}generateNoise(){this.ctx.generateNoise()}}function noext(s){return s.replace(/\.[^/.]+$/,"")}class EffectModel{constructor(scene,scriptText,options){n(this,"gamePlugin");n(this,"scene");n(this,"effectModel");n(this,"textureFrames",[]);n(this,"texturesRemap",[]);n(this,"_numTexturesToLoadLeft",0);options=Object.assign({atlases:[]},options),this.gamePlugin=scene.plugins.get("neutrino"),this.scene=scene;const evalScript=`(function(ctx) {
|
|
1166
1249
|
`+scriptText+`
|
|
1167
1250
|
return new NeutrinoEffect(ctx);
|
|
1168
|
-
})(this.gamePlugin.neutrino);`;this.effectModel=eval(evalScript),this._startLoadTextures(options.atlases)}get ready(){return this._numTexturesToLoadLeft===0}glTexture(s){const e=this.textureFrames[s];return e?e.glTexture.webGLTexture:null}_startLoadTextures(s){const e=this.effectModel.textures.length;this._numTexturesToLoadLeft=e;for(let t=0;t<e;++t){const a=this.effectModel.textures[t],r=this.gamePlugin.texturesBasePath+a,o=noext(r);let l=this._findFrameInAtlases(s,a);if(l||(l=this._findFrameInAtlases(s,noext(a))),!l&&this.scene.sys.textures.exists(o)){const c=this.scene.sys.textures.get(o);l=c.get(c.firstFrame)}l?this._onTextureLoaded(t,l):(this.scene.load.once("filecomplete-image-"+o,((c,i)=>()=>{const u=this.scene.sys.textures.get(i);this._onTextureLoaded(c,u.get(u.firstFrame))})(t,o)),this.scene.load.image(o,r))}}_findFrameInAtlases(s,e){for(let t=0;t<s.length;++t){const a=s[t];if(!this.scene.sys.textures.exists(a))continue;const r=this.scene.sys.textures.get(a);if(r.has(e))return r.get(e)}return null}_onTextureLoaded(s,e){this.textureFrames[s]=e,this._numTexturesToLoadLeft--,this._numTexturesToLoadLeft===0&&this._initTexturesRemapIfNeeded()}_fullCover(s){return s.width===s.source.width&&s.height===s.source.height}_initTexturesRemapIfNeeded(){let s=!1;for(let e=0;e<this.textureFrames.length;++e)if(!this._fullCover(this.textureFrames[e])){s=!0;break}if(s)for(let e=0;e<this.textureFrames.length;++e){const t=this.textureFrames[e];this.texturesRemap[e]={x:t.u0,y:1-t.v1,width:t.u1-t.u0,height:t.v1-t.v0}}}}class NeutrinoFile extends Phaser.Loader.File{constructor(t,a){const{key:r,url:o,options:l,xhrSettings:c}=a;super(t,{type:"binary",extension:"js",responseType:"text",key:r,url:o,xhrSettings:c});n(this,"_options");this.cache=t.cacheManager.binary,this._options=l}onProcess(){this.state=Phaser.Loader.FILE_PROCESSING;const t=this.xhrLoader.response;this.data=new EffectModel(this.loader.scene,t,this._options),this.onProcessComplete()}}var Pause=(s=>(s[s.NO=0]="NO",s[s.BEFORE_UPDATE_OR_RENDER=1]="BEFORE_UPDATE_OR_RENDER",s[s.YES=2]="YES",s))(Pause||{});const RING_BUFFER_SIZE$1=3;class DataTextureManager{constructor(e,t,a,r){n(this,"textureWidth");n(this,"textureHeight");n(this,"_gl");n(this,"_floatView");n(this,"_textures",[]);n(this,"_currentIndex",0);const o=e.getParameter(e.MAX_TEXTURE_SIZE);if(a>o||r>o)throw new Error(`NeutrinoParticles: data texture ${a}x${r} exceeds GL MAX_TEXTURE_SIZE (${o}). Reduce effect particle capacity.`);this._gl=e,this.textureWidth=a,this.textureHeight=r,this._floatView=new Float32Array(t.buffer,t.byteOffset,t.length);for(let l=0;l<RING_BUFFER_SIZE$1;l++){const c=e.createTexture();e.bindTexture(e.TEXTURE_2D,c),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.RGBA32F,a,r,0,e.RGBA,e.FLOAT,null),this._textures.push(c)}e.bindTexture(e.TEXTURE_2D,null)}get currentTexture(){return this._textures[this._currentIndex]}uploadAndBind(e){const t=this._gl;t.activeTexture(t.TEXTURE0+e),t.bindTexture(t.TEXTURE_2D,this._textures[this._currentIndex]),t.pixelStorei(t.UNPACK_ALIGNMENT,4),t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texSubImage2D(t.TEXTURE_2D,0,0,0,this.textureWidth,this.textureHeight,t.RGBA,t.FLOAT,this._floatView)}advance(){this._currentIndex=(this._currentIndex+1)%RING_BUFFER_SIZE$1}destroy(){const e=this._gl;for(const t of this._textures)t&&e.deleteTexture(t);this._textures=[]}}class MetaTextureManager{constructor(e,t){n(this,"bytes");n(this,"_u32");this.bytes=new Uint8Array(e*t*4),this._u32=new Uint32Array(this.bytes.buffer)}build(e,t){const a=this._u32;for(let r=0;r<t;r++){const o=r*16,l=r*4;a[l]=e[o],a[l+1]=e[o+12],a[l+2]=e[o+13],a[l+3]=e[o+14]}}patchSlot(e,t,a){const r=this.bytes;let o=e*16;for(let l=0;l<t;l++)r[o]=a,o+=16}}const RING_BUFFER_SIZE=3;class DataTextureManagerGL1{constructor(e,t,a,r){n(this,"textureWidth");n(this,"textureHeight");n(this,"meta");n(this,"_gl");n(this,"_floatView");n(this,"_dataTextures",[]);n(this,"_metaTextures",[]);n(this,"_currentIndex",0);const o=e.getParameter(e.MAX_TEXTURE_SIZE);if(a>o||r>o)throw new Error(`NeutrinoParticles: data texture ${a}x${r} exceeds GL MAX_TEXTURE_SIZE (${o}). Reduce effect particle capacity.`);if(a*r>16777216)throw new Error(`NeutrinoParticles: data texture ${a}x${r} exceeds the WebGL1 render path texel cap (2^24). Reduce effect particle capacity.`);this._gl=e,this.textureWidth=a,this.textureHeight=r,this._floatView=new Float32Array(t.buffer,t.byteOffset,t.length),this.meta=new MetaTextureManager(a,r);const l=e.getParameter(e.ACTIVE_TEXTURE);e.activeTexture(e.TEXTURE0);const c=e.getParameter(e.TEXTURE_BINDING_2D);for(let i=0;i<RING_BUFFER_SIZE;i++)this._dataTextures.push(this._createTexture(e.FLOAT)),this._metaTextures.push(this._createTexture(e.UNSIGNED_BYTE));e.bindTexture(e.TEXTURE_2D,c),e.activeTexture(l)}get currentDataTexture(){return this._dataTextures[this._currentIndex]}get currentMetaTexture(){return this._metaTextures[this._currentIndex]}upload(e,t,a){const r=this._gl,o=this.textureWidth,l=Math.min(this.textureHeight,Math.ceil(e*4/o));if(l===0)return;const c=l*o*4;r.pixelStorei(r.UNPACK_FLIP_Y_WEBGL,!1),r.pixelStorei(r.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),r.pixelStorei(r.UNPACK_ALIGNMENT,4),r.activeTexture(r.TEXTURE0+t),r.bindTexture(r.TEXTURE_2D,this.currentDataTexture),r.texSubImage2D(r.TEXTURE_2D,0,0,0,o,l,r.RGBA,r.FLOAT,this._floatView.subarray(0,c)),r.activeTexture(r.TEXTURE0+a),r.bindTexture(r.TEXTURE_2D,this.currentMetaTexture),r.texSubImage2D(r.TEXTURE_2D,0,0,0,o,l,r.RGBA,r.UNSIGNED_BYTE,this.meta.bytes.subarray(0,c))}advance(){this._currentIndex=(this._currentIndex+1)%RING_BUFFER_SIZE}destroy(){const e=this._gl;for(const t of this._dataTextures)e.deleteTexture(t);for(const t of this._metaTextures)e.deleteTexture(t);this._dataTextures=[],this._metaTextures=[]}_createTexture(e){const t=this._gl,a=t.createTexture();return t.bindTexture(t.TEXTURE_2D,a),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureWidth,this.textureHeight,0,t.RGBA,e,null),a}}const DATA_TEXTURE_UNIT=0,META_TEXTURE_UNIT=1,PARTICLE_TEXTURE_START_UNIT=1,PARTICLE_TEXTURE_START_UNIT_GL1=2,FLOATS_PER_PARTICLE=16,BYTES_PER_PARTICLE=FLOATS_PER_PARTICLE*4,MAX_BATCHES=64;class DrawBatch{constructor(){n(this,"blendMode",0);n(this,"startParticle",0);n(this,"numParticles",0);n(this,"numTextures",0);n(this,"glTextures",new Array(NeutrinoContext.MAX_BATCH_TEXTURES).fill(null));n(this,"remaps",new Array(NeutrinoContext.MAX_BATCH_TEXTURES).fill(null))}reset(){this.blendMode=0,this.startParticle=0,this.numParticles=0,this.numTextures=0}}class NeutrinoRenderer{constructor(){n(this,"_orthoMatrix",new Float32Array(16));n(this,"_modelMatrix",new Float32Array(16));n(this,"_texSlotMap",new Map);n(this,"_batchPool");n(this,"_batchCount",0);this._batchPool=[];for(let e=0;e<MAX_BATCHES;e++)this._batchPool.push(new DrawBatch)}render(e,t,a,r,o,l,c){if(l===0)return;const i=e.gl,u=e.isWebGL1,_=e.maxBatchTextures,U=c.renderStyles,E=c.materials,I=u?t.meta:null;I&&I.build(r,l),this._batchCount=0;const x=this._texSlotMap;for(;this._batchPool.length<o.length;)this._batchPool.push(new DrawBatch);let b=0;for(;b<o.length;){const p=this._batchPool[this._batchCount];p.reset(),p.blendMode=this._resolveBlend(o[b].blendMode,E),p.startParticle=o[b].startParticleIndex,x.clear();let v=b;for(;v<o.length&&this._resolveBlend(o[v].blendMode,E)===p.blendMode;){const T=U[o[v].renderStyleIndex].textureIndices[0];if(!x.has(T)){if(x.size>=_)break;const f=x.size;x.set(T,f),p.glTextures[f]=c.glTextures[T]||null,p.remaps[f]=c.remaps[T]||null,p.numTextures=f+1}const d=x.get(T),w=o[v];if(I)I.patchSlot(w.startParticleIndex,w.numParticles,d);else for(let f=0;f<w.numParticles;f++){const h=(w.startParticleIndex+f)*BYTES_PER_PARTICLE,y=a.getUint32(h,!0);a.setUint32(h,y&4294967040|d,!0)}p.numParticles+=w.numParticles,v++}this._batchCount++,b=v}const B=i.isEnabled(i.SCISSOR_TEST);try{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){const g=t;g.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,g.textureWidth,g.textureHeight)}else{const g=t;g.uploadAndBind(DATA_TEXTURE_UNIT),i.uniform1i(e.uDataTexture,DATA_TEXTURE_UNIT),i.uniform1i(e.uDataTextureWidth,g.textureWidth)}i.uniform3f(e.uCameraRight,1,0,0),i.uniform3f(e.uCameraUp,0,-1,0),i.uniform3f(e.uCameraDir,0,0,-1);const p=c.viewportWidth,v=c.viewportHeight,T=c.zoom||1,d=this._orthoMatrix;d.fill(0),d[0]=2/p*T,d[5]=-2/v*T,d[10]=1,d[15]=1,d[12]=-1-2/p*T*c.scrollX,d[13]=1+2/v*T*c.scrollY,i.uniformMatrix4fv(e.uViewProjMatrix,!1,d);const w=v>0?p/v:1;e.uViewportAspect&&i.uniform1f(e.uViewportAspect,w),e.uWorldAlpha&&i.uniform1f(e.uWorldAlpha,c.worldAlpha);const f=c.model,h=this._modelMatrix;h[0]=f.a,h[1]=f.b,h[2]=0,h[3]=0,h[4]=f.c,h[5]=f.d,h[6]=0,h[7]=0,h[8]=0,h[9]=0,h[10]=1,h[11]=0,h[12]=f.tx,h[13]=f.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);const y=u?PARTICLE_TEXTURE_START_UNIT_GL1:PARTICLE_TEXTURE_START_UNIT;i.enable(i.BLEND);for(let g=0;g<this._batchCount;g++){const P=this._batchPool[g];this._applyBlendMode(i,P.blendMode);for(let m=0;m<P.numTextures;m++){const C=y+m;i.activeTexture(i.TEXTURE0+C),i.bindTexture(i.TEXTURE_2D,P.glTextures[m]),i.uniform1i(e.uTextures[m],C);const R=P.remaps[m];R?i.uniform4f(e.uTexRemaps[m],R.x,R.y,R.width,R.height):i.uniform4f(e.uTexRemaps[m],0,0,1,1)}const D=P.startParticle*6,S=P.numParticles*6;i.drawElements(i.TRIANGLES,S,e.indexType,D*(e.indexType===i.UNSIGNED_INT?4:2))}}finally{u?(i.disableVertexAttribArray(e.aIdLocation),i.bindBuffer(i.ARRAY_BUFFER,null),i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,null)):i.bindVertexArray(null),i.useProgram(null),B&&i.enable(i.SCISSOR_TEST)}}_resolveBlend(e,t){return t&&e>=0&&e<t.length?t[e]:e}_applyBlendMode(e,t){switch(t){default:case 0:e.blendFuncSeparate(e.ONE,e.ONE_MINUS_SRC_ALPHA,e.ONE,e.ONE_MINUS_SRC_ALPHA);break;case 1:e.blendFunc(e.ONE,e.ONE);break;case 2:e.blendFunc(e.DST_COLOR,e.ONE_MINUS_SRC_ALPHA);break}}}const sharedRenderer=new NeutrinoRenderer;class Effect extends Phaser.GameObjects.GameObject{constructor(t,a,r){r=Object.assign({position:[0,0,0],angle:0,scale:1,pause:Pause.BEFORE_UPDATE_OR_RENDER,generatorsPaused:!1},r||{});super(a,"Neutrino");n(this,"gamePlugin");n(this,"effectModel");n(this,"effect",null);n(this,"x",0);n(this,"y",0);n(this,"z",0);n(this,"angle",0);n(this,"rotation",0);n(this,"scaleX",1);n(this,"scaleY",1);n(this,"scrollFactorX",1);n(this,"scrollFactorY",1);n(this,"alpha",1);n(this,"depth",0);n(this,"blendMode",Phaser.BlendModes.NORMAL);n(this,"_dataTextureManager",null);n(this,"_worldPosition");n(this,"_worldScaledPosition");n(this,"_worldRotation",[0,0,0,1]);n(this,"_worldScale");n(this,"_tempMatrix1");n(this,"_tempMatrix2");n(this,"_unpauseOnUpdateRender");n(this,"_glTexturesScratch",[]);this.gamePlugin=a.plugins.get("neutrino"),this.effectModel=t,this.x=r.position[0],this.y=r.position[1],this.z=r.position[2],this.angle=r.angle,this.scaleX=r.scale,this.scaleY=r.scale,this._worldPosition=new Phaser.Math.Vector2,this._worldScaledPosition=[0,0,0],this._worldScale=1,this._tempMatrix1=new Phaser.GameObjects.Components.TransformMatrix,this._tempMatrix2=new Phaser.GameObjects.Components.TransformMatrix,this._unpauseOnUpdateRender=r.pause===Pause.BEFORE_UPDATE_OR_RENDER,this._updateWorldTransform();const o={paused:r.pause!==Pause.NO,generatorsPaused:r.generatorsPaused};this.effectModel&&(this.effect=this.effectModel.effectModel.createInstance(this._renderPosition(),this._renderRotation(),o),this._dataTextureManager=this.gamePlugin.ctx.isWebGL1?new DataTextureManagerGL1(this.gamePlugin.ctx.gl,this.effect.particleDataUint32,this.effect.dataTextureWidth,this.effect.dataTextureHeight):new DataTextureManager(this.gamePlugin.ctx.gl,this.effect.particleDataUint32,this.effect.dataTextureWidth,this.effect.dataTextureHeight),this.gamePlugin.ctx.ensureIndexBuffer(this.effectModel.effectModel.totalParticles))}get ready(){return this.effectModel!=null&&this.effectModel.ready&&this.effect!=null}preUpdate(t,a){this.ready&&(this._checkUnpauseOnUpdateRender()||this._updateWorldTransform(),this.effect.update(a/1e3,this._renderPosition(),this._renderRotation()))}renderWebGL(t,a,r){if(!this.ready||this.alpha<=0)return;this._checkUnpauseOnUpdateRender();const o=this.gamePlugin.ctx,l=this._dataTextureManager;this.effect.construct([0,0,-1]);const c=this.effect.renderInstructions,i=c._totalParticles;if(i===0)return;t.flush();const u=this.effectModel.effectModel.textures.length,_=this._glTexturesScratch;_.length=u;for(let E=0;E<u;++E)_[E]=this.effectModel.glTexture(E);const U=this._worldScale;try{sharedRenderer.render(o,l,this.effect.particleDataView,this.effect.particleDataUint32,c,i,{model:{a:U,b:0,c:0,d:U,tx:0,ty:0},viewportWidth:t.width,viewportHeight:t.height,scrollX:r.scrollX*this.scrollFactorX,scrollY:r.scrollY*this.scrollFactorY,zoom:r.zoom,worldAlpha:this.alpha,glTextures:_,remaps:this.effectModel.texturesRemap,renderStyles:this.effect.model.renderStyles,materials:this.effect.model.materials}),l.advance()}finally{t.pipelines.rebind()}}restart(t){this.ready&&(this._applyTransformOptions(t),this._updateWorldTransform(),this.effect.restart(this._renderPosition(),this._renderRotation()))}resetPosition(t){this.ready&&(this._applyTransformOptions(t),this._updateWorldTransform(),this.effect.resetPosition(this._renderPosition(),this._renderRotation()))}pause(){this.ready&&this.effect.pauseAllEmitters()}unpause(){this.ready&&this.effect.unpauseAllEmitters()}get paused(){return this.ready?this.effect.areAllEmittersPaused():!1}pauseGenerators(){this.ready&&this.effect.pauseGeneratorsInAllEmitters()}unpauseGenerators(){this.ready&&this.effect.unpauseGeneratorsInAllEmitters()}get generatorsPaused(){return this.ready?this.effect.areGeneratorsInAllEmittersPaused():!1}setPropertyInAllEmitters(t,a){this.ready&&this.effect.setPropertyInAllEmitters(t,a)}getNumParticles(){return this.ready?this.effect.getNumParticles():0}setScrollFactor(t,a){return this.scrollFactorX=t,this.scrollFactorY=a===void 0?t:a,this}setAlpha(t,a,r,o){return this.alpha=t===void 0?1:t,this}destroy(t){this._dataTextureManager&&(this._dataTextureManager.destroy(),this._dataTextureManager=null),super.destroy(t)}_applyTransformOptions(t){t&&(t.position&&(this.x=t.position[0],this.y=t.position[1],this.z=t.position[2]),t.angle!==void 0?(this.angle=t.angle,this.rotation=Phaser.Math.DegToRad(t.angle)):t.rotation!==void 0&&(this.rotation=t.rotation,this.angle=Phaser.Math.RadToDeg(t.rotation)))}_updateWorldTransform(){const t=(o,l)=>{if(!o)return;const c=this._tempMatrix2;c.applyITRS(o.x,o.y,o.rotation,o.scaleX,o.scaleY),c.multiply(l.matrix,l.matrix),l.angle+=o.angle,l.scale*=(o.scaleX+o.scaleY)*.5,t(o.parentContainer,l)},a={matrix:this._tempMatrix1.loadIdentity(),angle:this.angle,scale:(this.scaleX+this.scaleY)*.5};t(this.parentContainer,a),a.matrix.transformPoint(this.x,this.y,this._worldPosition),this._worldRotation=this.gamePlugin.neutrino.axisangle2quat_([0,0,1],a.angle),this._worldScale=a.scale;const r=this._worldScale!==0?1/this._worldScale:0;this._worldScaledPosition[0]=this._worldPosition.x*r,this._worldScaledPosition[1]=this._worldPosition.y*r,this._worldScaledPosition[2]=this.z*r}_renderPosition(){return this._worldScaledPosition}_renderRotation(){return this._worldRotation}_checkUnpauseOnUpdateRender(){return this._unpauseOnUpdateRender?(this.resetPosition(),this.unpause(),this._unpauseOnUpdateRender=!1,!0):!1}}class PerspectiveProjection{constructor(e){n(this,"_angleTan",0);n(this,"_screenWidth",0);n(this,"_screenPosX",0);n(this,"_screenPosY",0);n(this,"_z",0);n(this,"_near",0);this.horizontalAngle=e}set horizontalAngle(e){this._angleTan=Math.tan(e*.5/180*Math.PI)}setScreenFrame(e){this._screenWidth=e.width,this._screenPosX=e.x+e.width*.5,this._screenPosY=e.y+e.height*.5,this._z=this._screenWidth*.5/this._angleTan,this._near=this._z*.99}transformPosition(e,t){if(t[2]>this._near)return!1;const a=this._getScale(t);return e[0]=(t[0]-this._screenPosX)*a+this._screenPosX,e[1]=(t[1]-this._screenPosY)*a+this._screenPosY,!0}transformSize(e,t,a){const r=this._getScale(t);e[0]=a[0]*r,e[1]=a[1]*r}_getScale(e){return this._z/(this._z-e[2])}}let _installed=!1;function installPlugin(){_installed||(_installed=!0,Phaser.Loader.FileTypesManager.register("neutrino",function(s,e,t,a){if(Array.isArray(s))for(const r of s)this.addFile(new NeutrinoFile(this,r));else typeof s=="object"?this.addFile(new NeutrinoFile(this,s)):this.addFile(new NeutrinoFile(this,{key:s,url:e,options:t,xhrSettings:a}));return this}),Phaser.GameObjects.GameObjectFactory.register("neutrino",function(s,e){const t=new Effect(s,this.scene,e);return this.displayList.add(t),this.updateList.add(t),t}),Phaser.GameObjects.GameObjectCreator.register("neutrino",function(s){const e=new Effect(s.effectModel,this.scene,s);return s.add!==!1&&(this.scene.sys.displayList.add(e),this.scene.sys.updateList.add(e)),e}))}installPlugin();exports.DataTextureManager=DataTextureManager;exports.Effect=Effect;exports.EffectModel=EffectModel;exports.GamePlugin=GamePlugin;exports.NeutrinoContext=NeutrinoContext;exports.NeutrinoFile=NeutrinoFile;exports.NeutrinoRenderer=NeutrinoRenderer;exports.Pause=Pause;exports.PerspectiveProjection=PerspectiveProjection;exports.installPlugin=installPlugin;
|
|
1251
|
+
})(this.gamePlugin.neutrino);`;this.effectModel=eval(evalScript),this._startLoadTextures(options.atlases)}get ready(){return this._numTexturesToLoadLeft===0}glTexture(s){const e=this.textureFrames[s];return e?e.glTexture.webGLTexture:null}_startLoadTextures(s){const e=this.effectModel.textures.length;this._numTexturesToLoadLeft=e;for(let t=0;t<e;++t){const a=this.effectModel.textures[t],r=this.gamePlugin.texturesBasePath+a,o=noext(r);let l=this._findFrameInAtlases(s,a);if(l||(l=this._findFrameInAtlases(s,noext(a))),!l&&this.scene.sys.textures.exists(o)){const d=this.scene.sys.textures.get(o);l=d.get(d.firstFrame)}l?this._onTextureLoaded(t,l):(this.scene.load.once("filecomplete-image-"+o,((d,i)=>()=>{const u=this.scene.sys.textures.get(i);this._onTextureLoaded(d,u.get(u.firstFrame))})(t,o)),this.scene.load.image(o,r))}}_findFrameInAtlases(s,e){for(let t=0;t<s.length;++t){const a=s[t];if(!this.scene.sys.textures.exists(a))continue;const r=this.scene.sys.textures.get(a);if(r.has(e))return r.get(e)}return null}_onTextureLoaded(s,e){this.textureFrames[s]=e,this._numTexturesToLoadLeft--,this._numTexturesToLoadLeft===0&&this._initTexturesRemapIfNeeded()}_fullCover(s){return s.width===s.source.width&&s.height===s.source.height}_initTexturesRemapIfNeeded(){let s=!1;for(let e=0;e<this.textureFrames.length;++e)if(!this._fullCover(this.textureFrames[e])){s=!0;break}if(s)for(let e=0;e<this.textureFrames.length;++e){const t=this.textureFrames[e];this.texturesRemap[e]={x:t.u0,y:1-t.v1,width:t.u1-t.u0,height:t.v1-t.v0}}}}class NeutrinoFile extends Phaser.Loader.File{constructor(t,a){const{key:r,url:o,options:l,xhrSettings:d}=a;super(t,{type:"binary",extension:"js",responseType:"text",key:r,url:o,xhrSettings:d});n(this,"_options");this.cache=t.cacheManager.binary,this._options=l}onProcess(){this.state=Phaser.Loader.FILE_PROCESSING;const t=this.xhrLoader.response;this.data=new EffectModel(this.loader.scene,t,this._options),this.onProcessComplete()}}var Pause=(s=>(s[s.NO=0]="NO",s[s.BEFORE_UPDATE_OR_RENDER=1]="BEFORE_UPDATE_OR_RENDER",s[s.YES=2]="YES",s))(Pause||{});const RING_BUFFER_SIZE$1=3;class DataTextureManager{constructor(e,t,a,r){n(this,"textureWidth");n(this,"textureHeight");n(this,"_gl");n(this,"_floatView");n(this,"_textures",[]);n(this,"_currentIndex",0);const o=e.getParameter(e.MAX_TEXTURE_SIZE);if(a>o||r>o)throw new Error(`NeutrinoParticles: data texture ${a}x${r} exceeds GL MAX_TEXTURE_SIZE (${o}). Reduce effect particle capacity.`);this._gl=e,this.textureWidth=a,this.textureHeight=r,this._floatView=new Float32Array(t.buffer,t.byteOffset,t.length);for(let l=0;l<RING_BUFFER_SIZE$1;l++){const d=e.createTexture();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(e.TEXTURE_2D,0,e.RGBA32F,a,r,0,e.RGBA,e.FLOAT,null),this._textures.push(d)}e.bindTexture(e.TEXTURE_2D,null)}get currentTexture(){return this._textures[this._currentIndex]}uploadAndBind(e){const t=this._gl;t.activeTexture(t.TEXTURE0+e),t.bindTexture(t.TEXTURE_2D,this._textures[this._currentIndex]),t.pixelStorei(t.UNPACK_ALIGNMENT,4),t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texSubImage2D(t.TEXTURE_2D,0,0,0,this.textureWidth,this.textureHeight,t.RGBA,t.FLOAT,this._floatView)}advance(){this._currentIndex=(this._currentIndex+1)%RING_BUFFER_SIZE$1}destroy(){const e=this._gl;for(const t of this._textures)t&&e.deleteTexture(t);this._textures=[]}}class MetaTextureManager{constructor(e,t){n(this,"bytes");n(this,"_u32");this.bytes=new Uint8Array(e*t*4),this._u32=new Uint32Array(this.bytes.buffer)}build(e,t){const a=this._u32;for(let r=0;r<t;r++){const o=r*16,l=r*4;a[l]=e[o],a[l+1]=e[o+12],a[l+2]=e[o+13],a[l+3]=e[o+14]}}patchSlot(e,t,a){const r=this.bytes;let o=e*16;for(let l=0;l<t;l++)r[o]=a,o+=16}}const RING_BUFFER_SIZE=3;class DataTextureManagerGL1{constructor(e,t,a,r){n(this,"textureWidth");n(this,"textureHeight");n(this,"meta");n(this,"_gl");n(this,"_floatView");n(this,"_dataTextures",[]);n(this,"_metaTextures",[]);n(this,"_currentIndex",0);const o=e.getParameter(e.MAX_TEXTURE_SIZE);if(a>o||r>o)throw new Error(`NeutrinoParticles: data texture ${a}x${r} exceeds GL MAX_TEXTURE_SIZE (${o}). Reduce effect particle capacity.`);if(a*r>16777216)throw new Error(`NeutrinoParticles: data texture ${a}x${r} exceeds the WebGL1 render path texel cap (2^24). Reduce effect particle capacity.`);this._gl=e,this.textureWidth=a,this.textureHeight=r,this._floatView=new Float32Array(t.buffer,t.byteOffset,t.length),this.meta=new MetaTextureManager(a,r);const l=e.getParameter(e.ACTIVE_TEXTURE);e.activeTexture(e.TEXTURE0);const d=e.getParameter(e.TEXTURE_BINDING_2D);for(let i=0;i<RING_BUFFER_SIZE;i++)this._dataTextures.push(this._createTexture(e.FLOAT)),this._metaTextures.push(this._createTexture(e.UNSIGNED_BYTE));e.bindTexture(e.TEXTURE_2D,d),e.activeTexture(l)}get currentDataTexture(){return this._dataTextures[this._currentIndex]}get currentMetaTexture(){return this._metaTextures[this._currentIndex]}upload(e,t,a){const r=this._gl,o=this.textureWidth,l=Math.min(this.textureHeight,Math.ceil(e*4/o));if(l===0)return;const d=l*o*4;r.pixelStorei(r.UNPACK_FLIP_Y_WEBGL,!1),r.pixelStorei(r.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),r.pixelStorei(r.UNPACK_ALIGNMENT,4),r.activeTexture(r.TEXTURE0+t),r.bindTexture(r.TEXTURE_2D,this.currentDataTexture),r.texSubImage2D(r.TEXTURE_2D,0,0,0,o,l,r.RGBA,r.FLOAT,this._floatView.subarray(0,d)),r.activeTexture(r.TEXTURE0+a),r.bindTexture(r.TEXTURE_2D,this.currentMetaTexture),r.texSubImage2D(r.TEXTURE_2D,0,0,0,o,l,r.RGBA,r.UNSIGNED_BYTE,this.meta.bytes.subarray(0,d))}advance(){this._currentIndex=(this._currentIndex+1)%RING_BUFFER_SIZE}destroy(){const e=this._gl;for(const t of this._dataTextures)e.deleteTexture(t);for(const t of this._metaTextures)e.deleteTexture(t);this._dataTextures=[],this._metaTextures=[]}_createTexture(e){const t=this._gl,a=t.createTexture();return t.bindTexture(t.TEXTURE_2D,a),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureWidth,this.textureHeight,0,t.RGBA,e,null),a}}const DATA_TEXTURE_UNIT=0,META_TEXTURE_UNIT=1,PARTICLE_TEXTURE_START_UNIT=1,PARTICLE_TEXTURE_START_UNIT_GL1=2,FLOATS_PER_PARTICLE=16,BYTES_PER_PARTICLE=FLOATS_PER_PARTICLE*4,MAX_BATCHES=64;class DrawBatch{constructor(){n(this,"blendMode",0);n(this,"startParticle",0);n(this,"numParticles",0);n(this,"numTextures",0);n(this,"glTextures",new Array(NeutrinoContext.MAX_BATCH_TEXTURES).fill(null));n(this,"remaps",new Array(NeutrinoContext.MAX_BATCH_TEXTURES).fill(null))}reset(){this.blendMode=0,this.startParticle=0,this.numParticles=0,this.numTextures=0}}class NeutrinoRenderer{constructor(){n(this,"_orthoMatrix",new Float32Array(16));n(this,"_modelMatrix",new Float32Array(16));n(this,"_texSlotMap",new Map);n(this,"_batchPool");n(this,"_batchCount",0);this._batchPool=[];for(let e=0;e<MAX_BATCHES;e++)this._batchPool.push(new DrawBatch)}render(e,t,a,r,o,l,d){if(l===0)return;const i=e.gl,u=e.isWebGL1,g=e.maxBatchTextures,I=d.renderStyles,E=d.materials,U=u?t.meta:null;U&&U.build(r,l),this._batchCount=0;const x=this._texSlotMap;for(;this._batchPool.length<o.length;)this._batchPool.push(new DrawBatch);let b=0;for(;b<o.length;){const p=this._batchPool[this._batchCount];p.reset(),p.blendMode=this._resolveBlend(o[b].blendMode,E),p.startParticle=o[b].startParticleIndex,x.clear();let v=b;for(;v<o.length&&this._resolveBlend(o[v].blendMode,E)===p.blendMode;){const T=I[o[v].renderStyleIndex].textureIndices[0];if(!x.has(T)){if(x.size>=g)break;const f=x.size;x.set(T,f),p.glTextures[f]=d.glTextures[T]||null,p.remaps[f]=d.remaps[T]||null,p.numTextures=f+1}const c=x.get(T),w=o[v];if(U)U.patchSlot(w.startParticleIndex,w.numParticles,c);else for(let f=0;f<w.numParticles;f++){const h=(w.startParticleIndex+f)*BYTES_PER_PARTICLE,y=a.getUint32(h,!0);a.setUint32(h,y&4294967040|c,!0)}p.numParticles+=w.numParticles,v++}this._batchCount++,b=v}const B=i.isEnabled(i.SCISSOR_TEST);try{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){const _=t;_.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,_.textureWidth,_.textureHeight)}else{const _=t;_.uploadAndBind(DATA_TEXTURE_UNIT),i.uniform1i(e.uDataTexture,DATA_TEXTURE_UNIT),i.uniform1i(e.uDataTextureWidth,_.textureWidth)}i.uniform3f(e.uCameraRight,1,0,0),i.uniform3f(e.uCameraUp,0,-1,0),i.uniform3f(e.uCameraDir,0,0,-1);const p=d.viewportWidth,v=d.viewportHeight,T=d.zoom||1,c=this._orthoMatrix;c.fill(0),c[0]=2/p*T,c[5]=-2/v*T,c[10]=1,c[15]=1,c[12]=-1-2/p*T*d.scrollX,c[13]=1+2/v*T*d.scrollY,i.uniformMatrix4fv(e.uViewProjMatrix,!1,c);const w=v>0?p/v:1;e.uViewportAspect&&i.uniform1f(e.uViewportAspect,w),e.uWorldAlpha&&i.uniform1f(e.uWorldAlpha,d.worldAlpha);const f=d.model,h=this._modelMatrix;h[0]=f.a,h[1]=f.b,h[2]=0,h[3]=0,h[4]=f.c,h[5]=f.d,h[6]=0,h[7]=0,h[8]=0,h[9]=0,h[10]=1,h[11]=0,h[12]=f.tx,h[13]=f.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);const y=u?PARTICLE_TEXTURE_START_UNIT_GL1:PARTICLE_TEXTURE_START_UNIT;i.enable(i.BLEND);for(let _=0;_<this._batchCount;_++){const P=this._batchPool[_];this._applyBlendMode(i,P.blendMode);for(let m=0;m<P.numTextures;m++){const C=y+m;i.activeTexture(i.TEXTURE0+C),i.bindTexture(i.TEXTURE_2D,P.glTextures[m]),i.uniform1i(e.uTextures[m],C);const R=P.remaps[m];R?i.uniform4f(e.uTexRemaps[m],R.x,R.y,R.width,R.height):i.uniform4f(e.uTexRemaps[m],0,0,1,1)}const D=P.startParticle*6,S=P.numParticles*6;i.drawElements(i.TRIANGLES,S,e.indexType,D*(e.indexType===i.UNSIGNED_INT?4:2))}}finally{u?(i.disableVertexAttribArray(e.aIdLocation),i.bindBuffer(i.ARRAY_BUFFER,null),i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,null)):i.bindVertexArray(null),i.useProgram(null),B&&i.enable(i.SCISSOR_TEST)}}_resolveBlend(e,t){return t&&e>=0&&e<t.length?t[e]:e}_applyBlendMode(e,t){switch(t){default:case 0:e.blendFuncSeparate(e.ONE,e.ONE_MINUS_SRC_ALPHA,e.ONE,e.ONE_MINUS_SRC_ALPHA);break;case 1:e.blendFunc(e.ONE,e.ONE);break;case 2:e.blendFunc(e.DST_COLOR,e.ONE_MINUS_SRC_ALPHA);break}}}const sharedRenderer=new NeutrinoRenderer;class Effect extends Phaser.GameObjects.GameObject{constructor(t,a,r){r=Object.assign({position:[0,0,0],angle:0,scale:1,pause:Pause.BEFORE_UPDATE_OR_RENDER,generatorsPaused:!1},r||{});super(a,"Neutrino");n(this,"gamePlugin");n(this,"effectModel");n(this,"effect",null);n(this,"x",0);n(this,"y",0);n(this,"z",0);n(this,"angle",0);n(this,"rotation",0);n(this,"scaleX",1);n(this,"scaleY",1);n(this,"scrollFactorX",1);n(this,"scrollFactorY",1);n(this,"alpha",1);n(this,"depth",0);n(this,"blendMode",Phaser.BlendModes.NORMAL);n(this,"_dataTextureManager",null);n(this,"_worldPosition");n(this,"_worldScaledPosition");n(this,"_worldRotation",[0,0,0,1]);n(this,"_worldScale");n(this,"_tempMatrix1");n(this,"_tempMatrix2");n(this,"_unpauseOnUpdateRender");n(this,"_glTexturesScratch",[]);this.gamePlugin=a.plugins.get("neutrino"),this.effectModel=t,this.x=r.position[0],this.y=r.position[1],this.z=r.position[2],this.angle=r.angle,this.scaleX=r.scale,this.scaleY=r.scale,this._worldPosition=new Phaser.Math.Vector2,this._worldScaledPosition=[0,0,0],this._worldScale=1,this._tempMatrix1=new Phaser.GameObjects.Components.TransformMatrix,this._tempMatrix2=new Phaser.GameObjects.Components.TransformMatrix,this._unpauseOnUpdateRender=r.pause===Pause.BEFORE_UPDATE_OR_RENDER,this._updateWorldTransform();const o={paused:r.pause!==Pause.NO,generatorsPaused:r.generatorsPaused};this.effectModel&&(this.effect=this.effectModel.effectModel.createInstance(this._renderPosition(),this._renderRotation(),o),this._dataTextureManager=this.gamePlugin.ctx.isWebGL1?new DataTextureManagerGL1(this.gamePlugin.ctx.gl,this.effect.particleDataUint32,this.effect.dataTextureWidth,this.effect.dataTextureHeight):new DataTextureManager(this.gamePlugin.ctx.gl,this.effect.particleDataUint32,this.effect.dataTextureWidth,this.effect.dataTextureHeight),this.gamePlugin.ctx.ensureIndexBuffer(this.effectModel.effectModel.totalParticles))}get ready(){return this.effectModel!=null&&this.effectModel.ready&&this.effect!=null}preUpdate(t,a){this.ready&&(this._checkUnpauseOnUpdateRender()||this._updateWorldTransform(),this.effect.update(a/1e3,this._renderPosition(),this._renderRotation()))}renderWebGL(t,a,r){if(!this.ready||this.alpha<=0)return;this._checkUnpauseOnUpdateRender();const o=this.gamePlugin.ctx,l=this._dataTextureManager;this.effect.construct([0,0,-1]);const d=this.effect.renderInstructions,i=d._totalParticles;if(i===0)return;t.flush();const u=this.effectModel.effectModel.textures.length,g=this._glTexturesScratch;g.length=u;for(let E=0;E<u;++E)g[E]=this.effectModel.glTexture(E);const I=this._worldScale;try{sharedRenderer.render(o,l,this.effect.particleDataView,this.effect.particleDataUint32,d,i,{model:{a:I,b:0,c:0,d:I,tx:0,ty:0},viewportWidth:t.width,viewportHeight:t.height,scrollX:r.scrollX*this.scrollFactorX,scrollY:r.scrollY*this.scrollFactorY,zoom:r.zoom,worldAlpha:this.alpha,glTextures:g,remaps:this.effectModel.texturesRemap,renderStyles:this.effect.model.renderStyles,materials:this.effect.model.materials}),l.advance()}finally{t.pipelines.rebind()}}restart(t){this.ready&&(this._applyTransformOptions(t),this._updateWorldTransform(),this.effect.restart(this._renderPosition(),this._renderRotation()))}resetPosition(t){this.ready&&(this._applyTransformOptions(t),this._updateWorldTransform(),this.effect.resetPosition(this._renderPosition(),this._renderRotation()))}pause(){this.ready&&this.effect.pauseAllEmitters()}unpause(){this.ready&&this.effect.unpauseAllEmitters()}get paused(){return this.ready?this.effect.areAllEmittersPaused():!1}pauseGenerators(){this.ready&&this.effect.pauseGeneratorsInAllEmitters()}unpauseGenerators(){this.ready&&this.effect.unpauseGeneratorsInAllEmitters()}get generatorsPaused(){return this.ready?this.effect.areGeneratorsInAllEmittersPaused():!1}setPropertyInAllEmitters(t,a){this.ready&&this.effect.setPropertyInAllEmitters(t,a)}getNumParticles(){return this.ready?this.effect.getNumParticles():0}setScrollFactor(t,a){return this.scrollFactorX=t,this.scrollFactorY=a===void 0?t:a,this}setAlpha(t,a,r,o){return this.alpha=t===void 0?1:t,this}destroy(t){this._dataTextureManager&&(this._dataTextureManager.destroy(),this._dataTextureManager=null),super.destroy(t)}_applyTransformOptions(t){t&&(t.position&&(this.x=t.position[0],this.y=t.position[1],this.z=t.position[2]),t.angle!==void 0?(this.angle=t.angle,this.rotation=Phaser.Math.DegToRad(t.angle)):t.rotation!==void 0&&(this.rotation=t.rotation,this.angle=Phaser.Math.RadToDeg(t.rotation)))}_updateWorldTransform(){const t=(o,l)=>{if(!o)return;const d=this._tempMatrix2;d.applyITRS(o.x,o.y,o.rotation,o.scaleX,o.scaleY),d.multiply(l.matrix,l.matrix),l.angle+=o.angle,l.scale*=(o.scaleX+o.scaleY)*.5,t(o.parentContainer,l)},a={matrix:this._tempMatrix1.loadIdentity(),angle:this.angle,scale:(this.scaleX+this.scaleY)*.5};t(this.parentContainer,a),a.matrix.transformPoint(this.x,this.y,this._worldPosition),this._worldRotation=this.gamePlugin.neutrino.axisangle2quat_([0,0,1],a.angle),this._worldScale=a.scale;const r=this._worldScale!==0?1/this._worldScale:0;this._worldScaledPosition[0]=this._worldPosition.x*r,this._worldScaledPosition[1]=this._worldPosition.y*r,this._worldScaledPosition[2]=this.z*r}_renderPosition(){return this._worldScaledPosition}_renderRotation(){return this._worldRotation}_checkUnpauseOnUpdateRender(){return this._unpauseOnUpdateRender?(this.resetPosition(),this.unpause(),this._unpauseOnUpdateRender=!1,!0):!1}}class PerspectiveProjection{constructor(e){n(this,"_angleTan",0);n(this,"_screenWidth",0);n(this,"_screenPosX",0);n(this,"_screenPosY",0);n(this,"_z",0);n(this,"_near",0);this.horizontalAngle=e}set horizontalAngle(e){this._angleTan=Math.tan(e*.5/180*Math.PI)}setScreenFrame(e){this._screenWidth=e.width,this._screenPosX=e.x+e.width*.5,this._screenPosY=e.y+e.height*.5,this._z=this._screenWidth*.5/this._angleTan,this._near=this._z*.99}transformPosition(e,t){if(t[2]>this._near)return!1;const a=this._getScale(t);return e[0]=(t[0]-this._screenPosX)*a+this._screenPosX,e[1]=(t[1]-this._screenPosY)*a+this._screenPosY,!0}transformSize(e,t,a){const r=this._getScale(t);e[0]=a[0]*r,e[1]=a[1]*r}_getScale(e){return this._z/(this._z-e[2])}}let _installed=!1;function installPlugin(){_installed||(_installed=!0,Phaser.Loader.FileTypesManager.register("neutrino",function(s,e,t,a){if(Array.isArray(s))for(const r of s)this.addFile(new NeutrinoFile(this,r));else typeof s=="object"?this.addFile(new NeutrinoFile(this,s)):this.addFile(new NeutrinoFile(this,{key:s,url:e,options:t,xhrSettings:a}));return this}),Phaser.GameObjects.GameObjectFactory.register("neutrino",function(s,e){const t=new Effect(s,this.scene,e);return this.displayList.add(t),this.updateList.add(t),t}),Phaser.GameObjects.GameObjectCreator.register("neutrino",function(s){const e=new Effect(s.effectModel,this.scene,s);return s.add!==!1&&(this.scene.sys.displayList.add(e),this.scene.sys.updateList.add(e)),e}))}installPlugin();exports.DataTextureManager=DataTextureManager;exports.Effect=Effect;exports.EffectModel=EffectModel;exports.GamePlugin=GamePlugin;exports.NeutrinoContext=NeutrinoContext;exports.NeutrinoFile=NeutrinoFile;exports.NeutrinoRenderer=NeutrinoRenderer;exports.Pause=Pause;exports.PerspectiveProjection=PerspectiveProjection;exports.installPlugin=installPlugin;
|
|
1169
1252
|
//# sourceMappingURL=neutrinoparticles.js-v1.1-phaser.cjs.js.map
|