@codexo/exojs-particles 0.15.2 → 0.16.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/README.md +21 -43
- package/dist/esm/ParticleStorage.d.ts +188 -0
- package/dist/esm/ParticleStorage.d.ts.map +1 -0
- package/dist/esm/ParticleStorage.js +208 -0
- package/dist/esm/ParticleStorage.js.map +1 -0
- package/dist/esm/ParticleSystem.d.ts +189 -60
- package/dist/esm/ParticleSystem.d.ts.map +1 -0
- package/dist/esm/ParticleSystem.js +660 -560
- package/dist/esm/ParticleSystem.js.map +1 -1
- package/dist/esm/distributions/BoxArea.d.ts +1 -0
- package/dist/esm/distributions/BoxArea.d.ts.map +1 -0
- package/dist/esm/distributions/BoxArea.js +38 -44
- package/dist/esm/distributions/BoxArea.js.map +1 -1
- package/dist/esm/distributions/CircleArea.d.ts +1 -0
- package/dist/esm/distributions/CircleArea.d.ts.map +1 -0
- package/dist/esm/distributions/CircleArea.js +30 -28
- package/dist/esm/distributions/CircleArea.js.map +1 -1
- package/dist/esm/distributions/ColorGradient.d.ts +3 -2
- package/dist/esm/distributions/ColorGradient.d.ts.map +1 -0
- package/dist/esm/distributions/ColorGradient.js +70 -75
- package/dist/esm/distributions/ColorGradient.js.map +1 -1
- package/dist/esm/distributions/ConeDirection.d.ts +2 -1
- package/dist/esm/distributions/ConeDirection.d.ts.map +1 -0
- package/dist/esm/distributions/ConeDirection.js +41 -39
- package/dist/esm/distributions/ConeDirection.js.map +1 -1
- package/dist/esm/distributions/Constant.d.ts +1 -0
- package/dist/esm/distributions/Constant.d.ts.map +1 -0
- package/dist/esm/distributions/Constant.js +32 -32
- package/dist/esm/distributions/Constant.js.map +1 -1
- package/dist/esm/distributions/Curve.d.ts +2 -1
- package/dist/esm/distributions/Curve.d.ts.map +1 -0
- package/dist/esm/distributions/Curve.js +46 -55
- package/dist/esm/distributions/Curve.js.map +1 -1
- package/dist/esm/distributions/Distribution.d.ts +4 -3
- package/dist/esm/distributions/Distribution.d.ts.map +1 -0
- package/dist/esm/distributions/LineSegment.d.ts +1 -0
- package/dist/esm/distributions/LineSegment.d.ts.map +1 -0
- package/dist/esm/distributions/LineSegment.js +25 -23
- package/dist/esm/distributions/LineSegment.js.map +1 -1
- package/dist/esm/distributions/Range.d.ts +1 -0
- package/dist/esm/distributions/Range.d.ts.map +1 -0
- package/dist/esm/distributions/Range.js +18 -16
- package/dist/esm/distributions/Range.js.map +1 -1
- package/dist/esm/distributions/VectorRange.d.ts +1 -0
- package/dist/esm/distributions/VectorRange.d.ts.map +1 -0
- package/dist/esm/distributions/VectorRange.js +29 -27
- package/dist/esm/distributions/VectorRange.js.map +1 -1
- package/dist/esm/distributions/index.d.ts +1 -0
- package/dist/esm/distributions/index.d.ts.map +1 -0
- package/dist/esm/gpu/ParticleGpuState.d.ts +143 -18
- package/dist/esm/gpu/ParticleGpuState.d.ts.map +1 -0
- package/dist/esm/gpu/ParticleGpuState.js +655 -497
- package/dist/esm/gpu/ParticleGpuState.js.map +1 -1
- package/dist/esm/gpu/shaders/particle-simulate.wgsl.js +6 -0
- package/dist/esm/gpu/shaders/particle-simulate.wgsl.js.map +1 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +39 -32
- package/dist/esm/modules/AlphaFadeOverLifetime.d.ts +4 -3
- package/dist/esm/modules/AlphaFadeOverLifetime.d.ts.map +1 -0
- package/dist/esm/modules/AlphaFadeOverLifetime.js +68 -55
- package/dist/esm/modules/AlphaFadeOverLifetime.js.map +1 -1
- package/dist/esm/modules/ApplyForce.d.ts +4 -3
- package/dist/esm/modules/ApplyForce.d.ts.map +1 -0
- package/dist/esm/modules/ApplyForce.js +49 -43
- package/dist/esm/modules/ApplyForce.js.map +1 -1
- package/dist/esm/modules/AttractToPoint.d.ts +4 -3
- package/dist/esm/modules/AttractToPoint.d.ts.map +1 -0
- package/dist/esm/modules/AttractToPoint.js +73 -62
- package/dist/esm/modules/AttractToPoint.js.map +1 -1
- package/dist/esm/modules/BurstSpawn.d.ts +6 -18
- package/dist/esm/modules/BurstSpawn.d.ts.map +1 -0
- package/dist/esm/modules/BurstSpawn.js +56 -91
- package/dist/esm/modules/BurstSpawn.js.map +1 -1
- package/dist/esm/modules/ColorOverLifetime.d.ts +4 -3
- package/dist/esm/modules/ColorOverLifetime.d.ts.map +1 -0
- package/dist/esm/modules/ColorOverLifetime.js +65 -53
- package/dist/esm/modules/ColorOverLifetime.js.map +1 -1
- package/dist/esm/modules/ColorOverSpeed.d.ts +5 -4
- package/dist/esm/modules/ColorOverSpeed.d.ts.map +1 -0
- package/dist/esm/modules/ColorOverSpeed.js +90 -75
- package/dist/esm/modules/ColorOverSpeed.js.map +1 -1
- package/dist/esm/modules/DeathModule.d.ts +26 -10
- package/dist/esm/modules/DeathModule.d.ts.map +1 -0
- package/dist/esm/modules/DeathModule.js +38 -22
- package/dist/esm/modules/DeathModule.js.map +1 -1
- package/dist/esm/modules/Drag.d.ts +3 -2
- package/dist/esm/modules/Drag.d.ts.map +1 -0
- package/dist/esm/modules/Drag.js +43 -37
- package/dist/esm/modules/Drag.js.map +1 -1
- package/dist/esm/modules/OrbitalForce.d.ts +4 -3
- package/dist/esm/modules/OrbitalForce.d.ts.map +1 -0
- package/dist/esm/modules/OrbitalForce.js +70 -58
- package/dist/esm/modules/OrbitalForce.js.map +1 -1
- package/dist/esm/modules/RateSpawn.d.ts +7 -22
- package/dist/esm/modules/RateSpawn.d.ts.map +1 -0
- package/dist/esm/modules/RateSpawn.js +39 -71
- package/dist/esm/modules/RateSpawn.js.map +1 -1
- package/dist/esm/modules/RepelFromPoint.d.ts +4 -3
- package/dist/esm/modules/RepelFromPoint.d.ts.map +1 -0
- package/dist/esm/modules/RepelFromPoint.js +72 -62
- package/dist/esm/modules/RepelFromPoint.js.map +1 -1
- package/dist/esm/modules/RotateOverLifetime.d.ts +3 -2
- package/dist/esm/modules/RotateOverLifetime.d.ts.map +1 -0
- package/dist/esm/modules/RotateOverLifetime.js +40 -36
- package/dist/esm/modules/RotateOverLifetime.js.map +1 -1
- package/dist/esm/modules/ScaleOverLifetime.d.ts +5 -4
- package/dist/esm/modules/ScaleOverLifetime.d.ts.map +1 -0
- package/dist/esm/modules/ScaleOverLifetime.js +60 -50
- package/dist/esm/modules/ScaleOverLifetime.js.map +1 -1
- package/dist/esm/modules/SpawnModule.d.ts +15 -12
- package/dist/esm/modules/SpawnModule.d.ts.map +1 -0
- package/dist/esm/modules/SpawnModule.js +32 -28
- package/dist/esm/modules/SpawnModule.js.map +1 -1
- package/dist/esm/modules/SpawnOnDeath.d.ts +13 -9
- package/dist/esm/modules/SpawnOnDeath.d.ts.map +1 -0
- package/dist/esm/modules/SpawnOnDeath.js +41 -43
- package/dist/esm/modules/SpawnOnDeath.js.map +1 -1
- package/dist/esm/modules/Turbulence.d.ts +4 -3
- package/dist/esm/modules/Turbulence.d.ts.map +1 -0
- package/dist/esm/modules/Turbulence.js +101 -89
- package/dist/esm/modules/Turbulence.js.map +1 -1
- package/dist/esm/modules/UpdateModule.d.ts +21 -13
- package/dist/esm/modules/UpdateModule.d.ts.map +1 -0
- package/dist/esm/modules/UpdateModule.js +65 -63
- package/dist/esm/modules/UpdateModule.js.map +1 -1
- package/dist/esm/modules/VelocityOverLifetime.d.ts +7 -6
- package/dist/esm/modules/VelocityOverLifetime.d.ts.map +1 -0
- package/dist/esm/modules/VelocityOverLifetime.js +75 -73
- package/dist/esm/modules/VelocityOverLifetime.js.map +1 -1
- package/dist/esm/modules/WgslContribution.d.ts +16 -15
- package/dist/esm/modules/WgslContribution.d.ts.map +1 -0
- package/dist/esm/modules/WgslContribution.js +37 -29
- package/dist/esm/modules/WgslContribution.js.map +1 -1
- package/dist/esm/modules/index.d.ts +3 -1
- package/dist/esm/modules/index.d.ts.map +1 -0
- package/dist/esm/modules/spawnFields.d.ts +32 -0
- package/dist/esm/modules/spawnFields.d.ts.map +1 -0
- package/dist/esm/modules/spawnFields.js +31 -0
- package/dist/esm/modules/spawnFields.js.map +1 -0
- package/dist/esm/particlesBuildInfo.d.ts +1 -0
- package/dist/esm/particlesBuildInfo.d.ts.map +1 -0
- package/dist/esm/particlesBuildInfo.js +6 -4
- package/dist/esm/particlesBuildInfo.js.map +1 -1
- package/dist/esm/particlesExtension.d.ts +13 -5
- package/dist/esm/particlesExtension.d.ts.map +1 -0
- package/dist/esm/particlesExtension.js +38 -42
- package/dist/esm/particlesExtension.js.map +1 -1
- package/dist/esm/public.d.ts +11 -0
- package/dist/esm/public.d.ts.map +1 -0
- package/dist/esm/renderModes/MeshParticles.d.ts +128 -0
- package/dist/esm/renderModes/MeshParticles.d.ts.map +1 -0
- package/dist/esm/renderModes/MeshParticles.js +263 -0
- package/dist/esm/renderModes/MeshParticles.js.map +1 -0
- package/dist/esm/renderModes/ParticleBufferLayout.d.ts +59 -0
- package/dist/esm/renderModes/ParticleBufferLayout.d.ts.map +1 -0
- package/dist/esm/renderModes/ParticleBufferLayout.js +99 -0
- package/dist/esm/renderModes/ParticleBufferLayout.js.map +1 -0
- package/dist/esm/renderModes/ParticleInstanceWriter.d.ts +58 -0
- package/dist/esm/renderModes/ParticleInstanceWriter.d.ts.map +1 -0
- package/dist/esm/renderModes/ParticleInstanceWriter.js +173 -0
- package/dist/esm/renderModes/ParticleInstanceWriter.js.map +1 -0
- package/dist/esm/renderModes/ParticleMaterial.d.ts +18 -0
- package/dist/esm/renderModes/ParticleMaterial.d.ts.map +1 -0
- package/dist/esm/renderModes/ParticleMaterial.js +24 -0
- package/dist/esm/renderModes/ParticleMaterial.js.map +1 -0
- package/dist/esm/renderModes/ParticleRenderMode.d.ts +114 -0
- package/dist/esm/renderModes/ParticleRenderMode.d.ts.map +1 -0
- package/dist/esm/renderModes/ParticleRenderMode.js +99 -0
- package/dist/esm/renderModes/ParticleRenderMode.js.map +1 -0
- package/dist/esm/renderModes/QuadParticles.d.ts +55 -0
- package/dist/esm/renderModes/QuadParticles.d.ts.map +1 -0
- package/dist/esm/renderModes/QuadParticles.js +95 -0
- package/dist/esm/renderModes/QuadParticles.js.map +1 -0
- package/dist/esm/renderModes/RibbonParticles.d.ts +96 -0
- package/dist/esm/renderModes/RibbonParticles.d.ts.map +1 -0
- package/dist/esm/renderModes/RibbonParticles.js +202 -0
- package/dist/esm/renderModes/RibbonParticles.js.map +1 -0
- package/dist/esm/renderModes/shaders/mesh-particles.wgsl.js +6 -0
- package/dist/esm/renderModes/shaders/mesh-particles.wgsl.js.map +1 -0
- package/dist/esm/renderModes/shaders/mesh.vert.js +6 -0
- package/dist/esm/renderModes/shaders/mesh.vert.js.map +1 -0
- package/dist/esm/renderModes/shaders/quad-particles.wgsl.js +6 -0
- package/dist/esm/renderModes/shaders/quad-particles.wgsl.js.map +1 -0
- package/dist/esm/renderModes/shaders/ribbon-particles.wgsl.js +6 -0
- package/dist/esm/renderModes/shaders/ribbon-particles.wgsl.js.map +1 -0
- package/dist/esm/renderModes/shaders/ribbon.frag.js +6 -0
- package/dist/esm/renderModes/shaders/ribbon.frag.js.map +1 -0
- package/dist/esm/renderModes/shaders/ribbon.vert.js +6 -0
- package/dist/esm/renderModes/shaders/ribbon.vert.js.map +1 -0
- package/dist/esm/renderers/WebGl2ParticleRenderer.d.ts +48 -20
- package/dist/esm/renderers/WebGl2ParticleRenderer.d.ts.map +1 -0
- package/dist/esm/renderers/WebGl2ParticleRenderer.js +317 -321
- package/dist/esm/renderers/WebGl2ParticleRenderer.js.map +1 -1
- package/dist/esm/renderers/WebGpuParticleRenderer.d.ts +99 -18
- package/dist/esm/renderers/WebGpuParticleRenderer.d.ts.map +1 -0
- package/dist/esm/renderers/WebGpuParticleRenderer.js +542 -551
- package/dist/esm/renderers/WebGpuParticleRenderer.js.map +1 -1
- package/dist/esm/renderers/shaders/particle.frag.js +6 -0
- package/dist/esm/renderers/shaders/particle.frag.js.map +1 -0
- package/dist/esm/renderers/shaders/particle.vert.js +6 -0
- package/dist/esm/renderers/shaders/particle.vert.js.map +1 -0
- package/package.json +7 -14
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/register.d.ts +0 -1
- package/dist/esm/register.js +0 -43
- package/dist/esm/register.js.map +0 -1
- package/dist/esm/renderers/glsl/particle.frag.js +0 -4
- package/dist/esm/renderers/glsl/particle.frag.js.map +0 -1
- package/dist/esm/renderers/glsl/particle.vert.js +0 -4
- package/dist/esm/renderers/glsl/particle.vert.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Seconds } from '@codexo/exojs';
|
|
2
2
|
import { Rectangle } from '@codexo/exojs';
|
|
3
3
|
import { Drawable } from '@codexo/exojs';
|
|
4
4
|
import { Spritesheet } from '@codexo/exojs';
|
|
@@ -8,8 +8,11 @@ import { ParticleGpuState } from '#gpu/ParticleGpuState';
|
|
|
8
8
|
import type { DeathModule } from '#modules/DeathModule';
|
|
9
9
|
import type { SpawnModule } from '#modules/SpawnModule';
|
|
10
10
|
import type { UpdateModule } from '#modules/UpdateModule';
|
|
11
|
+
import type { ParticleEmitter, ParticleWriter } from '#ParticleStorage';
|
|
12
|
+
import { ParticleStorage } from '#ParticleStorage';
|
|
13
|
+
import type { ParticleRenderMode } from '#renderModes/ParticleRenderMode';
|
|
11
14
|
/**
|
|
12
|
-
* Options for {@link ParticleSystem}'s constructor
|
|
15
|
+
* Options for {@link ParticleSystem}'s constructor - orthogonal config
|
|
13
16
|
* that's independent of the texture source. Texture / frames / spritesheet
|
|
14
17
|
* live in positional arguments to enforce mutual exclusivity at the type
|
|
15
18
|
* level (you can't pass both a texture and a spritesheet by accident).
|
|
@@ -21,30 +24,51 @@ export interface ParticleSystemOptions {
|
|
|
21
24
|
* Direct GPU device. Lets advanced consumers wire a `GPUDevice` owned
|
|
22
25
|
* outside an `Application` (or a mock device in tests). When omitted,
|
|
23
26
|
* the backend reference is captured automatically on the first
|
|
24
|
-
* {@link ParticleSystem.render} call
|
|
27
|
+
* {@link ParticleSystem.render} call - `WebGpuBackend` ⇒ GPU mode,
|
|
25
28
|
* anything else (incl. WebGL2) ⇒ CPU mode.
|
|
26
29
|
*/
|
|
27
30
|
device?: GPUDevice;
|
|
31
|
+
/**
|
|
32
|
+
* How this system's particles become vertices. Fixed at construction. A mode
|
|
33
|
+
* with `gpuEligible === false` forces the system onto the CPU path -
|
|
34
|
+
* silently, exactly like an update module without a `wgsl()` implementation,
|
|
35
|
+
* and observable through {@link ParticleSystem.gpuMode}.
|
|
36
|
+
*
|
|
37
|
+
* **Ownership.** A mode passed here belongs to the system: the system
|
|
38
|
+
* destroys it in {@link ParticleSystem.destroy}, which destroys the mode's
|
|
39
|
+
* material and geometry and releases the GPU resources cached against them.
|
|
40
|
+
* Pass one mode instance per system. Handing the same instance to two
|
|
41
|
+
* systems is not supported - destroying either one pulls the material out
|
|
42
|
+
* from under the other, which then silently rebuilds a fresh material and
|
|
43
|
+
* pays for a fresh shader compile mid-life. Two systems that should share
|
|
44
|
+
* one program simply omit this option; the default mode is shared for
|
|
45
|
+
* exactly that reason and is not owned by any system.
|
|
46
|
+
*
|
|
47
|
+
* @default a process-wide shared {@link QuadParticles}
|
|
48
|
+
*/
|
|
49
|
+
readonly render?: ParticleRenderMode;
|
|
28
50
|
}
|
|
29
51
|
/**
|
|
30
52
|
* The central coordinator of the particle pipeline. `ParticleSystem` is a
|
|
31
53
|
* {@link Drawable} that owns:
|
|
32
54
|
*
|
|
33
|
-
* - **
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* - **
|
|
55
|
+
* - **Particle storage** - one channel per attribute (position, velocity,
|
|
56
|
+
* scale, rotation, color, timing, ...), sized to a fixed capacity at
|
|
57
|
+
* construction. Modules and render modes address it by name through a
|
|
58
|
+
* {@link ParticleBatch}; user code brings particles into existence with
|
|
59
|
+
* {@link emit}.
|
|
60
|
+
* - **Spawn modules** - fill freshly emitted particles.
|
|
61
|
+
* - **Update modules** - mutate the live range each frame (forces, color
|
|
39
62
|
* blends, scale curves, drag, ...). Built-in modules ship both CPU and
|
|
40
63
|
* WGSL implementations; custom modules can opt into GPU acceleration by
|
|
41
64
|
* implementing `wgsl()`.
|
|
42
|
-
* - **Death modules**
|
|
65
|
+
* - **Death modules** - fire once per dying particle, before its slot is
|
|
43
66
|
* recycled (sub-emitters, event hooks).
|
|
44
67
|
*
|
|
45
68
|
* **Auto-routing CPU vs GPU:** at first {@link update}, the system checks:
|
|
46
69
|
* if a `WebGpuBackend` was supplied AND every registered update module has
|
|
47
|
-
* `wgsl()
|
|
70
|
+
* `wgsl()` AND the render mode is GPU-eligible, the GPU path engages - a
|
|
71
|
+
* composite compute pipeline runs
|
|
48
72
|
* integration plus all module bodies in one dispatch and writes directly
|
|
49
73
|
* into the renderer's instance buffer (no CPU readback). Otherwise the CPU
|
|
50
74
|
* path runs the existing per-module `apply()` loops.
|
|
@@ -60,21 +84,28 @@ export interface ParticleSystemOptions {
|
|
|
60
84
|
* 1. Run every spawn module (CPU writes initial values into the spawn slot).
|
|
61
85
|
* 2. Detect expiries on CPU (via `elapsed >= lifetime`); fire death modules;
|
|
62
86
|
* set `lifetime[slot] = -1` sentinel + clear `alive[slot]` so the GPU
|
|
63
|
-
* shader skips them. **No compaction**
|
|
87
|
+
* shader skips them. **No compaction** - slots are recycled on next spawn.
|
|
64
88
|
* 3. Dispatch the composite compute pipeline. Integration + update modules
|
|
65
89
|
* + pack-instances run in one pass; the instance buffer is written
|
|
66
90
|
* directly. CPU SoA stays as-is for spawn writes.
|
|
67
91
|
*
|
|
68
92
|
* **Coordinate space:** particle positions are LOCAL to the system. The
|
|
69
|
-
* system's `getGlobalTransform()` is applied on top during rendering
|
|
93
|
+
* system's `getGlobalTransform()` is applied on top during rendering - both
|
|
70
94
|
* the WebGL2 and WebGPU shaders multiply `projection * translation * rotated`.
|
|
71
95
|
* Setting world-space positions on individual particles double-translates.
|
|
72
96
|
* Position the system itself via `system.setPosition(...)` and emit relative
|
|
73
97
|
* to `(0, 0)`.
|
|
74
98
|
*
|
|
99
|
+
* **Pixel snapping:** {@link Drawable.pixelSnapMode} is intentionally ignored
|
|
100
|
+
* for particle systems. Particle instances bake their own per-particle
|
|
101
|
+
* transforms in the emitter/compute path rather than reading the shared
|
|
102
|
+
* pixel-snap transform row, so a snap mode set on the system has no effect on
|
|
103
|
+
* rendered output - snapping thousands of independently-moving sub-pixel
|
|
104
|
+
* particles to the device grid is neither meaningful nor desirable.
|
|
105
|
+
*
|
|
75
106
|
* @example
|
|
76
|
-
* // Backend-agnostic
|
|
77
|
-
* const system = new ParticleSystem(loader.get(
|
|
107
|
+
* // Backend-agnostic - runs CPU on WebGL2, GPU on WebGPU automatically.
|
|
108
|
+
* const system = new ParticleSystem(loader.get('spark.png'), {
|
|
78
109
|
* capacity: 8192,
|
|
79
110
|
* });
|
|
80
111
|
*
|
|
@@ -83,35 +114,18 @@ export interface ParticleSystemOptions {
|
|
|
83
114
|
* system.addUpdateModule(new ColorOverLifetime(fireGradient));
|
|
84
115
|
* scene.addChild(system);
|
|
85
116
|
*/
|
|
86
|
-
export declare class ParticleSystem extends Drawable {
|
|
117
|
+
export declare class ParticleSystem extends Drawable implements ParticleEmitter {
|
|
87
118
|
/** Maximum particle count this system will store. Fixed at construction. */
|
|
88
119
|
readonly capacity: number;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
readonly
|
|
97
|
-
|
|
98
|
-
readonly elapsed: Float32Array;
|
|
99
|
-
readonly lifetime: Float32Array;
|
|
100
|
-
readonly textureIndex: Uint16Array;
|
|
101
|
-
/**
|
|
102
|
-
* Number of currently live particles. In CPU mode this is exact: slots
|
|
103
|
-
* `[0, liveCount)` are all alive after each `update()`. In GPU mode
|
|
104
|
-
* this is a high-water mark — slots `[0, liveCount)` may contain dead
|
|
105
|
-
* holes (filled in by future spawns); use {@link aliveCount} for the
|
|
106
|
-
* actual alive count.
|
|
107
|
-
*/
|
|
108
|
-
liveCount: number;
|
|
109
|
-
/**
|
|
110
|
-
* Per-slot alive flag (1 = alive, 0 = dead). Maintained in both CPU
|
|
111
|
-
* and GPU mode. Custom modules iterating the live range should check
|
|
112
|
-
* this to skip dead slots in GPU mode.
|
|
113
|
-
*/
|
|
114
|
-
readonly alive: Uint8Array;
|
|
120
|
+
/**
|
|
121
|
+
* The simulation's channel storage. Handed to update modules and render modes
|
|
122
|
+
* as a {@link ParticleBatch}; never exposed as a property of the system,
|
|
123
|
+
* because outside those two callbacks its integrated values are not
|
|
124
|
+
* backend-true.
|
|
125
|
+
* @internal
|
|
126
|
+
*/
|
|
127
|
+
readonly _storage: ParticleStorage;
|
|
128
|
+
private _writer;
|
|
115
129
|
private readonly _spawnModules;
|
|
116
130
|
private readonly _updateModules;
|
|
117
131
|
private readonly _deathModules;
|
|
@@ -125,9 +139,31 @@ export declare class ParticleSystem extends Drawable {
|
|
|
125
139
|
* In GPU mode, slots whose CPU SoA values need re-uploading to the GPU
|
|
126
140
|
* (newly spawned, or just-expired with lifetime sentinel). Cleared
|
|
127
141
|
* after each compute dispatch. CPU never overwrites integrated GPU
|
|
128
|
-
* state
|
|
142
|
+
* state - only dirty slots flow CPU → GPU.
|
|
129
143
|
*/
|
|
130
144
|
private readonly _gpuDirtySlots;
|
|
145
|
+
/**
|
|
146
|
+
* Spawn lifetimes, in death order per slot, of the particles that expired
|
|
147
|
+
* since the last batch the device staged for readback. The device's own
|
|
148
|
+
* record cannot carry them: by the time the shader sees the particle, the CPU
|
|
149
|
+
* has already overwritten its lifetime with the expiry sentinel. A slot can
|
|
150
|
+
* appear more than once when it is recycled and dies again before the batch
|
|
151
|
+
* is staged, so the lifetimes queue up per slot.
|
|
152
|
+
*/
|
|
153
|
+
private _pendingDeathLifetimes;
|
|
154
|
+
/** Total entries across `_pendingDeathLifetimes`, which is what the dispatch reports. */
|
|
155
|
+
private _pendingDeathCount;
|
|
156
|
+
/** Whether this system has already reported that its death backlog overflowed. */
|
|
157
|
+
private _deathOverflowReported;
|
|
158
|
+
/**
|
|
159
|
+
* Slots handed out by `spawn()` while a recording window is open, or `null`
|
|
160
|
+
* when nothing is recording. Lets callers identify freshly spawned particles
|
|
161
|
+
* without diffing `liveCount`, which cannot see a recycled GPU slot.
|
|
162
|
+
*/
|
|
163
|
+
private _spawnRecord;
|
|
164
|
+
private readonly _renderMode;
|
|
165
|
+
/** Whether {@link destroy} may destroy {@link _renderMode} - false for the shared default. */
|
|
166
|
+
private readonly _ownsRenderMode;
|
|
131
167
|
private _texture;
|
|
132
168
|
private readonly _frames;
|
|
133
169
|
private readonly _textureFrame;
|
|
@@ -135,22 +171,32 @@ export declare class ParticleSystem extends Drawable {
|
|
|
135
171
|
private readonly _texCoords;
|
|
136
172
|
private _updateTexCoords;
|
|
137
173
|
private _updateVertices;
|
|
138
|
-
/** No texture
|
|
174
|
+
/** No texture - particles render as solid-color quads on a 1×1 white default. */
|
|
139
175
|
constructor(options?: ParticleSystemOptions);
|
|
140
|
-
/** Single texture, no atlas
|
|
176
|
+
/** Single texture, no atlas - every particle uses the full texture as one frame. */
|
|
141
177
|
constructor(texture: Texture, options?: ParticleSystemOptions);
|
|
142
|
-
/** Multi-frame atlas
|
|
178
|
+
/** Multi-frame atlas - each particle's `textureIndex` selects a frame. */
|
|
143
179
|
constructor(texture: Texture, frames: readonly Rectangle[], options?: ParticleSystemOptions);
|
|
144
|
-
/** Spritesheet shorthand
|
|
180
|
+
/** Spritesheet shorthand - texture + frames pulled from the sheet. */
|
|
145
181
|
constructor(spritesheet: Spritesheet, options?: ParticleSystemOptions);
|
|
182
|
+
/**
|
|
183
|
+
* The render mode this system's particles are drawn with. Fixed at
|
|
184
|
+
* construction via `ParticleSystemOptions.render`; the backend renderers
|
|
185
|
+
* read it every draw to learn the vertex layout, shader and draw model.
|
|
186
|
+
*
|
|
187
|
+
* Without that option this is the shared default mode - the same instance
|
|
188
|
+
* every other defaulted system draws with, so do not destroy it or mutate
|
|
189
|
+
* its material.
|
|
190
|
+
*/
|
|
191
|
+
get renderMode(): ParticleRenderMode;
|
|
146
192
|
get texture(): Texture;
|
|
147
193
|
set texture(texture: Texture);
|
|
148
194
|
get textureFrame(): Rectangle;
|
|
149
195
|
set textureFrame(frame: Rectangle);
|
|
150
196
|
/**
|
|
151
197
|
* Atlas frames declared on this system, or empty when the texture is
|
|
152
|
-
* used as a single frame. Each particle's
|
|
153
|
-
* an entry from this list; out
|
|
198
|
+
* used as a single frame. Each particle's {@link textureIndex} selects
|
|
199
|
+
* an entry from this list; anything out of range shows frame 0.
|
|
154
200
|
*/
|
|
155
201
|
get frames(): readonly Rectangle[];
|
|
156
202
|
/** `true` when the system declares more than one atlas frame. */
|
|
@@ -161,7 +207,15 @@ export declare class ParticleSystem extends Drawable {
|
|
|
161
207
|
get gpuMode(): boolean;
|
|
162
208
|
/** GPU-side state, or `null` in CPU mode. */
|
|
163
209
|
get gpuState(): ParticleGpuState | null;
|
|
164
|
-
/**
|
|
210
|
+
/**
|
|
211
|
+
* Upper bound of the slot range that can hold live particles.
|
|
212
|
+
*
|
|
213
|
+
* Exact on the CPU path: after each `update()` slots `[0, liveCount)` are all
|
|
214
|
+
* alive. On the GPU path it is a high-water mark whose range can contain dead
|
|
215
|
+
* holes that future emissions fill; {@link aliveCount} counts the live ones.
|
|
216
|
+
*/
|
|
217
|
+
get liveCount(): number;
|
|
218
|
+
/** Actual count of live particles. May be below {@link liveCount} on the GPU path. */
|
|
165
219
|
get aliveCount(): number;
|
|
166
220
|
get spawnModules(): readonly SpawnModule[];
|
|
167
221
|
get updateModules(): readonly UpdateModule[];
|
|
@@ -170,23 +224,83 @@ export declare class ParticleSystem extends Drawable {
|
|
|
170
224
|
setTextureFrame(frame: Rectangle): this;
|
|
171
225
|
resetTextureFrame(): this;
|
|
172
226
|
addSpawnModule(mod: SpawnModule): this;
|
|
227
|
+
/**
|
|
228
|
+
* Registers an update module. Modules run in registration order, each seeing
|
|
229
|
+
* what the previous ones did.
|
|
230
|
+
*
|
|
231
|
+
* Modules may be added and removed at any time, including mid-flight: the
|
|
232
|
+
* next update rebuilds whatever the change invalidated. On the GPU path that
|
|
233
|
+
* is the compute program alone - live particles keep the state the device has
|
|
234
|
+
* been integrating. Adding a module without a `wgsl()` implementation to a
|
|
235
|
+
* running GPU system is the one change that cannot preserve them: the
|
|
236
|
+
* simulation moves to the CPU, which has no copy of the integrated state, so
|
|
237
|
+
* the system clears its live particles rather than continuing from stale
|
|
238
|
+
* values (see {@link clearParticles}).
|
|
239
|
+
*/
|
|
173
240
|
addUpdateModule(mod: UpdateModule): this;
|
|
174
241
|
addDeathModule(mod: DeathModule): this;
|
|
175
242
|
clearSpawnModules(): this;
|
|
176
243
|
clearUpdateModules(): this;
|
|
177
244
|
clearDeathModules(): this;
|
|
178
245
|
/**
|
|
179
|
-
*
|
|
180
|
-
* the system is at {@link capacity}.
|
|
246
|
+
* Brings one particle into existence and returns a writer for its initial
|
|
247
|
+
* values, or `null` when the system is at {@link capacity}.
|
|
181
248
|
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
249
|
+
* The particle starts at the spawn defaults - origin, no velocity, unit
|
|
250
|
+
* scale, no rotation, opaque white, frame 0, one second of life - so a caller
|
|
251
|
+
* writes only what it varies. The returned writer is a cursor that the next
|
|
252
|
+
* `emit()` rebinds, so it must not be stored.
|
|
184
253
|
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
254
|
+
* Emission is the only per-particle write that is true on every backend:
|
|
255
|
+
* spawn values originate on the CPU and are uploaded from there, while
|
|
256
|
+
* everything the simulation integrates afterwards lives wherever the
|
|
257
|
+
* simulation runs.
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* ```ts
|
|
261
|
+
* const particle = system.emit();
|
|
262
|
+
*
|
|
263
|
+
* if (particle) {
|
|
264
|
+
* particle.position.set(120, 40);
|
|
265
|
+
* particle.velocity.set(0, -80);
|
|
266
|
+
* particle.lifetime = 2;
|
|
267
|
+
* }
|
|
268
|
+
* ```
|
|
269
|
+
*/
|
|
270
|
+
emit(): ParticleWriter | null;
|
|
271
|
+
/**
|
|
272
|
+
* Allocates one slot at the spawn defaults and returns its index, or `-1` at
|
|
273
|
+
* capacity. Backs {@link emit}; the simulation's own machinery addresses
|
|
274
|
+
* particles by slot, the public surface does not.
|
|
275
|
+
* @internal
|
|
188
276
|
*/
|
|
189
|
-
|
|
277
|
+
_spawnSlot(): number;
|
|
278
|
+
/**
|
|
279
|
+
* Begin recording the slots handed out by {@link spawn}.
|
|
280
|
+
*
|
|
281
|
+
* Callers that post-process freshly spawned particles cannot infer which
|
|
282
|
+
* slots those are from {@link liveCount}: in GPU mode a spawn may recycle a
|
|
283
|
+
* dead slot below the high-water mark, leaving the count unchanged, and the
|
|
284
|
+
* reused slots are scattered rather than contiguous. Pass the returned token
|
|
285
|
+
* back to {@link _endSpawnRecording}.
|
|
286
|
+
*
|
|
287
|
+
* @internal
|
|
288
|
+
*/
|
|
289
|
+
_beginSpawnRecording(): number[] | null;
|
|
290
|
+
/**
|
|
291
|
+
* End the recording started by {@link _beginSpawnRecording} and return the
|
|
292
|
+
* slots allocated during it. Slots are also handed to an enclosing recording
|
|
293
|
+
* so a nested spawn stays visible to the outer window.
|
|
294
|
+
*
|
|
295
|
+
* @internal
|
|
296
|
+
*/
|
|
297
|
+
_endSpawnRecording(previous: number[] | null): readonly number[];
|
|
298
|
+
/**
|
|
299
|
+
* Shifts the particles a sub-emitter just produced by `(x, y)`, so a child
|
|
300
|
+
* spawner's distributions read as offsets from the death position.
|
|
301
|
+
* @internal
|
|
302
|
+
*/
|
|
303
|
+
_offsetSpawned(slots: readonly number[], x: number, y: number): void;
|
|
190
304
|
/** Resets the system to zero live particles without destroying it. */
|
|
191
305
|
clearParticles(): this;
|
|
192
306
|
/**
|
|
@@ -200,12 +314,27 @@ export declare class ParticleSystem extends Drawable {
|
|
|
200
314
|
/** @internal */
|
|
201
315
|
_collect(builder: RenderPlanBuilder, seq?: number): void;
|
|
202
316
|
/** Per-frame entry point. Routes to CPU or GPU pipeline based on auto-detection at first call. */
|
|
203
|
-
update(delta:
|
|
317
|
+
update(delta: Seconds): this;
|
|
204
318
|
destroy(): void;
|
|
319
|
+
/**
|
|
320
|
+
* Marks the compiled program stale. The next update decides what that costs:
|
|
321
|
+
* a GPU system that stays GPU-eligible rebuilds only its program, everything
|
|
322
|
+
* else follows the transition rules in {@link _compile}.
|
|
323
|
+
*/
|
|
324
|
+
private _invalidateProgram;
|
|
205
325
|
private _compile;
|
|
206
326
|
private _spawnCpu;
|
|
207
327
|
private _spawnGpu;
|
|
328
|
+
private _claimGpuSlot;
|
|
208
329
|
private _updateCpu;
|
|
330
|
+
/** Hands one death snapshot to every registered death module, in registration order. */
|
|
331
|
+
private _reportDeath;
|
|
209
332
|
private _updateGpu;
|
|
210
|
-
|
|
333
|
+
/**
|
|
334
|
+
* Delivers a staged batch of deaths once its readback has landed. Each record
|
|
335
|
+
* carries what the device integrated; the lifetime comes from the CPU, which
|
|
336
|
+
* is where it was written at spawn.
|
|
337
|
+
*/
|
|
338
|
+
private _drainDeaths;
|
|
211
339
|
}
|
|
340
|
+
//# sourceMappingURL=ParticleSystem.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ParticleSystem.d.ts","sourceRoot":"","sources":["../../src/ParticleSystem.ts"],"names":[],"mappings":"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"}
|