@cyberluke/three-particles 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +197 -0
- package/dist/index.d.ts +2970 -0
- package/dist/index.js +3138 -0
- package/dist/index.js.map +1 -0
- package/dist/three-particles.min.js +1 -0
- package/dist/three-particles.min.js.map +1 -0
- package/dist/webgpu.js +2522 -0
- package/dist/webgpu.js.map +1 -0
- package/llms-full.txt +1005 -0
- package/llms.txt +339 -0
- package/package.json +111 -0
- package/webgpu.d.ts +98 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,2970 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { FBM } from 'three-noise/build/three-noise.module.js';
|
|
3
|
+
|
|
4
|
+
declare const REVISION: string;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Standard IEC 61966-2-1 sRGB → linear transfer function.
|
|
8
|
+
* Matches `THREE.ColorManagement.SRGBToLinear` and the GLSL
|
|
9
|
+
* `ShaderChunk.colorspace_fragment` implementation, so that user-provided
|
|
10
|
+
* colors go through the exact same conversion the rest of the Three.js
|
|
11
|
+
* pipeline uses for sRGB-tagged inputs.
|
|
12
|
+
*
|
|
13
|
+
* Input: a channel value in [0, 1] interpreted as sRGB.
|
|
14
|
+
* Output: the corresponding linear value in [0, 1].
|
|
15
|
+
*/
|
|
16
|
+
declare const sRGBToLinear: (c: number) => number;
|
|
17
|
+
/**
|
|
18
|
+
* Standard IEC 61966-2-1 linear → sRGB transfer function.
|
|
19
|
+
* Inverse of {@link sRGBToLinear}. Useful for one-shot migration of
|
|
20
|
+
* legacy color values that were authored under the old raw-byte pipeline.
|
|
21
|
+
*/
|
|
22
|
+
declare const linearToSRGB: (c: number) => number;
|
|
23
|
+
/**
|
|
24
|
+
* Converts an sRGB {r, g, b} triplet to linear space.
|
|
25
|
+
* Used when uploading user-authored colors (e.g. `backgroundColor`) as
|
|
26
|
+
* shader uniforms that must match the linear-space texture samples and
|
|
27
|
+
* vertex colors used elsewhere in the pipeline. Missing channels default
|
|
28
|
+
* to 0 to mirror the permissive shape of the `Rgb` config type.
|
|
29
|
+
*/
|
|
30
|
+
declare const rgbSRGBToLinear: (c: {
|
|
31
|
+
r?: number;
|
|
32
|
+
g?: number;
|
|
33
|
+
b?: number;
|
|
34
|
+
}) => {
|
|
35
|
+
r: number;
|
|
36
|
+
g: number;
|
|
37
|
+
b: number;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Defines the coordinate space in which particles are simulated.
|
|
42
|
+
*
|
|
43
|
+
* @enum {string}
|
|
44
|
+
*/
|
|
45
|
+
declare const enum SimulationSpace {
|
|
46
|
+
/**
|
|
47
|
+
* Particles move relative to the emitter's local coordinate system.
|
|
48
|
+
* When the emitter moves or rotates, particles move with it.
|
|
49
|
+
* Ideal for effects attached to moving objects (e.g., engine trails, character auras).
|
|
50
|
+
*/
|
|
51
|
+
LOCAL = "LOCAL",
|
|
52
|
+
/**
|
|
53
|
+
* Particles move in world space and are independent of the emitter's transform.
|
|
54
|
+
* Once emitted, particles remain stationary or move according to their velocity in world coordinates.
|
|
55
|
+
* Ideal for environmental effects (e.g., smoke, explosions, ambient particles).
|
|
56
|
+
*/
|
|
57
|
+
WORLD = "WORLD"
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Defines the geometric shape from which particles are emitted.
|
|
61
|
+
*
|
|
62
|
+
* @enum {string}
|
|
63
|
+
*/
|
|
64
|
+
declare const enum Shape {
|
|
65
|
+
/**
|
|
66
|
+
* Emit particles from a spherical volume or shell.
|
|
67
|
+
* Configure with {@link Sphere} properties (radius, arc, radiusThickness).
|
|
68
|
+
*/
|
|
69
|
+
SPHERE = "SPHERE",
|
|
70
|
+
/**
|
|
71
|
+
* Emit particles from a conical volume or shell.
|
|
72
|
+
* Configure with {@link Cone} properties (angle, radius, arc, radiusThickness).
|
|
73
|
+
* Useful for directional effects like fire, smoke plumes, or spray effects.
|
|
74
|
+
*/
|
|
75
|
+
CONE = "CONE",
|
|
76
|
+
/**
|
|
77
|
+
* Emit particles from a box volume, shell, or edges.
|
|
78
|
+
* Configure with {@link Box} properties (scale, emitFrom).
|
|
79
|
+
* Useful for area-based effects like dust clouds or rain.
|
|
80
|
+
*/
|
|
81
|
+
BOX = "BOX",
|
|
82
|
+
/**
|
|
83
|
+
* Emit particles from a circular area or edge.
|
|
84
|
+
* Configure with {@link Circle} properties (radius, arc, radiusThickness).
|
|
85
|
+
* Useful for ground impacts, rings, or radial effects.
|
|
86
|
+
*/
|
|
87
|
+
CIRCLE = "CIRCLE",
|
|
88
|
+
/**
|
|
89
|
+
* Emit particles from a rectangular area.
|
|
90
|
+
* Configure with {@link Rectangle} properties (scale, rotation).
|
|
91
|
+
* Useful for planar effects like rain on a surface or screen effects.
|
|
92
|
+
*/
|
|
93
|
+
RECTANGLE = "RECTANGLE"
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Defines where on a shape particles are emitted from.
|
|
97
|
+
* Not all shapes support all emit modes.
|
|
98
|
+
*
|
|
99
|
+
* @enum {string}
|
|
100
|
+
*/
|
|
101
|
+
declare const enum EmitFrom {
|
|
102
|
+
/**
|
|
103
|
+
* Emit particles from random positions within the entire volume of the shape.
|
|
104
|
+
* Supported by: SPHERE, CONE, BOX.
|
|
105
|
+
*/
|
|
106
|
+
VOLUME = "VOLUME",
|
|
107
|
+
/**
|
|
108
|
+
* Emit particles from the surface/shell of the shape.
|
|
109
|
+
* Supported by: SPHERE, CONE, BOX.
|
|
110
|
+
*/
|
|
111
|
+
SHELL = "SHELL",
|
|
112
|
+
/**
|
|
113
|
+
* Emit particles from the edges of the shape.
|
|
114
|
+
* Supported by: BOX.
|
|
115
|
+
*/
|
|
116
|
+
EDGE = "EDGE"
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Defines how texture sheet animation is timed.
|
|
120
|
+
*
|
|
121
|
+
* @enum {string}
|
|
122
|
+
*/
|
|
123
|
+
declare const enum TimeMode {
|
|
124
|
+
/**
|
|
125
|
+
* Animation frames are based on the particle's lifetime percentage.
|
|
126
|
+
* The animation completes once over the particle's lifetime.
|
|
127
|
+
*/
|
|
128
|
+
LIFETIME = "LIFETIME",
|
|
129
|
+
/**
|
|
130
|
+
* Animation frames are based on frames per second (FPS).
|
|
131
|
+
* The animation runs at a fixed speed regardless of particle lifetime.
|
|
132
|
+
*/
|
|
133
|
+
FPS = "FPS"
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Defines the type of curve function used for animating values over a particle's lifetime.
|
|
137
|
+
*
|
|
138
|
+
* @enum {string}
|
|
139
|
+
*/
|
|
140
|
+
declare const enum LifeTimeCurve {
|
|
141
|
+
/**
|
|
142
|
+
* Use custom Bezier curves with control points.
|
|
143
|
+
* Provides maximum control over the animation curve shape.
|
|
144
|
+
* See {@link BezierCurve} for configuration.
|
|
145
|
+
*/
|
|
146
|
+
BEZIER = "BEZIER",
|
|
147
|
+
/**
|
|
148
|
+
* Use predefined easing functions (e.g., easeInQuad, easeOutCubic).
|
|
149
|
+
* Convenient for common animation patterns.
|
|
150
|
+
* See {@link EasingCurve} and {@link CurveFunctionId} for available functions.
|
|
151
|
+
*/
|
|
152
|
+
EASING = "EASING"
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Defines when a sub-emitter is triggered relative to a particle's lifecycle.
|
|
156
|
+
*
|
|
157
|
+
* @enum {string}
|
|
158
|
+
*/
|
|
159
|
+
declare const enum SubEmitterTrigger {
|
|
160
|
+
/**
|
|
161
|
+
* Trigger the sub-emitter when a particle is born (activated).
|
|
162
|
+
* Useful for trail effects that start immediately with each particle.
|
|
163
|
+
*/
|
|
164
|
+
BIRTH = "BIRTH",
|
|
165
|
+
/**
|
|
166
|
+
* Trigger the sub-emitter when a particle dies (reaches end of lifetime).
|
|
167
|
+
* Useful for cascading effects like explosions spawning smoke.
|
|
168
|
+
*/
|
|
169
|
+
DEATH = "DEATH"
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Defines the type of force field that affects particles.
|
|
173
|
+
*
|
|
174
|
+
* @enum {string}
|
|
175
|
+
*/
|
|
176
|
+
declare const enum ForceFieldType {
|
|
177
|
+
/**
|
|
178
|
+
* Attract or repel particles toward/from a point in space.
|
|
179
|
+
* Positive strength attracts, negative strength repels.
|
|
180
|
+
* Configure with position, strength, range, and falloff.
|
|
181
|
+
*/
|
|
182
|
+
POINT = "POINT",
|
|
183
|
+
/**
|
|
184
|
+
* Apply a constant directional force to all particles (like wind).
|
|
185
|
+
* Configure with direction and strength.
|
|
186
|
+
*/
|
|
187
|
+
DIRECTIONAL = "DIRECTIONAL"
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Defines the rendering technique used for particles.
|
|
191
|
+
*
|
|
192
|
+
* @enum {string}
|
|
193
|
+
*/
|
|
194
|
+
declare const enum RendererType {
|
|
195
|
+
/**
|
|
196
|
+
* Render particles as point sprites using `THREE.Points`.
|
|
197
|
+
* This is the default renderer, efficient for small to medium particle counts.
|
|
198
|
+
* Note: point size is limited by `gl_PointSize` hardware caps (typically 64–256 px).
|
|
199
|
+
*/
|
|
200
|
+
POINTS = "POINTS",
|
|
201
|
+
/**
|
|
202
|
+
* Render particles as camera-facing quads using `THREE.InstancedBufferGeometry`.
|
|
203
|
+
* Removes the `gl_PointSize` hardware limit, supports stretched billboards,
|
|
204
|
+
* and enables batching multiple emitters into fewer draw calls.
|
|
205
|
+
* Recommended for 10 000+ particles or when large on-screen particle sizes are needed.
|
|
206
|
+
*/
|
|
207
|
+
INSTANCED = "INSTANCED",
|
|
208
|
+
/**
|
|
209
|
+
* Render each particle as a ribbon trail connecting its current and previous positions.
|
|
210
|
+
* Each particle stores a configurable number of position history samples, and the
|
|
211
|
+
* renderer builds a camera-facing triangle-strip ribbon through those samples.
|
|
212
|
+
*
|
|
213
|
+
* Trail width and opacity can taper along the ribbon length for effects like
|
|
214
|
+
* sword slashes, magic missiles, comet tails, and speed lines.
|
|
215
|
+
*
|
|
216
|
+
* Configure trail-specific properties via {@link TrailConfig} on the renderer.
|
|
217
|
+
*/
|
|
218
|
+
TRAIL = "TRAIL",
|
|
219
|
+
/**
|
|
220
|
+
* Render each particle as a 3D mesh using GPU instancing (`InstancedBufferGeometry`).
|
|
221
|
+
* Instead of flat billboard sprites, particles are rendered as real 3D geometry
|
|
222
|
+
* (e.g., cubes, spheres, tori, or any custom `THREE.BufferGeometry`).
|
|
223
|
+
*
|
|
224
|
+
* Key differences from billboard renderers:
|
|
225
|
+
* - **3D rotation**: Particles rotate in all three axes (quaternion-based).
|
|
226
|
+
* - **Normals**: Mesh geometry retains normals, enabling basic lighting.
|
|
227
|
+
* - **Arbitrary geometry**: Any `THREE.BufferGeometry` can be used per particle.
|
|
228
|
+
*
|
|
229
|
+
* All existing modifiers (sizeOverLifetime, colorOverLifetime, noise, force fields,
|
|
230
|
+
* sub-emitters) work with mesh particles.
|
|
231
|
+
*
|
|
232
|
+
* Configure mesh-specific properties via {@link MeshConfig} on the renderer.
|
|
233
|
+
*/
|
|
234
|
+
MESH = "MESH"
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Defines how force diminishes with distance from a POINT force field center.
|
|
238
|
+
* Only applicable to {@link ForceFieldType.POINT} force fields.
|
|
239
|
+
*
|
|
240
|
+
* @enum {string}
|
|
241
|
+
*/
|
|
242
|
+
declare const enum ForceFieldFalloff {
|
|
243
|
+
/**
|
|
244
|
+
* No falloff — force is constant within range.
|
|
245
|
+
*/
|
|
246
|
+
NONE = "NONE",
|
|
247
|
+
/**
|
|
248
|
+
* Force decreases linearly with distance: `1 - d/range`.
|
|
249
|
+
*/
|
|
250
|
+
LINEAR = "LINEAR",
|
|
251
|
+
/**
|
|
252
|
+
* Force decreases with the square of distance: `1 - (d/range)²`.
|
|
253
|
+
* More physically realistic than linear fallback.
|
|
254
|
+
*/
|
|
255
|
+
QUADRATIC = "QUADRATIC"
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Defines the behavior when a particle crosses a collision plane.
|
|
259
|
+
*
|
|
260
|
+
* @enum {string}
|
|
261
|
+
*/
|
|
262
|
+
declare const enum CollisionPlaneMode {
|
|
263
|
+
/**
|
|
264
|
+
* Kill the particle immediately when it crosses the plane.
|
|
265
|
+
* The particle is deactivated and returned to the free list.
|
|
266
|
+
* Ideal for boundaries like water surfaces where bubbles pop.
|
|
267
|
+
*/
|
|
268
|
+
KILL = "KILL",
|
|
269
|
+
/**
|
|
270
|
+
* Clamp the particle's position to the plane surface.
|
|
271
|
+
* The velocity component along the plane normal is zeroed.
|
|
272
|
+
* The particle stays alive and slides along the plane.
|
|
273
|
+
*/
|
|
274
|
+
CLAMP = "CLAMP",
|
|
275
|
+
/**
|
|
276
|
+
* Bounce the particle off the plane.
|
|
277
|
+
* The velocity is reflected across the plane normal and dampened.
|
|
278
|
+
* Use `dampen` to control energy loss on bounce.
|
|
279
|
+
*/
|
|
280
|
+
BOUNCE = "BOUNCE"
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Defines the simulation backend used for particle updates.
|
|
284
|
+
*
|
|
285
|
+
* @enum {string}
|
|
286
|
+
*/
|
|
287
|
+
declare const enum SimulationBackend {
|
|
288
|
+
/**
|
|
289
|
+
* Use GPU compute when the WebGPU path has been registered via
|
|
290
|
+
* `enableWebGPU()` / `registerTSLMaterialFactory()`, otherwise CPU.
|
|
291
|
+
*
|
|
292
|
+
* Note: the library does not inspect the renderer itself — pass your
|
|
293
|
+
* renderer to `enableWebGPU(renderer)` so registration (and therefore the
|
|
294
|
+
* GPU backend) is automatically skipped when the renderer cannot dispatch
|
|
295
|
+
* compute shaders.
|
|
296
|
+
*/
|
|
297
|
+
AUTO = "AUTO",
|
|
298
|
+
/**
|
|
299
|
+
* Force CPU-based simulation (JavaScript update loop).
|
|
300
|
+
* Always available regardless of renderer type.
|
|
301
|
+
*/
|
|
302
|
+
CPU = "CPU",
|
|
303
|
+
/**
|
|
304
|
+
* Use GPU compute shader simulation. Behaves like {@link SimulationBackend.AUTO}:
|
|
305
|
+
* the GPU backend requires the WebGPU path to be registered via
|
|
306
|
+
* `enableWebGPU()`; without it the system runs on the CPU.
|
|
307
|
+
*/
|
|
308
|
+
GPU = "GPU"
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* A fixed numerical value.
|
|
313
|
+
* Used for properties that require a constant value.
|
|
314
|
+
*
|
|
315
|
+
* @example
|
|
316
|
+
* const delay: Constant = 2; // Fixed delay of 2 seconds.
|
|
317
|
+
*/
|
|
318
|
+
type Constant = number;
|
|
319
|
+
/**
|
|
320
|
+
* An object that defines a range for random number generation.
|
|
321
|
+
* Contains `min` and `max` properties.
|
|
322
|
+
*
|
|
323
|
+
* @property min - The minimum value for the random range.
|
|
324
|
+
* @property max - The maximum value for the random range.
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* const randomDelay: RandomBetweenTwoConstants = { min: 0.5, max: 2 }; // Random delay between 0.5 and 2 seconds.
|
|
328
|
+
*/
|
|
329
|
+
type RandomBetweenTwoConstants = {
|
|
330
|
+
min?: number;
|
|
331
|
+
max?: number;
|
|
332
|
+
};
|
|
333
|
+
/**
|
|
334
|
+
* Base type for curves, containing common properties.
|
|
335
|
+
* @property scale - A scaling factor for the curve.
|
|
336
|
+
*/
|
|
337
|
+
type CurveBase = {
|
|
338
|
+
scale?: number;
|
|
339
|
+
};
|
|
340
|
+
/**
|
|
341
|
+
* A function that defines how the value changes over time.
|
|
342
|
+
* @param time - A normalized value between 0 and 1 representing the progress of the curve.
|
|
343
|
+
* @returns The corresponding value based on the curve function.
|
|
344
|
+
*/
|
|
345
|
+
type CurveFunction = (time: number) => number;
|
|
346
|
+
/**
|
|
347
|
+
* A B??zier curve point representing a control point.
|
|
348
|
+
* @property x - The time (normalized between 0 and 1).
|
|
349
|
+
* @property y - The value at that point.
|
|
350
|
+
* @property percentage - (Optional) Normalized position within the curve (for additional flexibility).
|
|
351
|
+
*/
|
|
352
|
+
type BezierPoint = {
|
|
353
|
+
x: number;
|
|
354
|
+
y: number;
|
|
355
|
+
percentage?: number;
|
|
356
|
+
};
|
|
357
|
+
/**
|
|
358
|
+
* A B??zier curve representation for controlling particle properties.
|
|
359
|
+
* @property type - Specifies that this curve is of type `bezier`.
|
|
360
|
+
* @property bezierPoints - An array of control points defining the B??zier curve.
|
|
361
|
+
* @example
|
|
362
|
+
* {
|
|
363
|
+
* type: LifeTimeCurve.BEZIER,
|
|
364
|
+
* bezierPoints: [
|
|
365
|
+
* { x: 0, y: 0.275, percentage: 0 },
|
|
366
|
+
* { x: 0.1666, y: 0.4416 },
|
|
367
|
+
* { x: 0.5066, y: 0.495, percentage: 0.5066 },
|
|
368
|
+
* { x: 1, y: 1, percentage: 1 }
|
|
369
|
+
* ]
|
|
370
|
+
* }
|
|
371
|
+
*/
|
|
372
|
+
type BezierCurve = CurveBase & {
|
|
373
|
+
type: LifeTimeCurve.BEZIER;
|
|
374
|
+
bezierPoints: Array<BezierPoint>;
|
|
375
|
+
};
|
|
376
|
+
/**
|
|
377
|
+
* An easing curve representation using a custom function.
|
|
378
|
+
* @property type - Specifies that this curve is of type `easing`.
|
|
379
|
+
* @property curveFunction - A function defining how the value changes over time.
|
|
380
|
+
* @example
|
|
381
|
+
* {
|
|
382
|
+
* type: LifeTimeCurve.EASING,
|
|
383
|
+
* curveFunction: (time) => Math.sin(time * Math.PI) // Simple easing function
|
|
384
|
+
* }
|
|
385
|
+
*/
|
|
386
|
+
type EasingCurve = CurveBase & {
|
|
387
|
+
type: LifeTimeCurve.EASING;
|
|
388
|
+
curveFunction: CurveFunction;
|
|
389
|
+
};
|
|
390
|
+
/**
|
|
391
|
+
* A flexible curve representation that supports B??zier curves and easing functions.
|
|
392
|
+
*/
|
|
393
|
+
type LifetimeCurve = BezierCurve | EasingCurve;
|
|
394
|
+
/**
|
|
395
|
+
* Represents a point in 3D space with optional x, y, and z coordinates.
|
|
396
|
+
* Each coordinate is a number and is optional, allowing for partial definitions.
|
|
397
|
+
*
|
|
398
|
+
* @example
|
|
399
|
+
* // A point with all coordinates defined
|
|
400
|
+
* const point: Point3D = { x: 10, y: 20, z: 30 };
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* // A point with only one coordinate defined
|
|
404
|
+
* const point: Point3D = { x: 10 };
|
|
405
|
+
*
|
|
406
|
+
* @default
|
|
407
|
+
* // Default values are undefined for all coordinates.
|
|
408
|
+
* const point: Point3D = {};
|
|
409
|
+
*/
|
|
410
|
+
type Point3D = {
|
|
411
|
+
x?: number;
|
|
412
|
+
y?: number;
|
|
413
|
+
z?: number;
|
|
414
|
+
};
|
|
415
|
+
/**
|
|
416
|
+
* Represents a transform in 3D space, including position, rotation, and scale.
|
|
417
|
+
* Each property is optional and represented as a THREE.Vector3 instance.
|
|
418
|
+
*
|
|
419
|
+
* - `position`: Defines the translation of an object in 3D space.
|
|
420
|
+
* - `rotation`: Defines the rotation of an object in radians for each axis (x, y, z).
|
|
421
|
+
* - `scale`: Defines the scale of an object along each axis.
|
|
422
|
+
*
|
|
423
|
+
* @example
|
|
424
|
+
* // A transform with all properties defined
|
|
425
|
+
* const transform: Transform = {
|
|
426
|
+
* position: new THREE.Vector3(10, 20, 30),
|
|
427
|
+
* rotation: new THREE.Vector3(Math.PI / 2, 0, 0),
|
|
428
|
+
* scale: new THREE.Vector3(1, 1, 1),
|
|
429
|
+
* };
|
|
430
|
+
*
|
|
431
|
+
* @example
|
|
432
|
+
* // A transform with only position defined
|
|
433
|
+
* const transform: Transform = {
|
|
434
|
+
* position: new THREE.Vector3(5, 5, 5),
|
|
435
|
+
* };
|
|
436
|
+
*
|
|
437
|
+
* @default
|
|
438
|
+
* // Default values are undefined for all properties.
|
|
439
|
+
* const transform: Transform = {};
|
|
440
|
+
*/
|
|
441
|
+
type Transform = {
|
|
442
|
+
position?: THREE.Vector3;
|
|
443
|
+
rotation?: THREE.Vector3;
|
|
444
|
+
scale?: THREE.Vector3;
|
|
445
|
+
};
|
|
446
|
+
/**
|
|
447
|
+
* Represents an RGB color with normalized values (0.0 to 1.0).
|
|
448
|
+
*
|
|
449
|
+
* @example
|
|
450
|
+
* ```typescript
|
|
451
|
+
* // Pure red
|
|
452
|
+
* const red: Rgb = { r: 1.0, g: 0.0, b: 0.0 };
|
|
453
|
+
*
|
|
454
|
+
* // Pure white
|
|
455
|
+
* const white: Rgb = { r: 1.0, g: 1.0, b: 1.0 };
|
|
456
|
+
*
|
|
457
|
+
* // Orange
|
|
458
|
+
* const orange: Rgb = { r: 1.0, g: 0.5, b: 0.0 };
|
|
459
|
+
* ```
|
|
460
|
+
*/
|
|
461
|
+
type Rgb = {
|
|
462
|
+
/** Red channel (0.0 to 1.0) */
|
|
463
|
+
r?: number;
|
|
464
|
+
/** Green channel (0.0 to 1.0) */
|
|
465
|
+
g?: number;
|
|
466
|
+
/** Blue channel (0.0 to 1.0) */
|
|
467
|
+
b?: number;
|
|
468
|
+
};
|
|
469
|
+
/**
|
|
470
|
+
* Defines a color range for random particle colors.
|
|
471
|
+
* Each particle will receive a random color between min and max on emission.
|
|
472
|
+
*
|
|
473
|
+
* @example
|
|
474
|
+
* ```typescript
|
|
475
|
+
* // Random colors between red and yellow
|
|
476
|
+
* const fireColors: MinMaxColor = {
|
|
477
|
+
* min: { r: 1.0, g: 0.0, b: 0.0 }, // Red
|
|
478
|
+
* max: { r: 1.0, g: 1.0, b: 0.0 } // Yellow
|
|
479
|
+
* };
|
|
480
|
+
*
|
|
481
|
+
* // Fixed white color (no randomness)
|
|
482
|
+
* const white: MinMaxColor = {
|
|
483
|
+
* min: { r: 1.0, g: 1.0, b: 1.0 },
|
|
484
|
+
* max: { r: 1.0, g: 1.0, b: 1.0 }
|
|
485
|
+
* };
|
|
486
|
+
* ```
|
|
487
|
+
*/
|
|
488
|
+
type MinMaxColor = {
|
|
489
|
+
/** Minimum color values (lower bound for random selection) */
|
|
490
|
+
min?: Rgb;
|
|
491
|
+
/** Maximum color values (upper bound for random selection) */
|
|
492
|
+
max?: Rgb;
|
|
493
|
+
};
|
|
494
|
+
/**
|
|
495
|
+
* Defines a burst emission event that emits a specific number of particles at a given time.
|
|
496
|
+
* Bursts are useful for explosions, impacts, fireworks, and other instantaneous particle effects.
|
|
497
|
+
*
|
|
498
|
+
* @property time - The time (in seconds) after the particle system starts when this burst should occur.
|
|
499
|
+
* @property count - The number of particles to emit. Can be a constant or a random range.
|
|
500
|
+
* @property cycles - The number of times this burst should repeat. Defaults to 1 (single burst).
|
|
501
|
+
* @property interval - The time interval (in seconds) between burst cycles. Only used when cycles > 1.
|
|
502
|
+
* @property probability - The probability (0.0 to 1.0) that this burst will occur. Defaults to 1.0.
|
|
503
|
+
*
|
|
504
|
+
* @example
|
|
505
|
+
* // Simple burst at start
|
|
506
|
+
* { time: 0, count: 50 }
|
|
507
|
+
*
|
|
508
|
+
* // Random count burst at 1 second
|
|
509
|
+
* { time: 1, count: { min: 20, max: 30 } }
|
|
510
|
+
*
|
|
511
|
+
* // Repeating burst with interval
|
|
512
|
+
* { time: 0.5, count: 10, cycles: 3, interval: 0.2 }
|
|
513
|
+
* // Emits at 0.5s, 0.7s, 0.9s
|
|
514
|
+
*
|
|
515
|
+
* // Probabilistic burst (50% chance)
|
|
516
|
+
* { time: 2, count: 100, probability: 0.5 }
|
|
517
|
+
*/
|
|
518
|
+
type Burst = {
|
|
519
|
+
/** Time in seconds when the burst should occur */
|
|
520
|
+
time: number;
|
|
521
|
+
/** Number of particles to emit (constant or random range) */
|
|
522
|
+
count: Constant | RandomBetweenTwoConstants;
|
|
523
|
+
/** Number of times to repeat this burst. Defaults to 1. */
|
|
524
|
+
cycles?: number;
|
|
525
|
+
/** Time interval in seconds between burst cycles. Defaults to 0. */
|
|
526
|
+
interval?: number;
|
|
527
|
+
/** Probability (0-1) that this burst will occur. Defaults to 1. */
|
|
528
|
+
probability?: number;
|
|
529
|
+
};
|
|
530
|
+
/**
|
|
531
|
+
* Defines the emission behavior of the particles.
|
|
532
|
+
* Supports rates defined over time or distance using constant values, random ranges, or curves (B??zier or easing).
|
|
533
|
+
* Also supports burst emissions for instantaneous particle effects.
|
|
534
|
+
*
|
|
535
|
+
* @default
|
|
536
|
+
* rateOverTime: 10.0
|
|
537
|
+
* rateOverDistance: 0.0
|
|
538
|
+
* bursts: []
|
|
539
|
+
*
|
|
540
|
+
* @example
|
|
541
|
+
* // Rate over time as a constant value
|
|
542
|
+
* rateOverTime: 10;
|
|
543
|
+
*
|
|
544
|
+
* // Rate over time as a random range
|
|
545
|
+
* rateOverTime: { min: 5, max: 15 };
|
|
546
|
+
*
|
|
547
|
+
* // Rate over time using a B??zier curve
|
|
548
|
+
* rateOverTime: {
|
|
549
|
+
* type: 'bezier',
|
|
550
|
+
* bezierPoints: [
|
|
551
|
+
* { x: 0, y: 0, percentage: 0 },
|
|
552
|
+
* { x: 0.5, y: 50 },
|
|
553
|
+
* { x: 1, y: 100, percentage: 1 }
|
|
554
|
+
* ],
|
|
555
|
+
* scale: 1
|
|
556
|
+
* };
|
|
557
|
+
*
|
|
558
|
+
* // Rate over distance as a constant value
|
|
559
|
+
* rateOverDistance: 2;
|
|
560
|
+
*
|
|
561
|
+
* // Rate over distance as a random range
|
|
562
|
+
* rateOverDistance: { min: 1, max: 3 };
|
|
563
|
+
*
|
|
564
|
+
* // Rate over distance using an easing curve
|
|
565
|
+
* rateOverDistance: {
|
|
566
|
+
* type: 'easing',
|
|
567
|
+
* curveFunction: (distance) => Math.sin(distance),
|
|
568
|
+
* scale: 0.5
|
|
569
|
+
* };
|
|
570
|
+
*
|
|
571
|
+
* // Burst emissions for explosions
|
|
572
|
+
* bursts: [
|
|
573
|
+
* { time: 0, count: 50 },
|
|
574
|
+
* { time: 1, count: { min: 20, max: 30 }, probability: 0.8 },
|
|
575
|
+
* { time: 0.5, count: 10, cycles: 3, interval: 0.2 }
|
|
576
|
+
* ];
|
|
577
|
+
*/
|
|
578
|
+
type Emission = {
|
|
579
|
+
rateOverTime?: Constant | RandomBetweenTwoConstants | LifetimeCurve;
|
|
580
|
+
rateOverDistance?: Constant | RandomBetweenTwoConstants | LifetimeCurve;
|
|
581
|
+
/** Array of burst configurations for instantaneous particle emissions */
|
|
582
|
+
bursts?: Array<Burst>;
|
|
583
|
+
};
|
|
584
|
+
/**
|
|
585
|
+
* Configuration for a sphere shape used in particle systems.
|
|
586
|
+
*
|
|
587
|
+
* @property radius - The radius of the sphere.
|
|
588
|
+
* @property radiusThickness - The thickness of the sphere's shell (0 to 1, where 1 is solid).
|
|
589
|
+
* @property arc - The angular arc of the sphere (in radians).
|
|
590
|
+
*
|
|
591
|
+
* @example
|
|
592
|
+
* const sphere: Sphere = {
|
|
593
|
+
* radius: 5,
|
|
594
|
+
* radiusThickness: 0.8,
|
|
595
|
+
* arc: Math.PI,
|
|
596
|
+
* };
|
|
597
|
+
*/
|
|
598
|
+
type Sphere = {
|
|
599
|
+
radius?: number;
|
|
600
|
+
radiusThickness?: number;
|
|
601
|
+
arc?: number;
|
|
602
|
+
};
|
|
603
|
+
/**
|
|
604
|
+
* Configuration for a cone shape used in particle systems.
|
|
605
|
+
*
|
|
606
|
+
* @property angle - The angle of the cone (in radians).
|
|
607
|
+
* @property radius - The radius of the cone's base.
|
|
608
|
+
* @property radiusThickness - The thickness of the cone's base (0 to 1, where 1 is solid).
|
|
609
|
+
* @property arc - The angular arc of the cone's base (in radians).
|
|
610
|
+
*
|
|
611
|
+
* @example
|
|
612
|
+
* const cone: Cone = {
|
|
613
|
+
* angle: Math.PI / 4,
|
|
614
|
+
* radius: 10,
|
|
615
|
+
* radiusThickness: 0.5,
|
|
616
|
+
* arc: Math.PI * 2,
|
|
617
|
+
* };
|
|
618
|
+
*/
|
|
619
|
+
type Cone = {
|
|
620
|
+
angle?: number;
|
|
621
|
+
radius?: number;
|
|
622
|
+
radiusThickness?: number;
|
|
623
|
+
arc?: number;
|
|
624
|
+
};
|
|
625
|
+
/**
|
|
626
|
+
* Configuration for a circle shape used in particle systems.
|
|
627
|
+
*
|
|
628
|
+
* @property radius - The radius of the circle.
|
|
629
|
+
* @property radiusThickness - The thickness of the circle's shell (0 to 1, where 1 is solid).
|
|
630
|
+
* @property arc - The angular arc of the circle (in radians).
|
|
631
|
+
*
|
|
632
|
+
* @example
|
|
633
|
+
* const circle: Circle = {
|
|
634
|
+
* radius: 10,
|
|
635
|
+
* radiusThickness: 0.5,
|
|
636
|
+
* arc: Math.PI,
|
|
637
|
+
* };
|
|
638
|
+
*/
|
|
639
|
+
type Circle = {
|
|
640
|
+
radius?: number;
|
|
641
|
+
radiusThickness?: number;
|
|
642
|
+
arc?: number;
|
|
643
|
+
};
|
|
644
|
+
/**
|
|
645
|
+
* Configuration for a rectangle shape used in particle systems.
|
|
646
|
+
*
|
|
647
|
+
* @property rotation - The rotation of the rectangle as a 3D point (in radians for each axis).
|
|
648
|
+
* @property scale - The scale of the rectangle as a 3D point.
|
|
649
|
+
*
|
|
650
|
+
* @example
|
|
651
|
+
* const rectangle: Rectangle = {
|
|
652
|
+
* rotation: { x: Math.PI / 4, y: 0, z: 0 },
|
|
653
|
+
* scale: { x: 10, y: 5, z: 1 },
|
|
654
|
+
* };
|
|
655
|
+
*/
|
|
656
|
+
type Rectangle = {
|
|
657
|
+
rotation?: Point3D;
|
|
658
|
+
scale?: Point3D;
|
|
659
|
+
};
|
|
660
|
+
/**
|
|
661
|
+
* Configuration for a box shape used in particle systems.
|
|
662
|
+
*
|
|
663
|
+
* @property scale - The scale of the box as a 3D point.
|
|
664
|
+
* @property emitFrom - Specifies where particles are emitted from within the box.
|
|
665
|
+
*
|
|
666
|
+
* @example
|
|
667
|
+
* const box: Box = {
|
|
668
|
+
* scale: { x: 10, y: 10, z: 10 },
|
|
669
|
+
* emitFrom: EmitFrom.EDGE,
|
|
670
|
+
* };
|
|
671
|
+
*/
|
|
672
|
+
type Box = {
|
|
673
|
+
scale?: Point3D;
|
|
674
|
+
emitFrom?: EmitFrom;
|
|
675
|
+
};
|
|
676
|
+
/**
|
|
677
|
+
* Configuration for defining a 3D shape used in particle systems.
|
|
678
|
+
* Specifies the shape type and its parameters, including spheres, cones, circles, rectangles, and boxes.
|
|
679
|
+
*
|
|
680
|
+
* @property shape - The type of the shape to be used.
|
|
681
|
+
* @property sphere - Configuration for a sphere shape.
|
|
682
|
+
* @property cone - Configuration for a cone shape.
|
|
683
|
+
* @property circle - Configuration for a circle shape.
|
|
684
|
+
* @property rectangle - Configuration for a rectangle shape.
|
|
685
|
+
* @property box - Configuration for a box shape.
|
|
686
|
+
*
|
|
687
|
+
* @example
|
|
688
|
+
* const shapeConfig: ShapeConfig = {
|
|
689
|
+
* shape: Shape.SPHERE,
|
|
690
|
+
* sphere: {
|
|
691
|
+
* radius: 5,
|
|
692
|
+
* radiusThickness: 0.8,
|
|
693
|
+
* arc: Math.PI,
|
|
694
|
+
* },
|
|
695
|
+
* };
|
|
696
|
+
*/
|
|
697
|
+
type ShapeConfig = {
|
|
698
|
+
shape?: Shape;
|
|
699
|
+
sphere?: Sphere;
|
|
700
|
+
cone?: Cone;
|
|
701
|
+
circle?: Circle;
|
|
702
|
+
rectangle?: Rectangle;
|
|
703
|
+
box?: Box;
|
|
704
|
+
};
|
|
705
|
+
/**
|
|
706
|
+
* Defines the texture sheet animation settings for particles.
|
|
707
|
+
* Allows configuring the animation frames, timing mode, frames per second, and the starting frame.
|
|
708
|
+
*
|
|
709
|
+
* @default
|
|
710
|
+
* tiles: new THREE.Vector2(1.0, 1.0)
|
|
711
|
+
* timeMode: TimeMode.LIFETIME
|
|
712
|
+
* fps: 30.0
|
|
713
|
+
* startFrame: 0
|
|
714
|
+
*
|
|
715
|
+
* @example
|
|
716
|
+
* // Basic configuration with default values
|
|
717
|
+
* textureSheetAnimation: {
|
|
718
|
+
* tiles: new THREE.Vector2(1.0, 1.0),
|
|
719
|
+
* timeMode: TimeMode.LIFETIME,
|
|
720
|
+
* fps: 30.0,
|
|
721
|
+
* startFrame: 0
|
|
722
|
+
* };
|
|
723
|
+
*
|
|
724
|
+
* // Custom configuration
|
|
725
|
+
* textureSheetAnimation: {
|
|
726
|
+
* tiles: new THREE.Vector2(4, 4), // 4x4 grid of animation tiles
|
|
727
|
+
* timeMode: TimeMode.SPEED,
|
|
728
|
+
* fps: 60.0,
|
|
729
|
+
* startFrame: { min: 0, max: 15 } // Random start frame between 0 and 15
|
|
730
|
+
* };
|
|
731
|
+
*/
|
|
732
|
+
type TextureSheetAnimation = {
|
|
733
|
+
tiles?: THREE.Vector2;
|
|
734
|
+
timeMode?: TimeMode;
|
|
735
|
+
fps?: number;
|
|
736
|
+
startFrame?: Constant | RandomBetweenTwoConstants;
|
|
737
|
+
};
|
|
738
|
+
/**
|
|
739
|
+
* Configuration for the trail/ribbon renderer.
|
|
740
|
+
* Controls how particle trails are drawn when using `RendererType.TRAIL`.
|
|
741
|
+
*
|
|
742
|
+
* @property length - Number of position history samples per particle (trail segments).
|
|
743
|
+
* Higher values produce longer, smoother trails but cost more memory.
|
|
744
|
+
* @default 20
|
|
745
|
+
* @property widthOverTrail - Lifetime curve that controls the ribbon width along its length.
|
|
746
|
+
* At 0 the trail head (current position), at 1 the trail tail (oldest position).
|
|
747
|
+
* @default constant 1.0
|
|
748
|
+
* @property opacityOverTrail - Lifetime curve that controls opacity along the trail length.
|
|
749
|
+
* @default linear fade from 1 (head) to 0 (tail)
|
|
750
|
+
*
|
|
751
|
+
* @example
|
|
752
|
+
* ```typescript
|
|
753
|
+
* // Long comet-style trail tapering to nothing
|
|
754
|
+
* trail: {
|
|
755
|
+
* length: 40,
|
|
756
|
+
* widthOverTrail: {
|
|
757
|
+
* type: LifeTimeCurve.BEZIER,
|
|
758
|
+
* scale: 1,
|
|
759
|
+
* bezierPoints: [
|
|
760
|
+
* { x: 0, y: 1, percentage: 0 },
|
|
761
|
+
* { x: 0.5, y: 0.4 },
|
|
762
|
+
* { x: 1, y: 0, percentage: 1 },
|
|
763
|
+
* ],
|
|
764
|
+
* },
|
|
765
|
+
* }
|
|
766
|
+
* ```
|
|
767
|
+
*/
|
|
768
|
+
type TrailConfig = {
|
|
769
|
+
/** Number of position history samples per particle. @default 20 */
|
|
770
|
+
length?: number;
|
|
771
|
+
/** Base ribbon width in world units. @default 1.0 */
|
|
772
|
+
width?: number;
|
|
773
|
+
/** Curve controlling ribbon width from head (0) to tail (1). */
|
|
774
|
+
widthOverTrail?: LifetimeCurve;
|
|
775
|
+
/** Curve controlling opacity from head (0) to tail (1). */
|
|
776
|
+
opacityOverTrail?: LifetimeCurve;
|
|
777
|
+
/**
|
|
778
|
+
* Per-channel color multiplier curves along the trail (head=0, tail=1).
|
|
779
|
+
* Works as multipliers on the particle's current color, same as colorOverLifetime.
|
|
780
|
+
* To achieve full color transitions, use white startColor.
|
|
781
|
+
*/
|
|
782
|
+
colorOverTrail?: {
|
|
783
|
+
isActive: boolean;
|
|
784
|
+
r: LifetimeCurve;
|
|
785
|
+
g: LifetimeCurve;
|
|
786
|
+
b: LifetimeCurve;
|
|
787
|
+
};
|
|
788
|
+
/**
|
|
789
|
+
* Minimum distance (in world units) a particle must travel before a new
|
|
790
|
+
* trail sample is recorded. When set, the trail becomes frame-rate
|
|
791
|
+
* independent ??? at high FPS the samples are spread further apart in time,
|
|
792
|
+
* at low FPS they cluster around sharp turns.
|
|
793
|
+
*
|
|
794
|
+
* When `0` or `undefined`, a sample is recorded every frame (legacy behavior).
|
|
795
|
+
* @default 0
|
|
796
|
+
*/
|
|
797
|
+
minVertexDistance?: number;
|
|
798
|
+
/**
|
|
799
|
+
* Maximum trail duration in seconds. Trail segments older than this value
|
|
800
|
+
* are faded out and expired, regardless of the ring-buffer `length`.
|
|
801
|
+
* This enables time-based trail length (e.g. "2-second trails") in addition
|
|
802
|
+
* to the segment-count cap.
|
|
803
|
+
*
|
|
804
|
+
* When `0` or `undefined`, trail length is governed only by `length`.
|
|
805
|
+
* @default 0
|
|
806
|
+
*/
|
|
807
|
+
maxTime?: number;
|
|
808
|
+
/**
|
|
809
|
+
* Enable Catmull-Rom spline interpolation between history samples.
|
|
810
|
+
* Inserts additional subdivided points between raw samples, eliminating
|
|
811
|
+
* sharp kinks at trail bends. The `smoothingSubdivisions` property controls
|
|
812
|
+
* how many extra points are inserted per segment.
|
|
813
|
+
*
|
|
814
|
+
* @default false
|
|
815
|
+
*/
|
|
816
|
+
smoothing?: boolean;
|
|
817
|
+
/**
|
|
818
|
+
* Number of Catmull-Rom subdivisions inserted between each pair of raw
|
|
819
|
+
* history samples when `smoothing` is enabled. Higher values produce
|
|
820
|
+
* smoother curves at the cost of more vertices.
|
|
821
|
+
*
|
|
822
|
+
* @default 3
|
|
823
|
+
*/
|
|
824
|
+
smoothingSubdivisions?: number;
|
|
825
|
+
/**
|
|
826
|
+
* Enable twist prevention for the ribbon. Uses frame tracking to maintain
|
|
827
|
+
* consistent ribbon orientation during rapid direction changes, preventing
|
|
828
|
+
* self-intersecting or flipped ribbon quads.
|
|
829
|
+
*
|
|
830
|
+
* @default false
|
|
831
|
+
*/
|
|
832
|
+
twistPrevention?: boolean;
|
|
833
|
+
/**
|
|
834
|
+
* Connect multiple particles into a single continuous ribbon.
|
|
835
|
+
* All particles that share the same `ribbonId` are sorted by age and
|
|
836
|
+
* their positions are chained into one continuous strip.
|
|
837
|
+
*
|
|
838
|
+
* When `undefined`, each particle has its own independent trail (default behavior).
|
|
839
|
+
*/
|
|
840
|
+
ribbonId?: number;
|
|
841
|
+
};
|
|
842
|
+
/**
|
|
843
|
+
* Configuration for the mesh particle renderer.
|
|
844
|
+
* Controls which 3D geometry is used when `rendererType` is `RendererType.MESH`.
|
|
845
|
+
*
|
|
846
|
+
* @property geometry - A `THREE.BufferGeometry` to render for each particle.
|
|
847
|
+
* Built-in Three.js primitives like `BoxGeometry`, `SphereGeometry`, `TorusGeometry`
|
|
848
|
+
* all work. The geometry's own normals and UVs are preserved.
|
|
849
|
+
*
|
|
850
|
+
* @example
|
|
851
|
+
* ```typescript
|
|
852
|
+
* // Cube mesh particles
|
|
853
|
+
* mesh: {
|
|
854
|
+
* geometry: new THREE.BoxGeometry(1, 1, 1),
|
|
855
|
+
* }
|
|
856
|
+
*
|
|
857
|
+
* // Icosahedron mesh particles
|
|
858
|
+
* mesh: {
|
|
859
|
+
* geometry: new THREE.IcosahedronGeometry(0.5, 0),
|
|
860
|
+
* }
|
|
861
|
+
* ```
|
|
862
|
+
*/
|
|
863
|
+
type MeshConfig = {
|
|
864
|
+
/** The geometry to render for each particle. */
|
|
865
|
+
geometry: THREE.BufferGeometry;
|
|
866
|
+
};
|
|
867
|
+
/**
|
|
868
|
+
* Configuration for the particle system renderer, controlling blending, transparency, depth, and background color behavior.
|
|
869
|
+
*
|
|
870
|
+
* @property blending - Defines the blending mode for the particle system (e.g., additive blending).
|
|
871
|
+
* @property discardBackgroundColor - Whether to discard particles that match the background color.
|
|
872
|
+
* @property backgroundColorTolerance - The tolerance for matching the background color when `discardBackgroundColor` is true.
|
|
873
|
+
* @property backgroundColor - The background color as an RGB value, used when `discardBackgroundColor` is enabled.
|
|
874
|
+
* @property transparent - Whether the particle system uses transparency.
|
|
875
|
+
* @property depthTest - Whether to enable depth testing for particles (determines if particles are rendered behind or in front of other objects).
|
|
876
|
+
* @property depthWrite - Whether to write depth information for the particles (affects sorting and rendering order).
|
|
877
|
+
*
|
|
878
|
+
* @example
|
|
879
|
+
* // A renderer configuration with additive blending and transparent particles
|
|
880
|
+
* const renderer: Renderer = {
|
|
881
|
+
* blending: THREE.AdditiveBlending,
|
|
882
|
+
* discardBackgroundColor: true,
|
|
883
|
+
* backgroundColorTolerance: 0.1,
|
|
884
|
+
* backgroundColor: { r: 0, g: 0, b: 0 },
|
|
885
|
+
* transparent: true,
|
|
886
|
+
* depthTest: true,
|
|
887
|
+
* depthWrite: false,
|
|
888
|
+
* };
|
|
889
|
+
*
|
|
890
|
+
* @default
|
|
891
|
+
* // Default values for the renderer configuration
|
|
892
|
+
* const renderer: Renderer = {
|
|
893
|
+
* blending: THREE.NormalBlending,
|
|
894
|
+
* discardBackgroundColor: false,
|
|
895
|
+
* backgroundColorTolerance: 1.0,
|
|
896
|
+
* backgroundColor: { r: 0, g: 0, b: 0 },
|
|
897
|
+
* transparent: false,
|
|
898
|
+
* depthTest: true,
|
|
899
|
+
* depthWrite: true,
|
|
900
|
+
* };
|
|
901
|
+
*/
|
|
902
|
+
type Renderer = {
|
|
903
|
+
blending: THREE.Blending;
|
|
904
|
+
discardBackgroundColor: boolean;
|
|
905
|
+
backgroundColorTolerance: number;
|
|
906
|
+
backgroundColor: Rgb;
|
|
907
|
+
transparent: boolean;
|
|
908
|
+
depthTest: boolean;
|
|
909
|
+
depthWrite: boolean;
|
|
910
|
+
/**
|
|
911
|
+
* Selects the rendering technique for particles.
|
|
912
|
+
*
|
|
913
|
+
* - `RendererType.POINTS` (default) ??? classic point-sprite renderer using `THREE.Points`.
|
|
914
|
+
* - `RendererType.INSTANCED` ??? camera-facing quads via `InstancedBufferGeometry`,
|
|
915
|
+
* removing the `gl_PointSize` hardware limit and enabling stretched billboards.
|
|
916
|
+
*
|
|
917
|
+
* @default RendererType.POINTS
|
|
918
|
+
*/
|
|
919
|
+
rendererType?: RendererType;
|
|
920
|
+
/**
|
|
921
|
+
* Trail/ribbon renderer configuration.
|
|
922
|
+
* Only used when `rendererType` is `RendererType.TRAIL`.
|
|
923
|
+
*
|
|
924
|
+
* @see TrailConfig
|
|
925
|
+
*/
|
|
926
|
+
trail?: TrailConfig;
|
|
927
|
+
/**
|
|
928
|
+
* Mesh particle renderer configuration.
|
|
929
|
+
* Only used when `rendererType` is `RendererType.MESH`.
|
|
930
|
+
*
|
|
931
|
+
* @see MeshConfig
|
|
932
|
+
*/
|
|
933
|
+
mesh?: MeshConfig;
|
|
934
|
+
/**
|
|
935
|
+
* Soft particles configuration.
|
|
936
|
+
* When enabled, particles fade smoothly near opaque geometry instead of
|
|
937
|
+
* producing a hard intersection line. Requires a depth texture from a
|
|
938
|
+
* `WebGLRenderTarget`.
|
|
939
|
+
*
|
|
940
|
+
* @see SoftParticlesConfig
|
|
941
|
+
*/
|
|
942
|
+
softParticles?: SoftParticlesConfig;
|
|
943
|
+
};
|
|
944
|
+
/**
|
|
945
|
+
* Configuration for soft (depth-faded) particles.
|
|
946
|
+
* When enabled, particles fade out smoothly near opaque geometry instead
|
|
947
|
+
* of producing a hard intersection line.
|
|
948
|
+
*
|
|
949
|
+
* Requires a depth texture from a `WebGLRenderTarget` with `DepthTexture`.
|
|
950
|
+
* If `depthTexture` is not provided, soft particles are automatically disabled
|
|
951
|
+
* regardless of the `enabled` flag.
|
|
952
|
+
*
|
|
953
|
+
* @property enabled - Whether soft particle fading is active. @default false
|
|
954
|
+
* @property intensity - Controls the fade distance in world units. Higher values
|
|
955
|
+
* produce a wider fade zone. Typical range: 0.1 to 5.0. @default 1.0
|
|
956
|
+
* @property depthTexture - A `THREE.DepthTexture` attached to the render target
|
|
957
|
+
* that contains the scene's depth pass. Must be updated every frame before
|
|
958
|
+
* the particle system renders.
|
|
959
|
+
*
|
|
960
|
+
* @example
|
|
961
|
+
* // Create a render target with a depth texture
|
|
962
|
+
* const rt = new THREE.WebGLRenderTarget(width, height, {
|
|
963
|
+
* depthTexture: new THREE.DepthTexture(width, height),
|
|
964
|
+
* });
|
|
965
|
+
*
|
|
966
|
+
* // Pass it to the particle system config
|
|
967
|
+
* const config = {
|
|
968
|
+
* renderer: {
|
|
969
|
+
* softParticles: {
|
|
970
|
+
* enabled: true,
|
|
971
|
+
* intensity: 1.5,
|
|
972
|
+
* depthTexture: rt.depthTexture,
|
|
973
|
+
* },
|
|
974
|
+
* },
|
|
975
|
+
* };
|
|
976
|
+
*/
|
|
977
|
+
type SoftParticlesConfig = {
|
|
978
|
+
enabled?: boolean;
|
|
979
|
+
intensity?: number;
|
|
980
|
+
depthTexture?: THREE.DepthTexture;
|
|
981
|
+
};
|
|
982
|
+
/**
|
|
983
|
+
* Configuration for noise effects applied to particles in a particle system.
|
|
984
|
+
* Noise can affect particle position, rotation, and size dynamically.
|
|
985
|
+
*
|
|
986
|
+
* @property isActive - Whether noise is enabled for the particle system.
|
|
987
|
+
* @property strength - The overall strength of the noise effect.
|
|
988
|
+
* @property positionAmount - The amount of noise applied to particle positions.
|
|
989
|
+
* @property rotationAmount - The amount of noise applied to particle rotations.
|
|
990
|
+
* @property sizeAmount - The amount of noise applied to particle sizes.
|
|
991
|
+
* @property sampler - An optional noise sampler (e.g., FBM for fractal Brownian motion) to generate noise values.
|
|
992
|
+
* @property offsets - An optional array of offsets to randomize noise generation per particle.
|
|
993
|
+
*
|
|
994
|
+
* @example
|
|
995
|
+
* // A noise configuration with position and rotation noise
|
|
996
|
+
* const noise: Noise = {
|
|
997
|
+
* isActive: true,
|
|
998
|
+
* strength: 0.5,
|
|
999
|
+
* positionAmount: 1.0,
|
|
1000
|
+
* rotationAmount: 0.3,
|
|
1001
|
+
* sizeAmount: 0.0,
|
|
1002
|
+
* sampler: new FBM(),
|
|
1003
|
+
* offsets: [0.1, 0.2, 0.3],
|
|
1004
|
+
* };
|
|
1005
|
+
*
|
|
1006
|
+
* @default
|
|
1007
|
+
* // Default values for noise configuration
|
|
1008
|
+
* const noise: Noise = {
|
|
1009
|
+
* isActive: false,
|
|
1010
|
+
* strength: 1.0,
|
|
1011
|
+
* positionAmount: 0.0,
|
|
1012
|
+
* rotationAmount: 0.0,
|
|
1013
|
+
* sizeAmount: 0.0,
|
|
1014
|
+
* sampler: undefined,
|
|
1015
|
+
* offsets: undefined,
|
|
1016
|
+
* };
|
|
1017
|
+
*/
|
|
1018
|
+
type Noise = {
|
|
1019
|
+
isActive: boolean;
|
|
1020
|
+
strength: number;
|
|
1021
|
+
noisePower: number;
|
|
1022
|
+
frequency: number;
|
|
1023
|
+
positionAmount: number;
|
|
1024
|
+
rotationAmount: number;
|
|
1025
|
+
sizeAmount: number;
|
|
1026
|
+
/** Pre-computed FBM normalisation divisor: `2 - 2^(-octaves)`. */
|
|
1027
|
+
fbmMax: number;
|
|
1028
|
+
sampler?: FBM;
|
|
1029
|
+
offsets?: Array<number>;
|
|
1030
|
+
};
|
|
1031
|
+
type NoiseConfig = {
|
|
1032
|
+
isActive: boolean;
|
|
1033
|
+
useRandomOffset: boolean;
|
|
1034
|
+
strength: number;
|
|
1035
|
+
frequency: number;
|
|
1036
|
+
octaves: number;
|
|
1037
|
+
positionAmount: number;
|
|
1038
|
+
rotationAmount: number;
|
|
1039
|
+
sizeAmount: number;
|
|
1040
|
+
};
|
|
1041
|
+
/**
|
|
1042
|
+
* Defines the velocity of particles over their lifetime, allowing for linear and orbital velocity (in degrees) adjustments.
|
|
1043
|
+
* Supports constant values, random ranges, or curves (B??zier or easing) for each axis.
|
|
1044
|
+
*
|
|
1045
|
+
* @default
|
|
1046
|
+
* isActive: false
|
|
1047
|
+
* linear: { x: 0.0, y: 0.0, z: 0.0 }
|
|
1048
|
+
* orbital: { x: 0.0, y: 0.0, z: 0.0 }
|
|
1049
|
+
*
|
|
1050
|
+
* @example
|
|
1051
|
+
* // Linear velocity with a constant value
|
|
1052
|
+
* linear: { x: 1, y: 0, z: -0.5 };
|
|
1053
|
+
*
|
|
1054
|
+
* // Linear velocity with random ranges
|
|
1055
|
+
* linear: {
|
|
1056
|
+
* x: { min: -1, max: 1 },
|
|
1057
|
+
* y: { min: 0, max: 2 }
|
|
1058
|
+
* };
|
|
1059
|
+
*
|
|
1060
|
+
* // Linear velocity using a B??zier curve
|
|
1061
|
+
* linear: {
|
|
1062
|
+
* z: {
|
|
1063
|
+
* type: 'bezier',
|
|
1064
|
+
* bezierPoints: [
|
|
1065
|
+
* { x: 0, y: 0, percentage: 0 },
|
|
1066
|
+
* { x: 0.5, y: 2 },
|
|
1067
|
+
* { x: 1, y: 10, percentage: 1 }
|
|
1068
|
+
* ],
|
|
1069
|
+
* scale: 2
|
|
1070
|
+
* }
|
|
1071
|
+
* };
|
|
1072
|
+
*
|
|
1073
|
+
* // Orbital velocity with a constant value
|
|
1074
|
+
* orbital: { x: 3, y: 5, z: 0 };
|
|
1075
|
+
*
|
|
1076
|
+
* // Orbital velocity using an easing curve
|
|
1077
|
+
* orbital: {
|
|
1078
|
+
* x: {
|
|
1079
|
+
* type: 'easing',
|
|
1080
|
+
* curveFunction: (time) => Math.sin(time * Math.PI),
|
|
1081
|
+
* scale: 1.5
|
|
1082
|
+
* }
|
|
1083
|
+
* };
|
|
1084
|
+
*/
|
|
1085
|
+
type VelocityOverLifetime = {
|
|
1086
|
+
isActive: boolean;
|
|
1087
|
+
linear: {
|
|
1088
|
+
x?: Constant | RandomBetweenTwoConstants | LifetimeCurve;
|
|
1089
|
+
y?: Constant | RandomBetweenTwoConstants | LifetimeCurve;
|
|
1090
|
+
z?: Constant | RandomBetweenTwoConstants | LifetimeCurve;
|
|
1091
|
+
};
|
|
1092
|
+
orbital: {
|
|
1093
|
+
x?: Constant | RandomBetweenTwoConstants | LifetimeCurve;
|
|
1094
|
+
y?: Constant | RandomBetweenTwoConstants | LifetimeCurve;
|
|
1095
|
+
z?: Constant | RandomBetweenTwoConstants | LifetimeCurve;
|
|
1096
|
+
};
|
|
1097
|
+
};
|
|
1098
|
+
/**
|
|
1099
|
+
* Configuration for a sub-emitter that spawns child particle systems
|
|
1100
|
+
* based on parent particle lifecycle events.
|
|
1101
|
+
*
|
|
1102
|
+
* @example
|
|
1103
|
+
* ```typescript
|
|
1104
|
+
* const subEmitter: SubEmitterConfig = {
|
|
1105
|
+
* trigger: SubEmitterTrigger.DEATH,
|
|
1106
|
+
* config: { startLifeTime: 0.5, startSpeed: 2, emission: { rateOverTime: 20 } },
|
|
1107
|
+
* inheritVelocity: 0.5,
|
|
1108
|
+
* maxInstances: 16,
|
|
1109
|
+
* };
|
|
1110
|
+
* ```
|
|
1111
|
+
*/
|
|
1112
|
+
type SubEmitterConfig = {
|
|
1113
|
+
/** The particle system configuration used when spawning the sub-emitter. */
|
|
1114
|
+
config: ParticleSystemConfig;
|
|
1115
|
+
/**
|
|
1116
|
+
* When to trigger the sub-emitter.
|
|
1117
|
+
* @default SubEmitterTrigger.DEATH
|
|
1118
|
+
*/
|
|
1119
|
+
trigger?: SubEmitterTrigger;
|
|
1120
|
+
/**
|
|
1121
|
+
* Multiplier (0???1) for inheriting the parent particle's velocity.
|
|
1122
|
+
* 0 = no inheritance, 1 = full velocity inheritance.
|
|
1123
|
+
* @default 0
|
|
1124
|
+
*/
|
|
1125
|
+
inheritVelocity?: number;
|
|
1126
|
+
/**
|
|
1127
|
+
* Maximum number of concurrent sub-emitter instances for this configuration.
|
|
1128
|
+
* Older completed instances are cleaned up to make room for new ones.
|
|
1129
|
+
* @default 32
|
|
1130
|
+
*/
|
|
1131
|
+
maxInstances?: number;
|
|
1132
|
+
};
|
|
1133
|
+
/**
|
|
1134
|
+
* Configuration for a force field that affects particle velocities.
|
|
1135
|
+
* Force fields can attract, repel, or push particles in a direction.
|
|
1136
|
+
*
|
|
1137
|
+
* @example
|
|
1138
|
+
* ```typescript
|
|
1139
|
+
* // Point attractor at origin
|
|
1140
|
+
* const attractor: ForceFieldConfig = {
|
|
1141
|
+
* type: ForceFieldType.POINT,
|
|
1142
|
+
* position: new THREE.Vector3(0, 0, 0),
|
|
1143
|
+
* strength: 5.0,
|
|
1144
|
+
* range: 10,
|
|
1145
|
+
* falloff: ForceFieldFalloff.QUADRATIC,
|
|
1146
|
+
* };
|
|
1147
|
+
*
|
|
1148
|
+
* // Repulsion shield
|
|
1149
|
+
* const shield: ForceFieldConfig = {
|
|
1150
|
+
* type: ForceFieldType.POINT,
|
|
1151
|
+
* position: new THREE.Vector3(0, 0, 0),
|
|
1152
|
+
* strength: -3.0,
|
|
1153
|
+
* range: 5,
|
|
1154
|
+
* falloff: ForceFieldFalloff.LINEAR,
|
|
1155
|
+
* };
|
|
1156
|
+
*
|
|
1157
|
+
* // Wind effect
|
|
1158
|
+
* const wind: ForceFieldConfig = {
|
|
1159
|
+
* type: ForceFieldType.DIRECTIONAL,
|
|
1160
|
+
* direction: new THREE.Vector3(1, 0, 0),
|
|
1161
|
+
* strength: 2.0,
|
|
1162
|
+
* };
|
|
1163
|
+
* ```
|
|
1164
|
+
*/
|
|
1165
|
+
type ForceFieldConfig = {
|
|
1166
|
+
/** Whether this force field is active. @default true */
|
|
1167
|
+
isActive?: boolean;
|
|
1168
|
+
/** Type of the force field. @default ForceFieldType.POINT */
|
|
1169
|
+
type?: ForceFieldType;
|
|
1170
|
+
/** Position in 3D space for POINT type force fields. @default (0,0,0) */
|
|
1171
|
+
position?: THREE.Vector3;
|
|
1172
|
+
/** Direction vector for DIRECTIONAL type force fields. @default (0,1,0) */
|
|
1173
|
+
direction?: THREE.Vector3;
|
|
1174
|
+
/**
|
|
1175
|
+
* Force strength. Positive = attract (POINT) or push along direction (DIRECTIONAL).
|
|
1176
|
+
* Negative = repel (POINT) or push against direction (DIRECTIONAL).
|
|
1177
|
+
* Supports constant, random range, or lifetime curve (evaluated against system lifetime).
|
|
1178
|
+
* @default 1
|
|
1179
|
+
*/
|
|
1180
|
+
strength?: Constant | RandomBetweenTwoConstants | LifetimeCurve;
|
|
1181
|
+
/**
|
|
1182
|
+
* Maximum effective range for POINT type. Particles beyond this distance are unaffected.
|
|
1183
|
+
* @default Infinity
|
|
1184
|
+
*/
|
|
1185
|
+
range?: number;
|
|
1186
|
+
/**
|
|
1187
|
+
* How force diminishes with distance for POINT type.
|
|
1188
|
+
* @default ForceFieldFalloff.LINEAR
|
|
1189
|
+
*/
|
|
1190
|
+
falloff?: ForceFieldFalloff;
|
|
1191
|
+
};
|
|
1192
|
+
/**
|
|
1193
|
+
* Internal normalized force field configuration where all properties are required.
|
|
1194
|
+
* Created during particle system initialization from user-provided {@link ForceFieldConfig}.
|
|
1195
|
+
*/
|
|
1196
|
+
type NormalizedForceFieldConfig = {
|
|
1197
|
+
isActive: boolean;
|
|
1198
|
+
type: ForceFieldType;
|
|
1199
|
+
position: THREE.Vector3;
|
|
1200
|
+
direction: THREE.Vector3;
|
|
1201
|
+
strength: Constant | RandomBetweenTwoConstants | LifetimeCurve;
|
|
1202
|
+
range: number;
|
|
1203
|
+
falloff: ForceFieldFalloff;
|
|
1204
|
+
};
|
|
1205
|
+
/**
|
|
1206
|
+
* Configuration for a collision plane that constrains particle positions.
|
|
1207
|
+
* Collision planes define infinite planes in 3D space. When a particle crosses
|
|
1208
|
+
* from the front side (positive normal direction) to the back side, the
|
|
1209
|
+
* configured response mode is triggered.
|
|
1210
|
+
*
|
|
1211
|
+
* @example
|
|
1212
|
+
* ```typescript
|
|
1213
|
+
* // Water surface ??? kill bubbles when they reach y=5
|
|
1214
|
+
* const waterSurface: CollisionPlaneConfig = {
|
|
1215
|
+
* position: { x: 0, y: 5, z: 0 },
|
|
1216
|
+
* normal: { x: 0, y: -1, z: 0 },
|
|
1217
|
+
* mode: CollisionPlaneMode.KILL,
|
|
1218
|
+
* };
|
|
1219
|
+
*
|
|
1220
|
+
* // Bouncy floor
|
|
1221
|
+
* const floor: CollisionPlaneConfig = {
|
|
1222
|
+
* position: { x: 0, y: 0, z: 0 },
|
|
1223
|
+
* normal: { x: 0, y: 1, z: 0 },
|
|
1224
|
+
* mode: CollisionPlaneMode.BOUNCE,
|
|
1225
|
+
* dampen: 0.6,
|
|
1226
|
+
* };
|
|
1227
|
+
*
|
|
1228
|
+
* // Invisible wall clamp
|
|
1229
|
+
* const wall: CollisionPlaneConfig = {
|
|
1230
|
+
* position: { x: 5, y: 0, z: 0 },
|
|
1231
|
+
* normal: { x: -1, y: 0, z: 0 },
|
|
1232
|
+
* mode: CollisionPlaneMode.CLAMP,
|
|
1233
|
+
* };
|
|
1234
|
+
* ```
|
|
1235
|
+
*/
|
|
1236
|
+
type CollisionPlaneConfig = {
|
|
1237
|
+
/** Whether this collision plane is active. @default true */
|
|
1238
|
+
isActive?: boolean;
|
|
1239
|
+
/** A point on the plane surface. @default (0,0,0) */
|
|
1240
|
+
position?: Point3D;
|
|
1241
|
+
/**
|
|
1242
|
+
* The plane normal vector (will be normalized internally).
|
|
1243
|
+
* Defines the "front" side of the plane. Particles crossing from front
|
|
1244
|
+
* to back trigger the collision response.
|
|
1245
|
+
* @default (0,1,0)
|
|
1246
|
+
*/
|
|
1247
|
+
normal?: Point3D;
|
|
1248
|
+
/** The collision response mode. @default CollisionPlaneMode.KILL */
|
|
1249
|
+
mode?: CollisionPlaneMode;
|
|
1250
|
+
/**
|
|
1251
|
+
* Energy retention factor for BOUNCE mode (0???1).
|
|
1252
|
+
* 0 = no bounce (all energy absorbed), 1 = perfect bounce (no energy loss).
|
|
1253
|
+
* @default 0.5
|
|
1254
|
+
*/
|
|
1255
|
+
dampen?: number;
|
|
1256
|
+
/**
|
|
1257
|
+
* Fraction of the particle's start lifetime to subtract on collision (0???1).
|
|
1258
|
+
* Applied on each collision for BOUNCE mode; ignored for KILL and CLAMP.
|
|
1259
|
+
* @default 0
|
|
1260
|
+
*/
|
|
1261
|
+
lifetimeLoss?: number;
|
|
1262
|
+
};
|
|
1263
|
+
/**
|
|
1264
|
+
* Internal normalized collision plane configuration where all properties are required.
|
|
1265
|
+
* Created during particle system initialization from user-provided {@link CollisionPlaneConfig}.
|
|
1266
|
+
*/
|
|
1267
|
+
type NormalizedCollisionPlaneConfig = {
|
|
1268
|
+
isActive: boolean;
|
|
1269
|
+
position: THREE.Vector3;
|
|
1270
|
+
normal: THREE.Vector3;
|
|
1271
|
+
mode: CollisionPlaneMode;
|
|
1272
|
+
dampen: number;
|
|
1273
|
+
lifetimeLoss: number;
|
|
1274
|
+
};
|
|
1275
|
+
/**
|
|
1276
|
+
* Configuration object for the particle system.
|
|
1277
|
+
* Defines all aspects of the particle system, including its appearance, behavior, and runtime events.
|
|
1278
|
+
*/
|
|
1279
|
+
type ParticleSystemConfig = {
|
|
1280
|
+
/**
|
|
1281
|
+
* Defines the position, rotation, and scale of the particle system.
|
|
1282
|
+
*
|
|
1283
|
+
* @see Transform
|
|
1284
|
+
* @default
|
|
1285
|
+
* transform: {
|
|
1286
|
+
* position: new THREE.Vector3(),
|
|
1287
|
+
* rotation: new THREE.Vector3(),
|
|
1288
|
+
* scale: new THREE.Vector3(1, 1, 1),
|
|
1289
|
+
* }
|
|
1290
|
+
*/
|
|
1291
|
+
transform?: Transform;
|
|
1292
|
+
/**
|
|
1293
|
+
* Duration of the particle system in seconds.
|
|
1294
|
+
* Must be a positive value.
|
|
1295
|
+
* @default 5.0
|
|
1296
|
+
* @example
|
|
1297
|
+
* const duration: number = 5; // System runs for 5 seconds.
|
|
1298
|
+
*/
|
|
1299
|
+
duration?: number;
|
|
1300
|
+
/**
|
|
1301
|
+
* Indicates whether the system should loop after finishing.
|
|
1302
|
+
* @default true
|
|
1303
|
+
* @example
|
|
1304
|
+
* looping: true; // System loops continuously.
|
|
1305
|
+
*/
|
|
1306
|
+
looping?: boolean;
|
|
1307
|
+
/**
|
|
1308
|
+
* Delay before the particle system starts emitting particles.
|
|
1309
|
+
* Supports a fixed value (`Constant`) or a random range (`RandomBetweenTwoConstants`).
|
|
1310
|
+
* @default 0.0
|
|
1311
|
+
* @example
|
|
1312
|
+
* startDelay: 2; // Fixed 2-second delay.
|
|
1313
|
+
* startDelay: { min: 0.5, max: 2 }; // Random delay between 0.5 and 2 seconds.
|
|
1314
|
+
*/
|
|
1315
|
+
startDelay?: Constant | RandomBetweenTwoConstants;
|
|
1316
|
+
/**
|
|
1317
|
+
* Initial lifetime of the particles.
|
|
1318
|
+
* Supports constant value, random range, or curves (B??zier or easing).
|
|
1319
|
+
* @default 5.0
|
|
1320
|
+
* @example
|
|
1321
|
+
* // Constant 3 seconds.
|
|
1322
|
+
* startLifetime: 3;
|
|
1323
|
+
*
|
|
1324
|
+
* // Random range between 1 and 4 seconds.
|
|
1325
|
+
* startLifetime: { min: 1, max: 4 };
|
|
1326
|
+
*
|
|
1327
|
+
* // B??zier curve example with scaling.
|
|
1328
|
+
* startLifetime: {
|
|
1329
|
+
* type: LifeTimeCurve.BEZIER,
|
|
1330
|
+
* bezierPoints: [
|
|
1331
|
+
* { x: 0, y: 0.275, percentage: 0 },
|
|
1332
|
+
* { x: 0.5, y: 0.5 },
|
|
1333
|
+
* { x: 1, y: 1, percentage: 1 }
|
|
1334
|
+
* ],
|
|
1335
|
+
* scale: 2
|
|
1336
|
+
* };
|
|
1337
|
+
*
|
|
1338
|
+
* // Easing curve example with scaling.
|
|
1339
|
+
* startLifetime: {
|
|
1340
|
+
* type: LifeTimeCurve.EASING,
|
|
1341
|
+
* curveFunction: (time) => Math.sin(time * Math.PI),
|
|
1342
|
+
* scale: 0.5
|
|
1343
|
+
* };
|
|
1344
|
+
*/
|
|
1345
|
+
startLifetime?: Constant | RandomBetweenTwoConstants | LifetimeCurve;
|
|
1346
|
+
/**
|
|
1347
|
+
* Defines the initial speed of the particles.
|
|
1348
|
+
* Supports constant values, random ranges, or curves (B??zier or easing).
|
|
1349
|
+
* @default 1.0
|
|
1350
|
+
* @example
|
|
1351
|
+
* // Constant value
|
|
1352
|
+
* startSpeed: 3;
|
|
1353
|
+
*
|
|
1354
|
+
* // Random range
|
|
1355
|
+
* startSpeed: { min: 1, max: 4 };
|
|
1356
|
+
*
|
|
1357
|
+
* // B??zier curve example with scaling.
|
|
1358
|
+
* startSpeed: {
|
|
1359
|
+
* type: 'bezier',
|
|
1360
|
+
* bezierPoints: [
|
|
1361
|
+
* { x: 0, y: 0.275, percentage: 0 },
|
|
1362
|
+
* { x: 0.5, y: 0.5 },
|
|
1363
|
+
* { x: 1, y: 1, percentage: 1 }
|
|
1364
|
+
* ],
|
|
1365
|
+
* scale: 2
|
|
1366
|
+
* };
|
|
1367
|
+
*
|
|
1368
|
+
* // Easing curve example with scaling.
|
|
1369
|
+
* startSpeed: {
|
|
1370
|
+
* type: 'easing',
|
|
1371
|
+
* curveFunction: (time) => Math.sin(time * Math.PI),
|
|
1372
|
+
* scale: 1.5
|
|
1373
|
+
* };
|
|
1374
|
+
*/
|
|
1375
|
+
startSpeed?: Constant | RandomBetweenTwoConstants | LifetimeCurve;
|
|
1376
|
+
/**
|
|
1377
|
+
* Defines the initial size of the particles.
|
|
1378
|
+
* Supports constant values, random ranges, or curves (B??zier or easing).
|
|
1379
|
+
* @default 1.0
|
|
1380
|
+
* @example
|
|
1381
|
+
* // Constant value
|
|
1382
|
+
* startSize: 3;
|
|
1383
|
+
*
|
|
1384
|
+
* // Random range
|
|
1385
|
+
* startSize: { min: 1, max: 4 };
|
|
1386
|
+
*
|
|
1387
|
+
* // B??zier curve example with scaling.
|
|
1388
|
+
* startSize: {
|
|
1389
|
+
* type: 'bezier',
|
|
1390
|
+
* bezierPoints: [
|
|
1391
|
+
* { x: 0, y: 0.275, percentage: 0 },
|
|
1392
|
+
* { x: 0.5, y: 0.5 },
|
|
1393
|
+
* { x: 1, y: 1, percentage: 1 }
|
|
1394
|
+
* ],
|
|
1395
|
+
* scale: 2
|
|
1396
|
+
* };
|
|
1397
|
+
*
|
|
1398
|
+
* // Easing curve example with scaling.
|
|
1399
|
+
* startSize: {
|
|
1400
|
+
* type: 'easing',
|
|
1401
|
+
* curveFunction: (time) => Math.sin(time * Math.PI),
|
|
1402
|
+
* scale: 1.5
|
|
1403
|
+
* };
|
|
1404
|
+
*/
|
|
1405
|
+
startSize?: Constant | RandomBetweenTwoConstants | LifetimeCurve;
|
|
1406
|
+
/**
|
|
1407
|
+
* Defines the initial opacity of the particles.
|
|
1408
|
+
* Supports constant values, random ranges, or curves (B??zier or easing).
|
|
1409
|
+
* @default 1.0
|
|
1410
|
+
* @example
|
|
1411
|
+
* // Constant value
|
|
1412
|
+
* startOpacity: 3;
|
|
1413
|
+
*
|
|
1414
|
+
* // Random range
|
|
1415
|
+
* startOpacity: { min: 1, max: 4 };
|
|
1416
|
+
*
|
|
1417
|
+
* // B??zier curve example with scaling.
|
|
1418
|
+
* startOpacity: {
|
|
1419
|
+
* type: 'bezier',
|
|
1420
|
+
* bezierPoints: [
|
|
1421
|
+
* { x: 0, y: 0.275, percentage: 0 },
|
|
1422
|
+
* { x: 0.5, y: 0.5 },
|
|
1423
|
+
* { x: 1, y: 1, percentage: 1 }
|
|
1424
|
+
* ],
|
|
1425
|
+
* scale: 2
|
|
1426
|
+
* };
|
|
1427
|
+
*
|
|
1428
|
+
* // Easing curve example with scaling.
|
|
1429
|
+
* startOpacity: {
|
|
1430
|
+
* type: 'easing',
|
|
1431
|
+
* curveFunction: (time) => Math.sin(time * Math.PI),
|
|
1432
|
+
* scale: 1.5
|
|
1433
|
+
* };
|
|
1434
|
+
*/
|
|
1435
|
+
startOpacity?: Constant | RandomBetweenTwoConstants | LifetimeCurve;
|
|
1436
|
+
/**
|
|
1437
|
+
* Defines the initial rotation of the particles in degrees.
|
|
1438
|
+
* Supports constant values, random ranges, or curves (B??zier or easing).
|
|
1439
|
+
* @default 0.0
|
|
1440
|
+
* @example
|
|
1441
|
+
* // Constant value
|
|
1442
|
+
* startRotation: 3;
|
|
1443
|
+
*
|
|
1444
|
+
* // Random range
|
|
1445
|
+
* startRotation: { min: 1, max: 4 };
|
|
1446
|
+
*
|
|
1447
|
+
* // B??zier curve example with scaling.
|
|
1448
|
+
* startRotation: {
|
|
1449
|
+
* type: 'bezier',
|
|
1450
|
+
* bezierPoints: [
|
|
1451
|
+
* { x: 0, y: 0.275, percentage: 0 },
|
|
1452
|
+
* { x: 0.5, y: 0.5 },
|
|
1453
|
+
* { x: 1, y: 1, percentage: 1 }
|
|
1454
|
+
* ],
|
|
1455
|
+
* scale: 2
|
|
1456
|
+
* };
|
|
1457
|
+
*
|
|
1458
|
+
* // Easing curve example with scaling.
|
|
1459
|
+
* startRotation: {
|
|
1460
|
+
* type: 'easing',
|
|
1461
|
+
* curveFunction: (time) => Math.sin(time * Math.PI),
|
|
1462
|
+
* scale: 1.5
|
|
1463
|
+
* };
|
|
1464
|
+
*/
|
|
1465
|
+
startRotation?: Constant | RandomBetweenTwoConstants | LifetimeCurve;
|
|
1466
|
+
/**
|
|
1467
|
+
* Initial color of the particles.
|
|
1468
|
+
* Supports a min-max range for color interpolation.
|
|
1469
|
+
*
|
|
1470
|
+
* @default
|
|
1471
|
+
* startColor: {
|
|
1472
|
+
* min: { r: 1.0, g: 1.0, b: 1.0 },
|
|
1473
|
+
* max: { r: 1.0, g: 1.0, b: 1.0 },
|
|
1474
|
+
* }
|
|
1475
|
+
*/
|
|
1476
|
+
startColor?: MinMaxColor;
|
|
1477
|
+
/**
|
|
1478
|
+
* Defines the gravity strength applied to particles.
|
|
1479
|
+
* This value affects the downward acceleration of particles over time.
|
|
1480
|
+
*
|
|
1481
|
+
* @default 0.0
|
|
1482
|
+
*
|
|
1483
|
+
* @example
|
|
1484
|
+
* // No gravity
|
|
1485
|
+
* gravity: 0;
|
|
1486
|
+
*
|
|
1487
|
+
* // Moderate gravity
|
|
1488
|
+
* gravity: 9.8; // Similar to Earth's gravity
|
|
1489
|
+
*
|
|
1490
|
+
* // Strong gravity
|
|
1491
|
+
* gravity: 20.0;
|
|
1492
|
+
*/
|
|
1493
|
+
gravity?: Constant;
|
|
1494
|
+
/**
|
|
1495
|
+
* Defines the simulation space in which particles are simulated.
|
|
1496
|
+
* Determines whether the particles move relative to the local object space or the world space.
|
|
1497
|
+
*
|
|
1498
|
+
* @default SimulationSpace.LOCAL
|
|
1499
|
+
*
|
|
1500
|
+
* @example
|
|
1501
|
+
* // Simulate particles in local space (default)
|
|
1502
|
+
* simulationSpace: SimulationSpace.LOCAL;
|
|
1503
|
+
*
|
|
1504
|
+
* // Simulate particles in world space
|
|
1505
|
+
* simulationSpace: SimulationSpace.WORLD;
|
|
1506
|
+
*/
|
|
1507
|
+
simulationSpace?: SimulationSpace;
|
|
1508
|
+
/**
|
|
1509
|
+
* Selects the simulation backend for particle updates.
|
|
1510
|
+
*
|
|
1511
|
+
* - `AUTO` (default): Uses GPU compute when a WebGPU-capable renderer is
|
|
1512
|
+
* detected, otherwise falls back to CPU.
|
|
1513
|
+
* - `CPU`: Always uses the JavaScript update loop (works with any renderer).
|
|
1514
|
+
* - `GPU`: Requests GPU compute simulation. Falls back to CPU if the renderer
|
|
1515
|
+
* does not support compute shaders.
|
|
1516
|
+
*
|
|
1517
|
+
* @default SimulationBackend.AUTO
|
|
1518
|
+
*/
|
|
1519
|
+
simulationBackend?: SimulationBackend;
|
|
1520
|
+
/**
|
|
1521
|
+
* Defines the maximum number of particles allowed in the system.
|
|
1522
|
+
* This value limits the total number of active particles at any given time.
|
|
1523
|
+
*
|
|
1524
|
+
* @default 100.0
|
|
1525
|
+
*
|
|
1526
|
+
* @example
|
|
1527
|
+
* // Default value
|
|
1528
|
+
* maxParticles: 100.0;
|
|
1529
|
+
*
|
|
1530
|
+
* // Increase the maximum number of particles
|
|
1531
|
+
* maxParticles: 500.0;
|
|
1532
|
+
*
|
|
1533
|
+
* // Limit to a small number of particles
|
|
1534
|
+
* maxParticles: 10.0;
|
|
1535
|
+
*/
|
|
1536
|
+
maxParticles?: Constant;
|
|
1537
|
+
/**
|
|
1538
|
+
* Defines the particle emission settings.
|
|
1539
|
+
* Configures the emission rate over time and distance.
|
|
1540
|
+
*
|
|
1541
|
+
* @see Emission
|
|
1542
|
+
* @default
|
|
1543
|
+
* emission: {
|
|
1544
|
+
* rateOverTime: 10.0,
|
|
1545
|
+
* rateOverDistance: 0.0,
|
|
1546
|
+
* }
|
|
1547
|
+
*/
|
|
1548
|
+
emission?: Emission;
|
|
1549
|
+
/**
|
|
1550
|
+
* Configuration for the emitter shape.
|
|
1551
|
+
* Determines the shape and parameters for particle emission.
|
|
1552
|
+
*
|
|
1553
|
+
* @see ShapeConfig
|
|
1554
|
+
*/
|
|
1555
|
+
shape?: ShapeConfig;
|
|
1556
|
+
/**
|
|
1557
|
+
* Defines the texture used for rendering particles.
|
|
1558
|
+
* This texture is applied to all particles in the system, and can be used to control their appearance.
|
|
1559
|
+
*
|
|
1560
|
+
* @default undefined
|
|
1561
|
+
*
|
|
1562
|
+
* @example
|
|
1563
|
+
* // Using a predefined texture
|
|
1564
|
+
* map: new THREE.TextureLoader().load('path/to/texture.png');
|
|
1565
|
+
*
|
|
1566
|
+
* // No texture (default behavior)
|
|
1567
|
+
* map: undefined;
|
|
1568
|
+
*/
|
|
1569
|
+
map?: THREE.Texture;
|
|
1570
|
+
/**
|
|
1571
|
+
* Renderer configuration for blending, transparency, and depth testing.
|
|
1572
|
+
*
|
|
1573
|
+
* @see Renderer
|
|
1574
|
+
* @default
|
|
1575
|
+
* renderer: {
|
|
1576
|
+
* blending: THREE.NormalBlending,
|
|
1577
|
+
* discardBackgroundColor: false,
|
|
1578
|
+
* backgroundColorTolerance: 1.0,
|
|
1579
|
+
* backgroundColor: { r: 1.0, g: 1.0, b: 1.0 },
|
|
1580
|
+
* transparent: true,
|
|
1581
|
+
* depthTest: true,
|
|
1582
|
+
* depthWrite: false
|
|
1583
|
+
* }
|
|
1584
|
+
*/
|
|
1585
|
+
renderer?: Renderer;
|
|
1586
|
+
/**
|
|
1587
|
+
* Defines the velocity settings of particles over their lifetime.
|
|
1588
|
+
* Configures both linear and orbital velocity changes.
|
|
1589
|
+
*
|
|
1590
|
+
* @see VelocityOverLifetime
|
|
1591
|
+
* @default
|
|
1592
|
+
* velocityOverLifetime: {
|
|
1593
|
+
* isActive: false,
|
|
1594
|
+
* linear: {
|
|
1595
|
+
* x: 0,
|
|
1596
|
+
* y: 0,
|
|
1597
|
+
* z: 0,
|
|
1598
|
+
* },
|
|
1599
|
+
* orbital: {
|
|
1600
|
+
* x: 0,
|
|
1601
|
+
* y: 0,
|
|
1602
|
+
* z: 0,
|
|
1603
|
+
* },
|
|
1604
|
+
* }
|
|
1605
|
+
*/
|
|
1606
|
+
velocityOverLifetime?: VelocityOverLifetime;
|
|
1607
|
+
/**
|
|
1608
|
+
* Controls the size of particles over their lifetime.
|
|
1609
|
+
* The size can be adjusted using a lifetime curve (B??zier or other supported types).
|
|
1610
|
+
*
|
|
1611
|
+
* @default
|
|
1612
|
+
* sizeOverLifetime: {
|
|
1613
|
+
* isActive: false,
|
|
1614
|
+
* lifetimeCurve: {
|
|
1615
|
+
* type: LifeTimeCurve.BEZIER,
|
|
1616
|
+
* scale: 1,
|
|
1617
|
+
* bezierPoints: [
|
|
1618
|
+
* { x: 0, y: 0, percentage: 0 },
|
|
1619
|
+
* { x: 1, y: 1, percentage: 1 },
|
|
1620
|
+
* ],
|
|
1621
|
+
* },
|
|
1622
|
+
* }
|
|
1623
|
+
*/
|
|
1624
|
+
sizeOverLifetime?: {
|
|
1625
|
+
isActive: boolean;
|
|
1626
|
+
lifetimeCurve: LifetimeCurve;
|
|
1627
|
+
};
|
|
1628
|
+
/**
|
|
1629
|
+
* Controls the opacity of particles over their lifetime.
|
|
1630
|
+
* The opacity can be adjusted using a lifetime curve (B??zier or other supported types).
|
|
1631
|
+
*
|
|
1632
|
+
* @default
|
|
1633
|
+
* opacityOverLifetime: {
|
|
1634
|
+
* isActive: false,
|
|
1635
|
+
* lifetimeCurve: {
|
|
1636
|
+
* type: LifeTimeCurve.BEZIER,
|
|
1637
|
+
* scale: 1,
|
|
1638
|
+
* bezierPoints: [
|
|
1639
|
+
* { x: 0, y: 0, percentage: 0 },
|
|
1640
|
+
* { x: 1, y: 1, percentage: 1 },
|
|
1641
|
+
* ],
|
|
1642
|
+
* },
|
|
1643
|
+
* }
|
|
1644
|
+
*/
|
|
1645
|
+
opacityOverLifetime?: {
|
|
1646
|
+
isActive: boolean;
|
|
1647
|
+
lifetimeCurve: LifetimeCurve;
|
|
1648
|
+
};
|
|
1649
|
+
/**
|
|
1650
|
+
* Controls the color of particles over their lifetime.
|
|
1651
|
+
* Each RGB channel can be adjusted independently using a lifetime curve (B??zier or easing).
|
|
1652
|
+
* The curves act as multipliers (0-1 range) that are applied to the particle's start color.
|
|
1653
|
+
*
|
|
1654
|
+
* This follows Unity's Color over Lifetime behavior where the final color is:
|
|
1655
|
+
* finalColor = startColor * colorOverLifetime
|
|
1656
|
+
*
|
|
1657
|
+
* **IMPORTANT**: To achieve full color transitions, set startColor to white { r: 1, g: 1, b: 1 }.
|
|
1658
|
+
* If startColor has any channel set to 0, that channel cannot be modified by colorOverLifetime.
|
|
1659
|
+
*
|
|
1660
|
+
* @example
|
|
1661
|
+
* // Rainbow effect - requires white startColor
|
|
1662
|
+
* startColor: { min: { r: 1, g: 1, b: 1 }, max: { r: 1, g: 1, b: 1 } }
|
|
1663
|
+
* colorOverLifetime: {
|
|
1664
|
+
* isActive: true,
|
|
1665
|
+
* r: { // Red: full -> half -> off
|
|
1666
|
+
* type: LifeTimeCurve.BEZIER,
|
|
1667
|
+
* scale: 1,
|
|
1668
|
+
* bezierPoints: [
|
|
1669
|
+
* { x: 0, y: 1, percentage: 0 },
|
|
1670
|
+
* { x: 0.5, y: 0.5, percentage: 0.5 },
|
|
1671
|
+
* { x: 1, y: 0, percentage: 1 },
|
|
1672
|
+
* ],
|
|
1673
|
+
* },
|
|
1674
|
+
* g: { // Green: off -> full -> off
|
|
1675
|
+
* type: LifeTimeCurve.BEZIER,
|
|
1676
|
+
* scale: 1,
|
|
1677
|
+
* bezierPoints: [
|
|
1678
|
+
* { x: 0, y: 0, percentage: 0 },
|
|
1679
|
+
* { x: 0.5, y: 1, percentage: 0.5 },
|
|
1680
|
+
* { x: 1, y: 0, percentage: 1 },
|
|
1681
|
+
* ],
|
|
1682
|
+
* },
|
|
1683
|
+
* b: { // Blue: off -> half -> full
|
|
1684
|
+
* type: LifeTimeCurve.BEZIER,
|
|
1685
|
+
* scale: 1,
|
|
1686
|
+
* bezierPoints: [
|
|
1687
|
+
* { x: 0, y: 0, percentage: 0 },
|
|
1688
|
+
* { x: 0.5, y: 0.5, percentage: 0.5 },
|
|
1689
|
+
* { x: 1, y: 1, percentage: 1 },
|
|
1690
|
+
* ],
|
|
1691
|
+
* },
|
|
1692
|
+
* }
|
|
1693
|
+
*
|
|
1694
|
+
* @default
|
|
1695
|
+
* colorOverLifetime: {
|
|
1696
|
+
* isActive: false,
|
|
1697
|
+
* r: {
|
|
1698
|
+
* type: LifeTimeCurve.BEZIER,
|
|
1699
|
+
* scale: 1,
|
|
1700
|
+
* bezierPoints: [
|
|
1701
|
+
* { x: 0, y: 1, percentage: 0 },
|
|
1702
|
+
* { x: 1, y: 1, percentage: 1 },
|
|
1703
|
+
* ],
|
|
1704
|
+
* },
|
|
1705
|
+
* g: {
|
|
1706
|
+
* type: LifeTimeCurve.BEZIER,
|
|
1707
|
+
* scale: 1,
|
|
1708
|
+
* bezierPoints: [
|
|
1709
|
+
* { x: 0, y: 1, percentage: 0 },
|
|
1710
|
+
* { x: 1, y: 1, percentage: 1 },
|
|
1711
|
+
* ],
|
|
1712
|
+
* },
|
|
1713
|
+
* b: {
|
|
1714
|
+
* type: LifeTimeCurve.BEZIER,
|
|
1715
|
+
* scale: 1,
|
|
1716
|
+
* bezierPoints: [
|
|
1717
|
+
* { x: 0, y: 1, percentage: 0 },
|
|
1718
|
+
* { x: 1, y: 1, percentage: 1 },
|
|
1719
|
+
* ],
|
|
1720
|
+
* },
|
|
1721
|
+
* }
|
|
1722
|
+
*/
|
|
1723
|
+
colorOverLifetime?: {
|
|
1724
|
+
isActive: boolean;
|
|
1725
|
+
r: LifetimeCurve;
|
|
1726
|
+
g: LifetimeCurve;
|
|
1727
|
+
b: LifetimeCurve;
|
|
1728
|
+
};
|
|
1729
|
+
/**
|
|
1730
|
+
* Controls the rotation of particles over their lifetime.
|
|
1731
|
+
* The rotation can be randomized between two constants, and the feature can be toggled on or off.
|
|
1732
|
+
*
|
|
1733
|
+
* @default
|
|
1734
|
+
* rotationOverLifetime: {
|
|
1735
|
+
* isActive: false,
|
|
1736
|
+
* min: 0.0,
|
|
1737
|
+
* max: 0.0,
|
|
1738
|
+
* }
|
|
1739
|
+
*/
|
|
1740
|
+
rotationOverLifetime?: {
|
|
1741
|
+
isActive: boolean;
|
|
1742
|
+
} & RandomBetweenTwoConstants;
|
|
1743
|
+
/**
|
|
1744
|
+
* Noise configuration affecting position, rotation, and size.
|
|
1745
|
+
*
|
|
1746
|
+
* @see NoiseConfig
|
|
1747
|
+
* @default
|
|
1748
|
+
* noise: {
|
|
1749
|
+
* isActive: false,
|
|
1750
|
+
* useRandomOffset: false,
|
|
1751
|
+
* strength: 1.0,
|
|
1752
|
+
* frequency: 0.5,
|
|
1753
|
+
* octaves: 1,
|
|
1754
|
+
* positionAmount: 1.0,
|
|
1755
|
+
* rotationAmount: 0.0,
|
|
1756
|
+
* sizeAmount: 0.0,
|
|
1757
|
+
* }
|
|
1758
|
+
*/
|
|
1759
|
+
noise?: NoiseConfig;
|
|
1760
|
+
/**
|
|
1761
|
+
* Configures the texture sheet animation settings for particles.
|
|
1762
|
+
* Controls how textures are animated over the lifetime of particles.
|
|
1763
|
+
*
|
|
1764
|
+
* @see TextureSheetAnimation
|
|
1765
|
+
* @default
|
|
1766
|
+
* textureSheetAnimation: {
|
|
1767
|
+
* tiles: new THREE.Vector2(1.0, 1.0),
|
|
1768
|
+
* timeMode: TimeMode.LIFETIME,
|
|
1769
|
+
* fps: 30.0,
|
|
1770
|
+
* startFrame: 0,
|
|
1771
|
+
* }
|
|
1772
|
+
*/
|
|
1773
|
+
textureSheetAnimation?: TextureSheetAnimation;
|
|
1774
|
+
/**
|
|
1775
|
+
* Sub-emitters that spawn child particle systems on particle lifecycle events.
|
|
1776
|
+
* Each sub-emitter is triggered when a particle is born or dies, creating a new
|
|
1777
|
+
* particle system at the parent particle's position.
|
|
1778
|
+
*
|
|
1779
|
+
* @example
|
|
1780
|
+
* ```typescript
|
|
1781
|
+
* subEmitters: [
|
|
1782
|
+
* {
|
|
1783
|
+
* trigger: SubEmitterTrigger.DEATH,
|
|
1784
|
+
* config: { startLifeTime: 0.5, startSpeed: 1, emission: { rateOverTime: 10 } },
|
|
1785
|
+
* },
|
|
1786
|
+
* ]
|
|
1787
|
+
* ```
|
|
1788
|
+
*/
|
|
1789
|
+
subEmitters?: Array<SubEmitterConfig>;
|
|
1790
|
+
/**
|
|
1791
|
+
* Force fields that affect particle velocities.
|
|
1792
|
+
* Each force field can attract, repel, or push particles in a direction.
|
|
1793
|
+
* Multiple force fields are applied cumulatively.
|
|
1794
|
+
*
|
|
1795
|
+
* @default []
|
|
1796
|
+
*
|
|
1797
|
+
* @example
|
|
1798
|
+
* ```typescript
|
|
1799
|
+
* forceFields: [
|
|
1800
|
+
* {
|
|
1801
|
+
* type: ForceFieldType.POINT,
|
|
1802
|
+
* position: new THREE.Vector3(0, 0, 0),
|
|
1803
|
+
* strength: 5.0,
|
|
1804
|
+
* range: 10,
|
|
1805
|
+
* falloff: ForceFieldFalloff.QUADRATIC,
|
|
1806
|
+
* },
|
|
1807
|
+
* ]
|
|
1808
|
+
* ```
|
|
1809
|
+
*/
|
|
1810
|
+
forceFields?: Array<ForceFieldConfig>;
|
|
1811
|
+
/**
|
|
1812
|
+
* Collision planes that constrain particle positions.
|
|
1813
|
+
*
|
|
1814
|
+
* Each plane defines an infinite surface in 3D space. When a particle crosses
|
|
1815
|
+
* from the front side (positive normal direction) to the back side, the
|
|
1816
|
+
* configured response mode is triggered: KILL (remove), CLAMP (stop at surface),
|
|
1817
|
+
* or BOUNCE (reflect with energy loss).
|
|
1818
|
+
*
|
|
1819
|
+
* Plane positions and normals are in world space. Multiple planes are checked
|
|
1820
|
+
* in order; for KILL mode, the first collision deactivates the particle.
|
|
1821
|
+
*
|
|
1822
|
+
* @default []
|
|
1823
|
+
*
|
|
1824
|
+
* @example
|
|
1825
|
+
* ```typescript
|
|
1826
|
+
* collisionPlanes: [
|
|
1827
|
+
* {
|
|
1828
|
+
* position: { x: 0, y: 5, z: 0 },
|
|
1829
|
+
* normal: { x: 0, y: -1, z: 0 },
|
|
1830
|
+
* mode: CollisionPlaneMode.KILL,
|
|
1831
|
+
* },
|
|
1832
|
+
* ]
|
|
1833
|
+
* ```
|
|
1834
|
+
*/
|
|
1835
|
+
collisionPlanes?: Array<CollisionPlaneConfig>;
|
|
1836
|
+
/**
|
|
1837
|
+
* Called on every update frame with particle system data.
|
|
1838
|
+
*/
|
|
1839
|
+
onUpdate?: (data: {
|
|
1840
|
+
particleSystem: THREE.Points | THREE.Mesh;
|
|
1841
|
+
delta: number;
|
|
1842
|
+
elapsed: number;
|
|
1843
|
+
lifetime: number;
|
|
1844
|
+
iterationCount: number;
|
|
1845
|
+
}) => void;
|
|
1846
|
+
/**
|
|
1847
|
+
* Called when the system completes an iteration.
|
|
1848
|
+
*/
|
|
1849
|
+
onComplete?: () => void;
|
|
1850
|
+
};
|
|
1851
|
+
type NormalizedParticleSystemConfig = Required<ParticleSystemConfig>;
|
|
1852
|
+
/**
|
|
1853
|
+
* Tracks the state of a burst emission event.
|
|
1854
|
+
* Used internally to determine when bursts should fire and how many cycles remain.
|
|
1855
|
+
*/
|
|
1856
|
+
type BurstState = {
|
|
1857
|
+
/** Number of cycles that have been executed so far */
|
|
1858
|
+
cyclesExecuted: number;
|
|
1859
|
+
/** Time (in ms) when the last cycle was executed */
|
|
1860
|
+
lastCycleTime: number;
|
|
1861
|
+
/** Whether the probability check passed for this iteration */
|
|
1862
|
+
probabilityPassed: boolean;
|
|
1863
|
+
};
|
|
1864
|
+
type GeneralData = {
|
|
1865
|
+
particleSystemId: number;
|
|
1866
|
+
normalizedLifetimePercentage: number;
|
|
1867
|
+
creationTimes: Float32Array;
|
|
1868
|
+
distanceFromLastEmitByDistance: number;
|
|
1869
|
+
lastWorldPosition: THREE.Vector3;
|
|
1870
|
+
currentWorldPosition: THREE.Vector3;
|
|
1871
|
+
worldPositionChange: THREE.Vector3;
|
|
1872
|
+
/**
|
|
1873
|
+
* For WORLD simulation space: the full world transform of the emitter
|
|
1874
|
+
* (parent.matrixWorld ?? particleSystem.matrix). Used to position new
|
|
1875
|
+
* particles in world coordinates at emit time and to orient the
|
|
1876
|
+
* emission shape. The particleSystem's own matrixWorld is forced to
|
|
1877
|
+
* identity so the buffer coordinates render as world coordinates.
|
|
1878
|
+
*/
|
|
1879
|
+
sourceWorldMatrix: THREE.Matrix4;
|
|
1880
|
+
wrapperQuaternion: THREE.Quaternion;
|
|
1881
|
+
worldQuaternion: THREE.Quaternion;
|
|
1882
|
+
/**
|
|
1883
|
+
* Emitter world scale (decomposed from the full parent chain). Used to
|
|
1884
|
+
* match Unity's parent-scale semantics:
|
|
1885
|
+
* - WORLD mode: scales the shape-emission offset at spawn time (the
|
|
1886
|
+
* Shape module in Unity obeys parent scale when Scaling Mode is
|
|
1887
|
+
* Local/Hierarchy). Live particles are unaffected.
|
|
1888
|
+
* - LOCAL mode: gravity is stored in local units, so it is divided by
|
|
1889
|
+
* this scale so the rendered fall matches world -g m/s?? regardless
|
|
1890
|
+
* of parent scale.
|
|
1891
|
+
*/
|
|
1892
|
+
worldScale: THREE.Vector3;
|
|
1893
|
+
worldEuler: THREE.Euler;
|
|
1894
|
+
gravityVelocity: THREE.Vector3;
|
|
1895
|
+
startValues: Record<string, Array<number>>;
|
|
1896
|
+
linearVelocityData?: Array<{
|
|
1897
|
+
speed: THREE.Vector3;
|
|
1898
|
+
valueModifiers: {
|
|
1899
|
+
x?: CurveFunction;
|
|
1900
|
+
y?: CurveFunction;
|
|
1901
|
+
z?: CurveFunction;
|
|
1902
|
+
};
|
|
1903
|
+
}>;
|
|
1904
|
+
orbitalVelocityData?: Array<{
|
|
1905
|
+
speed: THREE.Vector3;
|
|
1906
|
+
positionOffset: THREE.Vector3;
|
|
1907
|
+
valueModifiers: {
|
|
1908
|
+
x?: CurveFunction;
|
|
1909
|
+
y?: CurveFunction;
|
|
1910
|
+
z?: CurveFunction;
|
|
1911
|
+
};
|
|
1912
|
+
}>;
|
|
1913
|
+
lifetimeValues: Record<string, Array<number>>;
|
|
1914
|
+
noise: Noise;
|
|
1915
|
+
isEnabled: boolean;
|
|
1916
|
+
/** Tracks the state of each burst emission event */
|
|
1917
|
+
burstStates?: Array<BurstState>;
|
|
1918
|
+
/**
|
|
1919
|
+
* Circular buffer storing position history for trail renderer.
|
|
1920
|
+
* Each particle has `trailLength` slots of (x, y, z) positions.
|
|
1921
|
+
* Only allocated when `RendererType.TRAIL` is used.
|
|
1922
|
+
*/
|
|
1923
|
+
positionHistory?: Float32Array;
|
|
1924
|
+
/** Write index per particle into the circular position history buffer. */
|
|
1925
|
+
positionHistoryIndex?: Uint16Array;
|
|
1926
|
+
/** Number of valid history samples per particle (fills up from 0 to trailLength). */
|
|
1927
|
+
positionHistoryCount?: Uint16Array;
|
|
1928
|
+
/** Trail length (number of history samples per particle). */
|
|
1929
|
+
trailLength?: number;
|
|
1930
|
+
/** Cached camera world position, updated each frame via onBeforeRender for billboard trails. */
|
|
1931
|
+
trailCameraPosition?: THREE.Vector3;
|
|
1932
|
+
/**
|
|
1933
|
+
* Timestamp (in ms) when each trail history sample was recorded.
|
|
1934
|
+
* Used by `maxTime` to expire old segments.
|
|
1935
|
+
* Layout: `maxParticles * trailLength` entries.
|
|
1936
|
+
*/
|
|
1937
|
+
trailSampleTimes?: Float64Array;
|
|
1938
|
+
/**
|
|
1939
|
+
* Last recorded position per particle for adaptive sampling (`minVertexDistance`).
|
|
1940
|
+
* Layout: `maxParticles * 3` (x, y, z).
|
|
1941
|
+
*/
|
|
1942
|
+
trailLastSampledPosition?: Float32Array;
|
|
1943
|
+
/**
|
|
1944
|
+
* Per-particle previous ribbon normal vector for twist prevention.
|
|
1945
|
+
* Layout: `maxParticles * 3` (nx, ny, nz).
|
|
1946
|
+
*/
|
|
1947
|
+
trailPrevNormal?: Float32Array;
|
|
1948
|
+
/**
|
|
1949
|
+
* Number of trail vertex-buffer slots filled per particle in the previous
|
|
1950
|
+
* frame. Lets the trail update skip re-clearing slots that are already
|
|
1951
|
+
* cleared (they stay invisible via zero alpha/half-width).
|
|
1952
|
+
*/
|
|
1953
|
+
trailPrevFilledCount?: Uint16Array;
|
|
1954
|
+
/**
|
|
1955
|
+
* Highest particle index ever written on the CPU path (monotonic).
|
|
1956
|
+
* The per-frame buffer flush uploads `[0, watermark]` as a single update
|
|
1957
|
+
* range ??? a provably covering superset of every write since the last GPU
|
|
1958
|
+
* upload, independent of render timing. -1 = nothing written yet.
|
|
1959
|
+
*/
|
|
1960
|
+
cpuDirtyParticleWatermark: number;
|
|
1961
|
+
/** Highest ever-active slot + 1 (monotonic). Bounds every per-frame per-particle walk. 0 = nothing emitted yet. */
|
|
1962
|
+
highWaterIndex: number;
|
|
1963
|
+
/**
|
|
1964
|
+
* Pre-resolved lifetime-curve functions for the size / opacity / color
|
|
1965
|
+
* modifiers (scale already applied). Resolved once at system creation and
|
|
1966
|
+
* re-resolved by `updateConfig` ??? evaluating these per particle per frame
|
|
1967
|
+
* avoids the curve-function lookup and closure allocations of
|
|
1968
|
+
* `calculateValue`. Undefined entries fall back to `calculateValue`
|
|
1969
|
+
* (e.g. constant or random-range values).
|
|
1970
|
+
*/
|
|
1971
|
+
modifierCurves?: {
|
|
1972
|
+
size?: CurveFunction;
|
|
1973
|
+
opacity?: CurveFunction;
|
|
1974
|
+
colorR?: CurveFunction;
|
|
1975
|
+
colorG?: CurveFunction;
|
|
1976
|
+
colorB?: CurveFunction;
|
|
1977
|
+
};
|
|
1978
|
+
};
|
|
1979
|
+
/** Union of all buffer attribute types Three.js uses in geometry. */
|
|
1980
|
+
type AnyBufferAttribute = THREE.BufferAttribute | THREE.InstancedBufferAttribute | THREE.InterleavedBufferAttribute;
|
|
1981
|
+
/**
|
|
1982
|
+
* A view that maps standard attribute names (e.g. 'position', 'size') to
|
|
1983
|
+
* their actual geometry attribute objects, which may have different names
|
|
1984
|
+
* in the instanced renderer (e.g. 'instanceOffset', 'instanceSize').
|
|
1985
|
+
*/
|
|
1986
|
+
type MappedAttributes = {
|
|
1987
|
+
position: AnyBufferAttribute;
|
|
1988
|
+
isActive: AnyBufferAttribute;
|
|
1989
|
+
lifetime: AnyBufferAttribute;
|
|
1990
|
+
startLifetime: AnyBufferAttribute;
|
|
1991
|
+
startFrame: AnyBufferAttribute;
|
|
1992
|
+
size: AnyBufferAttribute;
|
|
1993
|
+
rotation: AnyBufferAttribute;
|
|
1994
|
+
/** Packed RGBA color (vec4). */
|
|
1995
|
+
color: AnyBufferAttribute;
|
|
1996
|
+
/** Packed quaternion vec4 for 3D mesh rotation (only present for RendererType.MESH). */
|
|
1997
|
+
quat?: AnyBufferAttribute;
|
|
1998
|
+
};
|
|
1999
|
+
type ParticleSystemInstance = {
|
|
2000
|
+
particleSystem: THREE.Points | THREE.Mesh;
|
|
2001
|
+
mappedAttributes: MappedAttributes;
|
|
2002
|
+
/** Shared interleaved Float32Array backing all scalar per-particle attributes. */
|
|
2003
|
+
scalarArray: Float32Array;
|
|
2004
|
+
/** The InterleavedBuffer (or InstancedInterleavedBuffer) for scalar attributes. */
|
|
2005
|
+
scalarInterleavedBuffer: THREE.InterleavedBuffer;
|
|
2006
|
+
elapsedUniform: {
|
|
2007
|
+
value: number;
|
|
2008
|
+
};
|
|
2009
|
+
generalData: GeneralData;
|
|
2010
|
+
onUpdate: (data: {
|
|
2011
|
+
particleSystem: THREE.Points | THREE.Mesh;
|
|
2012
|
+
delta: number;
|
|
2013
|
+
elapsed: number;
|
|
2014
|
+
lifetime: number;
|
|
2015
|
+
normalizedLifetime: number;
|
|
2016
|
+
iterationCount: number;
|
|
2017
|
+
}) => void;
|
|
2018
|
+
onComplete: (data: {
|
|
2019
|
+
particleSystem: THREE.Points | THREE.Mesh;
|
|
2020
|
+
}) => void;
|
|
2021
|
+
creationTime: number;
|
|
2022
|
+
lastEmissionTime: number;
|
|
2023
|
+
/**
|
|
2024
|
+
* Fractional particles carried over between frames by time-based emission.
|
|
2025
|
+
* Prevents `Math.floor` from systematically dropping the remainder
|
|
2026
|
+
* (e.g. rate 100/s at 60 FPS = 1.66 particles/frame).
|
|
2027
|
+
*/
|
|
2028
|
+
emissionAccumulator: number;
|
|
2029
|
+
duration: number;
|
|
2030
|
+
looping: boolean;
|
|
2031
|
+
simulationSpace: SimulationSpace;
|
|
2032
|
+
gravity: number;
|
|
2033
|
+
normalizedForceFields: Array<NormalizedForceFieldConfig>;
|
|
2034
|
+
normalizedCollisionPlanes: Array<NormalizedCollisionPlaneConfig>;
|
|
2035
|
+
emission: Emission;
|
|
2036
|
+
normalizedConfig: NormalizedParticleSystemConfig;
|
|
2037
|
+
iterationCount: number;
|
|
2038
|
+
velocities: Array<THREE.Vector3>;
|
|
2039
|
+
freeList: Array<number>;
|
|
2040
|
+
deactivateParticle: (particleIndex: number) => void;
|
|
2041
|
+
/**
|
|
2042
|
+
* Deactivates a particle and fires death sub-emitters first (when
|
|
2043
|
+
* configured). Stable per-system callback so the collision-plane hot loop
|
|
2044
|
+
* does not allocate a closure per particle per frame.
|
|
2045
|
+
*/
|
|
2046
|
+
killParticle: (particleIndex: number) => void;
|
|
2047
|
+
activateParticle: (data: {
|
|
2048
|
+
particleIndex: number;
|
|
2049
|
+
activationTime: number;
|
|
2050
|
+
position: Required<Point3D>;
|
|
2051
|
+
}) => void;
|
|
2052
|
+
/** Called when a particle dies to trigger death sub-emitters */
|
|
2053
|
+
onParticleDeath?: (particleIndex: number, positionArr: THREE.TypedArray, velocity: THREE.Vector3, now: number) => void;
|
|
2054
|
+
/** Called when a particle is born to trigger birth sub-emitters */
|
|
2055
|
+
onParticleBirth?: (particleIndex: number, positionArr: THREE.TypedArray, velocity: THREE.Vector3, now: number) => void;
|
|
2056
|
+
/** Trail mesh for RendererType.TRAIL */
|
|
2057
|
+
trailMesh?: THREE.Mesh;
|
|
2058
|
+
/** Trail geometry position attribute */
|
|
2059
|
+
trailPositionAttr?: THREE.BufferAttribute;
|
|
2060
|
+
/** Trail geometry alpha attribute */
|
|
2061
|
+
trailAlphaAttr?: THREE.BufferAttribute;
|
|
2062
|
+
/** Trail geometry color attribute */
|
|
2063
|
+
trailColorAttr?: THREE.BufferAttribute;
|
|
2064
|
+
/** Trail geometry next-position attribute (cached to avoid repeated getAttribute) */
|
|
2065
|
+
trailNextAttr?: THREE.BufferAttribute;
|
|
2066
|
+
/** Trail geometry half-width attribute (cached) */
|
|
2067
|
+
trailHalfWidthAttr?: THREE.BufferAttribute;
|
|
2068
|
+
/** Trail geometry UV attribute (cached) */
|
|
2069
|
+
trailUVAttr?: THREE.BufferAttribute;
|
|
2070
|
+
/** Trail width curve function */
|
|
2071
|
+
trailWidthCurveFn?: CurveFunction;
|
|
2072
|
+
/** Trail opacity curve function */
|
|
2073
|
+
trailOpacityCurveFn?: CurveFunction;
|
|
2074
|
+
/** Trail color-over-trail curve functions (r, g, b multipliers) */
|
|
2075
|
+
trailColorOverTrailFns?: {
|
|
2076
|
+
r: CurveFunction;
|
|
2077
|
+
g: CurveFunction;
|
|
2078
|
+
b: CurveFunction;
|
|
2079
|
+
};
|
|
2080
|
+
/** Trail config (length, width, and advanced features) */
|
|
2081
|
+
trailConfig?: {
|
|
2082
|
+
length: number;
|
|
2083
|
+
width: number;
|
|
2084
|
+
minVertexDistance: number;
|
|
2085
|
+
maxTime: number;
|
|
2086
|
+
smoothing: boolean;
|
|
2087
|
+
smoothingSubdivisions: number;
|
|
2088
|
+
twistPrevention: boolean;
|
|
2089
|
+
ribbonId?: number;
|
|
2090
|
+
};
|
|
2091
|
+
/** GPU compute pipeline for WebGPU simulation. Opaque type to avoid pulling TSL types into DTS. */
|
|
2092
|
+
computePipeline?: {
|
|
2093
|
+
computeNode: unknown;
|
|
2094
|
+
/** Ordered list of compute dispatches: [emitNode, simNode] on the GPU-only engine. */
|
|
2095
|
+
computeNodes?: unknown[];
|
|
2096
|
+
/** Emission dispatch; its numeric `count` is refreshed from `emitCount` per frame. */
|
|
2097
|
+
emitNode?: unknown;
|
|
2098
|
+
/** Per-frame simulation dispatch (count = `maxParticles`). */
|
|
2099
|
+
simNode?: unknown;
|
|
2100
|
+
/** Dedicated trail-history pass node (after simulate; 4 storage bindings). */
|
|
2101
|
+
trailHistoryNode?: unknown;
|
|
2102
|
+
/** Dedicated sub-emitter BIRTH event pass node (5..7 storage bindings). */
|
|
2103
|
+
subBirthEventsNode?: unknown;
|
|
2104
|
+
/** Dedicated sub-emitter DEATH event pass node (5..7 storage bindings). */
|
|
2105
|
+
subDeathEventsNode?: unknown;
|
|
2106
|
+
/** Real per-pass storage/uniform budgets (every pass <= 8 storages). */
|
|
2107
|
+
passLayouts?: Array<{
|
|
2108
|
+
name: string;
|
|
2109
|
+
storageBindings: number;
|
|
2110
|
+
uniformBindings: number;
|
|
2111
|
+
}>;
|
|
2112
|
+
uniforms: Record<string, unknown>;
|
|
2113
|
+
/** GPU storage buffers that are ALSO attached as geometry attributes. */
|
|
2114
|
+
buffers: Record<string, unknown>;
|
|
2115
|
+
/** Element count of the uint atomic allocator stack (`maxParticles + 1`). */
|
|
2116
|
+
allocatorCount?: number;
|
|
2117
|
+
/** Non-atomic f32 uniform-table node (baked curves + force fields + collision planes). */
|
|
2118
|
+
packedDataNode?: unknown;
|
|
2119
|
+
/**
|
|
2120
|
+
* Emitter-pose uniforms written per frame by the update loop:
|
|
2121
|
+
* `positionW` = (x, y, z, isWorldFlag), `wrapperQuat` = (x, y, z, w),
|
|
2122
|
+
* `worldScale` = (sx, sy, sz).
|
|
2123
|
+
*/
|
|
2124
|
+
emitterPose?: {
|
|
2125
|
+
positionW: unknown;
|
|
2126
|
+
wrapperQuat: unknown;
|
|
2127
|
+
worldScale: unknown;
|
|
2128
|
+
};
|
|
2129
|
+
forceFieldInfo: {
|
|
2130
|
+
offset: number;
|
|
2131
|
+
countUniform: unknown;
|
|
2132
|
+
} | null;
|
|
2133
|
+
/** Optional for backwards compat with the older single-forceFieldInfo shape. */
|
|
2134
|
+
collisionPlaneInfo?: {
|
|
2135
|
+
offset: number;
|
|
2136
|
+
countUniform: unknown;
|
|
2137
|
+
} | null;
|
|
2138
|
+
/** Shape/start-value scalar uniforms for construction-time diagnostics. */
|
|
2139
|
+
shapeUniforms?: Record<string, unknown>;
|
|
2140
|
+
/** Semantic compute pass names in dispatch order. */
|
|
2141
|
+
passNames?: string[];
|
|
2142
|
+
/** Trail ring integer metadata attribute (null when there is no trail). */
|
|
2143
|
+
trailMeta?: unknown;
|
|
2144
|
+
};
|
|
2145
|
+
/** Whether this system uses GPU compute for simulation. */
|
|
2146
|
+
useGPUCompute?: boolean;
|
|
2147
|
+
/** Flag set by update loop, consumed by onBeforeRender to dispatch compute. */
|
|
2148
|
+
computeDispatchReady?: boolean;
|
|
2149
|
+
/** Storage-pool capacity, used to cap `instanceCount` on the geometry. */
|
|
2150
|
+
maxParticles?: number;
|
|
2151
|
+
/** Attached material (TSL NodeMaterial or legacy ShaderMaterial). */
|
|
2152
|
+
material?: THREE.Material;
|
|
2153
|
+
/** Attached geometry (used to sync `instanceCount` on CPU/GPU transitions). */
|
|
2154
|
+
geometry?: THREE.BufferGeometry | THREE.InstancedBufferGeometry;
|
|
2155
|
+
/** Chosen renderer type; used to derive `instanceCount` behaviour after `updateConfig`. */
|
|
2156
|
+
rrType?: "POINTS" | "INSTANCED" | "MESH" | "TRAIL";
|
|
2157
|
+
/** Original `renderer.rendererType` from the config (§2). */
|
|
2158
|
+
requestedRendererType?: "POINTS" | "INSTANCED" | "MESH" | "TRAIL";
|
|
2159
|
+
/** Canonical effective GPU renderer class after POINTS resolution (§2). */
|
|
2160
|
+
effectiveRendererType?: "POINTS" | "INSTANCED" | "MESH" | "TRAIL";
|
|
2161
|
+
/** Cached TSL shared uniform table. */
|
|
2162
|
+
sharedUniforms?: {
|
|
2163
|
+
[k: string]: {
|
|
2164
|
+
value: unknown;
|
|
2165
|
+
};
|
|
2166
|
+
};
|
|
2167
|
+
/**
|
|
2168
|
+
* Every compute node of this system in dispatch order:
|
|
2169
|
+
* `[emit, sim, ribbon?, (init, childEmit, childSim)?]`.
|
|
2170
|
+
*/
|
|
2171
|
+
allComputeNodes?: unknown[];
|
|
2172
|
+
/** Semantic pass names in dispatch order (for `[PS:pipeline]` logging). */
|
|
2173
|
+
passNames?: string[];
|
|
2174
|
+
/** Per-system sub-emitter child kernels + their own scalar state. */
|
|
2175
|
+
subEntries?: {
|
|
2176
|
+
fifo: {
|
|
2177
|
+
capacity: number;
|
|
2178
|
+
windowSize: number;
|
|
2179
|
+
};
|
|
2180
|
+
requestedRendererType?: "POINTS" | "INSTANCED" | "MESH" | "TRAIL";
|
|
2181
|
+
effectiveRendererType?: "POINTS" | "INSTANCED" | "MESH" | "TRAIL";
|
|
2182
|
+
pipeline: Record<string, any> | undefined;
|
|
2183
|
+
init: {
|
|
2184
|
+
commandBuildNode: unknown;
|
|
2185
|
+
childInitNode: unknown;
|
|
2186
|
+
counterClearNode?: unknown;
|
|
2187
|
+
commandBuffer?: unknown;
|
|
2188
|
+
passLayouts?: Array<{
|
|
2189
|
+
name: string;
|
|
2190
|
+
storageBindings: number;
|
|
2191
|
+
uniformBindings: number;
|
|
2192
|
+
}>;
|
|
2193
|
+
passName?: string;
|
|
2194
|
+
counterClearPassName?: string;
|
|
2195
|
+
uniforms: Record<string, {
|
|
2196
|
+
value: unknown;
|
|
2197
|
+
}>;
|
|
2198
|
+
};
|
|
2199
|
+
gravity: number;
|
|
2200
|
+
noise: GeneralData['noise'] | null;
|
|
2201
|
+
rate: number;
|
|
2202
|
+
acc: number;
|
|
2203
|
+
isWorld: 0 | 1;
|
|
2204
|
+
quat: [number, number, number, number];
|
|
2205
|
+
scale: [number, number, number];
|
|
2206
|
+
position: [number, number, number];
|
|
2207
|
+
}[];
|
|
2208
|
+
/** Shared ping-pong window stride of the FIFO buffers. */
|
|
2209
|
+
fifoBaseStride?: number;
|
|
2210
|
+
/** Trail ribbon kernel uniforms (`nowMs`), present for RendererType.TRAIL. */
|
|
2211
|
+
ribbonUniforms?: {
|
|
2212
|
+
[k: string]: {
|
|
2213
|
+
value: unknown;
|
|
2214
|
+
};
|
|
2215
|
+
};
|
|
2216
|
+
/** Trail ribbon storage attributes (first-frame upload only). */
|
|
2217
|
+
ribbonBuffers?: {
|
|
2218
|
+
[k: string]: THREE.BufferAttribute;
|
|
2219
|
+
};
|
|
2220
|
+
/** Frame parity counter (0/1) driving the FIFO ping-pong windows. */
|
|
2221
|
+
frameParity?: number;
|
|
2222
|
+
};
|
|
2223
|
+
/**
|
|
2224
|
+
* Represents a particle system instance, providing methods to control and manage its lifecycle.
|
|
2225
|
+
*
|
|
2226
|
+
* @property instance - The underlying Three.js `Points` or `Mesh` object used for particle rendering.
|
|
2227
|
+
* @property resumeEmitter - Resumes the particle emitter, allowing particles to be emitted again.
|
|
2228
|
+
* @property pauseEmitter - Pauses the particle emitter, stopping any new particles from being emitted.
|
|
2229
|
+
* @property dispose - Disposes of the particle system, cleaning up resources to free memory.
|
|
2230
|
+
*
|
|
2231
|
+
* @example
|
|
2232
|
+
* const particleSystem: ParticleSystem = {
|
|
2233
|
+
* instance: new THREE.Points(geometry, material),
|
|
2234
|
+
* resumeEmitter: () => { /* resume logic * / },
|
|
2235
|
+
* pauseEmitter: () => { /* pause logic * / },
|
|
2236
|
+
* dispose: () => { /* cleanup logic * / },
|
|
2237
|
+
* };
|
|
2238
|
+
*
|
|
2239
|
+
* particleSystem.pauseEmitter(); // Stop particle emission
|
|
2240
|
+
* particleSystem.resumeEmitter(); // Resume particle emission
|
|
2241
|
+
* particleSystem.dispose(); // Cleanup the particle system
|
|
2242
|
+
*/
|
|
2243
|
+
type ParticleSystem = {
|
|
2244
|
+
instance: THREE.Points | THREE.Mesh;
|
|
2245
|
+
resumeEmitter: () => void;
|
|
2246
|
+
pauseEmitter: () => void;
|
|
2247
|
+
dispose: () => void;
|
|
2248
|
+
update: (cycleData: CycleData) => void;
|
|
2249
|
+
/**
|
|
2250
|
+
* ?? Deprecated synchronous count ???? Returns `-1` (unsupported) on the
|
|
2251
|
+
* GPU-only engine. Authoritative value: `maxParticles - allocator[0]`, read
|
|
2252
|
+
* on demand through `renderer.getArrayBufferAsync` + `gpuDebug`.
|
|
2253
|
+
*/
|
|
2254
|
+
getActiveParticleCount?: () => number;
|
|
2255
|
+
/**
|
|
2256
|
+
* ?? Temporary / deprecated one-shot GPU debug handle ????
|
|
2257
|
+
* Raw material for an explicit `renderer.getArrayBufferAsync(...)` read-back
|
|
2258
|
+
* (byte offset + byte count, multiples of 4). No per-frame cost.
|
|
2259
|
+
*/
|
|
2260
|
+
gpuDebug?: {
|
|
2261
|
+
maxParticles: number;
|
|
2262
|
+
allocatorCount: number;
|
|
2263
|
+
buffers: Record<string, unknown>;
|
|
2264
|
+
emitNode: unknown;
|
|
2265
|
+
simNode: unknown;
|
|
2266
|
+
passNames?: string[];
|
|
2267
|
+
allPassNames?: string[];
|
|
2268
|
+
storageBindingCount?: number;
|
|
2269
|
+
passBindingCounts?: Array<[string, number]>;
|
|
2270
|
+
lastEmitCount: () => number;
|
|
2271
|
+
snapshot?: () => Record<string, unknown>;
|
|
2272
|
+
};
|
|
2273
|
+
/** Ordered WebGPU compute nodes, dispatched in order. `renderer.compute(...)` accepts a single `Node` or an array; the GPU-only engine returns the [emitNode, simNode] pair. */
|
|
2274
|
+
computeNode: unknown | unknown[] | null;
|
|
2275
|
+
/**
|
|
2276
|
+
* Updates the particle system configuration at runtime without recreating the system.
|
|
2277
|
+
*
|
|
2278
|
+
* System-level properties (gravity, force fields, noise, emission rates, color/size/opacity
|
|
2279
|
+
* over lifetime curves) take effect immediately for all particles.
|
|
2280
|
+
* Per-particle spawn properties (startColor, startSize, startSpeed, startLifetime, etc.)
|
|
2281
|
+
* only affect newly emitted particles ??? already-alive particles retain their original values.
|
|
2282
|
+
*
|
|
2283
|
+
* @param config - A partial configuration object. Only the provided properties will be updated;
|
|
2284
|
+
* all other settings remain unchanged.
|
|
2285
|
+
*
|
|
2286
|
+
* @remarks
|
|
2287
|
+
* Structural properties that are set at creation time cannot be changed at runtime:
|
|
2288
|
+
* `maxParticles`, `renderer.rendererType`, `shape`, and `map` (texture).
|
|
2289
|
+
* Passing these will update the internal config but have no visible effect since the
|
|
2290
|
+
* geometry and material are pre-allocated.
|
|
2291
|
+
*
|
|
2292
|
+
* **GPU compute limitation:** when the system runs on the WebGPU compute
|
|
2293
|
+
* backend, modifier activation flags and lifetime curves
|
|
2294
|
+
* (`sizeOverLifetime`, `opacityOverLifetime`, `colorOverLifetime`,
|
|
2295
|
+
* `rotationOverLifetime`, `velocityOverLifetime`, `noise.isActive`) are
|
|
2296
|
+
* baked into the compute kernel at creation and cannot be changed live ???
|
|
2297
|
+
* a console warning is emitted and the system must be recreated instead.
|
|
2298
|
+
* On the CPU backend all of these update live.
|
|
2299
|
+
*
|
|
2300
|
+
* @example
|
|
2301
|
+
* ```typescript
|
|
2302
|
+
* const system = createParticleSystem(config);
|
|
2303
|
+
*
|
|
2304
|
+
* // Change wind direction in real time
|
|
2305
|
+
* system.updateConfig({
|
|
2306
|
+
* forceFields: [{ type: ForceFieldType.DIRECTIONAL, direction: { x: 1, y: 0, z: 0 }, strength: 5 }],
|
|
2307
|
+
* });
|
|
2308
|
+
*
|
|
2309
|
+
* // Gradually change color of new particles
|
|
2310
|
+
* system.updateConfig({
|
|
2311
|
+
* startColor: { min: { r: 1, g: 0, b: 0 }, max: { r: 1, g: 0.5, b: 0 } },
|
|
2312
|
+
* });
|
|
2313
|
+
* ```
|
|
2314
|
+
*/
|
|
2315
|
+
updateConfig: (config: Partial<ParticleSystemConfig>) => void;
|
|
2316
|
+
};
|
|
2317
|
+
/**
|
|
2318
|
+
* Data representing the current cycle of the particle system's update loop.
|
|
2319
|
+
*
|
|
2320
|
+
* @property now - The current timestamp in milliseconds.
|
|
2321
|
+
* @property delta - The time elapsed since the last update, in seconds.
|
|
2322
|
+
* @property elapsed - The total time elapsed since the particle system started, in seconds.
|
|
2323
|
+
*
|
|
2324
|
+
* @example
|
|
2325
|
+
* const cycleData: CycleData = {
|
|
2326
|
+
* now: performance.now(),
|
|
2327
|
+
* delta: 0.016, // 16ms frame time
|
|
2328
|
+
* elapsed: 1.25, // 1.25 seconds since start
|
|
2329
|
+
* };
|
|
2330
|
+
*/
|
|
2331
|
+
type CycleData = {
|
|
2332
|
+
now: number;
|
|
2333
|
+
delta: number;
|
|
2334
|
+
elapsed: number;
|
|
2335
|
+
};
|
|
2336
|
+
|
|
2337
|
+
declare const createBezierCurveFunction: (particleSystemId: number, bezierPoints: Array<BezierPoint>) => CurveFunction;
|
|
2338
|
+
declare const removeBezierCurveFunction: (particleSystemId: number) => void;
|
|
2339
|
+
declare const getBezierCacheSize: () => number;
|
|
2340
|
+
|
|
2341
|
+
/**
|
|
2342
|
+
* Predefined easing function identifiers for animating particle properties
|
|
2343
|
+
* over their lifetime.
|
|
2344
|
+
*
|
|
2345
|
+
* These functions control the rate of change and create different animation
|
|
2346
|
+
* feels. Each type has three variants:
|
|
2347
|
+
* - **IN**: Starts slow, accelerates toward the end
|
|
2348
|
+
* - **OUT**: Starts fast, decelerates toward the end
|
|
2349
|
+
* - **IN_OUT**: Combines both, slow at start and end, fast in middle
|
|
2350
|
+
*
|
|
2351
|
+
* @enum {string}
|
|
2352
|
+
*
|
|
2353
|
+
* @see {@link https://easings.net/} - Visual reference for easing functions
|
|
2354
|
+
*/
|
|
2355
|
+
declare const enum CurveFunctionId {
|
|
2356
|
+
/** Use custom Bezier curve (not an easing function) */
|
|
2357
|
+
BEZIER = "BEZIER",
|
|
2358
|
+
/** Linear interpolation with constant rate of change */
|
|
2359
|
+
LINEAR = "LINEAR",
|
|
2360
|
+
/** Quadratic (t??) easing - gentle acceleration */
|
|
2361
|
+
QUADRATIC_IN = "QUADRATIC_IN",
|
|
2362
|
+
/** Quadratic (t??) easing - gentle deceleration */
|
|
2363
|
+
QUADRATIC_OUT = "QUADRATIC_OUT",
|
|
2364
|
+
/** Quadratic (t??) easing - gentle acceleration then deceleration */
|
|
2365
|
+
QUADRATIC_IN_OUT = "QUADRATIC_IN_OUT",
|
|
2366
|
+
/** Cubic (t??) easing - moderate acceleration */
|
|
2367
|
+
CUBIC_IN = "CUBIC_IN",
|
|
2368
|
+
/** Cubic (t??) easing - moderate deceleration */
|
|
2369
|
+
CUBIC_OUT = "CUBIC_OUT",
|
|
2370
|
+
/** Cubic (t??) easing - moderate acceleration then deceleration */
|
|
2371
|
+
CUBIC_IN_OUT = "CUBIC_IN_OUT",
|
|
2372
|
+
/** Quartic (t???) easing - strong acceleration */
|
|
2373
|
+
QUARTIC_IN = "QUARTIC_IN",
|
|
2374
|
+
/** Quartic (t???) easing - strong deceleration */
|
|
2375
|
+
QUARTIC_OUT = "QUARTIC_OUT",
|
|
2376
|
+
/** Quartic (t???) easing - strong acceleration then deceleration */
|
|
2377
|
+
QUARTIC_IN_OUT = "QUARTIC_IN_OUT",
|
|
2378
|
+
/** Quintic (t???) easing - very strong acceleration */
|
|
2379
|
+
QUINTIC_IN = "QUINTIC_IN",
|
|
2380
|
+
/** Quintic (t???) easing - very strong deceleration */
|
|
2381
|
+
QUINTIC_OUT = "QUINTIC_OUT",
|
|
2382
|
+
/** Quintic (t???) easing - very strong acceleration then deceleration */
|
|
2383
|
+
QUINTIC_IN_OUT = "QUINTIC_IN_OUT",
|
|
2384
|
+
/** Sinusoidal easing - smooth, natural acceleration */
|
|
2385
|
+
SINUSOIDAL_IN = "SINUSOIDAL_IN",
|
|
2386
|
+
/** Sinusoidal easing - smooth, natural deceleration */
|
|
2387
|
+
SINUSOIDAL_OUT = "SINUSOIDAL_OUT",
|
|
2388
|
+
/** Sinusoidal easing - smooth acceleration then deceleration */
|
|
2389
|
+
SINUSOIDAL_IN_OUT = "SINUSOIDAL_IN_OUT",
|
|
2390
|
+
/** Exponential easing - dramatic, explosive acceleration */
|
|
2391
|
+
EXPONENTIAL_IN = "EXPONENTIAL_IN",
|
|
2392
|
+
/** Exponential easing - dramatic, explosive deceleration */
|
|
2393
|
+
EXPONENTIAL_OUT = "EXPONENTIAL_OUT",
|
|
2394
|
+
/** Exponential easing - dramatic acceleration then deceleration */
|
|
2395
|
+
EXPONENTIAL_IN_OUT = "EXPONENTIAL_IN_OUT",
|
|
2396
|
+
/** Circular easing - sharp acceleration with curved trajectory */
|
|
2397
|
+
CIRCULAR_IN = "CIRCULAR_IN",
|
|
2398
|
+
/** Circular easing - sharp deceleration with curved trajectory */
|
|
2399
|
+
CIRCULAR_OUT = "CIRCULAR_OUT",
|
|
2400
|
+
/** Circular easing - sharp acceleration then deceleration */
|
|
2401
|
+
CIRCULAR_IN_OUT = "CIRCULAR_IN_OUT",
|
|
2402
|
+
/** Elastic easing - oscillates back before accelerating (spring-like) */
|
|
2403
|
+
ELASTIC_IN = "ELASTIC_IN",
|
|
2404
|
+
/** Elastic easing - overshoots then oscillates back (spring-like) */
|
|
2405
|
+
ELASTIC_OUT = "ELASTIC_OUT",
|
|
2406
|
+
/** Elastic easing - oscillates at both ends (spring-like) */
|
|
2407
|
+
ELASTIC_IN_OUT = "ELASTIC_IN_OUT",
|
|
2408
|
+
/** Back easing - pulls back before accelerating forward */
|
|
2409
|
+
BACK_IN = "BACK_IN",
|
|
2410
|
+
/** Back easing - overshoots forward then pulls back */
|
|
2411
|
+
BACK_OUT = "BACK_OUT",
|
|
2412
|
+
/** Back easing - pulls back, overshoots, then settles */
|
|
2413
|
+
BACK_IN_OUT = "BACK_IN_OUT",
|
|
2414
|
+
/** Bounce easing - bounces at the start */
|
|
2415
|
+
BOUNCE_IN = "BOUNCE_IN",
|
|
2416
|
+
/** Bounce easing - bounces at the end (like a ball landing) */
|
|
2417
|
+
BOUNCE_OUT = "BOUNCE_OUT",
|
|
2418
|
+
/** Bounce easing - bounces at both start and end */
|
|
2419
|
+
BOUNCE_IN_OUT = "BOUNCE_IN_OUT"
|
|
2420
|
+
}
|
|
2421
|
+
declare const curveFunctionIdMap: Partial<Record<CurveFunctionId, CurveFunction>>;
|
|
2422
|
+
/**
|
|
2423
|
+
* Resolves a curve function from an identifier or returns the function itself.
|
|
2424
|
+
*
|
|
2425
|
+
* This utility function allows you to use either a {@link CurveFunctionId} string
|
|
2426
|
+
* identifier or a custom function directly.
|
|
2427
|
+
*
|
|
2428
|
+
* @param curveFunctionId - Either a {@link CurveFunctionId} enum value or a
|
|
2429
|
+
* custom {@link CurveFunction} implementation
|
|
2430
|
+
* @returns The actual easing function that takes a normalized time value (0-1)
|
|
2431
|
+
* and returns the eased value
|
|
2432
|
+
*
|
|
2433
|
+
* @example
|
|
2434
|
+
* ```typescript
|
|
2435
|
+
* import { getCurveFunction, CurveFunctionId } from '@cyberluke/three-particles';
|
|
2436
|
+
*
|
|
2437
|
+
* // Using a predefined easing function
|
|
2438
|
+
* const easingFunc = getCurveFunction(CurveFunctionId.CUBIC_OUT);
|
|
2439
|
+
* console.log(easingFunc(0.5)); // Returns eased value at 50% progress
|
|
2440
|
+
*
|
|
2441
|
+
* // Using a custom function
|
|
2442
|
+
* const customEasing = (t: number) => t * t; // Quadratic
|
|
2443
|
+
* const customFunc = getCurveFunction(customEasing);
|
|
2444
|
+
* console.log(customFunc(0.5)); // Returns 0.25
|
|
2445
|
+
* ```
|
|
2446
|
+
*/
|
|
2447
|
+
declare const getCurveFunction: (curveFunctionId: CurveFunctionId | CurveFunction) => CurveFunction;
|
|
2448
|
+
|
|
2449
|
+
/**
|
|
2450
|
+
* Applies all active modifiers to a single particle during the update cycle.
|
|
2451
|
+
*
|
|
2452
|
+
* This function handles the animation and modification of particle properties over its lifetime,
|
|
2453
|
+
* including velocity (linear and orbital), size, opacity, color, rotation, and noise-based effects.
|
|
2454
|
+
* It is called once per particle per frame by the {@link updateParticleSystems} function.
|
|
2455
|
+
*
|
|
2456
|
+
* @param params - Configuration object containing:
|
|
2457
|
+
* @param params.delta - Time elapsed since the last frame in seconds. Used for velocity and rotation calculations.
|
|
2458
|
+
* @param params.generalData - Internal particle system state and cached values.
|
|
2459
|
+
* @param params.normalizedConfig - The normalized particle system configuration with all modifiers.
|
|
2460
|
+
* @param params.attributes - Three.js buffer attributes for position, size, rotation, and color.
|
|
2461
|
+
* @param params.particleLifetimePercentage - Normalized lifetime of the particle (0.0 to 1.0).
|
|
2462
|
+
* - 0.0 = particle just born
|
|
2463
|
+
* - 1.0 = particle at end of life
|
|
2464
|
+
* @param params.particleIndex - Index of the particle in the buffer arrays.
|
|
2465
|
+
*
|
|
2466
|
+
* @remarks
|
|
2467
|
+
* The function modifies the following particle properties based on configuration:
|
|
2468
|
+
*
|
|
2469
|
+
* - **Linear Velocity**: Moves particles in a straight line (velocityOverLifetime.linear)
|
|
2470
|
+
* - **Orbital Velocity**: Rotates particles around their emission point (velocityOverLifetime.orbital)
|
|
2471
|
+
* - **Size Over Lifetime**: Scales particle size based on lifetime curve (sizeOverLifetime)
|
|
2472
|
+
* - **Opacity Over Lifetime**: Fades particles in/out based on lifetime curve (opacityOverLifetime)
|
|
2473
|
+
* - **Color Over Lifetime**: Animates RGB channels independently based on lifetime curves (colorOverLifetime)
|
|
2474
|
+
* - **Rotation Over Lifetime**: Rotates particles around their center (rotationOverLifetime)
|
|
2475
|
+
* - **Noise**: Adds organic, turbulent motion to position, rotation, and size (noise)
|
|
2476
|
+
*
|
|
2477
|
+
* Each modifier only runs if it's active in the configuration, optimizing performance for simple effects.
|
|
2478
|
+
*
|
|
2479
|
+
* @example
|
|
2480
|
+
* ```typescript
|
|
2481
|
+
* // This function is called internally by updateParticleSystems
|
|
2482
|
+
* // You typically don't need to call it directly
|
|
2483
|
+
*
|
|
2484
|
+
* // However, understanding its behavior helps configure particle systems:
|
|
2485
|
+
* const config = {
|
|
2486
|
+
* sizeOverLifetime: {
|
|
2487
|
+
* isActive: true,
|
|
2488
|
+
* lifetimeCurve: {
|
|
2489
|
+
* type: 'BEZIER',
|
|
2490
|
+
* bezierPoints: [
|
|
2491
|
+
* { x: 0, y: 0, percentage: 0 }, // Start at 0% size
|
|
2492
|
+
* { x: 0.5, y: 1, percentage: 0.5 }, // Grow to 100% at midlife
|
|
2493
|
+
* { x: 1, y: 0, percentage: 1 } // Shrink to 0% at end
|
|
2494
|
+
* ]
|
|
2495
|
+
* }
|
|
2496
|
+
* },
|
|
2497
|
+
* opacityOverLifetime: {
|
|
2498
|
+
* isActive: true,
|
|
2499
|
+
* lifetimeCurve: {
|
|
2500
|
+
* type: 'EASING',
|
|
2501
|
+
* curveFunction: 'easeOutQuad'
|
|
2502
|
+
* }
|
|
2503
|
+
* }
|
|
2504
|
+
* };
|
|
2505
|
+
* ```
|
|
2506
|
+
*
|
|
2507
|
+
* @see {@link updateParticleSystems} - Calls this function for each active particle
|
|
2508
|
+
* @see {@link VelocityOverLifetime} - Configuration for velocity modifiers
|
|
2509
|
+
* @see {@link NoiseConfig} - Configuration for noise-based effects
|
|
2510
|
+
*/
|
|
2511
|
+
declare const applyModifiers: ({ delta, generalData, normalizedConfig, attributes, scalarArray, particleLifetimePercentage, particleIndex, updateFlags, }: {
|
|
2512
|
+
delta: number;
|
|
2513
|
+
generalData: GeneralData;
|
|
2514
|
+
normalizedConfig: NormalizedParticleSystemConfig;
|
|
2515
|
+
attributes: MappedAttributes;
|
|
2516
|
+
scalarArray: Float32Array;
|
|
2517
|
+
particleLifetimePercentage: number;
|
|
2518
|
+
particleIndex: number;
|
|
2519
|
+
/**
|
|
2520
|
+
* Optional aggregation target for attribute dirty flags. When provided,
|
|
2521
|
+
* `position`/`quat` are set to `true` here instead of writing
|
|
2522
|
+
* `attribute.needsUpdate` — the caller flushes once per frame rather than
|
|
2523
|
+
* bumping the attribute version once per particle.
|
|
2524
|
+
*/
|
|
2525
|
+
updateFlags?: {
|
|
2526
|
+
position: boolean;
|
|
2527
|
+
quat: boolean;
|
|
2528
|
+
};
|
|
2529
|
+
}) => void;
|
|
2530
|
+
|
|
2531
|
+
/**
|
|
2532
|
+
* Checks whether the given renderer supports GPU compute dispatches.
|
|
2533
|
+
*
|
|
2534
|
+
* Uses duck-typing: a renderer is considered WebGPU-capable when it exposes
|
|
2535
|
+
* a `.compute()` method and a `.hasFeature()` method (both present on
|
|
2536
|
+
* `THREE.WebGPURenderer` but absent from `THREE.WebGLRenderer`).
|
|
2537
|
+
*
|
|
2538
|
+
* @param renderer - Any Three.js renderer instance.
|
|
2539
|
+
* @returns `true` when the renderer supports compute shaders.
|
|
2540
|
+
*/
|
|
2541
|
+
declare function isComputeCapableRenderer(renderer: unknown): boolean;
|
|
2542
|
+
/**
|
|
2543
|
+
* Resolves the effective simulation backend based on the user's preference
|
|
2544
|
+
* and the capabilities of the provided renderer.
|
|
2545
|
+
*
|
|
2546
|
+
* | Preference | WebGPURenderer | WebGLRenderer |
|
|
2547
|
+
* |------------|---------------|---------------|
|
|
2548
|
+
* | `AUTO` | `GPU` | `CPU` |
|
|
2549
|
+
* | `CPU` | `CPU` | `CPU` |
|
|
2550
|
+
* | `GPU` | `GPU` | `CPU` (fallback) |
|
|
2551
|
+
*
|
|
2552
|
+
* @param renderer - The Three.js renderer instance used for rendering.
|
|
2553
|
+
* @param preference - The user-specified simulation backend preference.
|
|
2554
|
+
* @returns The resolved {@link SimulationBackend} (`CPU` or `GPU`).
|
|
2555
|
+
*/
|
|
2556
|
+
declare function resolveSimulationBackend(renderer: unknown, preference?: SimulationBackend): SimulationBackend.CPU | SimulationBackend.GPU;
|
|
2557
|
+
|
|
2558
|
+
/**
|
|
2559
|
+
* Serializes a `ParticleSystemConfig` to a JSON string.
|
|
2560
|
+
*
|
|
2561
|
+
* - `THREE.Vector3` / `THREE.Vector2` are converted to plain `{x, y, z}` / `{x, y}` objects.
|
|
2562
|
+
* - `renderer.blending` is converted to its string identifier (e.g. `"THREE.AdditiveBlending"`).
|
|
2563
|
+
* - `EasingCurve.curveFunction` is replaced by a `curveFunctionId` string.
|
|
2564
|
+
* Only predefined `CurveFunctionId` functions can be serialized; custom functions throw.
|
|
2565
|
+
* - `THREE.Texture` (`map`), callback fields (`onUpdate`, `onComplete`) are omitted.
|
|
2566
|
+
* - An `_editorData` field and other unknown fields are preserved as-is.
|
|
2567
|
+
* - A `_version` field is added for forward-compatibility.
|
|
2568
|
+
*
|
|
2569
|
+
* @param config - The particle system configuration to serialize.
|
|
2570
|
+
* @returns A JSON string representation of the config.
|
|
2571
|
+
* @throws If the config contains a custom (non-predefined) `curveFunction`.
|
|
2572
|
+
*
|
|
2573
|
+
* @example
|
|
2574
|
+
* ```typescript
|
|
2575
|
+
* import { serializeParticleSystem } from '@cyberluke/three-particles';
|
|
2576
|
+
*
|
|
2577
|
+
* const json = serializeParticleSystem(config);
|
|
2578
|
+
* localStorage.setItem('myEffect', json);
|
|
2579
|
+
* ```
|
|
2580
|
+
*/
|
|
2581
|
+
declare function serializeParticleSystem(config: ParticleSystemConfig): string;
|
|
2582
|
+
/**
|
|
2583
|
+
* Deserializes a JSON string produced by `serializeParticleSystem` (or by the
|
|
2584
|
+
* three-particles-editor) into a `ParticleSystemConfig` object.
|
|
2585
|
+
*
|
|
2586
|
+
* - Blending strings (e.g. `"THREE.AdditiveBlending"`) are converted back to
|
|
2587
|
+
* `THREE.Blending` constants.
|
|
2588
|
+
* - `{x, y, z}` objects under `transform` are reconstructed as `THREE.Vector3`.
|
|
2589
|
+
* - `{x, y}` objects under `textureSheetAnimation.tiles` are reconstructed as `THREE.Vector2`.
|
|
2590
|
+
* - Legacy B??zier curves without a `type` field (editor format) are normalized.
|
|
2591
|
+
* - Easing curves stored as `{ type: "EASING", curveFunctionId }` have their
|
|
2592
|
+
* `curveFunction` resolved from the predefined map.
|
|
2593
|
+
* - `_editorData` and other unknown fields are preserved.
|
|
2594
|
+
*
|
|
2595
|
+
* @param json - A JSON string produced by `serializeParticleSystem` or the editor.
|
|
2596
|
+
* @returns A fully reconstructed `ParticleSystemConfig`.
|
|
2597
|
+
*
|
|
2598
|
+
* @example
|
|
2599
|
+
* ```typescript
|
|
2600
|
+
* import { deserializeParticleSystem } from '@cyberluke/three-particles';
|
|
2601
|
+
*
|
|
2602
|
+
* const config = deserializeParticleSystem(localStorage.getItem('myEffect')!);
|
|
2603
|
+
* createParticleSystem(config);
|
|
2604
|
+
* ```
|
|
2605
|
+
*/
|
|
2606
|
+
declare function deserializeParticleSystem(json: string): ParticleSystemConfig;
|
|
2607
|
+
|
|
2608
|
+
/**
|
|
2609
|
+
* Calculates random position and velocity for particles emitted from a sphere.
|
|
2610
|
+
*
|
|
2611
|
+
* Supports emission from the entire volume or just the shell of the sphere.
|
|
2612
|
+
* Uses spherical coordinates for uniform distribution across the surface.
|
|
2613
|
+
*
|
|
2614
|
+
* @param position - Output vector for the particle's starting position
|
|
2615
|
+
* @param quaternion - Rotation to apply to the emission shape
|
|
2616
|
+
* @param velocity - Output vector for the particle's initial velocity
|
|
2617
|
+
* @param speed - Speed multiplier for the velocity
|
|
2618
|
+
* @param params - Sphere configuration
|
|
2619
|
+
* @param params.radius - Radius of the sphere
|
|
2620
|
+
* @param params.radiusThickness - Controls emission from volume (1.0) vs shell (0.0)
|
|
2621
|
+
* @param params.arc - Arc angle in degrees (360 = full sphere, 180 = hemisphere)
|
|
2622
|
+
*
|
|
2623
|
+
* @remarks
|
|
2624
|
+
* - `radiusThickness = 1.0`: Emit from entire volume
|
|
2625
|
+
* - `radiusThickness = 0.0`: Emit only from surface shell
|
|
2626
|
+
* - Particles are emitted radially outward from the center
|
|
2627
|
+
*
|
|
2628
|
+
* @see {@link Sphere} - Configuration type for sphere shape
|
|
2629
|
+
*/
|
|
2630
|
+
declare const calculateRandomPositionAndVelocityOnSphere: (position: THREE.Vector3, quaternion: THREE.Quaternion, velocity: THREE.Vector3, speed: number, { radius, radiusThickness, arc, }: {
|
|
2631
|
+
radius: number;
|
|
2632
|
+
radiusThickness: number;
|
|
2633
|
+
arc: number;
|
|
2634
|
+
}) => void;
|
|
2635
|
+
/**
|
|
2636
|
+
* Calculates random position and velocity for particles emitted from a cone.
|
|
2637
|
+
*
|
|
2638
|
+
* Useful for directional particle effects like fire, smoke plumes, fountains,
|
|
2639
|
+
* or spray effects. The cone emits particles in a spreading pattern.
|
|
2640
|
+
*
|
|
2641
|
+
* @param position - Output vector for the particle's starting position
|
|
2642
|
+
* @param quaternion - Rotation to apply to the emission shape
|
|
2643
|
+
* @param velocity - Output vector for the particle's initial velocity
|
|
2644
|
+
* @param speed - Speed multiplier for the velocity
|
|
2645
|
+
* @param params - Cone configuration
|
|
2646
|
+
* @param params.radius - Base radius of the cone
|
|
2647
|
+
* @param params.radiusThickness - Controls emission from volume (1.0) vs shell (0.0)
|
|
2648
|
+
* @param params.arc - Arc angle in degrees (360 = full cone, 180 = half cone)
|
|
2649
|
+
* @param params.angle - Cone opening angle in degrees (default: 90)
|
|
2650
|
+
* Smaller values create tighter cones
|
|
2651
|
+
*
|
|
2652
|
+
* @remarks
|
|
2653
|
+
* - The cone emits from its base (circular area) outward
|
|
2654
|
+
* - Particles travel in a conical spread pattern
|
|
2655
|
+
* - `angle = 0`: Straight line (no spread)
|
|
2656
|
+
* - `angle = 90`: Wide cone
|
|
2657
|
+
* - Common for fire (10-30°), smoke (30-60°), explosions (60-90°)
|
|
2658
|
+
*
|
|
2659
|
+
* @see {@link Cone} - Configuration type for cone shape
|
|
2660
|
+
*/
|
|
2661
|
+
declare const calculateRandomPositionAndVelocityOnCone: (position: THREE.Vector3, quaternion: THREE.Quaternion, velocity: THREE.Vector3, speed: number, { radius, radiusThickness, arc, angle, }: {
|
|
2662
|
+
radius: number;
|
|
2663
|
+
radiusThickness: number;
|
|
2664
|
+
arc: number;
|
|
2665
|
+
angle?: number;
|
|
2666
|
+
}) => void;
|
|
2667
|
+
/**
|
|
2668
|
+
* Calculates random position and velocity for particles emitted from a box.
|
|
2669
|
+
*
|
|
2670
|
+
* Supports three emission modes: volume, shell (surface), and edges.
|
|
2671
|
+
* Useful for area-based effects like dust clouds, rain, or geometric patterns.
|
|
2672
|
+
*
|
|
2673
|
+
* @param position - Output vector for the particle's starting position
|
|
2674
|
+
* @param quaternion - Rotation to apply to the emission shape
|
|
2675
|
+
* @param velocity - Output vector for the particle's initial velocity
|
|
2676
|
+
* @param speed - Speed multiplier for the velocity
|
|
2677
|
+
* @param params - Box configuration
|
|
2678
|
+
* @param params.scale - Size of the box on each axis (width, height, depth)
|
|
2679
|
+
* @param params.emitFrom - Emission mode:
|
|
2680
|
+
* - `VOLUME`: Random positions throughout the entire box volume
|
|
2681
|
+
* - `SHELL`: Random positions on the 6 faces (surface)
|
|
2682
|
+
* - `EDGE`: Random positions along the 12 edges
|
|
2683
|
+
*
|
|
2684
|
+
* @remarks
|
|
2685
|
+
* - All particles emit with velocity along the +Z axis (forward)
|
|
2686
|
+
* - Box is centered at the origin before rotation
|
|
2687
|
+
* - VOLUME mode: Best for rain, snow, or volumetric clouds
|
|
2688
|
+
* - SHELL mode: Best for hollow effects or surface particles
|
|
2689
|
+
* - EDGE mode: Best for wireframe effects or particle outlines
|
|
2690
|
+
*
|
|
2691
|
+
* @see {@link Box} - Configuration type for box shape
|
|
2692
|
+
* @see {@link EmitFrom} - Emission mode enum
|
|
2693
|
+
*/
|
|
2694
|
+
declare const calculateRandomPositionAndVelocityOnBox: (position: THREE.Vector3, quaternion: THREE.Quaternion, velocity: THREE.Vector3, speed: number, { scale, emitFrom }: {
|
|
2695
|
+
scale: Point3D;
|
|
2696
|
+
emitFrom: EmitFrom;
|
|
2697
|
+
}) => void;
|
|
2698
|
+
/**
|
|
2699
|
+
* Calculates random position and velocity for particles emitted from a circle.
|
|
2700
|
+
*
|
|
2701
|
+
* Emits particles from a circular area or ring. Useful for ground impacts,
|
|
2702
|
+
* radial effects, magic circles, or any circular planar emission.
|
|
2703
|
+
*
|
|
2704
|
+
* @param position - Output vector for the particle's starting position
|
|
2705
|
+
* @param quaternion - Rotation to apply to the emission shape
|
|
2706
|
+
* @param velocity - Output vector for the particle's initial velocity
|
|
2707
|
+
* @param speed - Speed multiplier for the velocity
|
|
2708
|
+
* @param params - Circle configuration
|
|
2709
|
+
* @param params.radius - Radius of the circle
|
|
2710
|
+
* @param params.radiusThickness - Controls emission from area (1.0) vs edge (0.0)
|
|
2711
|
+
* @param params.arc - Arc angle in degrees (360 = full circle, 180 = semicircle)
|
|
2712
|
+
*
|
|
2713
|
+
* @remarks
|
|
2714
|
+
* - Circle lies in the XY plane by default (Z = 0)
|
|
2715
|
+
* - Particles emit along the +Z axis (perpendicular to circle)
|
|
2716
|
+
* - `radiusThickness = 1.0`: Filled circle (disc)
|
|
2717
|
+
* - `radiusThickness = 0.0`: Ring (circle edge only)
|
|
2718
|
+
* - Good for ground impact effects, teleport circles, or radial bursts
|
|
2719
|
+
*
|
|
2720
|
+
* @see {@link Circle} - Configuration type for circle shape
|
|
2721
|
+
*/
|
|
2722
|
+
declare const calculateRandomPositionAndVelocityOnCircle: (position: THREE.Vector3, quaternion: THREE.Quaternion, velocity: THREE.Vector3, speed: number, { radius, radiusThickness, arc, }: {
|
|
2723
|
+
radius: number;
|
|
2724
|
+
radiusThickness: number;
|
|
2725
|
+
arc: number;
|
|
2726
|
+
}) => void;
|
|
2727
|
+
/**
|
|
2728
|
+
* Calculates random position and velocity for particles emitted from a rectangle.
|
|
2729
|
+
*
|
|
2730
|
+
* Emits particles from a rectangular planar area. Useful for rain on a surface,
|
|
2731
|
+
* screen-space effects, or any planar emission pattern.
|
|
2732
|
+
*
|
|
2733
|
+
* @param position - Output vector for the particle's starting position
|
|
2734
|
+
* @param quaternion - Rotation to apply to the emission shape
|
|
2735
|
+
* @param velocity - Output vector for the particle's initial velocity
|
|
2736
|
+
* @param speed - Speed multiplier for the velocity
|
|
2737
|
+
* @param params - Rectangle configuration
|
|
2738
|
+
* @param params.rotation - Local rotation of the rectangle (degrees) before
|
|
2739
|
+
* applying quaternion
|
|
2740
|
+
* @param params.scale - Size of the rectangle (width and height)
|
|
2741
|
+
*
|
|
2742
|
+
* @remarks
|
|
2743
|
+
* - Rectangle lies in the XY plane by default
|
|
2744
|
+
* - Particles emit along the +Z axis (perpendicular to rectangle)
|
|
2745
|
+
* - The rotation parameter allows tilting the rectangle before the main
|
|
2746
|
+
* quaternion rotation is applied
|
|
2747
|
+
* - Good for rain effects, screen particles, or planar area emissions
|
|
2748
|
+
*
|
|
2749
|
+
* @see {@link Rectangle} - Configuration type for rectangle shape
|
|
2750
|
+
*/
|
|
2751
|
+
declare const calculateRandomPositionAndVelocityOnRectangle: (position: THREE.Vector3, quaternion: THREE.Quaternion, velocity: THREE.Vector3, speed: number, { rotation, scale }: {
|
|
2752
|
+
rotation: Point3D;
|
|
2753
|
+
scale: Point3D;
|
|
2754
|
+
}) => void;
|
|
2755
|
+
/**
|
|
2756
|
+
* Creates a solid white 1x1 texture for mesh particles.
|
|
2757
|
+
* Unlike the circle texture used by point/billboard renderers, mesh particles
|
|
2758
|
+
* need a neutral texture so the geometry shape is visible.
|
|
2759
|
+
* @returns {THREE.CanvasTexture | null} The generated texture or null if context fails.
|
|
2760
|
+
*/
|
|
2761
|
+
declare const createDefaultMeshTexture: () => THREE.CanvasTexture | null;
|
|
2762
|
+
/**
|
|
2763
|
+
* Creates a default white circle texture using CanvasTexture.
|
|
2764
|
+
* @returns {THREE.CanvasTexture | null} The generated texture or null if context fails.
|
|
2765
|
+
*/
|
|
2766
|
+
declare const createDefaultParticleTexture: () => THREE.CanvasTexture | null;
|
|
2767
|
+
declare const isLifeTimeCurve: (value: Constant | RandomBetweenTwoConstants | LifetimeCurve) => value is LifetimeCurve;
|
|
2768
|
+
declare const getCurveFunctionFromConfig: (particleSystemId: number, lifetimeCurve: LifetimeCurve) => CurveFunction;
|
|
2769
|
+
declare const calculateValue: (particleSystemId: number, value: Constant | RandomBetweenTwoConstants | LifetimeCurve, time?: number) => number;
|
|
2770
|
+
|
|
2771
|
+
/**
|
|
2772
|
+
* Interleaved scalar buffer layout constants.
|
|
2773
|
+
*
|
|
2774
|
+
* All per-particle float attributes (except position and quat) are packed
|
|
2775
|
+
* into a single InterleavedBuffer to stay within the WebGPU vertex buffer
|
|
2776
|
+
* limit of 8.
|
|
2777
|
+
*
|
|
2778
|
+
* Buffer layout per particle (stride = 10 floats):
|
|
2779
|
+
* ```
|
|
2780
|
+
* [isActive, lifetime, startLifetime, startFrame, size, rotation, colorR, colorG, colorB, colorA]
|
|
2781
|
+
* ```
|
|
2782
|
+
*/
|
|
2783
|
+
/** Number of float32 elements per particle in the interleaved scalar buffer. */
|
|
2784
|
+
declare const SCALAR_STRIDE = 10;
|
|
2785
|
+
/** Offset for the isActive flag (0 = inactive, 1 = active). */
|
|
2786
|
+
declare const S_IS_ACTIVE = 0;
|
|
2787
|
+
/** Offset for the current lifetime of the particle in milliseconds. */
|
|
2788
|
+
declare const S_LIFETIME = 1;
|
|
2789
|
+
/** Offset for the total lifetime of the particle in milliseconds. */
|
|
2790
|
+
declare const S_START_LIFETIME = 2;
|
|
2791
|
+
/** Offset for the texture sheet animation start frame index. */
|
|
2792
|
+
declare const S_START_FRAME = 3;
|
|
2793
|
+
/** Offset for the particle size. */
|
|
2794
|
+
declare const S_SIZE = 4;
|
|
2795
|
+
/** Offset for the particle rotation (radians). */
|
|
2796
|
+
declare const S_ROTATION = 5;
|
|
2797
|
+
/** Offset for the red color channel (0..1). */
|
|
2798
|
+
declare const S_COLOR_R = 6;
|
|
2799
|
+
/** Offset for the green color channel (0..1). */
|
|
2800
|
+
declare const S_COLOR_G = 7;
|
|
2801
|
+
/** Offset for the blue color channel (0..1). */
|
|
2802
|
+
declare const S_COLOR_B = 8;
|
|
2803
|
+
/** Offset for the alpha (opacity) channel (0..1). */
|
|
2804
|
+
declare const S_COLOR_A = 9;
|
|
2805
|
+
|
|
2806
|
+
/**
|
|
2807
|
+
* `resolveWebGPUEffectiveRendererType` — canonical mapping between the four
|
|
2808
|
+
* requested `rendererType` values and the four effective GPU render paths
|
|
2809
|
+
* (native runtime classes in parentheses).
|
|
2810
|
+
*
|
|
2811
|
+
* requested POINTS -> effective POINTS (billboard quad + `THREE.Points`).
|
|
2812
|
+
* POINTS IS a supported runtime class in this build: the billboard quad
|
|
2813
|
+
* is drawn as a non-instanced `THREE.Points`; the TSL point material uses
|
|
2814
|
+
* `pointUV` (r186 provides it for `PointsNodeMaterial`).
|
|
2815
|
+
* requested INSTANCED -> effective INSTANCED (quad/box + `THREE.Mesh` with
|
|
2816
|
+
* `InstancedBufferGeometry`).
|
|
2817
|
+
* requested TRAIL -> effective TRAIL (ribbon strip + `THREE.Mesh`).
|
|
2818
|
+
* requested MESH -> effective MESH (mesh/reused geometry +
|
|
2819
|
+
* `THREE.Mesh`).
|
|
2820
|
+
*
|
|
2821
|
+
* A missing / unknown request resolves to POINTS because `POINTS` is the
|
|
2822
|
+
* default value of `renderer.rendererType` in the merged default config.
|
|
2823
|
+
*/
|
|
2824
|
+
declare function resolveWebGPUEffectiveRendererType(requested: RendererType | string | undefined): RendererType;
|
|
2825
|
+
|
|
2826
|
+
type TSLMaterialFactory = {
|
|
2827
|
+
createTSLParticleMaterial: (rendererType: RendererType, sharedUniforms: Record<string, {
|
|
2828
|
+
value: unknown;
|
|
2829
|
+
}>, rendererConfig: {
|
|
2830
|
+
transparent: boolean;
|
|
2831
|
+
blending: THREE.Blending;
|
|
2832
|
+
depthTest: boolean;
|
|
2833
|
+
depthWrite: boolean;
|
|
2834
|
+
}, gpuCompute?: boolean) => THREE.Material;
|
|
2835
|
+
createTSLTrailMaterial: (trailUniforms: Record<string, {
|
|
2836
|
+
value: unknown;
|
|
2837
|
+
}>, rendererConfig: {
|
|
2838
|
+
transparent: boolean;
|
|
2839
|
+
blending: THREE.Blending;
|
|
2840
|
+
depthTest: boolean;
|
|
2841
|
+
depthWrite: boolean;
|
|
2842
|
+
}) => THREE.Material;
|
|
2843
|
+
createComputePipeline?: (...args: any[]) => any;
|
|
2844
|
+
writeParticleToModifierBuffers?: (...args: any[]) => void;
|
|
2845
|
+
deactivateParticleInModifierBuffers?: (...args: any[]) => void;
|
|
2846
|
+
flushEmitQueue?: (...args: any[]) => number;
|
|
2847
|
+
registerCurveDataLength?: (...args: any[]) => void;
|
|
2848
|
+
encodeForceFieldsForGPU?: (...args: any[]) => Float32Array;
|
|
2849
|
+
encodeCollisionPlanesForGPU?: (...args: any[]) => Float32Array;
|
|
2850
|
+
createSubEmitterFifoAttribute?: (...args: any[]) => any;
|
|
2851
|
+
createSubEmitterInitUpdate?: (...args: any[]) => any;
|
|
2852
|
+
createTrailRibbonUpdate?: (...args: any[]) => any;
|
|
2853
|
+
encodeShapeEmitParams?: (...args: any[]) => any;
|
|
2854
|
+
};
|
|
2855
|
+
/**
|
|
2856
|
+
* Registers the TSL (Three Shading Language) material factory for WebGPU support.
|
|
2857
|
+
*
|
|
2858
|
+
* Call this **once** before creating any particle systems that use WebGPU rendering.
|
|
2859
|
+
* The factory functions are imported from the `@cyberluke/three-particles/webgpu` sub-module.
|
|
2860
|
+
*
|
|
2861
|
+
* When registered, all particle systems will use TSL-based `NodeMaterial` (compiles to WGSL)
|
|
2862
|
+
* instead of GLSL `ShaderMaterial`. If the factory also includes the GPU compute functions
|
|
2863
|
+
* (`createComputePipeline`, `writeParticleToModifierBuffers`, etc.), particle systems with
|
|
2864
|
+
* `simulationBackend: 'AUTO'` or `'GPU'` will run physics and modifiers on the GPU.
|
|
2865
|
+
*
|
|
2866
|
+
* @param factory - Object containing TSL material creators and optional GPU compute helpers.
|
|
2867
|
+
*
|
|
2868
|
+
* @example
|
|
2869
|
+
* ```typescript
|
|
2870
|
+
* import { registerTSLMaterialFactory } from '@cyberluke/three-particles';
|
|
2871
|
+
* import {
|
|
2872
|
+
* createTSLParticleMaterial,
|
|
2873
|
+
* createTSLTrailMaterial,
|
|
2874
|
+
* createComputePipeline,
|
|
2875
|
+
* writeParticleToModifierBuffers,
|
|
2876
|
+
* deactivateParticleInModifierBuffers,
|
|
2877
|
+
* flushEmitQueue,
|
|
2878
|
+
* registerCurveDataLength,
|
|
2879
|
+
* encodeForceFieldsForGPU,
|
|
2880
|
+
* } from '@cyberluke/three-particles/webgpu';
|
|
2881
|
+
*
|
|
2882
|
+
* registerTSLMaterialFactory({
|
|
2883
|
+
* createTSLParticleMaterial,
|
|
2884
|
+
* createTSLTrailMaterial,
|
|
2885
|
+
* createComputePipeline,
|
|
2886
|
+
* writeParticleToModifierBuffers,
|
|
2887
|
+
* deactivateParticleInModifierBuffers,
|
|
2888
|
+
* flushEmitQueue,
|
|
2889
|
+
* registerCurveDataLength,
|
|
2890
|
+
* encodeForceFieldsForGPU,
|
|
2891
|
+
* });
|
|
2892
|
+
* ```
|
|
2893
|
+
*/
|
|
2894
|
+
declare const registerTSLMaterialFactory: (factory: TSLMaterialFactory, options?: {
|
|
2895
|
+
renderer?: unknown;
|
|
2896
|
+
}) => boolean;
|
|
2897
|
+
/** Throw the first fatal, named (never empty) normalization error. */
|
|
2898
|
+
declare const assertNamed: (cond: unknown, message: string) => void;
|
|
2899
|
+
/**
|
|
2900
|
+
* Canonical `Vector2` input: `THREE.Vector2 | [x,y] | [u,v] | {x,y} | {u,v}`
|
|
2901
|
+
* (or undefined/null => fallback). Anything else throws a labeled error.
|
|
2902
|
+
*/
|
|
2903
|
+
declare const normalizeVector2Value: (raw: unknown, fallback: [number, number], label: string) => THREE.Vector2;
|
|
2904
|
+
/** Canonical map slot: `null` (no map -> white dummy in the material) or a
|
|
2905
|
+
* texture object with `.image`. Anything else throws a labeled error. */
|
|
2906
|
+
declare const normalizeTextureValue: (raw: unknown, label: string) => THREE.Texture | null;
|
|
2907
|
+
/** `null` (absent) or a texture object with `.image` — nothing else. */
|
|
2908
|
+
declare const normalizeDepthTextureValue: (raw: unknown, label: string) => THREE.Texture | null;
|
|
2909
|
+
/**
|
|
2910
|
+
* Background color from serialized data: `{r,g,b,a?}` object, `0x` number,
|
|
2911
|
+
* `#rgb`/`#rrggbb` string, or `[r,g,b]` array -> `Vector3`.
|
|
2912
|
+
*/
|
|
2913
|
+
declare const normalizeBackgroundToVector3: (raw: unknown, label: string) => THREE.Vector3;
|
|
2914
|
+
/**
|
|
2915
|
+
* Mapping of blending mode string identifiers to Three.js blending constants.
|
|
2916
|
+
*
|
|
2917
|
+
* Used for converting serialized particle system configurations (e.g., from JSON)
|
|
2918
|
+
* to actual Three.js blending mode constants.
|
|
2919
|
+
*
|
|
2920
|
+
* @example
|
|
2921
|
+
* ```typescript
|
|
2922
|
+
* import { blendingMap } from '@cyberluke/three-particles';
|
|
2923
|
+
*
|
|
2924
|
+
* // Convert string to Three.js constant
|
|
2925
|
+
* const blending = blendingMap['THREE.AdditiveBlending'];
|
|
2926
|
+
* // blending === THREE.AdditiveBlending
|
|
2927
|
+
* ```
|
|
2928
|
+
*/
|
|
2929
|
+
declare const blendingMap: {
|
|
2930
|
+
'THREE.NoBlending': 0;
|
|
2931
|
+
'THREE.NormalBlending': 1;
|
|
2932
|
+
'THREE.AdditiveBlending': 2;
|
|
2933
|
+
'THREE.SubtractiveBlending': 3;
|
|
2934
|
+
'THREE.MultiplyBlending': 4;
|
|
2935
|
+
};
|
|
2936
|
+
/**
|
|
2937
|
+
* Returns a deep copy of the default particle system configuration.
|
|
2938
|
+
*
|
|
2939
|
+
* This is useful when you want to start with default settings and modify specific properties
|
|
2940
|
+
* without affecting the internal default configuration object.
|
|
2941
|
+
*
|
|
2942
|
+
* @returns A new object containing all default particle system settings
|
|
2943
|
+
*
|
|
2944
|
+
* @example
|
|
2945
|
+
* ```typescript
|
|
2946
|
+
* import { getDefaultParticleSystemConfig, createParticleSystem } from '@cyberluke/three-particles';
|
|
2947
|
+
*
|
|
2948
|
+
* // Get default config and modify it
|
|
2949
|
+
* const config = getDefaultParticleSystemConfig();
|
|
2950
|
+
* config.emission.rateOverTime = 100;
|
|
2951
|
+
* config.startColor.min = { r: 1, g: 0, b: 0 };
|
|
2952
|
+
*
|
|
2953
|
+
* const { instance } = createParticleSystem(config);
|
|
2954
|
+
* scene.add(instance);
|
|
2955
|
+
* ```
|
|
2956
|
+
*/
|
|
2957
|
+
declare const getDefaultParticleSystemConfig: () => any;
|
|
2958
|
+
/**
|
|
2959
|
+
* Create a new particle system (GPU-only). Every per-particle slot lives
|
|
2960
|
+
* on the GPU inside the 8 storage buffers that the WebGPU compute kernels
|
|
2961
|
+
* read/write. The CPU only:
|
|
2962
|
+
* - merges the incoming config,
|
|
2963
|
+
* - creates the TSL material + pipeline,
|
|
2964
|
+
* - writes ~12 scalar uniforms per frame,
|
|
2965
|
+
* - dispatches [emitNode, simNode] via renderer.compute(...).
|
|
2966
|
+
*/
|
|
2967
|
+
declare const createParticleSystem: (config?: ParticleSystemConfig, externalNow?: number) => ParticleSystem;
|
|
2968
|
+
declare const updateParticleSystems: (cycleData: CycleData) => void;
|
|
2969
|
+
|
|
2970
|
+
export { type BezierCurve, type BezierPoint, type Box, type Burst, type BurstState, type Circle, type CollisionPlaneConfig, CollisionPlaneMode, type Cone, type Constant, type CurveBase, type CurveFunction, CurveFunctionId, type CycleData, type EasingCurve, type Emission, EmitFrom, type ForceFieldConfig, ForceFieldFalloff, ForceFieldType, type GeneralData, LifeTimeCurve, type LifetimeCurve, type MappedAttributes, type MeshConfig, type MinMaxColor, type Noise, type NoiseConfig, type NormalizedCollisionPlaneConfig, type NormalizedForceFieldConfig, type NormalizedParticleSystemConfig, type ParticleSystem, type ParticleSystemConfig, type ParticleSystemInstance, type Point3D, REVISION, type RandomBetweenTwoConstants, type Rectangle, type Renderer, RendererType, type Rgb, SCALAR_STRIDE, S_COLOR_A, S_COLOR_B, S_COLOR_G, S_COLOR_R, S_IS_ACTIVE, S_LIFETIME, S_ROTATION, S_SIZE, S_START_FRAME, S_START_LIFETIME, Shape, type ShapeConfig, SimulationBackend, SimulationSpace, type SoftParticlesConfig, type Sphere, type SubEmitterConfig, SubEmitterTrigger, type TextureSheetAnimation, TimeMode, type TrailConfig, type Transform, type VelocityOverLifetime, applyModifiers, assertNamed, blendingMap, calculateRandomPositionAndVelocityOnBox, calculateRandomPositionAndVelocityOnCircle, calculateRandomPositionAndVelocityOnCone, calculateRandomPositionAndVelocityOnRectangle, calculateRandomPositionAndVelocityOnSphere, calculateValue, createBezierCurveFunction, createDefaultMeshTexture, createDefaultParticleTexture, createParticleSystem, curveFunctionIdMap, deserializeParticleSystem, getBezierCacheSize, getCurveFunction, getCurveFunctionFromConfig, getDefaultParticleSystemConfig, isComputeCapableRenderer, isLifeTimeCurve, linearToSRGB, normalizeBackgroundToVector3, normalizeDepthTextureValue, normalizeTextureValue, normalizeVector2Value, registerTSLMaterialFactory, removeBezierCurveFunction, resolveSimulationBackend, resolveWebGPUEffectiveRendererType, rgbSRGBToLinear, sRGBToLinear, serializeParticleSystem, updateParticleSystems };
|