@newkrok/three-particles 2.15.1 → 2.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -0
- package/dist/index.d.ts +368 -7
- package/dist/index.js +1149 -420
- package/dist/index.js.map +1 -1
- package/dist/three-particles.min.js +1 -1
- package/dist/three-particles.min.js.map +1 -1
- package/dist/webgpu.js +1664 -0
- package/dist/webgpu.js.map +1 -0
- package/llms-full.txt +189 -0
- package/llms.txt +89 -0
- package/package.json +15 -10
- package/webgpu.d.ts +88 -0
package/llms-full.txt
CHANGED
|
@@ -68,6 +68,7 @@ function animate() {
|
|
|
68
68
|
| `dispose()` | `() => void` | Destroy system, free resources |
|
|
69
69
|
| `update(cycleData)` | `(CycleData) => void` | Update this system individually |
|
|
70
70
|
| `updateConfig(config)` | `(Partial<ParticleSystemConfig>) => void` | Update configuration at runtime without recreating the system. System-level properties (gravity, force fields, noise, emission, color/size/opacity over lifetime) take effect immediately. Per-particle spawn properties (startColor, startSize, etc.) affect only newly emitted particles. |
|
|
71
|
+
| `computeNode` | `unknown \| null` | GPU compute node for WebGPU dispatch. Non-null when GPU compute is active. Must be dispatched via `renderer.compute(system.computeNode)` every frame before `renderer.render()`. Null when CPU simulation is used. |
|
|
71
72
|
|
|
72
73
|
---
|
|
73
74
|
|
|
@@ -96,6 +97,7 @@ type CycleData = {
|
|
|
96
97
|
| `maxParticles` | `number` | 100 | Maximum concurrent particles |
|
|
97
98
|
| `gravity` | `number` | 0.0 | Downward acceleration |
|
|
98
99
|
| `simulationSpace` | `SimulationSpace` | LOCAL | LOCAL or WORLD coordinate space |
|
|
100
|
+
| `simulationBackend` | `SimulationBackend` | AUTO | Simulation backend: AUTO (GPU if WebGPU available, else CPU), CPU, or GPU |
|
|
99
101
|
|
|
100
102
|
### Start Properties
|
|
101
103
|
|
|
@@ -523,6 +525,12 @@ const system = createParticleSystem({
|
|
|
523
525
|
### RendererType
|
|
524
526
|
`POINTS` (default — classic point sprites) | `INSTANCED` (GPU instanced quads, no gl_PointSize limit) | `TRAIL` (ribbon trails behind particles) | `MESH` (3D mesh particles via GPU instancing)
|
|
525
527
|
|
|
528
|
+
### CollisionPlaneMode
|
|
529
|
+
`KILL` (deactivate particle immediately) | `CLAMP` (stop particle at the plane surface) | `BOUNCE` (reflect velocity with optional dampen)
|
|
530
|
+
|
|
531
|
+
### SimulationBackend
|
|
532
|
+
`AUTO` (default — GPU compute if WebGPU renderer detected, else CPU) | `CPU` (always JavaScript update loop) | `GPU` (request GPU compute, falls back to CPU if unavailable)
|
|
533
|
+
|
|
526
534
|
---
|
|
527
535
|
|
|
528
536
|
## Callbacks
|
|
@@ -693,6 +701,48 @@ createParticleSystem({
|
|
|
693
701
|
|
|
694
702
|
---
|
|
695
703
|
|
|
704
|
+
## Collision Planes
|
|
705
|
+
|
|
706
|
+
Infinite planes that constrain particle positions. When a particle crosses from the front side (positive normal direction) to the back side, the configured response mode is triggered.
|
|
707
|
+
|
|
708
|
+
```typescript
|
|
709
|
+
type CollisionPlaneConfig = {
|
|
710
|
+
isActive?: boolean; // Whether this plane is active (default: true)
|
|
711
|
+
position?: Point3D; // A point on the plane surface (default: {x:0, y:0, z:0})
|
|
712
|
+
normal?: Point3D; // Plane normal vector, defines the "front" side (default: {x:0, y:1, z:0})
|
|
713
|
+
mode?: CollisionPlaneMode; // Response mode (default: KILL)
|
|
714
|
+
dampen?: number; // Velocity dampen factor for BOUNCE mode, 0-1 (default: 0)
|
|
715
|
+
lifetimeLoss?: number; // Fraction of start lifetime to subtract on collision, 0-1 (default: 0)
|
|
716
|
+
};
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
### CollisionPlaneMode
|
|
720
|
+
- `KILL` — Deactivate the particle immediately when it crosses the plane
|
|
721
|
+
- `CLAMP` — Stop the particle at the plane surface (zero velocity toward plane)
|
|
722
|
+
- `BOUNCE` — Reflect the velocity vector off the plane normal with optional dampen
|
|
723
|
+
|
|
724
|
+
**Example — Bouncy floor and kill ceiling:**
|
|
725
|
+
```typescript
|
|
726
|
+
createParticleSystem({
|
|
727
|
+
// ... particle config
|
|
728
|
+
collisionPlanes: [
|
|
729
|
+
{
|
|
730
|
+
position: { x: 0, y: 0, z: 0 },
|
|
731
|
+
normal: { x: 0, y: 1, z: 0 },
|
|
732
|
+
mode: CollisionPlaneMode.BOUNCE,
|
|
733
|
+
dampen: 0.6,
|
|
734
|
+
},
|
|
735
|
+
{
|
|
736
|
+
position: { x: 0, y: 10, z: 0 },
|
|
737
|
+
normal: { x: 0, y: -1, z: 0 },
|
|
738
|
+
mode: CollisionPlaneMode.KILL,
|
|
739
|
+
},
|
|
740
|
+
],
|
|
741
|
+
});
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
---
|
|
745
|
+
|
|
696
746
|
## Serialization
|
|
697
747
|
|
|
698
748
|
Save and load particle system configurations as JSON.
|
|
@@ -785,6 +835,145 @@ function FireEffect({ config }: { config?: Record<string, unknown> }) {
|
|
|
785
835
|
|
|
786
836
|
---
|
|
787
837
|
|
|
838
|
+
## WebGPU Compute Support
|
|
839
|
+
|
|
840
|
+
Optional GPU-accelerated particle simulation via Three.js WebGPU renderer and TSL (Three Shading Language). Offloads all per-particle physics and modifiers to GPU compute shaders, enabling **50K-350K+ particles** at interactive frame rates.
|
|
841
|
+
|
|
842
|
+
**Requirements:** Three.js r182+ with WebGPU build (`three/webgpu`), browser with WebGPU support (Chrome 113+, Edge 113+, Firefox Nightly). No breaking changes — all existing WebGL code works unchanged.
|
|
843
|
+
|
|
844
|
+
### Setup
|
|
845
|
+
|
|
846
|
+
```typescript
|
|
847
|
+
// 1. Enable WebGPU support (once, before creating any particle system)
|
|
848
|
+
import { enableWebGPU } from "@newkrok/three-particles/webgpu";
|
|
849
|
+
enableWebGPU();
|
|
850
|
+
|
|
851
|
+
// 2. Create a WebGPU renderer
|
|
852
|
+
import * as THREE from "three/webgpu";
|
|
853
|
+
const renderer = new THREE.WebGPURenderer({ antialias: true });
|
|
854
|
+
await renderer.init();
|
|
855
|
+
|
|
856
|
+
// 3. Create a GPU-accelerated particle system
|
|
857
|
+
import { createParticleSystem, SimulationBackend } from "@newkrok/three-particles";
|
|
858
|
+
const system = createParticleSystem({
|
|
859
|
+
simulationBackend: SimulationBackend.AUTO, // GPU if WebGPU available, else CPU
|
|
860
|
+
maxParticles: 100000,
|
|
861
|
+
// ... rest of config (same API as CPU)
|
|
862
|
+
});
|
|
863
|
+
|
|
864
|
+
scene.add(system.instance);
|
|
865
|
+
|
|
866
|
+
// 4. In your render loop — dispatch compute before rendering
|
|
867
|
+
function animate() {
|
|
868
|
+
system.update({ now: performance.now(), delta, elapsed });
|
|
869
|
+
|
|
870
|
+
if (system.computeNode) {
|
|
871
|
+
renderer.compute(system.computeNode);
|
|
872
|
+
}
|
|
873
|
+
renderer.render(scene, camera);
|
|
874
|
+
}
|
|
875
|
+
```
|
|
876
|
+
|
|
877
|
+
For fine-grained control (e.g., selective registration of individual WebGPU functions), you can also use `registerTSLMaterialFactory()` directly — see the API reference below.
|
|
878
|
+
|
|
879
|
+
### SimulationBackend
|
|
880
|
+
|
|
881
|
+
```typescript
|
|
882
|
+
enum SimulationBackend {
|
|
883
|
+
AUTO = 'AUTO', // GPU compute if WebGPU renderer detected, else CPU (default)
|
|
884
|
+
CPU = 'CPU', // Always JavaScript update loop (works with any renderer)
|
|
885
|
+
GPU = 'GPU', // Request GPU compute; falls back to CPU if renderer lacks compute support
|
|
886
|
+
}
|
|
887
|
+
```
|
|
888
|
+
|
|
889
|
+
| Value | WebGPU Renderer | WebGL Renderer |
|
|
890
|
+
|-------|----------------|----------------|
|
|
891
|
+
| `AUTO` | GPU compute | CPU (JavaScript) |
|
|
892
|
+
| `CPU` | CPU (JavaScript) | CPU (JavaScript) |
|
|
893
|
+
| `GPU` | GPU compute | CPU (fallback) |
|
|
894
|
+
|
|
895
|
+
### What Runs on GPU
|
|
896
|
+
|
|
897
|
+
- **Core physics:** gravity, velocity integration, position update, lifetime tracking, death detection
|
|
898
|
+
- **All 7 modifiers:** size over lifetime, opacity over lifetime, color over lifetime (per-channel RGB curves), rotation over lifetime, linear velocity over lifetime (per-axis X/Y/Z curves), orbital velocity, noise (3D simplex FBM)
|
|
899
|
+
- **Force fields:** point attractors/repulsors and directional forces with all falloff modes (NONE, LINEAR, QUADRATIC), up to 16 per system
|
|
900
|
+
- **Collision planes:** kill/clamp/bounce modes with dampen and lifetime loss, encoded as packed uniform buffer
|
|
901
|
+
- **Curves:** baked into 256-sample Float32Array lookup tables at system creation for fast GPU evaluation (<0.4% interpolation error)
|
|
902
|
+
|
|
903
|
+
### What Stays on CPU
|
|
904
|
+
|
|
905
|
+
- **Emission:** particle activation, burst scheduling, rate-over-time, rate-over-distance
|
|
906
|
+
- **Sub-emitters:** birth/death trigger spawning (sub-emitters are always forced to `SimulationBackend.CPU`)
|
|
907
|
+
- **Configuration changes:** `updateConfig()` applies on the next frame
|
|
908
|
+
- **Trail renderer:** `RendererType.TRAIL` always uses CPU simulation (POINTS, INSTANCED, and MESH work with GPU compute)
|
|
909
|
+
|
|
910
|
+
### ParticleSystem.computeNode
|
|
911
|
+
|
|
912
|
+
When GPU compute is active, the returned `ParticleSystem` object exposes a `computeNode` property. This must be dispatched every frame **before** `renderer.render()`:
|
|
913
|
+
|
|
914
|
+
```typescript
|
|
915
|
+
const system = createParticleSystem({ simulationBackend: SimulationBackend.GPU, ... });
|
|
916
|
+
|
|
917
|
+
// In render loop:
|
|
918
|
+
if (system.computeNode) {
|
|
919
|
+
renderer.compute(system.computeNode); // Dispatch GPU compute
|
|
920
|
+
}
|
|
921
|
+
renderer.render(scene, camera);
|
|
922
|
+
```
|
|
923
|
+
|
|
924
|
+
When CPU simulation is active (no WebGPU, or `simulationBackend: 'CPU'`), `computeNode` is `null`.
|
|
925
|
+
|
|
926
|
+
### Fallback Behavior
|
|
927
|
+
|
|
928
|
+
WebGPU is fully opt-in and non-breaking:
|
|
929
|
+
- If `enableWebGPU()` not called (or no TSL factory registered via `registerTSLMaterialFactory()`), the library uses GLSL shaders (existing WebGL path)
|
|
930
|
+
- If `simulationBackend: 'GPU'` but the renderer lacks compute support, it silently falls back to CPU
|
|
931
|
+
- The same `ParticleSystemConfig` works identically on both backends — no config changes needed
|
|
932
|
+
- Renderer detection is duck-typed (checks for `.compute()` and `.hasFeature()` methods), not class-based
|
|
933
|
+
|
|
934
|
+
### WebGPU with React Three Fiber
|
|
935
|
+
|
|
936
|
+
```tsx
|
|
937
|
+
import { useRef, useEffect } from "react";
|
|
938
|
+
import { useFrame, useThree } from "@react-three/fiber";
|
|
939
|
+
import { createParticleSystem, SimulationBackend } from "@newkrok/three-particles";
|
|
940
|
+
import { enableWebGPU } from "@newkrok/three-particles/webgpu";
|
|
941
|
+
|
|
942
|
+
// Enable once at module level
|
|
943
|
+
enableWebGPU();
|
|
944
|
+
|
|
945
|
+
function GPUParticleEffect({ config }) {
|
|
946
|
+
const groupRef = useRef(null);
|
|
947
|
+
const systemRef = useRef(null);
|
|
948
|
+
const { gl: renderer } = useThree();
|
|
949
|
+
|
|
950
|
+
useEffect(() => {
|
|
951
|
+
const system = createParticleSystem({
|
|
952
|
+
simulationBackend: SimulationBackend.AUTO,
|
|
953
|
+
...config,
|
|
954
|
+
});
|
|
955
|
+
systemRef.current = system;
|
|
956
|
+
groupRef.current?.add(system.instance);
|
|
957
|
+
return () => system.dispose();
|
|
958
|
+
}, [config]);
|
|
959
|
+
|
|
960
|
+
useFrame((_, delta) => {
|
|
961
|
+
const system = systemRef.current;
|
|
962
|
+
if (!system) return;
|
|
963
|
+
system.update({ now: performance.now(), delta, elapsed: 0 });
|
|
964
|
+
if (system.computeNode) {
|
|
965
|
+
renderer.compute(system.computeNode);
|
|
966
|
+
}
|
|
967
|
+
});
|
|
968
|
+
|
|
969
|
+
return <group ref={groupRef} />;
|
|
970
|
+
}
|
|
971
|
+
```
|
|
972
|
+
|
|
973
|
+
**Important:** R3F must be configured to use `WebGPURenderer` (via the `gl` prop on `<Canvas>`) for GPU compute to activate.
|
|
974
|
+
|
|
975
|
+
---
|
|
976
|
+
|
|
788
977
|
## Links
|
|
789
978
|
|
|
790
979
|
- Repository: https://github.com/NewKrok/three-particles
|
package/llms.txt
CHANGED
|
@@ -67,6 +67,7 @@ function animate() {
|
|
|
67
67
|
| startColor | MinMaxColor | white | Color range |
|
|
68
68
|
| gravity | number | 0.0 | Gravity strength |
|
|
69
69
|
| simulationSpace | LOCAL / WORLD | LOCAL | Coordinate space |
|
|
70
|
+
| simulationBackend | AUTO / CPU / GPU | AUTO | Simulation backend (AUTO: GPU if WebGPU, else CPU) |
|
|
70
71
|
| emission | Emission | rateOverTime: 10 | Emission config |
|
|
71
72
|
| shape | ShapeConfig | — | Emitter shape |
|
|
72
73
|
| map | THREE.Texture | undefined | Particle texture |
|
|
@@ -198,6 +199,94 @@ forceFields: [
|
|
|
198
199
|
]
|
|
199
200
|
```
|
|
200
201
|
|
|
202
|
+
## Collision Planes
|
|
203
|
+
|
|
204
|
+
Infinite planes that constrain particles with three response modes: kill, clamp, or bounce.
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
collisionPlanes: [
|
|
208
|
+
{ position: { x: 0, y: 0, z: 0 }, normal: { x: 0, y: 1, z: 0 }, mode: CollisionPlaneMode.BOUNCE, dampen: 0.6 },
|
|
209
|
+
{ position: { x: 0, y: 5, z: 0 }, normal: { x: 0, y: -1, z: 0 }, mode: CollisionPlaneMode.KILL },
|
|
210
|
+
]
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## WebGPU Compute Support
|
|
214
|
+
|
|
215
|
+
Optional GPU-accelerated particle simulation via Three.js WebGPU renderer and TSL (Three Shading Language). Enables **50K-350K+ particles** with full physics on the GPU.
|
|
216
|
+
|
|
217
|
+
**Requirements:** Three.js r182+ with WebGPU build (`three/webgpu`), browser with WebGPU support (Chrome 113+, Edge 113+). No breaking changes — all existing WebGL code works unchanged.
|
|
218
|
+
|
|
219
|
+
### Setup
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
// 1. Enable WebGPU support (once, before creating any particle system)
|
|
223
|
+
import { enableWebGPU } from "@newkrok/three-particles/webgpu";
|
|
224
|
+
enableWebGPU();
|
|
225
|
+
|
|
226
|
+
// 2. Create a WebGPU renderer
|
|
227
|
+
import * as THREE from "three/webgpu";
|
|
228
|
+
const renderer = new THREE.WebGPURenderer({ antialias: true });
|
|
229
|
+
await renderer.init();
|
|
230
|
+
|
|
231
|
+
// 3. Create a GPU-accelerated particle system
|
|
232
|
+
import { createParticleSystem, SimulationBackend } from "@newkrok/three-particles";
|
|
233
|
+
const system = createParticleSystem({
|
|
234
|
+
simulationBackend: SimulationBackend.AUTO, // GPU if WebGPU available, else CPU
|
|
235
|
+
maxParticles: 100000,
|
|
236
|
+
// ... rest of config (same API as CPU)
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
scene.add(system.instance);
|
|
240
|
+
|
|
241
|
+
// 4. In your render loop — dispatch compute before rendering
|
|
242
|
+
system.update({ now: performance.now(), delta, elapsed });
|
|
243
|
+
if (system.computeNode) {
|
|
244
|
+
renderer.compute(system.computeNode);
|
|
245
|
+
}
|
|
246
|
+
renderer.render(scene, camera);
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
For fine-grained control, you can also use `registerTSLMaterialFactory()` to selectively register individual WebGPU functions — see the full API reference.
|
|
250
|
+
|
|
251
|
+
### SimulationBackend
|
|
252
|
+
|
|
253
|
+
| Value | WebGPU Renderer | WebGL Renderer |
|
|
254
|
+
|-------|----------------|----------------|
|
|
255
|
+
| `AUTO` (default) | GPU compute | CPU (JavaScript) |
|
|
256
|
+
| `CPU` | CPU (JavaScript) | CPU (JavaScript) |
|
|
257
|
+
| `GPU` | GPU compute | CPU (fallback) |
|
|
258
|
+
|
|
259
|
+
### What runs on GPU
|
|
260
|
+
|
|
261
|
+
- Core physics: gravity, velocity integration, position update, lifetime tracking
|
|
262
|
+
- All 7 modifiers: size/opacity/color over lifetime, rotation, linear/orbital velocity, noise (3D simplex FBM)
|
|
263
|
+
- Force fields: point/directional with falloff (up to 16 per system)
|
|
264
|
+
- Collision planes: kill/clamp/bounce with dampen and lifetime loss
|
|
265
|
+
- Curves: baked into 256-sample Float32Array lookup tables (<0.4% error)
|
|
266
|
+
|
|
267
|
+
### What stays on CPU
|
|
268
|
+
|
|
269
|
+
- Emission (particle activation, burst scheduling, rate-over-distance)
|
|
270
|
+
- Sub-emitter spawning (birth/death triggers; sub-emitters are forced to CPU backend)
|
|
271
|
+
- Configuration changes (`updateConfig`)
|
|
272
|
+
- Trail renderer (`RendererType.TRAIL` always uses CPU simulation)
|
|
273
|
+
|
|
274
|
+
### Compute dispatch
|
|
275
|
+
|
|
276
|
+
The returned `ParticleSystem` exposes `computeNode` (non-null when GPU compute is active). This must be dispatched every frame **before** `renderer.render()`:
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
if (system.computeNode) {
|
|
280
|
+
renderer.compute(system.computeNode);
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Fallback behavior
|
|
285
|
+
|
|
286
|
+
- If `enableWebGPU()` not called (or no TSL factory registered): uses GLSL shaders (WebGL path)
|
|
287
|
+
- If `GPU` requested but renderer lacks compute: silently falls back to CPU
|
|
288
|
+
- Same `ParticleSystemConfig` works on both backends — no config changes needed
|
|
289
|
+
|
|
201
290
|
## Usage with React Three Fiber
|
|
202
291
|
|
|
203
292
|
No wrapper package needed — use hooks directly:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@newkrok/three-particles",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.16.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Three.js-based high-performance particle system library designed for creating visually stunning particle effects with ease. Perfect for game developers and 3D applications.",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
9
|
"files": [
|
|
10
10
|
"dist/",
|
|
11
|
+
"webgpu.d.ts",
|
|
11
12
|
"README.md",
|
|
12
13
|
"LICENSE",
|
|
13
14
|
"llms.txt",
|
|
@@ -19,6 +20,10 @@
|
|
|
19
20
|
".": {
|
|
20
21
|
"import": "./dist/index.js",
|
|
21
22
|
"types": "./dist/index.d.ts"
|
|
23
|
+
},
|
|
24
|
+
"./webgpu": {
|
|
25
|
+
"import": "./dist/webgpu.js",
|
|
26
|
+
"types": "./webgpu.d.ts"
|
|
22
27
|
}
|
|
23
28
|
},
|
|
24
29
|
"repository": {
|
|
@@ -73,15 +78,15 @@
|
|
|
73
78
|
"three": "^0.182.0"
|
|
74
79
|
},
|
|
75
80
|
"devDependencies": {
|
|
76
|
-
"@babel/preset-env": "^7.29.
|
|
81
|
+
"@babel/preset-env": "^7.29.2",
|
|
77
82
|
"@babel/preset-typescript": "^7.28.5",
|
|
78
83
|
"@commitlint/cli": "^20.5.0",
|
|
79
84
|
"@commitlint/config-conventional": "^20.5.0",
|
|
80
85
|
"@types/jest": "^30.0.0",
|
|
81
|
-
"@types/node": "^25.
|
|
86
|
+
"@types/node": "^25.6.0",
|
|
82
87
|
"@types/three": "^0.183.1",
|
|
83
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
84
|
-
"@typescript-eslint/parser": "^8.
|
|
88
|
+
"@typescript-eslint/eslint-plugin": "^8.58.2",
|
|
89
|
+
"@typescript-eslint/parser": "^8.58.2",
|
|
85
90
|
"babel-jest": "^30.3.0",
|
|
86
91
|
"eslint": "^9.39.2",
|
|
87
92
|
"eslint-config-prettier": "^10.1.8",
|
|
@@ -90,14 +95,14 @@
|
|
|
90
95
|
"husky": "^9.1.7",
|
|
91
96
|
"jest": "^30.3.0",
|
|
92
97
|
"madge": "^8.0.0",
|
|
93
|
-
"prettier": "^3.8.
|
|
98
|
+
"prettier": "^3.8.3",
|
|
94
99
|
"rimraf": "^6.1.3",
|
|
95
|
-
"ts-jest": "^29.4.
|
|
100
|
+
"ts-jest": "^29.4.9",
|
|
96
101
|
"ts-node": "^10.9.2",
|
|
97
102
|
"tsup": "^8.5.1",
|
|
98
|
-
"typedoc": "^0.28.
|
|
103
|
+
"typedoc": "^0.28.19",
|
|
99
104
|
"typescript": "^5.9.3",
|
|
100
|
-
"webpack": "^5.
|
|
101
|
-
"webpack-cli": "^7.0.
|
|
105
|
+
"webpack": "^5.106.2",
|
|
106
|
+
"webpack-cli": "^7.0.2"
|
|
102
107
|
}
|
|
103
108
|
}
|
package/webgpu.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebGPU entry point type declarations for @newkrok/three-particles/webgpu.
|
|
3
|
+
*
|
|
4
|
+
* Hand-written because automatic DTS generation fails on TSL node types
|
|
5
|
+
* (Three.js TSL Fn return types resolve to `unknown` in the type system).
|
|
6
|
+
*/
|
|
7
|
+
import type { Material, Blending } from 'three';
|
|
8
|
+
import type { RendererType } from '@newkrok/three-particles';
|
|
9
|
+
|
|
10
|
+
/** Renderer configuration for material creation. */
|
|
11
|
+
export interface RendererConfig {
|
|
12
|
+
transparent: boolean;
|
|
13
|
+
blending: Blending;
|
|
14
|
+
depthTest: boolean;
|
|
15
|
+
depthWrite: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Creates a TSL NodeMaterial for the main particle system (non-trail). */
|
|
19
|
+
export declare function createTSLParticleMaterial(
|
|
20
|
+
rendererType: RendererType,
|
|
21
|
+
sharedUniforms: Record<string, { value: unknown }>,
|
|
22
|
+
rendererConfig: RendererConfig,
|
|
23
|
+
gpuCompute?: boolean
|
|
24
|
+
): Material;
|
|
25
|
+
|
|
26
|
+
/** Creates a TSL NodeMaterial for the trail ribbon renderer. */
|
|
27
|
+
export declare function createTSLTrailMaterial(
|
|
28
|
+
trailUniforms: Record<string, { value: unknown }>,
|
|
29
|
+
rendererConfig: RendererConfig
|
|
30
|
+
): Material;
|
|
31
|
+
|
|
32
|
+
/** Creates the GPU compute pipeline for particle simulation. */
|
|
33
|
+
export declare function createComputePipeline(
|
|
34
|
+
maxParticles: number,
|
|
35
|
+
instanced: boolean,
|
|
36
|
+
normalizedConfig: unknown,
|
|
37
|
+
particleSystemId: number,
|
|
38
|
+
forceFieldCount: number,
|
|
39
|
+
collisionPlaneCount?: number
|
|
40
|
+
): unknown;
|
|
41
|
+
|
|
42
|
+
/** Writes init data for a newly emitted particle into modifier storage buffers. */
|
|
43
|
+
export declare function writeParticleToModifierBuffers(
|
|
44
|
+
buffers: unknown,
|
|
45
|
+
index: number,
|
|
46
|
+
data: Record<string, unknown>
|
|
47
|
+
): void;
|
|
48
|
+
|
|
49
|
+
/** Deactivates a particle in the modifier storage buffers. */
|
|
50
|
+
export declare function deactivateParticleInModifierBuffers(
|
|
51
|
+
buffers: unknown,
|
|
52
|
+
index: number
|
|
53
|
+
): void;
|
|
54
|
+
|
|
55
|
+
/** Flushes pending init data to the GPU. Call once per frame before compute dispatch. */
|
|
56
|
+
export declare function flushEmitQueue(buffers: unknown): number;
|
|
57
|
+
|
|
58
|
+
/** Registers the curve data length for a buffer. Called once during pipeline creation. */
|
|
59
|
+
export declare function registerCurveDataLength(
|
|
60
|
+
buffers: unknown,
|
|
61
|
+
curveDataLength: number
|
|
62
|
+
): void;
|
|
63
|
+
|
|
64
|
+
/** Packs force field configs into a flat Float32Array for GPU upload. */
|
|
65
|
+
export declare function encodeForceFieldsForGPU(
|
|
66
|
+
forceFields: ReadonlyArray<unknown>,
|
|
67
|
+
particleSystemId: number,
|
|
68
|
+
systemLifetimePercentage: number
|
|
69
|
+
): Float32Array;
|
|
70
|
+
|
|
71
|
+
/** Packs collision plane configs into a flat Float32Array for GPU upload. */
|
|
72
|
+
export declare function encodeCollisionPlanesForGPU(
|
|
73
|
+
planes: ReadonlyArray<unknown>
|
|
74
|
+
): Float32Array;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Convenience function that registers all WebGPU TSL material factories
|
|
78
|
+
* and GPU compute helpers in a single call.
|
|
79
|
+
*
|
|
80
|
+
* Call this **once** before creating any particle systems that use WebGPU rendering.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```typescript
|
|
84
|
+
* import { enableWebGPU } from '@newkrok/three-particles/webgpu';
|
|
85
|
+
* enableWebGPU();
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
export declare function enableWebGPU(): void;
|