@neutrinoparticles/js-v1.1-phaser 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -1
- package/README.md +37 -0
- package/dist/Effect.d.ts +11 -1
- package/dist/NeutrinoRenderer.d.ts +8 -0
- package/dist/PerspectiveProjection.d.ts +10 -0
- package/dist/neutrinoparticles.js-v1.1-phaser.cjs.js +82 -20
- package/dist/neutrinoparticles.js-v1.1-phaser.cjs.js.map +1 -1
- package/dist/neutrinoparticles.js-v1.1-phaser.d.ts +37 -1
- package/dist/neutrinoparticles.js-v1.1-phaser.es.js +211 -106
- package/dist/neutrinoparticles.js-v1.1-phaser.es.js.map +1 -1
- package/dist/neutrinoparticles.js-v1.1-phaser.umd.js +82 -20
- package/dist/neutrinoparticles.js-v1.1-phaser.umd.js.map +1 -1
- package/dist/types.d.ts +12 -0
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## [1.0
|
|
3
|
+
## [1.1.0] - 2026-08-03
|
|
4
|
+
|
|
5
|
+
- Emitter properties can now be **read** as well as written: `getEmitterPropertyValue()`, `hasEmitterProperty()` and `getEmitterProperties()` (which lists every property an effect exposes, with its live value). `setPropertyInEmitter()`, for addressing a single emitter by name, is now available on the effect too
|
|
4
6
|
|
|
5
7
|
- 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.
|
|
8
|
+
- Added perspective projection (Projection3D) support, matching the PIXI and Phaser 4 integrations: pass `projection: new PhaserNeutrino.PerspectiveProjection(angle)` in the effect options and particles scale with their distance from the camera. Particles that cross the near plane are discarded as whole quads.
|
|
6
9
|
- 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
10
|
- Emitter-anchored strips no longer show a brief mis-oriented sliver at the emitter end right after a new particle spawns.
|
|
8
11
|
- 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
12
|
|
|
13
|
+
## [1.0.1] - 2026-07-25
|
|
14
|
+
|
|
15
|
+
- 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.
|
|
16
|
+
- 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).
|
|
17
|
+
- Emitter-anchored strips no longer show a brief mis-oriented sliver at the emitter end right after a new particle spawns.
|
|
18
|
+
- 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).
|
package/README.md
CHANGED
|
@@ -187,10 +187,41 @@ effect.unpause();
|
|
|
187
187
|
Control exposed emitter properties at runtime. Properties are defined in Emitter Guide or Emitter Scheme in the Editor.
|
|
188
188
|
|
|
189
189
|
```javascript
|
|
190
|
+
// Write to every emitter that declares the property...
|
|
190
191
|
effect.setPropertyInAllEmitters('MyParticlesPerSecond', 100);
|
|
191
192
|
effect.setPropertyInAllEmitters('MyColor', [1.0, 0.5, 0.2]);
|
|
193
|
+
|
|
194
|
+
// ...or address a single emitter by name.
|
|
195
|
+
effect.setPropertyInEmitter('Sparks', 'MyColor', [1.0, 0.5, 0.2]);
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Read the current values back. A scalar property returns a `number`, a vector
|
|
199
|
+
property returns a `number[]`, and an unknown property returns `undefined`:
|
|
200
|
+
|
|
201
|
+
```javascript
|
|
202
|
+
effect.getEmitterPropertyValue('Sparks', 'MyColor'); // [1.0, 0.5, 0.2]
|
|
203
|
+
effect.getEmitterPropertyValue('MyParticlesPerSecond'); // 100 — first emitter with it
|
|
204
|
+
|
|
205
|
+
effect.hasEmitterProperty('Sparks', 'MyColor'); // true
|
|
206
|
+
effect.hasEmitterProperty('NoSuchProperty'); // false
|
|
192
207
|
```
|
|
193
208
|
|
|
209
|
+
Discover what an effect exposes without knowing the names up front:
|
|
210
|
+
|
|
211
|
+
```javascript
|
|
212
|
+
for (const p of effect.getEmitterProperties()) {
|
|
213
|
+
// { emitterName: 'Sparks', name: 'MyColor', arity: 3, value: [1, 0.5, 0.2] }
|
|
214
|
+
console.log(p.emitterName, p.name, p.arity, p.value);
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Values are read live from the simulation buffer at call time.
|
|
219
|
+
|
|
220
|
+
> **Use only the documented methods above.** Exported effects are minified, and
|
|
221
|
+
> the internal property names/objects they contain (`_globParamMeta`, or whatever
|
|
222
|
+
> short name it was mangled to) are not a stable API — they change between editor
|
|
223
|
+
> versions and differ between commercial and non-commercial exports.
|
|
224
|
+
|
|
194
225
|
## Number of Particles
|
|
195
226
|
|
|
196
227
|
```javascript
|
|
@@ -203,6 +234,12 @@ const numParticles = effect.getNumParticles();
|
|
|
203
234
|
- **No particles visible:** Make sure the export target in the editor is set to JavaScript v1.1. Verify `texturesBasePath` points to the correct textures directory.
|
|
204
235
|
- **Turbulence not working:** Set `generateNoise: true` in the plugin config, or call the plugin's `generateNoise()` before creating effects that use noise.
|
|
205
236
|
|
|
237
|
+
## HDR Bloom (optional add-on)
|
|
238
|
+
|
|
239
|
+
The scene-preserving HDR glow that matches the editor preview is currently available for
|
|
240
|
+
**PIXI.js** ([`bloom-v1.1-pixi7`](../bloom-pixi7) / [`bloom-v1.1-pixi8`](../bloom-pixi8)) and
|
|
241
|
+
**MonoGame**. A Phaser bloom add-on is not available yet.
|
|
242
|
+
|
|
206
243
|
## Documentation
|
|
207
244
|
|
|
208
245
|
Full documentation at [neutrinoparticles.com](https://neutrinoparticles.com/en/docs/199).
|
package/dist/Effect.d.ts
CHANGED
|
@@ -2,13 +2,15 @@ import Phaser from 'phaser';
|
|
|
2
2
|
import { Pause, Vec2, Vec3 } from './types';
|
|
3
3
|
import { GamePlugin } from './GamePlugin';
|
|
4
4
|
import { EffectModel } from './EffectModel';
|
|
5
|
-
import { NeutrinoSystem } from './types';
|
|
5
|
+
import { NeutrinoEmitterProperty, NeutrinoSystem } from './types';
|
|
6
|
+
import { PerspectiveProjection } from './PerspectiveProjection';
|
|
6
7
|
export interface EffectOptions {
|
|
7
8
|
position?: Vec3;
|
|
8
9
|
angle?: number;
|
|
9
10
|
scale?: number;
|
|
10
11
|
pause?: Pause;
|
|
11
12
|
generatorsPaused?: boolean;
|
|
13
|
+
projection?: PerspectiveProjection;
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
14
16
|
* A NeutrinoParticles effect on a Phaser scene (JS v1.1 runtime).
|
|
@@ -34,6 +36,8 @@ export declare class Effect extends Phaser.GameObjects.GameObject {
|
|
|
34
36
|
alpha: number;
|
|
35
37
|
depth: number;
|
|
36
38
|
blendMode: number;
|
|
39
|
+
/** Optional v1.0-parity perspective projection (Projection3D). */
|
|
40
|
+
projection?: PerspectiveProjection;
|
|
37
41
|
private _dataTextureManager;
|
|
38
42
|
private _worldPosition;
|
|
39
43
|
private _worldScaledPosition;
|
|
@@ -64,6 +68,12 @@ export declare class Effect extends Phaser.GameObjects.GameObject {
|
|
|
64
68
|
unpauseGenerators(): void;
|
|
65
69
|
get generatorsPaused(): boolean;
|
|
66
70
|
setPropertyInAllEmitters(name: string, value: Vec3 | Vec2 | number): void;
|
|
71
|
+
setPropertyInEmitter(emitterName: string, name: string, value: Vec3 | Vec2 | number): void;
|
|
72
|
+
getEmitterPropertyValue(name: string): number | number[] | undefined;
|
|
73
|
+
getEmitterPropertyValue(emitterName: string, name: string): number | number[] | undefined;
|
|
74
|
+
hasEmitterProperty(name: string): boolean;
|
|
75
|
+
hasEmitterProperty(emitterName: string, name: string): boolean;
|
|
76
|
+
getEmitterProperties(): NeutrinoEmitterProperty[];
|
|
67
77
|
getNumParticles(): number;
|
|
68
78
|
setScrollFactor(x: number, y?: number): this;
|
|
69
79
|
setAlpha(topLeft?: number, _topRight?: number, _bottomLeft?: number, _bottomRight?: number): this;
|
|
@@ -2,6 +2,7 @@ import { NeutrinoContext } from "./NeutrinoContext";
|
|
|
2
2
|
import { DataTextureManager } from "./DataTextureManager";
|
|
3
3
|
import { DataTextureManagerGL1 } from "./gl1/DataTextureManagerGL1";
|
|
4
4
|
import { NeutrinoSubRect } from "./types";
|
|
5
|
+
import { PerspectiveProjection } from "./PerspectiveProjection";
|
|
5
6
|
export interface RenderParams {
|
|
6
7
|
/** Effect world transform (2x3) already including world scale. */
|
|
7
8
|
model: {
|
|
@@ -21,6 +22,9 @@ export interface RenderParams {
|
|
|
21
22
|
zoom: number;
|
|
22
23
|
/** Host scene-graph world alpha, multiplied into each particle's alpha. */
|
|
23
24
|
worldAlpha: number;
|
|
25
|
+
/** Optional v1.0-parity perspective projection (Projection3D); when set,
|
|
26
|
+
* uViewProjMatrix = ortho * perspective (both in screen space). */
|
|
27
|
+
projection?: PerspectiveProjection;
|
|
24
28
|
/** Per-particle GL textures (one per render-style texture index). */
|
|
25
29
|
glTextures: (WebGLTexture | null)[];
|
|
26
30
|
remaps: Array<NeutrinoSubRect | null>;
|
|
@@ -43,12 +47,16 @@ export interface RenderParams {
|
|
|
43
47
|
*/
|
|
44
48
|
export declare class NeutrinoRenderer {
|
|
45
49
|
private _orthoMatrix;
|
|
50
|
+
private _perspMatrix;
|
|
51
|
+
private _vpMatrix;
|
|
52
|
+
private _projFrame;
|
|
46
53
|
private _modelMatrix;
|
|
47
54
|
private _texSlotMap;
|
|
48
55
|
private _batchPool;
|
|
49
56
|
private _batchCount;
|
|
50
57
|
constructor();
|
|
51
58
|
render(ctx: NeutrinoContext, dtm: DataTextureManager | DataTextureManagerGL1, dataView: DataView, dataUint32: Uint32Array, instructions: any[], numParticles: number, params: RenderParams): void;
|
|
59
|
+
private _mulMatrix;
|
|
52
60
|
private _resolveBlend;
|
|
53
61
|
private _applyBlendMode;
|
|
54
62
|
}
|
|
@@ -62,4 +62,14 @@ export declare class PerspectiveProjection {
|
|
|
62
62
|
*/
|
|
63
63
|
transformSize(outSize: Vec2, pos: Vec3, size: Vec2): void;
|
|
64
64
|
_getScale(pos: Vec3): number;
|
|
65
|
+
/**
|
|
66
|
+
* Writes the projection as a 4x4 column-major matrix operating in screen
|
|
67
|
+
* space, for the GPU render path. Homogeneous equivalent of
|
|
68
|
+
* transformPosition(): clip.xy = p.xy - center * (p.z / z),
|
|
69
|
+
* clip.w = 1 - p.z / z; the z row is zeroed (no depth on this path).
|
|
70
|
+
* setScreenFrame() must have been called before.
|
|
71
|
+
*
|
|
72
|
+
* @param {Float32Array} out 16-element column-major output matrix.
|
|
73
|
+
*/
|
|
74
|
+
writeMatrix(out: Float32Array): void;
|
|
65
75
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var K=Object.defineProperty;var z=(s,e,t)=>e in s?K(s,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):s[e]=t;var a=(s,e,t)=>z(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 n=Object.getOwnPropertyDescriptor(s,t);Object.defineProperty(e,t,n.get?n:{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;
|
|
@@ -49,7 +49,8 @@ vec4 fetchTexel(int globalTexelIndex) {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
// Strip geometry helpers (port of GPU33 makeScreenSpaceStrip).
|
|
52
|
-
// 2D screen-space variant
|
|
52
|
+
// 2D screen-space variant used by the Faced strip frame; world Z reaches
|
|
53
|
+
// gl_Position only through uViewProjMatrix (ortho or v1.0-parity perspective).
|
|
53
54
|
vec2 stripOrtho(vec2 v) {
|
|
54
55
|
return vec2(-v.y, v.x);
|
|
55
56
|
}
|
|
@@ -86,9 +87,9 @@ void main() {
|
|
|
86
87
|
// 0 (Faced): screen-space ortho to dir12 — equivalent to camera-faced
|
|
87
88
|
// billboard normal in a 2D camera setup.
|
|
88
89
|
// 1 (Free): the quaternion stored in texel 2 nominally encodes a 3D
|
|
89
|
-
// orientation. The
|
|
90
|
-
//
|
|
91
|
-
// the quat is read but its 3D y-axis is projected to screen
|
|
90
|
+
// orientation. The PIXI7 renderer has no true 3D camera
|
|
91
|
+
// (uViewProjMatrix is ortho or the v1.0-parity perspective),
|
|
92
|
+
// so the quat is read but its 3D y-axis is projected to screen
|
|
92
93
|
// and used as the section normal. When the projection
|
|
93
94
|
// degenerates (looking along the y-axis) we fall back to
|
|
94
95
|
// the screen-space ortho. Real 3D free-rotation requires a
|
|
@@ -123,6 +124,10 @@ void main() {
|
|
|
123
124
|
float((packedColorNex >> 8u) & 0xFFu) / 255.0,
|
|
124
125
|
float((packedColorNex >> 16u) & 0xFFu) / 255.0,
|
|
125
126
|
float((packedColorNex >> 24u) & 0xFFu) / 255.0);
|
|
127
|
+
// HDR color scale S (RGBS, bloom TDD #175 §13.12): offset+60 (t3.a) per-particle
|
|
128
|
+
// float scale; multiply BEFORE the cross-fade. S=1 for LDR (no-op).
|
|
129
|
+
color1.rgb *= (isCur ? t3.a : ts3.a);
|
|
130
|
+
color2.rgb *= (isCur ? ts3.a : t3.a);
|
|
126
131
|
|
|
127
132
|
// neighborIdxP0 / neighborIdxP3 are stored on every meta of a pair
|
|
128
133
|
// (both meta_cur and meta_nex hold the same pair of indices), so we
|
|
@@ -170,7 +175,7 @@ void main() {
|
|
|
170
175
|
bool nearPlaneClipped = (sp1.w < 1e-3) || (sp2.w < 1e-3);
|
|
171
176
|
|
|
172
177
|
// #236: set when the segment itself is degenerate (much shorter than
|
|
173
|
-
// the ribbon half-width)
|
|
178
|
+
// the ribbon half-width) — the pair is discarded like nearPlaneClipped.
|
|
174
179
|
bool stripDegenerate = false;
|
|
175
180
|
|
|
176
181
|
// Aspect correction so the 2D Faced ortho gives visually-perpendicular
|
|
@@ -256,7 +261,7 @@ void main() {
|
|
|
256
261
|
vec3 K2 = Kmul2 * normalize(cross(wdir12 + wdir23, n2));
|
|
257
262
|
Bmul2 = sign(dot(B2raw, K2));
|
|
258
263
|
vec3 B2 = B2raw * Bmul2;
|
|
259
|
-
// #236: see ik1
|
|
264
|
+
// #236: see ik1 — inner vertex at the ribbon half-width.
|
|
260
265
|
float ik2 = halfSize2;
|
|
261
266
|
worldK2 = p2 + K2 * halfSize2;
|
|
262
267
|
worldB2 = p2 + B2 * halfSize2;
|
|
@@ -274,10 +279,16 @@ void main() {
|
|
|
274
279
|
// Faced: screen-space NDC frame around dir12.
|
|
275
280
|
vec4 sp0 = mvpMatrix * vec4(p0, 1.0);
|
|
276
281
|
vec4 sp3 = mvpMatrix * vec4(p3, 1.0);
|
|
277
|
-
vec2 ndc0 = (sp0.xy / sp0.w) * aspectMul;
|
|
278
282
|
vec2 ndc1 = (sp1.xy / sp1.w) * aspectMul;
|
|
279
283
|
vec2 ndc2 = (sp2.xy / sp2.w) * aspectMul;
|
|
280
|
-
|
|
284
|
+
// Neighbor anchors behind the near plane produce garbage NDC after
|
|
285
|
+
// the perspective divide (possible only with Projection3D, where w
|
|
286
|
+
// varies); collapse them onto their segment anchor so the existing
|
|
287
|
+
// zero-length degeneracy path (dir01 = dir12 / dir23 = dir12)
|
|
288
|
+
// handles the knee instead of a poisoned miter. spU1/spU2 need no
|
|
289
|
+
// guard: uCameraUp has zero Z, so their w equals sp1.w / sp2.w.
|
|
290
|
+
vec2 ndc0 = (sp0.w < 1e-3) ? ndc1 : (sp0.xy / sp0.w) * aspectMul;
|
|
291
|
+
vec2 ndc3 = (sp3.w < 1e-3) ? ndc2 : (sp3.xy / sp3.w) * aspectMul;
|
|
281
292
|
|
|
282
293
|
vec2 d01 = ndc1 - ndc0;
|
|
283
294
|
vec2 d12 = ndc2 - ndc1;
|
|
@@ -328,7 +339,7 @@ void main() {
|
|
|
328
339
|
vec2 K2 = Kmul2 * normalize(stripOrtho(dir12 + dir23));
|
|
329
340
|
Bmul2 = sign(dot(B, K2));
|
|
330
341
|
vec2 B2 = B * Bmul2;
|
|
331
|
-
// #236: see ik1
|
|
342
|
+
// #236: see ik1 — inner vertex at the ribbon half-width.
|
|
332
343
|
float ik2 = ndcHalfSize2;
|
|
333
344
|
k2 = ndc2 + K2 * ndcHalfSize2;
|
|
334
345
|
b2 = ndc2 + B2 * ndcHalfSize2;
|
|
@@ -344,7 +355,7 @@ void main() {
|
|
|
344
355
|
}
|
|
345
356
|
}
|
|
346
357
|
|
|
347
|
-
// #236: a noKnee (straight-cap) end carries no bend side of its own
|
|
358
|
+
// #236: a noKnee (straight-cap) end carries no bend side of its own —
|
|
348
359
|
// its raw side label is always the +B side. If the segment's other
|
|
349
360
|
// end is a real knee on the -B side, the mismatched labels would send
|
|
350
361
|
// the ladder into the opposite-sides (twist) branch and flip the
|
|
@@ -371,6 +382,7 @@ void main() {
|
|
|
371
382
|
Bmul2 = Bmul1;
|
|
372
383
|
}
|
|
373
384
|
|
|
385
|
+
|
|
374
386
|
// V coords (mirror of preview3 / GPU33 make*Strip):
|
|
375
387
|
// V at outer knee (k) = (Bmul + 1) * 0.5
|
|
376
388
|
// V at inner knee (IK) = 1 - V_outer ; bend (b) = outer
|
|
@@ -473,7 +485,7 @@ void main() {
|
|
|
473
485
|
// Free projects the world-space vertex through MVP directly; Faced
|
|
474
486
|
// reconstructs clip space from aspect-corrected NDC (mirror of preview3).
|
|
475
487
|
if (stripDegenerate) {
|
|
476
|
-
// #236: sub-visual segment
|
|
488
|
+
// #236: sub-visual segment — discard the pair entirely.
|
|
477
489
|
gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
|
|
478
490
|
} else if (isFreeRotation) {
|
|
479
491
|
gl_Position = mvpMatrix * vec4(vertPos3D, 1.0);
|
|
@@ -512,6 +524,10 @@ void main() {
|
|
|
512
524
|
float((packedColor >> 16u) & 0xFFu) / 255.0,
|
|
513
525
|
float((packedColor >> 24u) & 0xFFu) / 255.0
|
|
514
526
|
);
|
|
527
|
+
// HDR color scale S (RGBS, bloom TDD #175 §13.12): offset+60 (t3.a) is a
|
|
528
|
+
// per-particle float scale. RGB was normalized by S at pack time; restore HDR
|
|
529
|
+
// here. S=1 for LDR colors (no-op). Alpha is untouched.
|
|
530
|
+
vColor.rgb *= t3.a;
|
|
515
531
|
|
|
516
532
|
uint gridConfig = floatBitsToUint(t3.g);
|
|
517
533
|
float gridWidth = max(float(gridConfig & 0xFFFFu), 1.0);
|
|
@@ -559,7 +575,23 @@ void main() {
|
|
|
559
575
|
|
|
560
576
|
mat4 mvpMatrix = uViewProjMatrix * uModelMatrix;
|
|
561
577
|
vec3 worldPos = position + posDisp;
|
|
562
|
-
gl_Position = mvpMatrix * vec4(worldPos
|
|
578
|
+
gl_Position = mvpMatrix * vec4(worldPos, 1.0);
|
|
579
|
+
|
|
580
|
+
// v1.0-parity near-plane culling for the perspective projection: the
|
|
581
|
+
// whole quad is discarded when ANY of its 4 corners is behind the near
|
|
582
|
+
// plane (w < 0.01 == pos.z > 0.99 * z_cam in PerspectiveProjection
|
|
583
|
+
// terms). w is linear in position, so the corner minimum comes from the
|
|
584
|
+
// w-row and the corner offsets (x in {-ox, 1-ox}, y in {-oy, 1-oy}).
|
|
585
|
+
// Without a projection every w is 1.0 and this is a no-op.
|
|
586
|
+
vec4 wRow = vec4(mvpMatrix[0].w, mvpMatrix[1].w, mvpMatrix[2].w, mvpMatrix[3].w);
|
|
587
|
+
float wx = dot(wRow.xyz, xaxis);
|
|
588
|
+
float wy = dot(wRow.xyz, yaxis);
|
|
589
|
+
float minW = dot(wRow.xyz, position) + wRow.w
|
|
590
|
+
- origin.x * wx + min(wx, 0.0)
|
|
591
|
+
- origin.y * wy + min(wy, 0.0);
|
|
592
|
+
if (minW < 0.01) {
|
|
593
|
+
gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
|
|
594
|
+
}
|
|
563
595
|
|
|
564
596
|
// Texture coordinates with grid + atlas remap
|
|
565
597
|
vec2 baseTexCoord = TEX_COORD[vertexIndex];
|
|
@@ -779,6 +811,11 @@ void main() {
|
|
|
779
811
|
// Colors: the meta M1 sample is the normalized RGBA directly.
|
|
780
812
|
vec4 color1 = fetchMeta(curBase + 1.0);
|
|
781
813
|
vec4 color2 = fetchMeta(nexBase + 1.0);
|
|
814
|
+
// HDR color scale S (RGBS, bloom TDD #175 §13.12): a plain float at offset+60,
|
|
815
|
+
// read straight from the float DATA texture (texel 3, .a) — like gridIndex — not
|
|
816
|
+
// the meta texture. Multiply BEFORE the cross-fade. S=1 → no-op.
|
|
817
|
+
color1.rgb *= fetchData(curBase + 3.0).a;
|
|
818
|
+
color2.rgb *= fetchData(nexBase + 3.0).a;
|
|
782
819
|
|
|
783
820
|
// Neighbor RECORD indices (system.js convention: neighborIdxP0 on the
|
|
784
821
|
// pair-cur meta, neighborIdxP3 on the pair-nex meta; boundary
|
|
@@ -914,10 +951,16 @@ void main() {
|
|
|
914
951
|
// Faced: screen-space NDC frame around dir12.
|
|
915
952
|
vec4 sp0 = mvpMatrix * vec4(p0, 1.0);
|
|
916
953
|
vec4 sp3 = mvpMatrix * vec4(p3, 1.0);
|
|
917
|
-
vec2 ndc0 = (sp0.xy / sp0.w) * aspectMul;
|
|
918
954
|
vec2 ndc1 = (sp1.xy / sp1.w) * aspectMul;
|
|
919
955
|
vec2 ndc2 = (sp2.xy / sp2.w) * aspectMul;
|
|
920
|
-
|
|
956
|
+
// Neighbor anchors behind the near plane produce garbage NDC after
|
|
957
|
+
// the perspective divide (possible only with Projection3D, where w
|
|
958
|
+
// varies); collapse them onto their segment anchor so the existing
|
|
959
|
+
// zero-length degeneracy path (dir01 = dir12 / dir23 = dir12)
|
|
960
|
+
// handles the knee instead of a poisoned miter. spU1/spU2 need no
|
|
961
|
+
// guard: uCameraUp has zero Z, so their w equals sp1.w / sp2.w.
|
|
962
|
+
vec2 ndc0 = (sp0.w < 1e-3) ? ndc1 : (sp0.xy / sp0.w) * aspectMul;
|
|
963
|
+
vec2 ndc3 = (sp3.w < 1e-3) ? ndc2 : (sp3.xy / sp3.w) * aspectMul;
|
|
921
964
|
|
|
922
965
|
vec2 d01 = ndc1 - ndc0;
|
|
923
966
|
vec2 d12 = ndc2 - ndc1;
|
|
@@ -1109,6 +1152,9 @@ void main() {
|
|
|
1109
1152
|
|
|
1110
1153
|
// Meta M1: the packedColor u32 LE bytes ARE the normalized RGBA sample.
|
|
1111
1154
|
vColor = fetchMeta(baseTexel + 1.0);
|
|
1155
|
+
// HDR color scale S (RGBS, bloom TDD #175 §13.12): a plain float at offset+60,
|
|
1156
|
+
// read directly from the float DATA texture (t3.a) like gridIndex. S=1 → no-op.
|
|
1157
|
+
vColor.rgb *= t3.a;
|
|
1112
1158
|
|
|
1113
1159
|
// Meta M2: gridConfig — [gridW lo, gridW hi, gridH lo, gridH hi].
|
|
1114
1160
|
vec4 m2 = fetchMeta(baseTexel + 2.0);
|
|
@@ -1155,7 +1201,23 @@ void main() {
|
|
|
1155
1201
|
|
|
1156
1202
|
mat4 mvpMatrix = uViewProjMatrix * uModelMatrix;
|
|
1157
1203
|
vec3 worldPos = position + posDisp;
|
|
1158
|
-
gl_Position = mvpMatrix * vec4(worldPos
|
|
1204
|
+
gl_Position = mvpMatrix * vec4(worldPos, 1.0);
|
|
1205
|
+
|
|
1206
|
+
// v1.0-parity near-plane culling for the perspective projection: the
|
|
1207
|
+
// whole quad is discarded when ANY of its 4 corners is behind the near
|
|
1208
|
+
// plane (w < 0.01 == pos.z > 0.99 * z_cam in PerspectiveProjection
|
|
1209
|
+
// terms). w is linear in position, so the corner minimum comes from the
|
|
1210
|
+
// w-row and the corner offsets (x in {-ox, 1-ox}, y in {-oy, 1-oy}).
|
|
1211
|
+
// Without a projection every w is 1.0 and this is a no-op.
|
|
1212
|
+
vec4 wRow = vec4(mvpMatrix[0].w, mvpMatrix[1].w, mvpMatrix[2].w, mvpMatrix[3].w);
|
|
1213
|
+
float wx = dot(wRow.xyz, xaxis);
|
|
1214
|
+
float wy = dot(wRow.xyz, yaxis);
|
|
1215
|
+
float minW = dot(wRow.xyz, position) + wRow.w
|
|
1216
|
+
- origin.x * wx + min(wx, 0.0)
|
|
1217
|
+
- origin.y * wy + min(wy, 0.0);
|
|
1218
|
+
if (minW < 0.01) {
|
|
1219
|
+
gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
|
|
1220
|
+
}
|
|
1159
1221
|
|
|
1160
1222
|
// Texture coordinates with grid + atlas remap
|
|
1161
1223
|
vec2 baseTexCoord = texCoordOf(corner);
|
|
@@ -1230,7 +1292,7 @@ void main() {
|
|
|
1230
1292
|
// world alpha scales the whole RGBA (mirror of the ES 3.00 shader).
|
|
1231
1293
|
gl_FragColor = texColor * vColor * uWorldAlpha;
|
|
1232
1294
|
}
|
|
1233
|
-
`,A=class A{constructor(e,t){
|
|
1295
|
+
`,A=class A{constructor(e,t){a(this,"neutrino");a(this,"gl");a(this,"_shaderProgram",null);a(this,"_indexBuffer",null);a(this,"_dummyVB",null);a(this,"_indexBufferCapacity",0);a(this,"_vao",null);a(this,"_isWebGL1",!1);a(this,"_maxBatchTextures",A.MAX_BATCH_TEXTURES);a(this,"_hasElementIndexUint",!1);a(this,"_vaoExt",null);a(this,"_aIdBuffer",null);a(this,"_aIdLocation",-1);a(this,"_uDataTexture",null);a(this,"_uDataTextureWidth",null);a(this,"_uMetaTexture",null);a(this,"_uDataTexSize",null);a(this,"_uCameraRight",null);a(this,"_uCameraUp",null);a(this,"_uCameraDir",null);a(this,"_uViewProjMatrix",null);a(this,"_uModelMatrix",null);a(this,"_uViewportAspect",null);a(this,"_uWorldAlpha",null);a(this,"_uTextures",[]);a(this,"_uTexRemaps",[]);a(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,n){if(this._noiseInitialized){t&&t();return}this.neutrino.initializeNoise(e,()=>{this._noiseInitialized=!0,t&&t()},n)}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,n=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 c=l?new Uint32Array(e*6):new Uint16Array(e*6);for(let i=0;i<e;i++){const u=i*4,_=i*6;c[_+0]=u+0,c[_+1]=u+1,c[_+2]=u+2,c[_+3]=u+0,c[_+4]=u+2,c[_+5]=u+3}if(this._indexBuffer=t.createBuffer(),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this._indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,c,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(n);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 n=e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT);if(!n||n.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;
|
|
1234
1296
|
attribute float aId;
|
|
1235
1297
|
uniform sampler2D uF;
|
|
1236
1298
|
uniform sampler2D uB;
|
|
@@ -1242,11 +1304,11 @@ void main() {
|
|
|
1242
1304
|
gl_Position = vec4(aId, 0.0, 0.0, 1.0);
|
|
1243
1305
|
gl_PointSize = 1.0;
|
|
1244
1306
|
}
|
|
1245
|
-
`,
|
|
1307
|
+
`,n=`precision mediump float;
|
|
1246
1308
|
varying vec4 vC;
|
|
1247
1309
|
void main() { gl_FragColor = vC; }
|
|
1248
|
-
`,r=e.getParameter(e.VIEWPORT),o=e.getParameter(e.CURRENT_PROGRAM),l=e.getParameter(e.ARRAY_BUFFER_BINDING),
|
|
1310
|
+
`,r=e.getParameter(e.VIEWPORT),o=e.getParameter(e.CURRENT_PROGRAM),l=e.getParameter(e.ARRAY_BUFFER_BINDING),c=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 _=e.getParameter(e.TEXTURE_BINDING_2D),y=e.isEnabled(e.BLEND),E=e.isEnabled(e.DEPTH_TEST),I=e.isEnabled(e.SCISSOR_TEST);let m=null,b=null,B=null,f=null,v=null,g=null,d=-1,w=!1,x=null,h=4,U=0,p=0,P=0,D=!1,S=!1;const T=new Uint8Array(4);try{m=e.createProgram(),e.attachShader(m,this._compileShader(e.VERTEX_SHADER,t)),e.attachShader(m,this._compileShader(e.FRAGMENT_SHADER,n)),e.linkProgram(m);const C=(R,F)=>{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,F),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])),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,b),e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,B),e.uniform1i(e.getUniformLocation(m,"uF"),0),e.uniform1i(e.getUniformLocation(m,"uB"),1),d=e.getAttribLocation(m,"aId"),w=e.getVertexAttrib(d,e.VERTEX_ATTRIB_ARRAY_ENABLED),x=e.getVertexAttrib(d,e.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING),h=e.getVertexAttrib(d,e.VERTEX_ATTRIB_ARRAY_SIZE),U=e.getVertexAttrib(d,e.VERTEX_ATTRIB_ARRAY_TYPE),D=e.getVertexAttrib(d,e.VERTEX_ATTRIB_ARRAY_NORMALIZED),p=e.getVertexAttrib(d,e.VERTEX_ATTRIB_ARRAY_STRIDE),P=e.getVertexAttribOffset(d,e.VERTEX_ATTRIB_ARRAY_POINTER),e.enableVertexAttribArray(d),e.vertexAttribPointer(d,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)}finally{d>=0&&(x&&(e.bindBuffer(e.ARRAY_BUFFER,x),e.vertexAttribPointer(d,h,U,D,p,P)),w?e.enableVertexAttribArray(d):e.disableVertexAttribArray(d)),v&&e.deleteFramebuffer(v),f&&e.deleteTexture(f),b&&e.deleteTexture(b),B&&e.deleteTexture(B),g&&e.deleteBuffer(g),m&&e.deleteProgram(m),e.bindFramebuffer(e.FRAMEBUFFER,c),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])}if(!S)throw new Error(`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.`)}_initShader(){const e=this.gl,t=this._isWebGL1?vertexShaderSourceGL1:vertexShaderSource,n=this._isWebGL1?fragmentShaderSourceGL1:fragmentShaderSource,r=this._compileShader(e.VERTEX_SHADER,t),o=this._compileShader(e.FRAGMENT_SHADER,n);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 n=this.gl,r=n.createShader(e);if(n.shaderSource(r,t),n.compileShader(r),!n.getShaderParameter(r,n.COMPILE_STATUS)){const o=n.getShaderInfoLog(r);throw n.deleteShader(r),new Error("Shader compile error: "+o)}return r}};a(A,"MAX_BATCH_TEXTURES",8);let NeutrinoContext=A;class GamePlugin extends Phaser.Plugins.BasePlugin{constructor(){super(...arguments);a(this,"neutrino");a(this,"ctx");a(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,n,r){this.ctx.initializeNoise(t,n||(()=>{}),r||(()=>{}))}generateNoise(){this.ctx.generateNoise()}}function noext(s){return s.replace(/\.[^/.]+$/,"")}class EffectModel{constructor(scene,scriptText,options){a(this,"gamePlugin");a(this,"scene");a(this,"effectModel");a(this,"textureFrames",[]);a(this,"texturesRemap",[]);a(this,"_numTexturesToLoadLeft",0);options=Object.assign({atlases:[]},options),this.gamePlugin=scene.plugins.get("neutrino"),this.scene=scene;const evalScript=`(function(ctx) {
|
|
1249
1311
|
`+scriptText+`
|
|
1250
1312
|
return new NeutrinoEffect(ctx);
|
|
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;
|
|
1313
|
+
})(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 n=this.effectModel.textures[t],r=this.gamePlugin.texturesBasePath+n,o=noext(r);let l=this._findFrameInAtlases(s,n);if(l||(l=this._findFrameInAtlases(s,noext(n))),!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 n=s[t];if(!this.scene.sys.textures.exists(n))continue;const r=this.scene.sys.textures.get(n);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,n){const{key:r,url:o,options:l,xhrSettings:c}=n;super(t,{type:"binary",extension:"js",responseType:"text",key:r,url:o,xhrSettings:c});a(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,n,r){a(this,"textureWidth");a(this,"textureHeight");a(this,"_gl");a(this,"_floatView");a(this,"_textures",[]);a(this,"_currentIndex",0);const o=e.getParameter(e.MAX_TEXTURE_SIZE);if(n>o||r>o)throw new Error(`NeutrinoParticles: data texture ${n}x${r} exceeds GL MAX_TEXTURE_SIZE (${o}). Reduce effect particle capacity.`);this._gl=e,this.textureWidth=n,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,n,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){a(this,"bytes");a(this,"_u32");this.bytes=new Uint8Array(e*t*4),this._u32=new Uint32Array(this.bytes.buffer)}build(e,t){const n=this._u32;for(let r=0;r<t;r++){const o=r*16,l=r*4;n[l]=e[o],n[l+1]=e[o+12],n[l+2]=e[o+13],n[l+3]=e[o+14]}}patchSlot(e,t,n){const r=this.bytes;let o=e*16;for(let l=0;l<t;l++)r[o]=n,o+=16}}const RING_BUFFER_SIZE=3;class DataTextureManagerGL1{constructor(e,t,n,r){a(this,"textureWidth");a(this,"textureHeight");a(this,"meta");a(this,"_gl");a(this,"_floatView");a(this,"_dataTextures",[]);a(this,"_metaTextures",[]);a(this,"_currentIndex",0);const o=e.getParameter(e.MAX_TEXTURE_SIZE);if(n>o||r>o)throw new Error(`NeutrinoParticles: data texture ${n}x${r} exceeds GL MAX_TEXTURE_SIZE (${o}). Reduce effect particle capacity.`);if(n*r>16777216)throw new Error(`NeutrinoParticles: data texture ${n}x${r} exceeds the WebGL1 render path texel cap (2^24). Reduce effect particle capacity.`);this._gl=e,this.textureWidth=n,this.textureHeight=r,this._floatView=new Float32Array(t.buffer,t.byteOffset,t.length),this.meta=new MetaTextureManager(n,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,n){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+n),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,n=t.createTexture();return t.bindTexture(t.TEXTURE_2D,n),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),n}}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(){a(this,"blendMode",0);a(this,"startParticle",0);a(this,"numParticles",0);a(this,"numTextures",0);a(this,"glTextures",new Array(NeutrinoContext.MAX_BATCH_TEXTURES).fill(null));a(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(){a(this,"_orthoMatrix",new Float32Array(16));a(this,"_perspMatrix",new Float32Array(16));a(this,"_vpMatrix",new Float32Array(16));a(this,"_projFrame",{x:0,y:0,width:0,height:0});a(this,"_modelMatrix",new Float32Array(16));a(this,"_texSlotMap",new Map);a(this,"_batchPool");a(this,"_batchCount",0);this._batchPool=[];for(let e=0;e<MAX_BATCHES;e++)this._batchPool.push(new DrawBatch)}render(e,t,n,r,o,l,c){if(l===0)return;const i=e.gl,u=e.isWebGL1,_=e.maxBatchTextures,y=c.renderStyles,E=c.materials,I=u?t.meta:null;I&&I.build(r,l),this._batchCount=0;const m=this._texSlotMap;for(;this._batchPool.length<o.length;)this._batchPool.push(new DrawBatch);let b=0;for(;b<o.length;){const f=this._batchPool[this._batchCount];f.reset(),f.blendMode=this._resolveBlend(o[b].blendMode,E),f.startParticle=o[b].startParticleIndex,m.clear();let v=b;for(;v<o.length&&this._resolveBlend(o[v].blendMode,E)===f.blendMode;){const g=y[o[v].renderStyleIndex].textureIndices[0];if(!m.has(g)){if(m.size>=_)break;const x=m.size;m.set(g,x),f.glTextures[x]=c.glTextures[g]||null,f.remaps[x]=c.remaps[g]||null,f.numTextures=x+1}const d=m.get(g),w=o[v];if(I)I.patchSlot(w.startParticleIndex,w.numParticles,d);else if(d!==0)for(let x=0;x<w.numParticles;x++){const h=(w.startParticleIndex+x)*BYTES_PER_PARTICLE,U=n.getUint32(h,!0);n.setUint32(h,U&4294967040|d,!0)}f.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 p=t;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)}else{const p=t;p.uploadAndBind(DATA_TEXTURE_UNIT),i.uniform1i(e.uDataTexture,DATA_TEXTURE_UNIT),i.uniform1i(e.uDataTextureWidth,p.textureWidth)}i.uniform3f(e.uCameraRight,1,0,0),i.uniform3f(e.uCameraUp,0,-1,0),i.uniform3f(e.uCameraDir,0,0,-1);const f=c.viewportWidth,v=c.viewportHeight,g=c.zoom||1,d=this._orthoMatrix;if(d.fill(0),d[0]=2/f*g,d[5]=-2/v*g,d[10]=0,d[15]=1,d[12]=-1-2/f*g*c.scrollX,d[13]=1+2/v*g*c.scrollY,c.projection){const p=this._projFrame;p.x=0,p.y=0,p.width=f,p.height=v,c.projection.setScreenFrame(p),c.projection.writeMatrix(this._perspMatrix),this._mulMatrix(this._vpMatrix,d,this._perspMatrix),i.uniformMatrix4fv(e.uViewProjMatrix,!1,this._vpMatrix)}else i.uniformMatrix4fv(e.uViewProjMatrix,!1,d);const w=v>0?f/v:1;e.uViewportAspect&&i.uniform1f(e.uViewportAspect,w),e.uWorldAlpha&&i.uniform1f(e.uWorldAlpha,c.worldAlpha);const x=c.model,h=this._modelMatrix;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);const U=u?PARTICLE_TEXTURE_START_UNIT_GL1:PARTICLE_TEXTURE_START_UNIT;i.enable(i.BLEND);for(let p=0;p<this._batchCount;p++){const P=this._batchPool[p];this._applyBlendMode(i,P.blendMode);for(let T=0;T<P.numTextures;T++){const C=U+T;i.activeTexture(i.TEXTURE0+C),i.bindTexture(i.TEXTURE_2D,P.glTextures[T]),i.uniform1i(e.uTextures[T],C);const R=P.remaps[T];R?i.uniform4f(e.uTexRemaps[T],R.x,R.y,R.width,R.height):i.uniform4f(e.uTexRemaps[T],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)}}_mulMatrix(e,t,n){for(let r=0;r<16;r+=4){const o=n[r],l=n[r+1],c=n[r+2],i=n[r+3];e[r]=t[0]*o+t[4]*l+t[8]*c+t[12]*i,e[r+1]=t[1]*o+t[5]*l+t[9]*c+t[13]*i,e[r+2]=t[2]*o+t[6]*l+t[10]*c+t[14]*i,e[r+3]=t[3]*o+t[7]*l+t[11]*c+t[15]*i}}_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,n,r){r=Object.assign({position:[0,0,0],angle:0,scale:1,pause:Pause.BEFORE_UPDATE_OR_RENDER,generatorsPaused:!1},r||{});super(n,"Neutrino");a(this,"gamePlugin");a(this,"effectModel");a(this,"effect",null);a(this,"x",0);a(this,"y",0);a(this,"z",0);a(this,"angle",0);a(this,"rotation",0);a(this,"scaleX",1);a(this,"scaleY",1);a(this,"scrollFactorX",1);a(this,"scrollFactorY",1);a(this,"alpha",1);a(this,"depth",0);a(this,"blendMode",Phaser.BlendModes.NORMAL);a(this,"projection");a(this,"_dataTextureManager",null);a(this,"_worldPosition");a(this,"_worldScaledPosition");a(this,"_worldRotation",[0,0,0,1]);a(this,"_worldScale");a(this,"_tempMatrix1");a(this,"_tempMatrix2");a(this,"_unpauseOnUpdateRender");a(this,"_glTexturesScratch",[]);this.gamePlugin=n.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.projection=r.projection,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,n){this.ready&&(this._checkUnpauseOnUpdateRender()||this._updateWorldTransform(),this.effect.update(n/1e3,this._renderPosition(),this._renderRotation()))}renderWebGL(t,n,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 y=this._worldScale;try{sharedRenderer.render(o,l,this.effect.particleDataView,this.effect.particleDataUint32,c,i,{model:{a:y,b:0,c:0,d:y,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,projection:this.projection,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,n){this.ready&&this.effect.setPropertyInAllEmitters(t,n)}setPropertyInEmitter(t,n,r){this.ready&&this.effect.setPropertyInEmitter(t,n,r)}getEmitterPropertyValue(t,n){if(this.ready)return n===void 0?this.effect.getEmitterPropertyValue(t):this.effect.getEmitterPropertyValue(t,n)}hasEmitterProperty(t,n){return this.ready?n===void 0?this.effect.hasEmitterProperty(t):this.effect.hasEmitterProperty(t,n):!1}getEmitterProperties(){return this.ready?this.effect.getEmitterProperties():[]}getNumParticles(){return this.ready?this.effect.getNumParticles():0}setScrollFactor(t,n){return this.scrollFactorX=t,this.scrollFactorY=n===void 0?t:n,this}setAlpha(t,n,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)},n={matrix:this._tempMatrix1.loadIdentity(),angle:this.angle,scale:(this.scaleX+this.scaleY)*.5};t(this.parentContainer,n),n.matrix.transformPoint(this.x,this.y,this._worldPosition),this._worldRotation=this.gamePlugin.neutrino.axisangle2quat_([0,0,1],n.angle),this._worldScale=n.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){a(this,"_angleTan",0);a(this,"_screenWidth",0);a(this,"_screenPosX",0);a(this,"_screenPosY",0);a(this,"_z",0);a(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 n=this._getScale(t);return e[0]=(t[0]-this._screenPosX)*n+this._screenPosX,e[1]=(t[1]-this._screenPosY)*n+this._screenPosY,!0}transformSize(e,t,n){const r=this._getScale(t);e[0]=n[0]*r,e[1]=n[1]*r}_getScale(e){return this._z/(this._z-e[2])}writeMatrix(e){const t=this._z,n=Number.isFinite(t)&&t>0?1/t:0;e.fill(0),e[0]=1,e[5]=1,e[8]=-this._screenPosX*n,e[9]=-this._screenPosY*n,e[11]=-n,e[15]=1}}let _installed=!1;function installPlugin(){_installed||(_installed=!0,Phaser.Loader.FileTypesManager.register("neutrino",function(s,e,t,n){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:n}));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;
|
|
1252
1314
|
//# sourceMappingURL=neutrinoparticles.js-v1.1-phaser.cjs.js.map
|