@codexo/exojs-particles 0.15.3 → 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 +8 -15
- 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,58 +1,73 @@
|
|
|
1
|
-
import { UpdateModule } from
|
|
1
|
+
import { UpdateModule } from "./UpdateModule.js";
|
|
2
2
|
|
|
3
|
+
//#region src/modules/Turbulence.ts
|
|
3
4
|
/**
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
5
|
+
* Adds a smooth pseudo-random force field that animates over time.
|
|
6
|
+
* Implemented as 2D value noise with cubic Hermite smoothing - sampled
|
|
7
|
+
* twice per particle (offset to decorrelate x and y components) and scaled
|
|
8
|
+
* by `strength`. The field evolves at `timeScale` units per second; lower
|
|
9
|
+
* values produce slow-moving currents, higher values produce buzzy chaos.
|
|
10
|
+
*
|
|
11
|
+
* `frequency` controls the spatial granularity: small values (≈ 0.005)
|
|
12
|
+
* yield broad swirls across the playfield, large values (≈ 0.1) produce
|
|
13
|
+
* tight per-particle jitter.
|
|
14
|
+
*
|
|
15
|
+
* Use cases: smoke turbulence, organic swirls, wind eddies, dust haze.
|
|
16
|
+
* Pair with {@link Drag} to keep particle velocities bounded.
|
|
17
|
+
*
|
|
18
|
+
* GPU-eligible. The noise function is identical on CPU and GPU so visual
|
|
19
|
+
* results match across backends (modulo float precision).
|
|
20
|
+
*/
|
|
21
|
+
var Turbulence = class extends UpdateModule {
|
|
22
|
+
strength;
|
|
23
|
+
frequency;
|
|
24
|
+
timeScale;
|
|
25
|
+
_time = 0;
|
|
26
|
+
constructor(strength, frequency = .01, timeScale = 1) {
|
|
27
|
+
super();
|
|
28
|
+
this.strength = strength;
|
|
29
|
+
this.frequency = frequency;
|
|
30
|
+
this.timeScale = timeScale;
|
|
31
|
+
}
|
|
32
|
+
apply(particles, dt) {
|
|
33
|
+
this._time += dt * this.timeScale;
|
|
34
|
+
const t = this._time;
|
|
35
|
+
const f = this.frequency;
|
|
36
|
+
const s = this.strength * dt;
|
|
37
|
+
const { x: posX, y: posY } = particles.position;
|
|
38
|
+
const { x: velX, y: velY } = particles.velocity;
|
|
39
|
+
const liveCount = particles.count;
|
|
40
|
+
for (let i = 0; i < liveCount; i++) {
|
|
41
|
+
const x = (posX[i] ?? 0) * f;
|
|
42
|
+
const y = (posY[i] ?? 0) * f;
|
|
43
|
+
const nx = valueNoise2(x + t, y);
|
|
44
|
+
const ny = valueNoise2(x, y + t + 17.31);
|
|
45
|
+
velX[i] = (velX[i] ?? 0) + (nx * 2 - 1) * s;
|
|
46
|
+
velY[i] = (velY[i] ?? 0) + (ny * 2 - 1) * s;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
wgsl() {
|
|
50
|
+
return {
|
|
51
|
+
key: "Turbulence",
|
|
52
|
+
uniforms: [
|
|
53
|
+
{
|
|
54
|
+
name: "strength",
|
|
55
|
+
type: "f32"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: "frequency",
|
|
59
|
+
type: "f32"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: "time",
|
|
63
|
+
type: "f32"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: "_pad0",
|
|
67
|
+
type: "f32"
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
prelude: `
|
|
56
71
|
fn exojs_turbulence_hash21(p: vec2<f32>) -> f32 {
|
|
57
72
|
let n = sin(dot(p, vec2<f32>(127.1, 311.7))) * 43758.5453;
|
|
58
73
|
return fract(n);
|
|
@@ -74,7 +89,7 @@ fn exojs_turbulence_valueNoise2(x: f32, y: f32) -> f32 {
|
|
|
74
89
|
return ab + (cd - ab) * v;
|
|
75
90
|
}
|
|
76
91
|
`,
|
|
77
|
-
|
|
92
|
+
body: `
|
|
78
93
|
let turbF = modules.u_Turbulence.frequency;
|
|
79
94
|
let turbT = modules.u_Turbulence.time;
|
|
80
95
|
let turbS = modules.u_Turbulence.strength * dt;
|
|
@@ -83,40 +98,37 @@ fn exojs_turbulence_valueNoise2(x: f32, y: f32) -> f32 {
|
|
|
83
98
|
let turbNx = exojs_turbulence_valueNoise2(turbX + turbT, turbY);
|
|
84
99
|
let turbNy = exojs_turbulence_valueNoise2(turbX, turbY + turbT + 17.31);
|
|
85
100
|
velocities[idx] = velocities[idx] + vec2<f32>(turbNx * 2.0 - 1.0, turbNy * 2.0 - 1.0) * turbS;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const ab = a + (b - a) * u;
|
|
117
|
-
const cd = c + (d - c) * u;
|
|
118
|
-
return ab + (cd - ab) * v;
|
|
119
|
-
}
|
|
101
|
+
`
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
writeUniforms(view, offset, dt) {
|
|
105
|
+
this._time += dt * this.timeScale;
|
|
106
|
+
view.setFloat32(offset + 0, this.strength, true);
|
|
107
|
+
view.setFloat32(offset + 4, this.frequency, true);
|
|
108
|
+
view.setFloat32(offset + 8, this._time, true);
|
|
109
|
+
view.setFloat32(offset + 12, 0, true);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
const hash21 = (x, y) => {
|
|
113
|
+
let n = Math.sin(x * 127.1 + y * 311.7) * 43758.5453;
|
|
114
|
+
n = n - Math.floor(n);
|
|
115
|
+
return n;
|
|
116
|
+
};
|
|
117
|
+
const valueNoise2 = (x, y) => {
|
|
118
|
+
const xi = Math.floor(x);
|
|
119
|
+
const yi = Math.floor(y);
|
|
120
|
+
const xf = x - xi;
|
|
121
|
+
const yf = y - yi;
|
|
122
|
+
const u = xf * xf * (3 - 2 * xf);
|
|
123
|
+
const v = yf * yf * (3 - 2 * yf);
|
|
124
|
+
const a = hash21(xi, yi);
|
|
125
|
+
const b = hash21(xi + 1, yi);
|
|
126
|
+
const c = hash21(xi, yi + 1);
|
|
127
|
+
const d = hash21(xi + 1, yi + 1);
|
|
128
|
+
const ab = a + (b - a) * u;
|
|
129
|
+
return ab + (c + (d - c) * u - ab) * v;
|
|
130
|
+
};
|
|
120
131
|
|
|
132
|
+
//#endregion
|
|
121
133
|
export { Turbulence };
|
|
122
|
-
//# sourceMappingURL=Turbulence.js.map
|
|
134
|
+
//# sourceMappingURL=Turbulence.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Turbulence.js","sources":["
|
|
1
|
+
{"version":3,"file":"Turbulence.js","names":[],"sources":["../../../src/modules/Turbulence.ts"],"sourcesContent":["import type { ParticleBatch } from '#ParticleStorage';\n\nimport { UpdateModule } from './UpdateModule';\nimport type { WgslContribution } from './WgslContribution';\n\n/**\n * Adds a smooth pseudo-random force field that animates over time.\n * Implemented as 2D value noise with cubic Hermite smoothing - sampled\n * twice per particle (offset to decorrelate x and y components) and scaled\n * by `strength`. The field evolves at `timeScale` units per second; lower\n * values produce slow-moving currents, higher values produce buzzy chaos.\n *\n * `frequency` controls the spatial granularity: small values (≈ 0.005)\n * yield broad swirls across the playfield, large values (≈ 0.1) produce\n * tight per-particle jitter.\n *\n * Use cases: smoke turbulence, organic swirls, wind eddies, dust haze.\n * Pair with {@link Drag} to keep particle velocities bounded.\n *\n * GPU-eligible. The noise function is identical on CPU and GPU so visual\n * results match across backends (modulo float precision).\n */\nexport class Turbulence extends UpdateModule {\n public strength: number;\n public frequency: number;\n public timeScale: number;\n private _time = 0;\n\n public constructor(strength: number, frequency = 0.01, timeScale = 1) {\n super();\n this.strength = strength;\n this.frequency = frequency;\n this.timeScale = timeScale;\n }\n\n public override apply(particles: ParticleBatch, dt: number): void {\n this._time += dt * this.timeScale;\n const t = this._time;\n const f = this.frequency;\n const s = this.strength * dt;\n\n const { x: posX, y: posY } = particles.position;\n const { x: velX, y: velY } = particles.velocity;\n const liveCount = particles.count;\n\n for (let i = 0; i < liveCount; i++) {\n const x = (posX[i] ?? 0) * f;\n const y = (posY[i] ?? 0) * f;\n const nx = valueNoise2(x + t, y);\n const ny = valueNoise2(x, y + t + 17.31);\n\n velX[i] = (velX[i] ?? 0) + (nx * 2 - 1) * s;\n velY[i] = (velY[i] ?? 0) + (ny * 2 - 1) * s;\n }\n }\n\n public override wgsl(): WgslContribution {\n return {\n key: 'Turbulence',\n uniforms: [\n { name: 'strength', type: 'f32' },\n { name: 'frequency', type: 'f32' },\n { name: 'time', type: 'f32' },\n { name: '_pad0', type: 'f32' },\n ],\n prelude: `\nfn exojs_turbulence_hash21(p: vec2<f32>) -> f32 {\n let n = sin(dot(p, vec2<f32>(127.1, 311.7))) * 43758.5453;\n return fract(n);\n}\n\nfn exojs_turbulence_valueNoise2(x: f32, y: f32) -> f32 {\n let xi = floor(x);\n let yi = floor(y);\n let xf = x - xi;\n let yf = y - yi;\n let u = xf * xf * (3.0 - 2.0 * xf);\n let v = yf * yf * (3.0 - 2.0 * yf);\n let a = exojs_turbulence_hash21(vec2<f32>(xi, yi));\n let b = exojs_turbulence_hash21(vec2<f32>(xi + 1.0, yi));\n let c = exojs_turbulence_hash21(vec2<f32>(xi, yi + 1.0));\n let d = exojs_turbulence_hash21(vec2<f32>(xi + 1.0, yi + 1.0));\n let ab = a + (b - a) * u;\n let cd = c + (d - c) * u;\n return ab + (cd - ab) * v;\n}\n `,\n body: `\n let turbF = modules.u_Turbulence.frequency;\n let turbT = modules.u_Turbulence.time;\n let turbS = modules.u_Turbulence.strength * dt;\n let turbX = positions[idx].x * turbF;\n let turbY = positions[idx].y * turbF;\n let turbNx = exojs_turbulence_valueNoise2(turbX + turbT, turbY);\n let turbNy = exojs_turbulence_valueNoise2(turbX, turbY + turbT + 17.31);\n velocities[idx] = velocities[idx] + vec2<f32>(turbNx * 2.0 - 1.0, turbNy * 2.0 - 1.0) * turbS;\n `,\n };\n }\n\n public override writeUniforms(view: DataView, offset: number, dt: number): void {\n // GPU mode: apply() never runs, so advance _time here once per frame.\n // CPU mode: apply() already advances _time before update finishes,\n // and writeUniforms is not called → no double-advance.\n this._time += dt * this.timeScale;\n\n view.setFloat32(offset + 0, this.strength, true);\n view.setFloat32(offset + 4, this.frequency, true);\n view.setFloat32(offset + 8, this._time, true);\n view.setFloat32(offset + 12, 0, true);\n }\n}\n\nconst hash21 = (x: number, y: number): number => {\n let n = Math.sin(x * 127.1 + y * 311.7) * 43758.5453;\n n = n - Math.floor(n);\n return n;\n};\n\nconst valueNoise2 = (x: number, y: number): number => {\n const xi = Math.floor(x);\n const yi = Math.floor(y);\n const xf = x - xi;\n const yf = y - yi;\n\n const u = xf * xf * (3 - 2 * xf);\n const v = yf * yf * (3 - 2 * yf);\n\n const a = hash21(xi, yi);\n const b = hash21(xi + 1, yi);\n const c = hash21(xi, yi + 1);\n const d = hash21(xi + 1, yi + 1);\n\n const ab = a + (b - a) * u;\n const cd = c + (d - c) * u;\n return ab + (cd - ab) * v;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAsBA,IAAa,aAAb,cAAgC,aAAa;CAC3C,AAAO;CACP,AAAO;CACP,AAAO;CACP,AAAQ,QAAQ;CAEhB,AAAO,YAAY,UAAkB,YAAY,KAAM,YAAY,GAAG;EACpE,MAAM;EACN,KAAK,WAAW;EAChB,KAAK,YAAY;EACjB,KAAK,YAAY;CACnB;CAEA,AAAgB,MAAM,WAA0B,IAAkB;EAChE,KAAK,SAAS,KAAK,KAAK;EACxB,MAAM,IAAI,KAAK;EACf,MAAM,IAAI,KAAK;EACf,MAAM,IAAI,KAAK,WAAW;EAE1B,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,UAAU;EACvC,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,UAAU;EACvC,MAAM,YAAY,UAAU;EAE5B,KAAK,IAAI,IAAI,GAAG,IAAI,WAAW,KAAK;GAClC,MAAM,KAAK,KAAK,MAAM,KAAK;GAC3B,MAAM,KAAK,KAAK,MAAM,KAAK;GAC3B,MAAM,KAAK,YAAY,IAAI,GAAG,CAAC;GAC/B,MAAM,KAAK,YAAY,GAAG,IAAI,IAAI,KAAK;GAEvC,KAAK,MAAM,KAAK,MAAM,MAAM,KAAK,IAAI,KAAK;GAC1C,KAAK,MAAM,KAAK,MAAM,MAAM,KAAK,IAAI,KAAK;EAC5C;CACF;CAEA,AAAgB,OAAyB;EACvC,OAAO;GACL,KAAK;GACL,UAAU;IACR;KAAE,MAAM;KAAY,MAAM;IAAM;IAChC;KAAE,MAAM;KAAa,MAAM;IAAM;IACjC;KAAE,MAAM;KAAQ,MAAM;IAAM;IAC5B;KAAE,MAAM;KAAS,MAAM;IAAM;GAC/B;GACA,SAAS;;;;;;;;;;;;;;;;;;;;;;GAsBT,MAAM;;;;;;;;;;EAUR;CACF;CAEA,AAAgB,cAAc,MAAgB,QAAgB,IAAkB;EAI9E,KAAK,SAAS,KAAK,KAAK;EAExB,KAAK,WAAW,SAAS,GAAG,KAAK,UAAU,IAAI;EAC/C,KAAK,WAAW,SAAS,GAAG,KAAK,WAAW,IAAI;EAChD,KAAK,WAAW,SAAS,GAAG,KAAK,OAAO,IAAI;EAC5C,KAAK,WAAW,SAAS,IAAI,GAAG,IAAI;CACtC;AACF;AAEA,MAAM,UAAU,GAAW,MAAsB;CAC/C,IAAI,IAAI,KAAK,IAAI,IAAI,QAAQ,IAAI,KAAK,IAAI;CAC1C,IAAI,IAAI,KAAK,MAAM,CAAC;CACpB,OAAO;AACT;AAEA,MAAM,eAAe,GAAW,MAAsB;CACpD,MAAM,KAAK,KAAK,MAAM,CAAC;CACvB,MAAM,KAAK,KAAK,MAAM,CAAC;CACvB,MAAM,KAAK,IAAI;CACf,MAAM,KAAK,IAAI;CAEf,MAAM,IAAI,KAAK,MAAM,IAAI,IAAI;CAC7B,MAAM,IAAI,KAAK,MAAM,IAAI,IAAI;CAE7B,MAAM,IAAI,OAAO,IAAI,EAAE;CACvB,MAAM,IAAI,OAAO,KAAK,GAAG,EAAE;CAC3B,MAAM,IAAI,OAAO,IAAI,KAAK,CAAC;CAC3B,MAAM,IAAI,OAAO,KAAK,GAAG,KAAK,CAAC;CAE/B,MAAM,KAAK,KAAK,IAAI,KAAK;CAEzB,OAAO,MADI,KAAK,IAAI,KAAK,IACP,MAAM;AAC1B"}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ParticleBatch } from '#ParticleStorage';
|
|
2
2
|
import type { WgslContribution } from './WgslContribution';
|
|
3
3
|
/**
|
|
4
|
-
* Per-frame, per-batch mutator. Operates on the
|
|
5
|
-
*
|
|
6
|
-
* that reads
|
|
4
|
+
* Per-frame, per-batch mutator. Operates on the live particles through their
|
|
5
|
+
* named channels - typically a single tight loop over `[0, particles.count)`
|
|
6
|
+
* that reads and writes the channel arrays it needs.
|
|
7
7
|
*
|
|
8
8
|
* Implementations must always provide a CPU `apply()`. To make a module
|
|
9
9
|
* GPU-eligible (executed inside the system's composite compute shader on
|
|
10
10
|
* WebGPU backends), additionally implement {@link wgsl} and
|
|
11
11
|
* {@link writeUniforms}. Modules that declare a {@link WgslContribution}
|
|
12
12
|
* may also opt to declare a 1D texture binding via the `textures` field
|
|
13
|
-
* (used by `Curve` / `ColorGradient`-driven modules)
|
|
13
|
+
* (used by `Curve` / `ColorGradient`-driven modules) - in which case
|
|
14
14
|
* {@link uploadTextures} runs once at compile time to upload the data.
|
|
15
15
|
*
|
|
16
16
|
* Implementation pattern (CPU-only module):
|
|
17
17
|
*
|
|
18
18
|
* ```ts
|
|
19
19
|
* class MyModule extends UpdateModule {
|
|
20
|
-
* apply(
|
|
21
|
-
* const { velX, velY
|
|
22
|
-
* for (let i = 0; i <
|
|
20
|
+
* apply(particles, dt) {
|
|
21
|
+
* const { x: velX, y: velY } = particles.velocity;
|
|
22
|
+
* for (let i = 0; i < particles.count; i++) { velX[i] *= 0.99; velY[i] *= 0.99; }
|
|
23
23
|
* }
|
|
24
24
|
* }
|
|
25
25
|
* ```
|
|
@@ -30,9 +30,9 @@ import type { WgslContribution } from './WgslContribution';
|
|
|
30
30
|
* class MyForce extends UpdateModule {
|
|
31
31
|
* constructor(public ax: number, public ay: number) { super(); }
|
|
32
32
|
*
|
|
33
|
-
* apply(
|
|
34
|
-
* const { velX, velY
|
|
35
|
-
* for (let i = 0; i <
|
|
33
|
+
* apply(particles, dt) {
|
|
34
|
+
* const { x: velX, y: velY } = particles.velocity;
|
|
35
|
+
* for (let i = 0; i < particles.count; i++) { velX[i] += this.ax * dt; velY[i] += this.ay * dt; }
|
|
36
36
|
* }
|
|
37
37
|
*
|
|
38
38
|
* wgsl(): WgslContribution {
|
|
@@ -51,7 +51,7 @@ import type { WgslContribution } from './WgslContribution';
|
|
|
51
51
|
* ```
|
|
52
52
|
*
|
|
53
53
|
* If *any* registered update module on a system lacks `wgsl()`, the system
|
|
54
|
-
* forces CPU mode regardless of backend
|
|
54
|
+
* forces CPU mode regardless of backend - preserving the contract that
|
|
55
55
|
* `apply()` is always honoured. Built-in modules ship both
|
|
56
56
|
* implementations; custom modules can opt into GPU acceleration at their
|
|
57
57
|
* authors' discretion.
|
|
@@ -60,7 +60,14 @@ import type { WgslContribution } from './WgslContribution';
|
|
|
60
60
|
* in registration order; later modules see the effects of earlier ones.
|
|
61
61
|
*/
|
|
62
62
|
export declare abstract class UpdateModule {
|
|
63
|
-
|
|
63
|
+
/**
|
|
64
|
+
* Mutates the live particles for one frame.
|
|
65
|
+
*
|
|
66
|
+
* Runs only on the CPU path: a system whose modules are all GPU-eligible
|
|
67
|
+
* executes {@link wgsl} bodies inside its compute shader instead, and never
|
|
68
|
+
* calls this.
|
|
69
|
+
*/
|
|
70
|
+
abstract apply(particles: ParticleBatch, dt: number): void;
|
|
64
71
|
/**
|
|
65
72
|
* Override to declare a GPU contribution. Returning a {@link WgslContribution}
|
|
66
73
|
* makes this module GPU-eligible; omitting (or returning undefined)
|
|
@@ -93,3 +100,4 @@ export declare abstract class UpdateModule {
|
|
|
93
100
|
/** Optional cleanup hook called from `ParticleSystem.destroy`. */
|
|
94
101
|
destroy(): void;
|
|
95
102
|
}
|
|
103
|
+
//# sourceMappingURL=UpdateModule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UpdateModule.d.ts","sourceRoot":"","sources":["../../../src/modules/UpdateModule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,8BAAsB,YAAY;IAChC;;;;;;OAMG;aACa,KAAK,CAAC,SAAS,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAEjE;;;;OAIG;IACI,IAAI,CAAC,IAAI,gBAAgB;IAEhC;;;;;;;;;;;;OAYG;IACI,aAAa,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAE3E;;;;;;;OAOG;IACI,cAAc,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,IAAI;IAE1F,kEAAkE;IAC3D,OAAO,IAAI,IAAI;CACvB"}
|
|
@@ -1,66 +1,68 @@
|
|
|
1
|
+
//#region src/modules/UpdateModule.ts
|
|
1
2
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
3
|
+
* Per-frame, per-batch mutator. Operates on the live particles through their
|
|
4
|
+
* named channels - typically a single tight loop over `[0, particles.count)`
|
|
5
|
+
* that reads and writes the channel arrays it needs.
|
|
6
|
+
*
|
|
7
|
+
* Implementations must always provide a CPU `apply()`. To make a module
|
|
8
|
+
* GPU-eligible (executed inside the system's composite compute shader on
|
|
9
|
+
* WebGPU backends), additionally implement {@link wgsl} and
|
|
10
|
+
* {@link writeUniforms}. Modules that declare a {@link WgslContribution}
|
|
11
|
+
* may also opt to declare a 1D texture binding via the `textures` field
|
|
12
|
+
* (used by `Curve` / `ColorGradient`-driven modules) - in which case
|
|
13
|
+
* {@link uploadTextures} runs once at compile time to upload the data.
|
|
14
|
+
*
|
|
15
|
+
* Implementation pattern (CPU-only module):
|
|
16
|
+
*
|
|
17
|
+
* ```ts
|
|
18
|
+
* class MyModule extends UpdateModule {
|
|
19
|
+
* apply(particles, dt) {
|
|
20
|
+
* const { x: velX, y: velY } = particles.velocity;
|
|
21
|
+
* for (let i = 0; i < particles.count; i++) { velX[i] *= 0.99; velY[i] *= 0.99; }
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* Implementation pattern (GPU-eligible module):
|
|
27
|
+
*
|
|
28
|
+
* ```ts
|
|
29
|
+
* class MyForce extends UpdateModule {
|
|
30
|
+
* constructor(public ax: number, public ay: number) { super(); }
|
|
31
|
+
*
|
|
32
|
+
* apply(particles, dt) {
|
|
33
|
+
* const { x: velX, y: velY } = particles.velocity;
|
|
34
|
+
* for (let i = 0; i < particles.count; i++) { velX[i] += this.ax * dt; velY[i] += this.ay * dt; }
|
|
35
|
+
* }
|
|
36
|
+
*
|
|
37
|
+
* wgsl(): WgslContribution {
|
|
38
|
+
* return {
|
|
39
|
+
* key: 'MyForce',
|
|
40
|
+
* uniforms: [{ name: 'ax', type: 'f32' }, { name: 'ay', type: 'f32' }],
|
|
41
|
+
* body: `velX[idx] += u_MyForce.ax * dt; velY[idx] += u_MyForce.ay * dt;`,
|
|
42
|
+
* };
|
|
43
|
+
* }
|
|
44
|
+
*
|
|
45
|
+
* writeUniforms(view, offset) {
|
|
46
|
+
* view.setFloat32(offset + 0, this.ax, true);
|
|
47
|
+
* view.setFloat32(offset + 4, this.ay, true);
|
|
48
|
+
* }
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* If *any* registered update module on a system lacks `wgsl()`, the system
|
|
53
|
+
* forces CPU mode regardless of backend - preserving the contract that
|
|
54
|
+
* `apply()` is always honoured. Built-in modules ship both
|
|
55
|
+
* implementations; custom modules can opt into GPU acceleration at their
|
|
56
|
+
* authors' discretion.
|
|
57
|
+
*
|
|
58
|
+
* Update modules run after integration each frame. Multiple modules execute
|
|
59
|
+
* in registration order; later modules see the effects of earlier ones.
|
|
60
|
+
*/
|
|
61
|
+
var UpdateModule = class {
|
|
62
|
+
/** Optional cleanup hook called from `ParticleSystem.destroy`. */
|
|
63
|
+
destroy() {}
|
|
64
|
+
};
|
|
64
65
|
|
|
66
|
+
//#endregion
|
|
65
67
|
export { UpdateModule };
|
|
66
|
-
//# sourceMappingURL=UpdateModule.js.map
|
|
68
|
+
//# sourceMappingURL=UpdateModule.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UpdateModule.js","sources":["
|
|
1
|
+
{"version":3,"file":"UpdateModule.js","names":[],"sources":["../../../src/modules/UpdateModule.ts"],"sourcesContent":["import type { ParticleBatch } from '#ParticleStorage';\n\nimport type { WgslContribution } from './WgslContribution';\n\n/**\n * Per-frame, per-batch mutator. Operates on the live particles through their\n * named channels - typically a single tight loop over `[0, particles.count)`\n * that reads and writes the channel arrays it needs.\n *\n * Implementations must always provide a CPU `apply()`. To make a module\n * GPU-eligible (executed inside the system's composite compute shader on\n * WebGPU backends), additionally implement {@link wgsl} and\n * {@link writeUniforms}. Modules that declare a {@link WgslContribution}\n * may also opt to declare a 1D texture binding via the `textures` field\n * (used by `Curve` / `ColorGradient`-driven modules) - in which case\n * {@link uploadTextures} runs once at compile time to upload the data.\n *\n * Implementation pattern (CPU-only module):\n *\n * ```ts\n * class MyModule extends UpdateModule {\n * apply(particles, dt) {\n * const { x: velX, y: velY } = particles.velocity;\n * for (let i = 0; i < particles.count; i++) { velX[i] *= 0.99; velY[i] *= 0.99; }\n * }\n * }\n * ```\n *\n * Implementation pattern (GPU-eligible module):\n *\n * ```ts\n * class MyForce extends UpdateModule {\n * constructor(public ax: number, public ay: number) { super(); }\n *\n * apply(particles, dt) {\n * const { x: velX, y: velY } = particles.velocity;\n * for (let i = 0; i < particles.count; i++) { velX[i] += this.ax * dt; velY[i] += this.ay * dt; }\n * }\n *\n * wgsl(): WgslContribution {\n * return {\n * key: 'MyForce',\n * uniforms: [{ name: 'ax', type: 'f32' }, { name: 'ay', type: 'f32' }],\n * body: `velX[idx] += u_MyForce.ax * dt; velY[idx] += u_MyForce.ay * dt;`,\n * };\n * }\n *\n * writeUniforms(view, offset) {\n * view.setFloat32(offset + 0, this.ax, true);\n * view.setFloat32(offset + 4, this.ay, true);\n * }\n * }\n * ```\n *\n * If *any* registered update module on a system lacks `wgsl()`, the system\n * forces CPU mode regardless of backend - preserving the contract that\n * `apply()` is always honoured. Built-in modules ship both\n * implementations; custom modules can opt into GPU acceleration at their\n * authors' discretion.\n *\n * Update modules run after integration each frame. Multiple modules execute\n * in registration order; later modules see the effects of earlier ones.\n */\nexport abstract class UpdateModule {\n /**\n * Mutates the live particles for one frame.\n *\n * Runs only on the CPU path: a system whose modules are all GPU-eligible\n * executes {@link wgsl} bodies inside its compute shader instead, and never\n * calls this.\n */\n public abstract apply(particles: ParticleBatch, dt: number): void;\n\n /**\n * Override to declare a GPU contribution. Returning a {@link WgslContribution}\n * makes this module GPU-eligible; omitting (or returning undefined)\n * forces CPU mode for any system that uses this module.\n */\n public wgsl?(): WgslContribution;\n\n /**\n * Write this module's current uniform values into the shared uniform\n * buffer at `byteOffset`. Layout must match the field declarations\n * returned by {@link wgsl} (in the same order).\n *\n * Receives the current frame `dt` (seconds). Modules tracking\n * accumulated time (e.g. noise/turbulence) should advance their\n * internal counter here to stay in sync when running in GPU mode\n * (where {@link apply} is not called).\n *\n * Required when {@link wgsl} declares uniforms. Called every frame by\n * the system before dispatching compute.\n */\n public writeUniforms?(view: DataView, byteOffset: number, dt: number): void;\n\n /**\n * Upload texture data (Curve/ColorGradient lookup tables) to the GPU at\n * compile time. Receives the GPUDevice and a map of texture bindings\n * keyed by the `name` in {@link WgslContribution.textures}. Called once\n * after pipeline creation.\n *\n * Required when {@link wgsl} declares textures.\n */\n public uploadTextures?(device: GPUDevice, textures: ReadonlyMap<string, GPUTexture>): void;\n\n /** Optional cleanup hook called from `ParticleSystem.destroy`. */\n public destroy(): void {}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+DA,IAAsB,eAAtB,MAAmC;;CA2CjC,AAAO,UAAgB,CAAC;AAC1B"}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import type { Curve } from
|
|
2
|
-
import type {
|
|
1
|
+
import type { Curve } from '#distributions/Curve';
|
|
2
|
+
import type { ParticleBatch } from '#ParticleStorage';
|
|
3
3
|
import { UpdateModule } from './UpdateModule';
|
|
4
4
|
import type { WgslContribution } from './WgslContribution';
|
|
5
5
|
/**
|
|
6
6
|
* Multiplies every live particle's velocity by a curve sampled at the
|
|
7
7
|
* particle's current `elapsed / lifetime` ratio. The same scalar is applied
|
|
8
|
-
* to both axes
|
|
8
|
+
* to both axes - the direction is preserved, only the magnitude scales.
|
|
9
9
|
*
|
|
10
10
|
* Common patterns:
|
|
11
|
-
* - **Snappy spawn, slow drift:** `[0,1]→[1,0.1]`
|
|
11
|
+
* - **Snappy spawn, slow drift:** `[0,1]→[1,0.1]` - fast initial motion
|
|
12
12
|
* that decays over lifetime.
|
|
13
|
-
* - **Late acceleration:** `[0,0.2]→[1,1]`
|
|
13
|
+
* - **Late acceleration:** `[0,0.2]→[1,1]` - particles ease in.
|
|
14
14
|
* - **Pulse:** sine-shaped curve for breathing-style motion.
|
|
15
15
|
*
|
|
16
16
|
* Note: the curve **replaces** velocity each frame relative to the previous
|
|
@@ -24,7 +24,8 @@ export declare class VelocityOverLifetime extends UpdateModule {
|
|
|
24
24
|
curve: Curve;
|
|
25
25
|
private _prevSample;
|
|
26
26
|
constructor(curve: Curve);
|
|
27
|
-
apply(
|
|
27
|
+
apply(particles: ParticleBatch, _dt: number): void;
|
|
28
28
|
wgsl(): WgslContribution;
|
|
29
29
|
uploadTextures(device: GPUDevice, textures: ReadonlyMap<string, GPUTexture>): void;
|
|
30
30
|
}
|
|
31
|
+
//# sourceMappingURL=VelocityOverLifetime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VelocityOverLifetime.d.ts","sourceRoot":"","sources":["../../../src/modules/VelocityOverLifetime.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAI3D;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,oBAAqB,SAAQ,YAAY;IAC7C,KAAK,EAAE,KAAK,CAAC;IAEpB,OAAO,CAAC,WAAW,CAAuB;gBAEvB,KAAK,EAAE,KAAK;IAKf,KAAK,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IA2BlD,IAAI,IAAI,gBAAgB;IAsBxB,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,IAAI;CAoBnG"}
|