@neutrinoparticles/js-v1.1-phaser 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +212 -0
- package/dist/DataTextureManager.d.ts +32 -0
- package/dist/Effect.d.ts +76 -0
- package/dist/EffectModel.d.ts +27 -0
- package/dist/File.d.ts +18 -0
- package/dist/GamePlugin.d.ts +27 -0
- package/dist/NeutrinoContext.d.ts +88 -0
- package/dist/NeutrinoRenderer.d.ts +54 -0
- package/dist/PerspectiveProjection.d.ts +65 -0
- package/dist/gl1/DataTextureManagerGL1.d.ts +23 -0
- package/dist/gl1/MetaTextureManager.d.ts +9 -0
- package/dist/index.d.ts +43 -0
- package/dist/neutrinoparticles.js-v1.1-phaser.cjs.js +1169 -0
- package/dist/neutrinoparticles.js-v1.1-phaser.cjs.js.map +1 -0
- package/dist/neutrinoparticles.js-v1.1-phaser.d.ts +481 -0
- package/dist/neutrinoparticles.js-v1.1-phaser.es.js +2105 -0
- package/dist/neutrinoparticles.js-v1.1-phaser.es.js.map +1 -0
- package/dist/neutrinoparticles.js-v1.1-phaser.umd.js +1169 -0
- package/dist/neutrinoparticles.js-v1.1-phaser.umd.js.map +1 -0
- package/dist/types.d.ts +64 -0
- package/package.json +56 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## CurrentVersion
|
|
4
|
+
|
|
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
|
+
- 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).
|
package/README.md
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# @neutrinoparticles/js-v1.1-phaser
|
|
2
|
+
|
|
3
|
+
Phaser 3 integration for [NeutrinoParticles](https://neutrinoparticles.com/) real-time particle effects (format **v1.1**).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @neutrinoparticles/js-v1.1-phaser
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The core runtime (`@neutrinoparticles/js-v1.1`) is installed automatically as a dependency.
|
|
12
|
+
|
|
13
|
+
**Peer dependency:** Phaser 3.60+
|
|
14
|
+
|
|
15
|
+
## Requirements
|
|
16
|
+
|
|
17
|
+
The v1.1 renderer reconstructs particle geometry on the GPU. It works on:
|
|
18
|
+
|
|
19
|
+
- **WebGL2** — the primary path;
|
|
20
|
+
- **WebGL1** (the Phaser 3 default) — supported automatically on contexts
|
|
21
|
+
that provide `OES_texture_float`, at least 2 vertex texture image units,
|
|
22
|
+
`highp` float in fragment shaders, and pass a one-time
|
|
23
|
+
vertex-float-texture smoke test at startup. The renderer detects the
|
|
24
|
+
context version and picks the path by itself — no configuration needed,
|
|
25
|
+
a plain `new Phaser.Game({ type: Phaser.WEBGL })` works out of the box.
|
|
26
|
+
|
|
27
|
+
On a WebGL1 context missing those capabilities, the plugin's `init` throws an
|
|
28
|
+
`Error` naming the missing capability (for example
|
|
29
|
+
`NeutrinoParticles (js-v1.1): WebGL1 context lacks OES_texture_float; WebGL2
|
|
30
|
+
or WebGL1 with vertex float textures is required.`).
|
|
31
|
+
|
|
32
|
+
### WebGL2 vs WebGL1: which to use
|
|
33
|
+
|
|
34
|
+
**Prefer WebGL2 whenever it is available** — it is the faster and leaner
|
|
35
|
+
path. WebGL1 is a compatibility fallback for devices and embeds that cannot
|
|
36
|
+
create a WebGL2 context. Rough comparison of the same effect on the two
|
|
37
|
+
paths:
|
|
38
|
+
|
|
39
|
+
- **Rendering speed:** identical at typical particle counts (up to ~20k
|
|
40
|
+
live particles the difference is not measurable); on very heavy effects
|
|
41
|
+
(~100k live particles) WebGL1 costs roughly 10% more render time per
|
|
42
|
+
frame — the vertex shader does almost twice as many texture reads and
|
|
43
|
+
extra math to unpack data that WebGL2 reads directly.
|
|
44
|
+
- **GPU memory:** WebGL1 uses about 25% more per effect (an extra byte
|
|
45
|
+
texture carries the data WebGL1 shaders cannot decode from the float
|
|
46
|
+
texture).
|
|
47
|
+
- **Features/visuals:** identical — both paths render the same effects with
|
|
48
|
+
full parity (quads and ribbons).
|
|
49
|
+
|
|
50
|
+
Phaser 3 creates a **WebGL1** context by default. To run on the faster
|
|
51
|
+
WebGL2 path, create a WebGL2 context yourself and hand it to the game via
|
|
52
|
+
the `context` option — WebGL2 is a superset of WebGL1, so Phaser's own
|
|
53
|
+
rendering keeps working:
|
|
54
|
+
|
|
55
|
+
```javascript
|
|
56
|
+
const canvas = document.createElement('canvas');
|
|
57
|
+
canvas.width = 800;
|
|
58
|
+
canvas.height = 600;
|
|
59
|
+
document.body.appendChild(canvas);
|
|
60
|
+
const gl2 = canvas.getContext('webgl2');
|
|
61
|
+
|
|
62
|
+
new Phaser.Game({
|
|
63
|
+
type: Phaser.WEBGL,
|
|
64
|
+
canvas: canvas,
|
|
65
|
+
context: gl2, // hand the WebGL2 context to Phaser
|
|
66
|
+
width: 800,
|
|
67
|
+
height: 600,
|
|
68
|
+
// ...
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Export Target in Editor
|
|
73
|
+
|
|
74
|
+
In the NeutrinoParticles Editor, set the export target to **JavaScript v1.1**.
|
|
75
|
+
|
|
76
|
+
Export the effect with **"For XHR Request"** format. After export you get a `.js`
|
|
77
|
+
file (e.g. `my_effect.js`) containing the effect model.
|
|
78
|
+
|
|
79
|
+
## Quick Start
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
import Phaser from 'phaser'
|
|
83
|
+
import { GamePlugin } from '@neutrinoparticles/js-v1.1-phaser'
|
|
84
|
+
|
|
85
|
+
class GameScene extends Phaser.Scene {
|
|
86
|
+
constructor() {
|
|
87
|
+
super({ key: 'GameScene' });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
preload() {
|
|
91
|
+
// Load exported effect (must be exported "For XHR Request")
|
|
92
|
+
this.load.neutrino('myEffect', 'export_js/my_effect.js');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
create() {
|
|
96
|
+
// Get effect model from cache (created by the loader)
|
|
97
|
+
const effectModel = this.cache.binary.get('myEffect');
|
|
98
|
+
|
|
99
|
+
// Create effect instance
|
|
100
|
+
this.effect = this.add.neutrino(effectModel, {
|
|
101
|
+
position: [this.cameras.main.centerX, this.cameras.main.centerY, 0]
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
new Phaser.Game({
|
|
107
|
+
type: Phaser.WEBGL, // Phaser's default WebGL1 context works out of the box;
|
|
108
|
+
// see "WebGL2 vs WebGL1" above for the faster WebGL2 setup
|
|
109
|
+
width: 800,
|
|
110
|
+
height: 600,
|
|
111
|
+
scene: GameScene,
|
|
112
|
+
plugins: {
|
|
113
|
+
global: [{
|
|
114
|
+
key: 'neutrino',
|
|
115
|
+
plugin: GamePlugin,
|
|
116
|
+
start: true,
|
|
117
|
+
data: {
|
|
118
|
+
texturesBasePath: 'textures/',
|
|
119
|
+
generateNoise: true
|
|
120
|
+
}
|
|
121
|
+
}]
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
For plain `<script>` tags (no bundler), reference the plugin as
|
|
127
|
+
`PhaserNeutrino.GamePlugin` and include the UMD builds of both
|
|
128
|
+
`@neutrinoparticles/js-v1.1` and `@neutrinoparticles/js-v1.1-phaser`.
|
|
129
|
+
|
|
130
|
+
## How It Works
|
|
131
|
+
|
|
132
|
+
`scene.load.neutrino(key, url)` fetches the exported `.js` file via XHR and
|
|
133
|
+
creates an effect model internally. The model is then available via
|
|
134
|
+
`this.cache.binary.get(key)`. Use `this.add.neutrino(model, options)` to create
|
|
135
|
+
an effect instance that auto-updates and renders as part of the Phaser scene.
|
|
136
|
+
|
|
137
|
+
## Instant Position Change (Teleporting)
|
|
138
|
+
|
|
139
|
+
Moving the effect via position creates a smooth trail of particles. To instantly teleport the effect without a trail:
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
effect.resetPosition({ position: [newX, newY, 0] });
|
|
143
|
+
|
|
144
|
+
// With new angle
|
|
145
|
+
effect.resetPosition({ position: [newX, newY, 0], angle: 45 }); // degrees
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Restart
|
|
149
|
+
|
|
150
|
+
Restart destroys all existing particles and starts the effect from scratch:
|
|
151
|
+
|
|
152
|
+
```javascript
|
|
153
|
+
effect.restart({ position: [newX, newY, 0] });
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Pause
|
|
157
|
+
|
|
158
|
+
**Full pause** — all particles freeze, nothing is generated:
|
|
159
|
+
|
|
160
|
+
```javascript
|
|
161
|
+
effect.pause();
|
|
162
|
+
effect.unpause();
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Generators pause** — existing particles continue to live, but no new particles are created:
|
|
166
|
+
|
|
167
|
+
```javascript
|
|
168
|
+
effect.pauseGenerators();
|
|
169
|
+
effect.unpauseGenerators();
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Set the initial pause state in the constructor:
|
|
173
|
+
|
|
174
|
+
```javascript
|
|
175
|
+
import { Pause } from '@neutrinoparticles/js-v1.1-phaser'
|
|
176
|
+
|
|
177
|
+
const effect = this.add.neutrino(effectModel, {
|
|
178
|
+
position: [400, 300, 0],
|
|
179
|
+
pause: Pause.YES // starts paused
|
|
180
|
+
});
|
|
181
|
+
// ...later:
|
|
182
|
+
effect.unpause();
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Emitter Properties
|
|
186
|
+
|
|
187
|
+
Control exposed emitter properties at runtime. Properties are defined in Emitter Guide or Emitter Scheme in the Editor.
|
|
188
|
+
|
|
189
|
+
```javascript
|
|
190
|
+
effect.setPropertyInAllEmitters('MyParticlesPerSecond', 100);
|
|
191
|
+
effect.setPropertyInAllEmitters('MyColor', [1.0, 0.5, 0.2]);
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Number of Particles
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
const numParticles = effect.getNumParticles();
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Common Issues
|
|
201
|
+
|
|
202
|
+
- **`Error: ... WebGL1 context lacks <capability>` at startup:** the (rare) WebGL1 context does not support the render technique — see [Requirements](#requirements). Running on a WebGL2 context (the `context` game option) lifts the requirement.
|
|
203
|
+
- **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
|
+
- **Turbulence not working:** Set `generateNoise: true` in the plugin config, or call the plugin's `generateNoise()` before creating effects that use noise.
|
|
205
|
+
|
|
206
|
+
## Documentation
|
|
207
|
+
|
|
208
|
+
Full documentation at [neutrinoparticles.com](https://neutrinoparticles.com/en/docs/199).
|
|
209
|
+
|
|
210
|
+
## License
|
|
211
|
+
|
|
212
|
+
Copyright (c) Yurii Miroshnyk. All rights reserved.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manages a small ring of RGBA32F WebGL textures that hold the runtime's flat
|
|
3
|
+
* particle data buffer. Each frame the current texture is re-uploaded (zero-copy
|
|
4
|
+
* from the runtime-owned Uint32Array via a Float32 view) and the ring advances,
|
|
5
|
+
* which avoids GPU pipeline stalls from re-uploading into a texture still in use.
|
|
6
|
+
*
|
|
7
|
+
* Unlike the pixi7 adapter this owns raw GL textures directly (no PIXI texture
|
|
8
|
+
* system), so the exact same class works for both the PIXI v8 and Phaser
|
|
9
|
+
* integrations, which both do their own raw WebGL2 draw.
|
|
10
|
+
*/
|
|
11
|
+
export declare class DataTextureManager {
|
|
12
|
+
readonly textureWidth: number;
|
|
13
|
+
readonly textureHeight: number;
|
|
14
|
+
private readonly _gl;
|
|
15
|
+
private readonly _floatView;
|
|
16
|
+
private _textures;
|
|
17
|
+
private _currentIndex;
|
|
18
|
+
/**
|
|
19
|
+
* @param gl - WebGL2 context (from the host renderer)
|
|
20
|
+
* @param data - Uint32Array from the runtime. A Float32Array view over the
|
|
21
|
+
* same buffer is uploaded as RGBA32F — bit patterns (incl. NaN/Inf) pass
|
|
22
|
+
* through unchanged.
|
|
23
|
+
* @param textureWidth - from runtime (system.dataTextureWidth)
|
|
24
|
+
* @param textureHeight - from runtime (system.dataTextureHeight)
|
|
25
|
+
*/
|
|
26
|
+
constructor(gl: WebGL2RenderingContext, data: Uint32Array, textureWidth: number, textureHeight: number);
|
|
27
|
+
get currentTexture(): WebGLTexture;
|
|
28
|
+
/** Bind the current texture to a unit and upload the latest particle data. */
|
|
29
|
+
uploadAndBind(unit: number): void;
|
|
30
|
+
advance(): void;
|
|
31
|
+
destroy(): void;
|
|
32
|
+
}
|
package/dist/Effect.d.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import Phaser from 'phaser';
|
|
2
|
+
import { Pause, Vec2, Vec3 } from './types';
|
|
3
|
+
import { GamePlugin } from './GamePlugin';
|
|
4
|
+
import { EffectModel } from './EffectModel';
|
|
5
|
+
import { NeutrinoSystem } from './types';
|
|
6
|
+
export interface EffectOptions {
|
|
7
|
+
position?: Vec3;
|
|
8
|
+
angle?: number;
|
|
9
|
+
scale?: number;
|
|
10
|
+
pause?: Pause;
|
|
11
|
+
generatorsPaused?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A NeutrinoParticles effect on a Phaser scene (JS v1.1 runtime).
|
|
15
|
+
*
|
|
16
|
+
* Simulation runs in preUpdate(); rendering happens in renderWebGL() via a raw
|
|
17
|
+
* WebGL data-texture draw (WebGL2 or the WebGL1 variant, chosen by the shared
|
|
18
|
+
* NeutrinoContext). Phaser's active pipeline is flushed before and rebound
|
|
19
|
+
* after the draw so its state machine stays consistent.
|
|
20
|
+
*/
|
|
21
|
+
export declare class Effect extends Phaser.GameObjects.GameObject {
|
|
22
|
+
gamePlugin: GamePlugin;
|
|
23
|
+
effectModel: EffectModel;
|
|
24
|
+
effect: NeutrinoSystem | null;
|
|
25
|
+
x: number;
|
|
26
|
+
y: number;
|
|
27
|
+
z: number;
|
|
28
|
+
angle: number;
|
|
29
|
+
rotation: number;
|
|
30
|
+
scaleX: number;
|
|
31
|
+
scaleY: number;
|
|
32
|
+
scrollFactorX: number;
|
|
33
|
+
scrollFactorY: number;
|
|
34
|
+
alpha: number;
|
|
35
|
+
depth: number;
|
|
36
|
+
blendMode: number;
|
|
37
|
+
private _dataTextureManager;
|
|
38
|
+
private _worldPosition;
|
|
39
|
+
private _worldScaledPosition;
|
|
40
|
+
private _worldRotation;
|
|
41
|
+
private _worldScale;
|
|
42
|
+
private _tempMatrix1;
|
|
43
|
+
private _tempMatrix2;
|
|
44
|
+
private _unpauseOnUpdateRender;
|
|
45
|
+
private _glTexturesScratch;
|
|
46
|
+
constructor(effectModel: EffectModel, scene: Phaser.Scene, options?: EffectOptions);
|
|
47
|
+
get ready(): boolean;
|
|
48
|
+
preUpdate(_time: number, ms: number): void;
|
|
49
|
+
renderWebGL(renderer: Phaser.Renderer.WebGL.WebGLRenderer, _src: Effect, camera: Phaser.Cameras.Scene2D.Camera): void;
|
|
50
|
+
restart(options?: {
|
|
51
|
+
position?: Vec3;
|
|
52
|
+
angle?: number;
|
|
53
|
+
rotation?: number;
|
|
54
|
+
}): void;
|
|
55
|
+
resetPosition(options?: {
|
|
56
|
+
position?: Vec3;
|
|
57
|
+
angle?: number;
|
|
58
|
+
rotation?: number;
|
|
59
|
+
}): void;
|
|
60
|
+
pause(): void;
|
|
61
|
+
unpause(): void;
|
|
62
|
+
get paused(): boolean;
|
|
63
|
+
pauseGenerators(): void;
|
|
64
|
+
unpauseGenerators(): void;
|
|
65
|
+
get generatorsPaused(): boolean;
|
|
66
|
+
setPropertyInAllEmitters(name: string, value: Vec3 | Vec2 | number): void;
|
|
67
|
+
getNumParticles(): number;
|
|
68
|
+
setScrollFactor(x: number, y?: number): this;
|
|
69
|
+
setAlpha(topLeft?: number, _topRight?: number, _bottomLeft?: number, _bottomRight?: number): this;
|
|
70
|
+
destroy(fromScene?: boolean): void;
|
|
71
|
+
private _applyTransformOptions;
|
|
72
|
+
private _updateWorldTransform;
|
|
73
|
+
private _renderPosition;
|
|
74
|
+
private _renderRotation;
|
|
75
|
+
private _checkUnpauseOnUpdateRender;
|
|
76
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import Phaser from 'phaser';
|
|
2
|
+
import { GamePlugin } from './GamePlugin';
|
|
3
|
+
import { NeutrinoEffectModel, NeutrinoSubRect } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* Wraps a neutrinoparticles.js v1.1 effect model for Phaser. Loads textures from
|
|
6
|
+
* standalone files or atlases via Phaser's loader, and computes atlas UV remaps
|
|
7
|
+
* as plain {x,y,width,height} objects (the v1.1 renderer reads them directly).
|
|
8
|
+
*/
|
|
9
|
+
export declare class EffectModel {
|
|
10
|
+
readonly gamePlugin: GamePlugin;
|
|
11
|
+
readonly scene: Phaser.Scene;
|
|
12
|
+
readonly effectModel: NeutrinoEffectModel;
|
|
13
|
+
textureFrames: Array<Phaser.Textures.Frame | null>;
|
|
14
|
+
texturesRemap: Array<NeutrinoSubRect | null>;
|
|
15
|
+
private _numTexturesToLoadLeft;
|
|
16
|
+
constructor(scene: Phaser.Scene, scriptText: string, options?: {
|
|
17
|
+
atlases?: string[];
|
|
18
|
+
});
|
|
19
|
+
get ready(): boolean;
|
|
20
|
+
/** Raw WebGL texture handle for a given texture index (or null). */
|
|
21
|
+
glTexture(index: number): WebGLTexture | null;
|
|
22
|
+
private _startLoadTextures;
|
|
23
|
+
private _findFrameInAtlases;
|
|
24
|
+
private _onTextureLoaded;
|
|
25
|
+
private _fullCover;
|
|
26
|
+
private _initTexturesRemapIfNeeded;
|
|
27
|
+
}
|
package/dist/File.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import Phaser from 'phaser';
|
|
2
|
+
export interface NeutrinoFileConfig {
|
|
3
|
+
key: string;
|
|
4
|
+
url: string;
|
|
5
|
+
options?: {
|
|
6
|
+
atlases?: string[];
|
|
7
|
+
};
|
|
8
|
+
xhrSettings?: Phaser.Types.Loader.XHRSettingsObject;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Custom Phaser loader file type for NeutrinoParticles effects (.js export).
|
|
12
|
+
* Parses the exported source into an {@link EffectModel} stored in the binary cache.
|
|
13
|
+
*/
|
|
14
|
+
export declare class NeutrinoFile extends Phaser.Loader.File {
|
|
15
|
+
private _options?;
|
|
16
|
+
constructor(loader: Phaser.Loader.LoaderPlugin, config: NeutrinoFileConfig);
|
|
17
|
+
onProcess(): void;
|
|
18
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import Phaser from 'phaser';
|
|
2
|
+
import { NeutrinoContext } from './NeutrinoContext';
|
|
3
|
+
export interface GamePluginOptions {
|
|
4
|
+
texturesBasePath?: string;
|
|
5
|
+
generateNoise?: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Main NeutrinoParticles plugin for Phaser (JS v1.1 runtime).
|
|
9
|
+
*
|
|
10
|
+
* Owns the shared {@link NeutrinoContext} (shader/index-buffer GL state) and
|
|
11
|
+
* the neutrino simulation context, and manages noise generation. A WebGL
|
|
12
|
+
* renderer is required — the v1.1 data-texture renderer has no Canvas
|
|
13
|
+
* fallback. Both WebGL2 and WebGL1 contexts are supported; the render path is
|
|
14
|
+
* selected automatically by {@link NeutrinoContext}.
|
|
15
|
+
*/
|
|
16
|
+
export declare class GamePlugin extends Phaser.Plugins.BasePlugin {
|
|
17
|
+
game: Phaser.Game;
|
|
18
|
+
neutrino: any;
|
|
19
|
+
ctx: NeutrinoContext;
|
|
20
|
+
texturesBasePath: string;
|
|
21
|
+
init(options?: GamePluginOptions): void;
|
|
22
|
+
start(): void;
|
|
23
|
+
stop(): void;
|
|
24
|
+
destroy(): void;
|
|
25
|
+
loadNoise(path: string, success?: () => void, fail?: () => void): void;
|
|
26
|
+
generateNoise(): void;
|
|
27
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { NeutrinoRuntimeContext as INeutrinoContext } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Engine-agnostic WebGL state for the NeutrinoParticles data-texture renderer:
|
|
4
|
+
* the shader program, a static quad index buffer + VAO (WebGL2) or aId vertex
|
|
5
|
+
* stream (WebGL1), and uniform locations.
|
|
6
|
+
*
|
|
7
|
+
* This is the Phaser counterpart of the pixi adapters' Context, but it holds no
|
|
8
|
+
* reference to a host renderer — it works purely off a WebGL context. Owned by
|
|
9
|
+
* {@link GamePlugin} and shared by every effect in the game.
|
|
10
|
+
*
|
|
11
|
+
* The render path is selected automatically (TDD_js-v1.1-webgl1.md): a WebGL2
|
|
12
|
+
* context uses the texelFetch/gl_VertexID renderer unchanged; a WebGL1 context
|
|
13
|
+
* with the required capabilities (probed here, §4.2) uses the two-texture +
|
|
14
|
+
* static-aId variant; anything else throws a capability-specific Error.
|
|
15
|
+
*/
|
|
16
|
+
export declare class NeutrinoContext {
|
|
17
|
+
readonly neutrino: INeutrinoContext;
|
|
18
|
+
readonly gl: WebGL2RenderingContext;
|
|
19
|
+
private _shaderProgram;
|
|
20
|
+
private _indexBuffer;
|
|
21
|
+
private _dummyVB;
|
|
22
|
+
private _indexBufferCapacity;
|
|
23
|
+
private _vao;
|
|
24
|
+
private _isWebGL1;
|
|
25
|
+
private _maxBatchTextures;
|
|
26
|
+
private _hasElementIndexUint;
|
|
27
|
+
private _vaoExt;
|
|
28
|
+
private _aIdBuffer;
|
|
29
|
+
private _aIdLocation;
|
|
30
|
+
static readonly MAX_BATCH_TEXTURES = 8;
|
|
31
|
+
private _uDataTexture;
|
|
32
|
+
private _uDataTextureWidth;
|
|
33
|
+
private _uMetaTexture;
|
|
34
|
+
private _uDataTexSize;
|
|
35
|
+
private _uCameraRight;
|
|
36
|
+
private _uCameraUp;
|
|
37
|
+
private _uCameraDir;
|
|
38
|
+
private _uViewProjMatrix;
|
|
39
|
+
private _uModelMatrix;
|
|
40
|
+
private _uViewportAspect;
|
|
41
|
+
private _uWorldAlpha;
|
|
42
|
+
private _uTextures;
|
|
43
|
+
private _uTexRemaps;
|
|
44
|
+
private _noiseInitialized;
|
|
45
|
+
constructor(gl: WebGL2RenderingContext, neutrino: INeutrinoContext);
|
|
46
|
+
initializeNoise(path: string, success: () => void, fail: () => void): void;
|
|
47
|
+
generateNoise(): void;
|
|
48
|
+
get shaderProgram(): WebGLProgram;
|
|
49
|
+
get isWebGL1(): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Textures usable in one batch. 8 on WebGL2; on WebGL1 reduced when the
|
|
52
|
+
* combined texture-unit budget is tight (the vertex stage takes 2 units).
|
|
53
|
+
* A lower cap only produces more batches, never wrong output.
|
|
54
|
+
*/
|
|
55
|
+
get maxBatchTextures(): number;
|
|
56
|
+
get uDataTexture(): WebGLUniformLocation | null;
|
|
57
|
+
get uDataTextureWidth(): WebGLUniformLocation | null;
|
|
58
|
+
get uMetaTexture(): WebGLUniformLocation | null;
|
|
59
|
+
get uDataTexSize(): WebGLUniformLocation | null;
|
|
60
|
+
get uCameraRight(): WebGLUniformLocation | null;
|
|
61
|
+
get uCameraUp(): WebGLUniformLocation | null;
|
|
62
|
+
get uCameraDir(): WebGLUniformLocation | null;
|
|
63
|
+
get uViewProjMatrix(): WebGLUniformLocation | null;
|
|
64
|
+
get uModelMatrix(): WebGLUniformLocation | null;
|
|
65
|
+
get uViewportAspect(): WebGLUniformLocation | null;
|
|
66
|
+
get uWorldAlpha(): WebGLUniformLocation | null;
|
|
67
|
+
get uTextures(): (WebGLUniformLocation | null)[];
|
|
68
|
+
get uTexRemaps(): (WebGLUniformLocation | null)[];
|
|
69
|
+
ensureIndexBuffer(maxParticles: number): void;
|
|
70
|
+
get vao(): WebGLVertexArrayObject;
|
|
71
|
+
get indexBuffer(): WebGLBuffer;
|
|
72
|
+
get aIdBuffer(): WebGLBuffer;
|
|
73
|
+
get aIdLocation(): number;
|
|
74
|
+
get indexType(): number;
|
|
75
|
+
/** Unbind any VAO (incl. OES on WebGL1) before raw attribute setup. */
|
|
76
|
+
unbindVao(): void;
|
|
77
|
+
destroy(): void;
|
|
78
|
+
private _probeWebGL1Capabilities;
|
|
79
|
+
/**
|
|
80
|
+
* Compile/link alone does not prove vertex texture fetch works on a
|
|
81
|
+
* driver — some fail only at draw time. One-time 1×1 smoke draw: a point
|
|
82
|
+
* whose color is produced by sampling a float and a byte texture in the
|
|
83
|
+
* vertex shader, rendered into a 1×1 RGBA8 FBO and read back.
|
|
84
|
+
*/
|
|
85
|
+
private _smokeTestVertexTextureFetch;
|
|
86
|
+
private _initShader;
|
|
87
|
+
private _compileShader;
|
|
88
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { NeutrinoContext } from "./NeutrinoContext";
|
|
2
|
+
import { DataTextureManager } from "./DataTextureManager";
|
|
3
|
+
import { DataTextureManagerGL1 } from "./gl1/DataTextureManagerGL1";
|
|
4
|
+
import { NeutrinoSubRect } from "./types";
|
|
5
|
+
export interface RenderParams {
|
|
6
|
+
/** Effect world transform (2x3) already including world scale. */
|
|
7
|
+
model: {
|
|
8
|
+
a: number;
|
|
9
|
+
b: number;
|
|
10
|
+
c: number;
|
|
11
|
+
d: number;
|
|
12
|
+
tx: number;
|
|
13
|
+
ty: number;
|
|
14
|
+
};
|
|
15
|
+
/** Canvas pixel dimensions, for the ortho projection. */
|
|
16
|
+
viewportWidth: number;
|
|
17
|
+
viewportHeight: number;
|
|
18
|
+
/** Camera scroll (subtracted in pixel space) and zoom. */
|
|
19
|
+
scrollX: number;
|
|
20
|
+
scrollY: number;
|
|
21
|
+
zoom: number;
|
|
22
|
+
/** Host scene-graph world alpha, multiplied into each particle's alpha. */
|
|
23
|
+
worldAlpha: number;
|
|
24
|
+
/** Per-particle GL textures (one per render-style texture index). */
|
|
25
|
+
glTextures: (WebGLTexture | null)[];
|
|
26
|
+
remaps: Array<NeutrinoSubRect | null>;
|
|
27
|
+
renderStyles: Array<{
|
|
28
|
+
materialIndex: number;
|
|
29
|
+
textureIndices: number[];
|
|
30
|
+
}>;
|
|
31
|
+
materials: number[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Raw WebGL data-texture renderer for the Phaser integration.
|
|
35
|
+
*
|
|
36
|
+
* Mirrors the pixi adapters: builds blend-mode batches (≤maxBatchTextures each),
|
|
37
|
+
* patches the per-particle texture-slot byte, uploads the data texture and draws
|
|
38
|
+
* each batch with gl.drawElements. On WebGL1 the u32-packed fields travel via an
|
|
39
|
+
* RGBA8 meta texture and the slot patch goes there instead of the float buffer
|
|
40
|
+
* (TDD_js-v1.1-webgl1.md §4.3/§4.6). Because Phaser owns the GL state machine,
|
|
41
|
+
* the caller is responsible for flushing Phaser's batch and restoring pipeline
|
|
42
|
+
* state around a render() call (see Effect.renderWebGL).
|
|
43
|
+
*/
|
|
44
|
+
export declare class NeutrinoRenderer {
|
|
45
|
+
private _orthoMatrix;
|
|
46
|
+
private _modelMatrix;
|
|
47
|
+
private _texSlotMap;
|
|
48
|
+
private _batchPool;
|
|
49
|
+
private _batchCount;
|
|
50
|
+
constructor();
|
|
51
|
+
render(ctx: NeutrinoContext, dtm: DataTextureManager | DataTextureManagerGL1, dataView: DataView, dataUint32: Uint32Array, instructions: any[], numParticles: number, params: RenderParams): void;
|
|
52
|
+
private _resolveBlend;
|
|
53
|
+
private _applyBlendMode;
|
|
54
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The class implements perspective projection transformation.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* // Create effect instance using loaded model
|
|
6
|
+
* let effect = new PIXINeutrino.Effect(resources.effectModel, {
|
|
7
|
+
* position: [400, 300, 0],
|
|
8
|
+
* projection: new PIXINeutrino.PerspectiveProjection(60.0)
|
|
9
|
+
* });
|
|
10
|
+
*
|
|
11
|
+
* @param {number} [horizontalAngle] Horizontal angle of the perspective projection in degrees.
|
|
12
|
+
*/
|
|
13
|
+
import { Vec2, Vec3 } from "./types";
|
|
14
|
+
export interface ScreenFrame {
|
|
15
|
+
x: number;
|
|
16
|
+
y: number;
|
|
17
|
+
width: number;
|
|
18
|
+
height: number;
|
|
19
|
+
}
|
|
20
|
+
export declare class PerspectiveProjection {
|
|
21
|
+
private _angleTan;
|
|
22
|
+
private _screenWidth;
|
|
23
|
+
private _screenPosX;
|
|
24
|
+
private _screenPosY;
|
|
25
|
+
private _z;
|
|
26
|
+
private _near;
|
|
27
|
+
set horizontalAngle(value: number);
|
|
28
|
+
constructor(horizontalAngle: number);
|
|
29
|
+
/**
|
|
30
|
+
* Changes horizontal angle of the projection.
|
|
31
|
+
*
|
|
32
|
+
* @param {number} value Angle in degrees.
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* Sets rendering frame for the projection.
|
|
36
|
+
*
|
|
37
|
+
* This method shouldn't be called manually when the class is used with effects. It is called
|
|
38
|
+
* on every render call for each effect automatically.
|
|
39
|
+
* @param {ScreenFrame} frame Rendering frame.
|
|
40
|
+
*/
|
|
41
|
+
setScreenFrame(frame: ScreenFrame): void;
|
|
42
|
+
/**
|
|
43
|
+
* Transforms 3D point accordingly to the projection.
|
|
44
|
+
*
|
|
45
|
+
* Basically, point's position X and Y components are simply scaled dependently on Z position. The method
|
|
46
|
+
* is used in WebGL and Canvas rendering.
|
|
47
|
+
*
|
|
48
|
+
* @param {Array} out [x, y] Transformed position.
|
|
49
|
+
* @param {Array} pos [x, y, z] Untransformed input vertex position.
|
|
50
|
+
* @returns false, if a particle is on the back side of the camera and should be discarded. Otherwise - true.
|
|
51
|
+
*/
|
|
52
|
+
transformPosition(out: Vec2, pos: Vec3): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Transforms 2D size of a particle accordingly to the projection.
|
|
55
|
+
*
|
|
56
|
+
* Basically, size is simply scaled dependently on Z position of a particle. The method is used
|
|
57
|
+
* only in Canvas rendering.
|
|
58
|
+
*
|
|
59
|
+
* @param {Array} outSize [width, height] Transformed size.
|
|
60
|
+
* @param {Array} pos [x, y, z] Untransformed particle position.
|
|
61
|
+
* @param {Array} size [width, height] Untransformed size.
|
|
62
|
+
*/
|
|
63
|
+
transformSize(outSize: Vec2, pos: Vec3, size: Vec2): void;
|
|
64
|
+
_getScale(pos: Vec3): number;
|
|
65
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { MetaTextureManager } from "./MetaTextureManager";
|
|
2
|
+
export declare class DataTextureManagerGL1 {
|
|
3
|
+
readonly textureWidth: number;
|
|
4
|
+
readonly textureHeight: number;
|
|
5
|
+
readonly meta: MetaTextureManager;
|
|
6
|
+
private readonly _gl;
|
|
7
|
+
private readonly _floatView;
|
|
8
|
+
private _dataTextures;
|
|
9
|
+
private _metaTextures;
|
|
10
|
+
private _currentIndex;
|
|
11
|
+
constructor(gl: WebGLRenderingContext, data: Uint32Array, textureWidth: number, textureHeight: number);
|
|
12
|
+
get currentDataTexture(): WebGLTexture;
|
|
13
|
+
get currentMetaTexture(): WebGLTexture;
|
|
14
|
+
/**
|
|
15
|
+
* Upload the rows covering `numParticles` into the current ring textures,
|
|
16
|
+
* leaving them bound to `dataUnit` / `metaUnit`. The caller invalidates
|
|
17
|
+
* PIXI's bound-texture bookkeeping for those units.
|
|
18
|
+
*/
|
|
19
|
+
upload(numParticles: number, dataUnit: number, metaUnit: number): void;
|
|
20
|
+
advance(): void;
|
|
21
|
+
destroy(): void;
|
|
22
|
+
private _createTexture;
|
|
23
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare class MetaTextureManager {
|
|
2
|
+
readonly bytes: Uint8Array;
|
|
3
|
+
private readonly _u32;
|
|
4
|
+
constructor(textureWidth: number, textureHeight: number);
|
|
5
|
+
/** Repack the packed-u32 record fields for the first `numParticles` records. */
|
|
6
|
+
build(dataUint32: Uint32Array, numParticles: number): void;
|
|
7
|
+
/** Write the batch texture slot into byte0 of M0 (flags) per particle. */
|
|
8
|
+
patchSlot(startParticle: number, count: number, slot: number): void;
|
|
9
|
+
}
|