lazy-vfx 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +231 -0
- package/dist/favicon.ico +0 -0
- package/dist/lazy-vfx.es.js +834 -0
- package/dist/lazy-vfx.umd.js +152 -0
- package/dist/vite.svg +1 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# ☄️ Lazy VFX
|
|
2
|
+
|
|
3
|
+
_Effortless high-end visual effects for the modern web, built for React & Three.js_
|
|
4
|
+
|
|
5
|
+
Lazy VFX is a minimal, shader-driven VFX engine designed for modern web apps using React and Three.js. It abstracts away all the math and plumbing for emitters, GPU-accelerated particles, and real-time shaders, so you can stay focused on building cinematic, interactive experiences.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
[Live demo](#) - [Fireworks demo](#) - [Wizard Game demo](#)
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## ✨ Features
|
|
13
|
+
|
|
14
|
+
- **Modular Emitters** — Create and control particle sources with flexible settings using `<VFXEmitter>`.
|
|
15
|
+
- **Custom GLSL Shaders** — GPU-accelerated with built-in vertex & fragment shaders, easily extensible for custom magic.
|
|
16
|
+
- **Centralized State** — Driven by a single VFXStore for consistent, live-reloadable scene effects and controls.
|
|
17
|
+
- **Fast Tooling** — Zero-config Vite setup, instant HMR, rapid production deployments.
|
|
18
|
+
- **Leva Controls** — Out-of-the-box UI for tuning and exporting effects.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 🚀 Quick Install
|
|
23
|
+
|
|
24
|
+
Use your favorite package manager:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# With pnpm
|
|
28
|
+
pnpm add lazy-vfx
|
|
29
|
+
|
|
30
|
+
# Or npm
|
|
31
|
+
npm install lazy-vfx
|
|
32
|
+
|
|
33
|
+
# Or yarn
|
|
34
|
+
yarn add lazy-vfx
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 🛠️ Usage Example
|
|
40
|
+
|
|
41
|
+
**Lazy VFX uses a two-component system:**
|
|
42
|
+
|
|
43
|
+
- **VFXParticles:** Defines the particle system and its rendering properties
|
|
44
|
+
- **VFXEmitter:** Controls how and when particles are emitted into the scene
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
Add cinematic particles in seconds to any [React Three Fiber](https://docs.pmnd.rs/react-three-fiber) scene:
|
|
48
|
+
|
|
49
|
+
```jsx
|
|
50
|
+
import { VFXParticals, VFXEmitter } from 'lazy-vfx';
|
|
51
|
+
// Also import your alphaMap or use a texture
|
|
52
|
+
|
|
53
|
+
function Experience() {
|
|
54
|
+
return (
|
|
55
|
+
<>
|
|
56
|
+
{/* Step 1: Define your particle system */}
|
|
57
|
+
<VFXParticles
|
|
58
|
+
name="particles" // A unique identifier for this particle system
|
|
59
|
+
settings={{
|
|
60
|
+
nbParticles: 100000, // Maximum number of particles to allocate
|
|
61
|
+
gravity: [0, -9.8, 0], // Apply gravity (x, y, z)
|
|
62
|
+
fadeSize: [0, 0], // Size fade in/out settings
|
|
63
|
+
fadeAlpha: [0, 0], // Opacity fade in/out settings
|
|
64
|
+
renderMode: "billboard", // "billboard" or "mesh" or "stretchBillboard"
|
|
65
|
+
intensity: 3, // Brightness multiplier
|
|
66
|
+
appearance: AppearanceMode.Circular, // Define the default appearance to be plane (default) or circular
|
|
67
|
+
easeFunction: "easeLinear", // add easing to the particle animations
|
|
68
|
+
}}
|
|
69
|
+
/>
|
|
70
|
+
|
|
71
|
+
{/* Step 2: Define your emitter */}
|
|
72
|
+
<VFXEmitter
|
|
73
|
+
debug // Show debug visualization
|
|
74
|
+
emitter="particles" // Target the particle system by name
|
|
75
|
+
settings={{
|
|
76
|
+
loop: true, // Continuously emit particles (only if `spawnMode` is 'time')
|
|
77
|
+
duration: 1, // Emission cycle duration in seconds
|
|
78
|
+
nbParticles: 100, // Number of particles to emit per cycle
|
|
79
|
+
spawnMode: "time", // Emission mode: 'time' or 'burst'
|
|
80
|
+
delay: 0, // Time delay before starting emission
|
|
81
|
+
|
|
82
|
+
// Particle lifetime range [min, max]
|
|
83
|
+
particlesLifetime: [0.1, 1],
|
|
84
|
+
|
|
85
|
+
// Position range (min/max)
|
|
86
|
+
startPositionMin: [-0.1, -0.1, -0.1],
|
|
87
|
+
startPositionMax: [0.1, 0.1, 0.1],
|
|
88
|
+
|
|
89
|
+
// Rotation range (min/max)
|
|
90
|
+
startRotationMin: [0, 0, 0],
|
|
91
|
+
startRotationMax: [0, 0, 0],
|
|
92
|
+
// Rotation speed range (min/max)
|
|
93
|
+
rotationSpeedMin: [0, 0, 0],
|
|
94
|
+
rotationSpeedMax: [0, 0, 0],
|
|
95
|
+
|
|
96
|
+
// Direction range (min/max)
|
|
97
|
+
directionMin: [-1, 0, -1],
|
|
98
|
+
directionMax: [1, 1, 1],
|
|
99
|
+
|
|
100
|
+
// Particle size range [min, max]
|
|
101
|
+
size: [0.01, 0.25],
|
|
102
|
+
|
|
103
|
+
// Particle speed range [min, max]
|
|
104
|
+
speed: [1, 12],
|
|
105
|
+
|
|
106
|
+
// Color at start - an array of strings for random selection
|
|
107
|
+
colorStart: ["white", "skyblue"],
|
|
108
|
+
|
|
109
|
+
// Color at end - an array of strings for random selection
|
|
110
|
+
colorEnd: ["white", "pink"],
|
|
111
|
+
|
|
112
|
+
// When true, the emitter will emit particles using its local axes (transformed by its world rotation)
|
|
113
|
+
useLocalDirection: true,
|
|
114
|
+
}}
|
|
115
|
+
/>
|
|
116
|
+
</>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Custom Geometry Example
|
|
123
|
+
|
|
124
|
+
You can use custom geometries for your particles:
|
|
125
|
+
|
|
126
|
+
```jsx
|
|
127
|
+
import { useGLTF } from '@react-three/drei';
|
|
128
|
+
|
|
129
|
+
const CustomParticles = () => {
|
|
130
|
+
// Load the GLTF model. Make sure the path to your .glb file is correct.
|
|
131
|
+
const { nodes } = useGLTF('/models/sword.glb');
|
|
132
|
+
|
|
133
|
+
return (
|
|
134
|
+
<>
|
|
135
|
+
<VFXParticles
|
|
136
|
+
name="swords"
|
|
137
|
+
geometry={nodes?.Sword?.geometry ? <primitive object={nodes.Sword.geometry} /> : null}
|
|
138
|
+
settings={{
|
|
139
|
+
nbParticles: 1000,
|
|
140
|
+
renderMode: "mesh",
|
|
141
|
+
intensity: 2,
|
|
142
|
+
}}
|
|
143
|
+
/>
|
|
144
|
+
|
|
145
|
+
<VFXEmitter
|
|
146
|
+
emitter="swords"
|
|
147
|
+
settings={{
|
|
148
|
+
spawnMode: "burst",
|
|
149
|
+
nbParticles: 100,
|
|
150
|
+
// Add any other emitter settings as needed
|
|
151
|
+
}}
|
|
152
|
+
/>
|
|
153
|
+
</>
|
|
154
|
+
);
|
|
155
|
+
};
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Note:**
|
|
159
|
+
- Ensure the GLTF file at `/models/sword.glb` has a node named `Sword`.
|
|
160
|
+
- If your model's node hierarchy is different, adjust `nodes.Sword.geometry` accordingly.
|
|
161
|
+
|
|
162
|
+
## API Reference
|
|
163
|
+
|
|
164
|
+
### VFXParticles Component
|
|
165
|
+
|
|
166
|
+
| Property | Type | Description |
|
|
167
|
+
|-------------|-------------------|-----------------------------------------------------|
|
|
168
|
+
| name | string | Unique identifier for this particle system |
|
|
169
|
+
| settings | object | Configuration options for particles |
|
|
170
|
+
| alphaMap | THREE.Texture | Optional texture for particle alpha/transparency |
|
|
171
|
+
| geometry | ReactElement | Optional custom geometry for particles |
|
|
172
|
+
|
|
173
|
+
#### VFXParticles Settings
|
|
174
|
+
|
|
175
|
+
| Setting | Type | Default | Description |
|
|
176
|
+
|-----------------|------------------------------|-----------------|--------------------------------------------------------------------------|
|
|
177
|
+
| nbParticles | number | 1000 | Maximum number of particles |
|
|
178
|
+
| intensity | number | 1 | Brightness multiplier |
|
|
179
|
+
| renderMode | 'billboard' \| 'mesh' \| 'stretchBillboard' | 'mesh' | How particles are rendered |
|
|
180
|
+
| stretchScale | number | 1.0 | Stretch factor for stretchBillboard mode |
|
|
181
|
+
| fadeSize | [number, number] | [0.1, 0.9] | Size fade in/out range (0-1 of lifetime) |
|
|
182
|
+
| fadeAlpha | [number, number] | [0, 1.0] | Opacity fade in/out range |
|
|
183
|
+
| gravity | [number, number, number] | [0, 0, 0] | Gravity force applied to particles |
|
|
184
|
+
| frustumCulled | boolean | true | Whether particles are frustum culled |
|
|
185
|
+
| appearance | AppearanceMode | Square | Particle appearance (Square or Circular) |
|
|
186
|
+
| easeFunction | EaseFunction | 'easeLinear' | Easing function for particle animations |
|
|
187
|
+
| blendingMode | THREE.Blending | AdditiveBlending| How particles blend with the scene |
|
|
188
|
+
| shadingHooks | object | {} | Custom GLSL shader hooks for advanced rendering effects |
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
### VFXEmitter Component
|
|
193
|
+
|
|
194
|
+
| Property | Type | Description |
|
|
195
|
+
|---------------|-----------|-----------------------------------------------------|
|
|
196
|
+
| emitter | string | Name of the target particle system |
|
|
197
|
+
| settings | object | Configuration options for emission behavior |
|
|
198
|
+
| debug | boolean | Show Leva controls to adjust settings |
|
|
199
|
+
| autoStart | boolean | Automatically start emitting |
|
|
200
|
+
| localDirection| boolean | Use emitter's local space for directions |
|
|
201
|
+
|
|
202
|
+
#### VFXEmitter Settings
|
|
203
|
+
|
|
204
|
+
| Setting | Type | Default | Description |
|
|
205
|
+
|---------------------|-----------------------------|---------------------------|-----------------------------------------------------|
|
|
206
|
+
| loop | boolean | true | Continuously emit particles |
|
|
207
|
+
| duration | number | 1 | Emission cycle duration in seconds |
|
|
208
|
+
| nbParticles | number | 100 | Number of particles to emit per cycle |
|
|
209
|
+
| spawnMode | 'time' \| 'burst' | 'time' | How particles are spawned |
|
|
210
|
+
| delay | number | 0 | Time delay before starting emission |
|
|
211
|
+
| particlesLifetime | [number, number] | [0.1, 1] | Particle lifetime range [min, max] |
|
|
212
|
+
| startPositionMin | [number, number, number] | [-0.1, -0.1, -0.1] | Minimum start position |
|
|
213
|
+
| startPositionMax | [number, number, number] | [0.1, 0.1, 0.1] | Maximum start position |
|
|
214
|
+
| startRotationMin | [number, number, number] | [0, 0, 0] | Minimum start rotation |
|
|
215
|
+
| startRotationMax | [number, number, number] | [0, 0, 0] | Maximum start rotation |
|
|
216
|
+
| rotationSpeedMin | [number, number, number] | [0, 0, 0] | Minimum rotation speed |
|
|
217
|
+
| rotationSpeedMax | [number, number, number] | [0, 0, 0] | Maximum rotation speed |
|
|
218
|
+
| directionMin | [number, number, number] | [-1, 0, -1] | Minimum emission direction |
|
|
219
|
+
| directionMax | [number, number, number] | [1, 1, 1] | Maximum emission direction |
|
|
220
|
+
| size | [number, number] | [0.01, 0.25] | Particle size range [min, max] |
|
|
221
|
+
| speed | [number, number] | [1, 12] | Particle speed range [min, max] |
|
|
222
|
+
| colorStart | string[] | ['white'] | Colors at start (randomly selected) |
|
|
223
|
+
| colorEnd | string[] | ['white'] | Colors at end (randomly selected) |
|
|
224
|
+
| useLocalDirection | boolean | false | Use emitter's local space for directions |
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
## 📄 License
|
|
230
|
+
|
|
231
|
+
MIT © [Dev-Sameerkhan](https://github.com/Dev-Sameer-Khan)
|
package/dist/favicon.ico
ADDED
|
Binary file
|
|
@@ -0,0 +1,834 @@
|
|
|
1
|
+
import ye, { useRef as D, useEffect as ge, forwardRef as Re, useState as Ee, useImperativeHandle as Pe, useCallback as Ae, useMemo as be } from "react";
|
|
2
|
+
import { create as he } from "zustand";
|
|
3
|
+
import { useFrame as Se } from "@react-three/fiber";
|
|
4
|
+
import * as p from "three";
|
|
5
|
+
import { useControls as ae, button as ie, folder as Q } from "leva";
|
|
6
|
+
var Z = { exports: {} }, J = {};
|
|
7
|
+
/**
|
|
8
|
+
* @license React
|
|
9
|
+
* react-jsx-runtime.production.js
|
|
10
|
+
*
|
|
11
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
12
|
+
*
|
|
13
|
+
* This source code is licensed under the MIT license found in the
|
|
14
|
+
* LICENSE file in the root directory of this source tree.
|
|
15
|
+
*/
|
|
16
|
+
var se;
|
|
17
|
+
function _e() {
|
|
18
|
+
if (se) return J;
|
|
19
|
+
se = 1;
|
|
20
|
+
var n = Symbol.for("react.transitional.element"), g = Symbol.for("react.fragment");
|
|
21
|
+
function l(o, r, a) {
|
|
22
|
+
var E = null;
|
|
23
|
+
if (a !== void 0 && (E = "" + a), r.key !== void 0 && (E = "" + r.key), "key" in r) {
|
|
24
|
+
a = {};
|
|
25
|
+
for (var c in r)
|
|
26
|
+
c !== "key" && (a[c] = r[c]);
|
|
27
|
+
} else a = r;
|
|
28
|
+
return r = a.ref, {
|
|
29
|
+
$$typeof: n,
|
|
30
|
+
type: o,
|
|
31
|
+
key: E,
|
|
32
|
+
ref: r !== void 0 ? r : null,
|
|
33
|
+
props: a
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return J.Fragment = g, J.jsx = l, J.jsxs = l, J;
|
|
37
|
+
}
|
|
38
|
+
var q = {};
|
|
39
|
+
/**
|
|
40
|
+
* @license React
|
|
41
|
+
* react-jsx-runtime.development.js
|
|
42
|
+
*
|
|
43
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
44
|
+
*
|
|
45
|
+
* This source code is licensed under the MIT license found in the
|
|
46
|
+
* LICENSE file in the root directory of this source tree.
|
|
47
|
+
*/
|
|
48
|
+
var ce;
|
|
49
|
+
function we() {
|
|
50
|
+
return ce || (ce = 1, process.env.NODE_ENV !== "production" && (function() {
|
|
51
|
+
function n(e) {
|
|
52
|
+
if (e == null) return null;
|
|
53
|
+
if (typeof e == "function")
|
|
54
|
+
return e.$$typeof === C ? null : e.displayName || e.name || null;
|
|
55
|
+
if (typeof e == "string") return e;
|
|
56
|
+
switch (e) {
|
|
57
|
+
case _:
|
|
58
|
+
return "Fragment";
|
|
59
|
+
case z:
|
|
60
|
+
return "Profiler";
|
|
61
|
+
case F:
|
|
62
|
+
return "StrictMode";
|
|
63
|
+
case f:
|
|
64
|
+
return "Suspense";
|
|
65
|
+
case B:
|
|
66
|
+
return "SuspenseList";
|
|
67
|
+
case T:
|
|
68
|
+
return "Activity";
|
|
69
|
+
}
|
|
70
|
+
if (typeof e == "object")
|
|
71
|
+
switch (typeof e.tag == "number" && console.error(
|
|
72
|
+
"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
|
|
73
|
+
), e.$$typeof) {
|
|
74
|
+
case h:
|
|
75
|
+
return "Portal";
|
|
76
|
+
case w:
|
|
77
|
+
return e.displayName || "Context";
|
|
78
|
+
case N:
|
|
79
|
+
return (e._context.displayName || "Context") + ".Consumer";
|
|
80
|
+
case S:
|
|
81
|
+
var t = e.render;
|
|
82
|
+
return e = e.displayName, e || (e = t.displayName || t.name || "", e = e !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e;
|
|
83
|
+
case X:
|
|
84
|
+
return t = e.displayName || null, t !== null ? t : n(e.type) || "Memo";
|
|
85
|
+
case A:
|
|
86
|
+
t = e._payload, e = e._init;
|
|
87
|
+
try {
|
|
88
|
+
return n(e(t));
|
|
89
|
+
} catch {
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
function g(e) {
|
|
95
|
+
return "" + e;
|
|
96
|
+
}
|
|
97
|
+
function l(e) {
|
|
98
|
+
try {
|
|
99
|
+
g(e);
|
|
100
|
+
var t = !1;
|
|
101
|
+
} catch {
|
|
102
|
+
t = !0;
|
|
103
|
+
}
|
|
104
|
+
if (t) {
|
|
105
|
+
t = console;
|
|
106
|
+
var u = t.error, m = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
|
|
107
|
+
return u.call(
|
|
108
|
+
t,
|
|
109
|
+
"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
|
|
110
|
+
m
|
|
111
|
+
), g(e);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function o(e) {
|
|
115
|
+
if (e === _) return "<>";
|
|
116
|
+
if (typeof e == "object" && e !== null && e.$$typeof === A)
|
|
117
|
+
return "<...>";
|
|
118
|
+
try {
|
|
119
|
+
var t = n(e);
|
|
120
|
+
return t ? "<" + t + ">" : "<...>";
|
|
121
|
+
} catch {
|
|
122
|
+
return "<...>";
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function r() {
|
|
126
|
+
var e = L.A;
|
|
127
|
+
return e === null ? null : e.getOwner();
|
|
128
|
+
}
|
|
129
|
+
function a() {
|
|
130
|
+
return Error("react-stack-top-frame");
|
|
131
|
+
}
|
|
132
|
+
function E(e) {
|
|
133
|
+
if (I.call(e, "key")) {
|
|
134
|
+
var t = Object.getOwnPropertyDescriptor(e, "key").get;
|
|
135
|
+
if (t && t.isReactWarning) return !1;
|
|
136
|
+
}
|
|
137
|
+
return e.key !== void 0;
|
|
138
|
+
}
|
|
139
|
+
function c(e, t) {
|
|
140
|
+
function u() {
|
|
141
|
+
V || (V = !0, console.error(
|
|
142
|
+
"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
|
|
143
|
+
t
|
|
144
|
+
));
|
|
145
|
+
}
|
|
146
|
+
u.isReactWarning = !0, Object.defineProperty(e, "key", {
|
|
147
|
+
get: u,
|
|
148
|
+
configurable: !0
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
function M() {
|
|
152
|
+
var e = n(this.type);
|
|
153
|
+
return W[e] || (W[e] = !0, console.error(
|
|
154
|
+
"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
|
|
155
|
+
)), e = this.props.ref, e !== void 0 ? e : null;
|
|
156
|
+
}
|
|
157
|
+
function P(e, t, u, m, H, te) {
|
|
158
|
+
var v = u.ref;
|
|
159
|
+
return e = {
|
|
160
|
+
$$typeof: y,
|
|
161
|
+
type: e,
|
|
162
|
+
key: t,
|
|
163
|
+
props: u,
|
|
164
|
+
_owner: m
|
|
165
|
+
}, (v !== void 0 ? v : null) !== null ? Object.defineProperty(e, "ref", {
|
|
166
|
+
enumerable: !1,
|
|
167
|
+
get: M
|
|
168
|
+
}) : Object.defineProperty(e, "ref", { enumerable: !1, value: null }), e._store = {}, Object.defineProperty(e._store, "validated", {
|
|
169
|
+
configurable: !1,
|
|
170
|
+
enumerable: !1,
|
|
171
|
+
writable: !0,
|
|
172
|
+
value: 0
|
|
173
|
+
}), Object.defineProperty(e, "_debugInfo", {
|
|
174
|
+
configurable: !1,
|
|
175
|
+
enumerable: !1,
|
|
176
|
+
writable: !0,
|
|
177
|
+
value: null
|
|
178
|
+
}), Object.defineProperty(e, "_debugStack", {
|
|
179
|
+
configurable: !1,
|
|
180
|
+
enumerable: !1,
|
|
181
|
+
writable: !0,
|
|
182
|
+
value: H
|
|
183
|
+
}), Object.defineProperty(e, "_debugTask", {
|
|
184
|
+
configurable: !1,
|
|
185
|
+
enumerable: !1,
|
|
186
|
+
writable: !0,
|
|
187
|
+
value: te
|
|
188
|
+
}), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
|
|
189
|
+
}
|
|
190
|
+
function d(e, t, u, m, H, te) {
|
|
191
|
+
var v = t.children;
|
|
192
|
+
if (v !== void 0)
|
|
193
|
+
if (m)
|
|
194
|
+
if (U(v)) {
|
|
195
|
+
for (m = 0; m < v.length; m++)
|
|
196
|
+
i(v[m]);
|
|
197
|
+
Object.freeze && Object.freeze(v);
|
|
198
|
+
} else
|
|
199
|
+
console.error(
|
|
200
|
+
"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
|
|
201
|
+
);
|
|
202
|
+
else i(v);
|
|
203
|
+
if (I.call(t, "key")) {
|
|
204
|
+
v = n(e);
|
|
205
|
+
var $ = Object.keys(t).filter(function(xe) {
|
|
206
|
+
return xe !== "key";
|
|
207
|
+
});
|
|
208
|
+
m = 0 < $.length ? "{key: someKey, " + $.join(": ..., ") + ": ...}" : "{key: someKey}", k[v + m] || ($ = 0 < $.length ? "{" + $.join(": ..., ") + ": ...}" : "{}", console.error(
|
|
209
|
+
`A props object containing a "key" prop is being spread into JSX:
|
|
210
|
+
let props = %s;
|
|
211
|
+
<%s {...props} />
|
|
212
|
+
React keys must be passed directly to JSX without using spread:
|
|
213
|
+
let props = %s;
|
|
214
|
+
<%s key={someKey} {...props} />`,
|
|
215
|
+
m,
|
|
216
|
+
v,
|
|
217
|
+
$,
|
|
218
|
+
v
|
|
219
|
+
), k[v + m] = !0);
|
|
220
|
+
}
|
|
221
|
+
if (v = null, u !== void 0 && (l(u), v = "" + u), E(t) && (l(t.key), v = "" + t.key), "key" in t) {
|
|
222
|
+
u = {};
|
|
223
|
+
for (var re in t)
|
|
224
|
+
re !== "key" && (u[re] = t[re]);
|
|
225
|
+
} else u = t;
|
|
226
|
+
return v && c(
|
|
227
|
+
u,
|
|
228
|
+
typeof e == "function" ? e.displayName || e.name || "Unknown" : e
|
|
229
|
+
), P(
|
|
230
|
+
e,
|
|
231
|
+
v,
|
|
232
|
+
u,
|
|
233
|
+
r(),
|
|
234
|
+
H,
|
|
235
|
+
te
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
function i(e) {
|
|
239
|
+
x(e) ? e._store && (e._store.validated = 1) : typeof e == "object" && e !== null && e.$$typeof === A && (e._payload.status === "fulfilled" ? x(e._payload.value) && e._payload.value._store && (e._payload.value._store.validated = 1) : e._store && (e._store.validated = 1));
|
|
240
|
+
}
|
|
241
|
+
function x(e) {
|
|
242
|
+
return typeof e == "object" && e !== null && e.$$typeof === y;
|
|
243
|
+
}
|
|
244
|
+
var s = ye, y = Symbol.for("react.transitional.element"), h = Symbol.for("react.portal"), _ = Symbol.for("react.fragment"), F = Symbol.for("react.strict_mode"), z = Symbol.for("react.profiler"), N = Symbol.for("react.consumer"), w = Symbol.for("react.context"), S = Symbol.for("react.forward_ref"), f = Symbol.for("react.suspense"), B = Symbol.for("react.suspense_list"), X = Symbol.for("react.memo"), A = Symbol.for("react.lazy"), T = Symbol.for("react.activity"), C = Symbol.for("react.client.reference"), L = s.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, I = Object.prototype.hasOwnProperty, U = Array.isArray, Y = console.createTask ? console.createTask : function() {
|
|
245
|
+
return null;
|
|
246
|
+
};
|
|
247
|
+
s = {
|
|
248
|
+
react_stack_bottom_frame: function(e) {
|
|
249
|
+
return e();
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
var V, W = {}, O = s.react_stack_bottom_frame.bind(
|
|
253
|
+
s,
|
|
254
|
+
a
|
|
255
|
+
)(), G = Y(o(a)), k = {};
|
|
256
|
+
q.Fragment = _, q.jsx = function(e, t, u) {
|
|
257
|
+
var m = 1e4 > L.recentlyCreatedOwnerStacks++;
|
|
258
|
+
return d(
|
|
259
|
+
e,
|
|
260
|
+
t,
|
|
261
|
+
u,
|
|
262
|
+
!1,
|
|
263
|
+
m ? Error("react-stack-top-frame") : O,
|
|
264
|
+
m ? Y(o(e)) : G
|
|
265
|
+
);
|
|
266
|
+
}, q.jsxs = function(e, t, u) {
|
|
267
|
+
var m = 1e4 > L.recentlyCreatedOwnerStacks++;
|
|
268
|
+
return d(
|
|
269
|
+
e,
|
|
270
|
+
t,
|
|
271
|
+
u,
|
|
272
|
+
!0,
|
|
273
|
+
m ? Error("react-stack-top-frame") : O,
|
|
274
|
+
m ? Y(o(e)) : G
|
|
275
|
+
);
|
|
276
|
+
};
|
|
277
|
+
})()), q;
|
|
278
|
+
}
|
|
279
|
+
var le;
|
|
280
|
+
function Me() {
|
|
281
|
+
return le || (le = 1, process.env.NODE_ENV === "production" ? Z.exports = _e() : Z.exports = we()), Z.exports;
|
|
282
|
+
}
|
|
283
|
+
var R = Me();
|
|
284
|
+
const oe = he((n, g) => ({
|
|
285
|
+
emitters: {},
|
|
286
|
+
registerEmitter: (l, o) => {
|
|
287
|
+
if (g().emitters[l]) {
|
|
288
|
+
console.warn(`Emitter ${l} already exists`);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
n((r) => (r.emitters[l] = o, r));
|
|
292
|
+
},
|
|
293
|
+
unregisterEmitter: (l) => {
|
|
294
|
+
n((o) => (delete o.emitters[l], o));
|
|
295
|
+
},
|
|
296
|
+
emit: (l, ...o) => {
|
|
297
|
+
const r = g().emitters[l];
|
|
298
|
+
if (!r) {
|
|
299
|
+
console.warn(`Emitter ${l} not found`);
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
r(...o);
|
|
303
|
+
}
|
|
304
|
+
}));
|
|
305
|
+
function ue(n, g) {
|
|
306
|
+
return n + Math.floor(Math.random() * (g - n + 1));
|
|
307
|
+
}
|
|
308
|
+
function b(n, g) {
|
|
309
|
+
return n + Math.random() * (g - n);
|
|
310
|
+
}
|
|
311
|
+
const Te = ({ settings: n, onChange: g, onRestart: l }) => {
|
|
312
|
+
ae("⚙️ Emitter Settings", {
|
|
313
|
+
Restart: ie(() => l()),
|
|
314
|
+
Export: ie(() => {
|
|
315
|
+
const c = JSON.stringify(E.current);
|
|
316
|
+
console.log("📋 Values saved to clipboard: ", c), navigator.clipboard.writeText(c);
|
|
317
|
+
})
|
|
318
|
+
});
|
|
319
|
+
const [{ ...o }, r] = ae(() => ({
|
|
320
|
+
"🪄 Emitter": Q({
|
|
321
|
+
duration: 4,
|
|
322
|
+
delay: 0,
|
|
323
|
+
nbParticles: 2e3,
|
|
324
|
+
spawnMode: {
|
|
325
|
+
options: ["time", "burst"],
|
|
326
|
+
value: "time"
|
|
327
|
+
},
|
|
328
|
+
loop: !1,
|
|
329
|
+
startPositionMin: {
|
|
330
|
+
value: [-1, -1, -1],
|
|
331
|
+
min: -10,
|
|
332
|
+
max: 10,
|
|
333
|
+
step: 0.1,
|
|
334
|
+
label: "startPositionMin"
|
|
335
|
+
},
|
|
336
|
+
startPositionMax: {
|
|
337
|
+
value: [1, 1, 1],
|
|
338
|
+
min: -10,
|
|
339
|
+
max: 10,
|
|
340
|
+
step: 0.1,
|
|
341
|
+
label: "startPositionMax"
|
|
342
|
+
},
|
|
343
|
+
startRotationMin: {
|
|
344
|
+
value: [0, 0, 0],
|
|
345
|
+
min: -Math.PI * 2,
|
|
346
|
+
max: Math.PI * 2,
|
|
347
|
+
step: 0.1,
|
|
348
|
+
label: "startRotationMin"
|
|
349
|
+
},
|
|
350
|
+
startRotationMax: {
|
|
351
|
+
value: [0, 0, 0],
|
|
352
|
+
min: -Math.PI * 2,
|
|
353
|
+
max: Math.PI * 2,
|
|
354
|
+
step: 0.1,
|
|
355
|
+
label: "startRotationMax"
|
|
356
|
+
}
|
|
357
|
+
}),
|
|
358
|
+
"✨ Particles": Q({
|
|
359
|
+
particlesLifetime: {
|
|
360
|
+
value: [0.1, 1],
|
|
361
|
+
min: 0,
|
|
362
|
+
max: 10,
|
|
363
|
+
step: 0.1,
|
|
364
|
+
label: "lifetime"
|
|
365
|
+
}
|
|
366
|
+
}),
|
|
367
|
+
"🌪 Forces": Q({
|
|
368
|
+
speed: {
|
|
369
|
+
value: [5, 20],
|
|
370
|
+
min: -100,
|
|
371
|
+
max: 100
|
|
372
|
+
},
|
|
373
|
+
directionMin: {
|
|
374
|
+
value: [-1, -1, -1],
|
|
375
|
+
min: -1,
|
|
376
|
+
max: 1,
|
|
377
|
+
step: 0.1
|
|
378
|
+
},
|
|
379
|
+
directionMax: {
|
|
380
|
+
value: [1, 1, 1],
|
|
381
|
+
min: -1,
|
|
382
|
+
max: 1,
|
|
383
|
+
step: 0.1
|
|
384
|
+
},
|
|
385
|
+
rotationSpeedMin: {
|
|
386
|
+
value: [0, 0, 0],
|
|
387
|
+
min: 0,
|
|
388
|
+
max: 10,
|
|
389
|
+
step: 0.1
|
|
390
|
+
},
|
|
391
|
+
rotationSpeedMax: {
|
|
392
|
+
value: [0, 0, 0],
|
|
393
|
+
min: 0,
|
|
394
|
+
max: 10,
|
|
395
|
+
step: 0.1
|
|
396
|
+
}
|
|
397
|
+
}),
|
|
398
|
+
"🎨 Appearance": Q({
|
|
399
|
+
nbColors: {
|
|
400
|
+
options: [1, 2, 3]
|
|
401
|
+
},
|
|
402
|
+
colorStart: "#ffffff",
|
|
403
|
+
colorEnd: "#ffffff",
|
|
404
|
+
colorStart2: {
|
|
405
|
+
value: "#ff0000",
|
|
406
|
+
render: (c) => c("🎨 Appearance.nbColors") > 1
|
|
407
|
+
},
|
|
408
|
+
colorEnd2: {
|
|
409
|
+
value: "#ffffff",
|
|
410
|
+
render: (c) => c("🎨 Appearance.nbColors") > 1
|
|
411
|
+
},
|
|
412
|
+
colorStart3: {
|
|
413
|
+
value: "#ff0000",
|
|
414
|
+
render: (c) => c("🎨 Appearance.nbColors") > 2
|
|
415
|
+
},
|
|
416
|
+
colorEnd3: {
|
|
417
|
+
value: "#ff0000",
|
|
418
|
+
render: (c) => c("🎨 Appearance.nbColors") > 2
|
|
419
|
+
},
|
|
420
|
+
size: {
|
|
421
|
+
value: [0.01, 1],
|
|
422
|
+
min: 0,
|
|
423
|
+
max: 5,
|
|
424
|
+
step: 0.01,
|
|
425
|
+
label: "size"
|
|
426
|
+
}
|
|
427
|
+
})
|
|
428
|
+
})), a = {
|
|
429
|
+
...o,
|
|
430
|
+
colorStart: [o.colorStart],
|
|
431
|
+
colorEnd: [o.colorEnd]
|
|
432
|
+
};
|
|
433
|
+
delete a.nbColors, delete a.colorStart2, delete a.colorEnd2, delete a.colorStart3, delete a.colorEnd3, o.nbColors > 1 && a.colorStart.push(o.colorStart2), o.nbColors > 1 && a.colorEnd.push(o.colorEnd2), o.nbColors > 2 && a.colorStart.push(o.colorStart3), o.nbColors > 2 && a.colorEnd.push(o.colorEnd3);
|
|
434
|
+
const E = D(a);
|
|
435
|
+
E.current = a, ge(() => {
|
|
436
|
+
var c, M;
|
|
437
|
+
if (n) {
|
|
438
|
+
const P = {
|
|
439
|
+
...n
|
|
440
|
+
};
|
|
441
|
+
for (let d = 0; d < 2; d++)
|
|
442
|
+
((c = n.colorStart) == null ? void 0 : c.length) > d && (P[d === 0 ? "colorStart" : `colorStart${d + 1}`] = n.colorStart[d], P.nbColors = d + 1), ((M = n.colorEnd) == null ? void 0 : M.length) > d && (P[d === 0 ? "colorEnd" : `colorEnd${d + 1}`] = n.colorEnd[d]);
|
|
443
|
+
r({
|
|
444
|
+
...P
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
}, [n]), g(a);
|
|
448
|
+
}, K = new p.Vector3(), ne = new p.Quaternion(), Ce = new p.Euler(), ee = new p.Euler(), Oe = new p.Vector3(), Le = Re(
|
|
449
|
+
({ debug: n = !1, emitter: g, settings: l = {}, ...o }, r) => {
|
|
450
|
+
const [{
|
|
451
|
+
duration: a = 1,
|
|
452
|
+
nParticles: E = 1e3,
|
|
453
|
+
spawnMode: c = "time",
|
|
454
|
+
// time, burst
|
|
455
|
+
loop: M = !1,
|
|
456
|
+
delay: P = 0,
|
|
457
|
+
colorStart: d = ["white", "skyblue"],
|
|
458
|
+
colorEnd: i = [],
|
|
459
|
+
particlesLifetime: x = [0.1, 1],
|
|
460
|
+
speed: s = [5, 20],
|
|
461
|
+
size: y = [0.1, 1],
|
|
462
|
+
startPositionMin: h = [-1, -1, -1],
|
|
463
|
+
startPositionMax: _ = [1, 1, 1],
|
|
464
|
+
startRotationMin: F = [0, 0, 0],
|
|
465
|
+
startRotationMax: z = [0, 0, 0],
|
|
466
|
+
rotationSpeedMin: N = [0, 0, 0],
|
|
467
|
+
rotationSpeedMax: w = [0, 0, 0],
|
|
468
|
+
directionMin: S = [0, 0, 0],
|
|
469
|
+
directionMax: f = [0, 0, 0]
|
|
470
|
+
}, B] = Ee(l), X = oe((U) => U.emit), A = D();
|
|
471
|
+
Pe(r, () => A.current);
|
|
472
|
+
const T = D(0), C = D(0);
|
|
473
|
+
Se(({ clock: U }, Y) => {
|
|
474
|
+
const V = U.elapsedTime;
|
|
475
|
+
if (C.current < E || M) {
|
|
476
|
+
if (!A)
|
|
477
|
+
return;
|
|
478
|
+
const O = (c === "burst" ? E : Math.max(
|
|
479
|
+
0,
|
|
480
|
+
Math.floor(
|
|
481
|
+
(T.current - P) / a * E
|
|
482
|
+
)
|
|
483
|
+
)) - C.current;
|
|
484
|
+
O > 0 && T.current >= P && (X(g, O, () => {
|
|
485
|
+
A.current.updateWorldMatrix(!0), A.current.matrixWorld.decompose(K, ne, Oe), Ce.setFromQuaternion(ne), ee.setFromQuaternion(ne);
|
|
486
|
+
const k = b(y[0], y[1]), e = d[ue(0, d.length - 1)];
|
|
487
|
+
return {
|
|
488
|
+
position: [
|
|
489
|
+
K.x + b(h[0], _[0]),
|
|
490
|
+
K.y + b(h[1], _[1]),
|
|
491
|
+
K.z + b(h[2], _[2])
|
|
492
|
+
],
|
|
493
|
+
direction: [
|
|
494
|
+
b(S[0], f[0]),
|
|
495
|
+
b(S[1], f[1]),
|
|
496
|
+
b(S[2], f[2])
|
|
497
|
+
],
|
|
498
|
+
scale: [k, k, k],
|
|
499
|
+
rotation: [
|
|
500
|
+
ee.x + b(F[0], z[0]),
|
|
501
|
+
ee.y + b(F[1], z[1]),
|
|
502
|
+
ee.z + b(F[2], z[2])
|
|
503
|
+
],
|
|
504
|
+
rotationSpeed: [
|
|
505
|
+
b(N[0], w[0]),
|
|
506
|
+
b(N[1], w[1]),
|
|
507
|
+
b(N[2], w[2])
|
|
508
|
+
],
|
|
509
|
+
lifetime: [
|
|
510
|
+
V,
|
|
511
|
+
b(x[0], x[1])
|
|
512
|
+
],
|
|
513
|
+
colorStart: e,
|
|
514
|
+
colorEnd: i != null && i.length ? i[ue(0, i.length - 1)] : e,
|
|
515
|
+
speed: [b(s[0], s[1])]
|
|
516
|
+
};
|
|
517
|
+
}), C.current += O);
|
|
518
|
+
}
|
|
519
|
+
T.current += Y;
|
|
520
|
+
});
|
|
521
|
+
const L = Ae(() => {
|
|
522
|
+
C.current = 0, T.current = 0;
|
|
523
|
+
}, []), I = be(
|
|
524
|
+
() => n ? /* @__PURE__ */ R.jsx(
|
|
525
|
+
Te,
|
|
526
|
+
{
|
|
527
|
+
settings: l,
|
|
528
|
+
onChange: B,
|
|
529
|
+
onRestart: L
|
|
530
|
+
}
|
|
531
|
+
) : null,
|
|
532
|
+
[n]
|
|
533
|
+
);
|
|
534
|
+
return /* @__PURE__ */ R.jsxs(R.Fragment, { children: [
|
|
535
|
+
I,
|
|
536
|
+
/* @__PURE__ */ R.jsx("object3D", { ...o, ref: A })
|
|
537
|
+
] });
|
|
538
|
+
}
|
|
539
|
+
);
|
|
540
|
+
var ke = `varying vec2 vUv;
|
|
541
|
+
varying vec3 vColor;
|
|
542
|
+
varying vec3 vColorEnd;
|
|
543
|
+
varying float vProgress;
|
|
544
|
+
|
|
545
|
+
uniform float uTime;
|
|
546
|
+
uniform vec2 uFadeSize;
|
|
547
|
+
uniform vec3 uGravity;
|
|
548
|
+
|
|
549
|
+
attribute vec3 instanceColor;
|
|
550
|
+
attribute vec3 instanceColorEnd;
|
|
551
|
+
attribute vec3 instanceDirection;
|
|
552
|
+
attribute vec2 instanceLifetime;
|
|
553
|
+
attribute float instanceSpeed;
|
|
554
|
+
attribute vec3 instanceRotationSpeed;
|
|
555
|
+
|
|
556
|
+
mat4 rotationX(float angle) {
|
|
557
|
+
float s = sin(angle);
|
|
558
|
+
float c = cos(angle);
|
|
559
|
+
return mat4(
|
|
560
|
+
1, 0, 0, 0,
|
|
561
|
+
0, c, -s, 0,
|
|
562
|
+
0, s, c, 0,
|
|
563
|
+
0, 0, 0, 1
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
mat4 rotationY(float angle) {
|
|
568
|
+
float s = sin(angle);
|
|
569
|
+
float c = cos(angle);
|
|
570
|
+
return mat4(
|
|
571
|
+
c, 0, s, 0,
|
|
572
|
+
0, 1, 0, 0,
|
|
573
|
+
-s, 0, c, 0,
|
|
574
|
+
0, 0, 0, 1
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
mat4 rotationZ(float angle) {
|
|
579
|
+
float s = sin(angle);
|
|
580
|
+
float c = cos(angle);
|
|
581
|
+
return mat4(
|
|
582
|
+
c, -s, 0, 0,
|
|
583
|
+
s, c, 0, 0,
|
|
584
|
+
0, 0, 1, 0,
|
|
585
|
+
0, 0, 0, 1
|
|
586
|
+
);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
vec3 billboard(vec2 v, mat4 view) {
|
|
590
|
+
vec3 up = vec3(view[0][1], view[1][1], view[2][1]);
|
|
591
|
+
vec3 right = vec3(view[0][0], view[1][0], view[2][0]);
|
|
592
|
+
vec3 p = right * v.x + up * v.y;
|
|
593
|
+
return p;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
void main() {
|
|
598
|
+
float startTime = instanceLifetime.x;
|
|
599
|
+
float duration = instanceLifetime.y;
|
|
600
|
+
float age = uTime - startTime;
|
|
601
|
+
vProgress = age / duration;
|
|
602
|
+
|
|
603
|
+
if (vProgress < 0.0 || vProgress > 1.0) {
|
|
604
|
+
gl_Position = vec4(vec3(999.9), 1.0);
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
float scale = smoothstep(0.0, uFadeSize.x, vProgress) * smoothstep(1.01, uFadeSize.y, vProgress);
|
|
609
|
+
vec3 gravity = 0.5 * uGravity * (age * age);
|
|
610
|
+
|
|
611
|
+
vec3 normalizedDirection = length(instanceDirection) > 0.0 ? normalize(instanceDirection) : vec3(0.0);
|
|
612
|
+
vec3 offset = normalizedDirection * age * instanceSpeed;
|
|
613
|
+
offset += gravity;
|
|
614
|
+
|
|
615
|
+
vec3 rotationSpeed = instanceRotationSpeed * age;
|
|
616
|
+
mat4 rotY = rotationY(rotationSpeed.y);
|
|
617
|
+
mat4 rotX = rotationX(rotationSpeed.x);
|
|
618
|
+
mat4 rotZ = rotationZ(rotationSpeed.z);
|
|
619
|
+
mat4 rotationMatrix = rotZ * rotX * rotX;
|
|
620
|
+
|
|
621
|
+
vec4 mvPosition;
|
|
622
|
+
#ifdef MESH_MODE
|
|
623
|
+
vec4 startPosition = modelMatrix * instanceMatrix * rotationMatrix * vec4(position * scale , 1.0);
|
|
624
|
+
|
|
625
|
+
vec3 instancePosition = startPosition.xyz;
|
|
626
|
+
|
|
627
|
+
vec3 finalPosition = instancePosition + offset;
|
|
628
|
+
mvPosition = modelViewMatrix * vec4(finalPosition, 1.0);
|
|
629
|
+
#endif
|
|
630
|
+
|
|
631
|
+
#ifdef BILLBOARD_MODE
|
|
632
|
+
vec4 localPos = vec4(position, 1.0);
|
|
633
|
+
localPos.xyz = billboard(position.xy, viewMatrix) * scale;
|
|
634
|
+
|
|
635
|
+
vec4 worldPos = modelMatrix * instanceMatrix * rotationMatrix * localPos;
|
|
636
|
+
worldPos.xyz += offset;
|
|
637
|
+
mvPosition = modelViewMatrix * worldPos;
|
|
638
|
+
#endif
|
|
639
|
+
|
|
640
|
+
gl_Position = projectionMatrix * mvPosition;
|
|
641
|
+
|
|
642
|
+
vUv = uv;
|
|
643
|
+
vColor = instanceColor;
|
|
644
|
+
vColorEnd = instanceColorEnd;
|
|
645
|
+
}`, je = `varying vec2 vUv;
|
|
646
|
+
varying vec3 vColor;
|
|
647
|
+
varying vec3 vColorEnd;
|
|
648
|
+
varying float vProgress;
|
|
649
|
+
|
|
650
|
+
uniform float uIntensity;
|
|
651
|
+
uniform vec2 uFadeAlpha;
|
|
652
|
+
|
|
653
|
+
uniform sampler2D uAlphaMap;
|
|
654
|
+
|
|
655
|
+
void main() {
|
|
656
|
+
if (vProgress < 0.0 || vProgress > 1.0) {
|
|
657
|
+
discard;
|
|
658
|
+
}
|
|
659
|
+
vec3 color = mix(vColor, vColorEnd, vProgress);
|
|
660
|
+
color *= uIntensity;
|
|
661
|
+
|
|
662
|
+
float alpha = smoothstep(0.0, uFadeAlpha.x, vProgress) * smoothstep(1.01, uFadeAlpha.y, vProgress);
|
|
663
|
+
|
|
664
|
+
#ifdef ALPHAMAP
|
|
665
|
+
vec4 tex = texture2D(uAlphaMap, vUv);
|
|
666
|
+
gl_FragColor = vec4(color, tex.a * alpha);
|
|
667
|
+
#else
|
|
668
|
+
gl_FragColor = vec4(color, alpha);
|
|
669
|
+
#endif
|
|
670
|
+
}`;
|
|
671
|
+
const fe = new p.Vector3(), de = new p.Euler(), me = new p.Quaternion(), ve = new p.Vector3(1, 1, 1), pe = new p.Matrix4(), j = new p.Color(), Ie = ({ name: n, settings: g = {}, alphaMap: l, geometry: o }) => {
|
|
672
|
+
const { nParticals: r = 1e3, intensity: a = 1, renderMode: E = "mesh", fadeSize: c = [0.1, 0.9], fadeAlpha: M = [0, 1], gravity: P = [0, 0, 0] } = g, d = new p.PlaneGeometry(), i = D(), [x] = Ee({
|
|
673
|
+
instanceColor: new Float32Array(r * 3),
|
|
674
|
+
instanceColorEnd: new Float32Array(r * 3),
|
|
675
|
+
instanceDirection: new Float32Array(r * 3),
|
|
676
|
+
instanceLifetime: new Float32Array(r * 2),
|
|
677
|
+
instanceSpeed: new Float32Array(r * 1),
|
|
678
|
+
instanceRotationSpeed: new Float32Array(r * 3)
|
|
679
|
+
}), s = D(0), y = D(0), h = D(!1), _ = (S, f) => {
|
|
680
|
+
const B = i.current.geometry.getAttribute("instanceColor"), X = i.current.geometry.getAttribute("instanceColorEnd"), A = i.current.geometry.getAttribute("instanceDirection"), T = i.current.geometry.getAttribute("instanceLifetime"), C = i.current.geometry.getAttribute("instanceSpeed"), L = i.current.geometry.getAttribute(
|
|
681
|
+
"instanceRotationSpeed"
|
|
682
|
+
);
|
|
683
|
+
for (let I = 0; I < S; I++) {
|
|
684
|
+
s.current >= r && (s.current = 0);
|
|
685
|
+
const {
|
|
686
|
+
scale: U,
|
|
687
|
+
rotation: Y,
|
|
688
|
+
rotationSpeed: V,
|
|
689
|
+
position: W,
|
|
690
|
+
direction: O,
|
|
691
|
+
lifetime: G,
|
|
692
|
+
colorStart: k,
|
|
693
|
+
colorEnd: e,
|
|
694
|
+
speed: t
|
|
695
|
+
} = f();
|
|
696
|
+
fe.set(...W), de.set(...Y), me.setFromEuler(de), ve.set(...U), pe.compose(fe, me, ve), j.set(k), j.set(e), A.set(O, s.current * 3), T.set(G, s.current * 2), C.set([t], s.current), L.set(V, s.current * 3), B.set(
|
|
697
|
+
[j.r, j.g, j.b],
|
|
698
|
+
s.current * 3
|
|
699
|
+
), X.set(
|
|
700
|
+
[j.r, j.g, j.b],
|
|
701
|
+
s.current * 3
|
|
702
|
+
), i.current.setMatrixAt(s.current, pe);
|
|
703
|
+
}
|
|
704
|
+
h.current = !0, s.current++, s.current = s.current % r;
|
|
705
|
+
}, F = () => {
|
|
706
|
+
if (!h.current || !i.current)
|
|
707
|
+
return;
|
|
708
|
+
[
|
|
709
|
+
i.current.instanceMatrix,
|
|
710
|
+
i.current.geometry.getAttribute("instanceColor"),
|
|
711
|
+
i.current.geometry.getAttribute("instanceColorEnd"),
|
|
712
|
+
i.current.geometry.getAttribute("instanceDirection"),
|
|
713
|
+
i.current.geometry.getAttribute("instanceLifetime"),
|
|
714
|
+
i.current.geometry.getAttribute("instanceSpeed"),
|
|
715
|
+
i.current.geometry.getAttribute("instanceRotationSpeed")
|
|
716
|
+
].forEach((f) => {
|
|
717
|
+
f.clearUpdateRanges(), y.current > s.current ? (f.addUpdateRange(0, s.current * f.itemSize), f.addUpdateRange(
|
|
718
|
+
y.current * f.itemSize,
|
|
719
|
+
r * f.itemSize - y.current * f.itemSize
|
|
720
|
+
)) : f.addUpdateRange(
|
|
721
|
+
y.current * f.itemSize,
|
|
722
|
+
s.current * f.itemSize - y.current * f.itemSize
|
|
723
|
+
), f.needsUpdate = !0;
|
|
724
|
+
}), y.current = s.current, h.current = !1;
|
|
725
|
+
}, z = oe((S) => S.registerEmitter), N = oe((S) => S.unregisterEmitter);
|
|
726
|
+
ge(() => (z(n, _), () => {
|
|
727
|
+
N(n);
|
|
728
|
+
}), []);
|
|
729
|
+
const w = be(
|
|
730
|
+
() => ({
|
|
731
|
+
uTime: { value: 0 },
|
|
732
|
+
uIntensity: { value: a },
|
|
733
|
+
uFadeSize: { value: c },
|
|
734
|
+
uFadeAlpha: { value: M },
|
|
735
|
+
uGravity: { value: P },
|
|
736
|
+
uAlphaMap: { value: l }
|
|
737
|
+
}),
|
|
738
|
+
[]
|
|
739
|
+
);
|
|
740
|
+
return Se(({ clock: S }) => {
|
|
741
|
+
w && (w.uTime.value = S.elapsedTime);
|
|
742
|
+
}), /* @__PURE__ */ R.jsxs(
|
|
743
|
+
"instancedMesh",
|
|
744
|
+
{
|
|
745
|
+
ref: i,
|
|
746
|
+
args: [d, null, r],
|
|
747
|
+
onBeforeRender: F,
|
|
748
|
+
children: [
|
|
749
|
+
o,
|
|
750
|
+
/* @__PURE__ */ R.jsx(
|
|
751
|
+
"shaderMaterial",
|
|
752
|
+
{
|
|
753
|
+
uniforms: w,
|
|
754
|
+
vertexShader: ke,
|
|
755
|
+
fragmentShader: je,
|
|
756
|
+
blending: p.AdditiveBlending,
|
|
757
|
+
depthTest: !1,
|
|
758
|
+
depthWrite: !1,
|
|
759
|
+
transparent: !0,
|
|
760
|
+
defines: {
|
|
761
|
+
BILLBOARD_MODE: E === "billboard",
|
|
762
|
+
MESH_MODE: E === "mesh",
|
|
763
|
+
ALPHAMAP: !!l
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
),
|
|
767
|
+
/* @__PURE__ */ R.jsx(
|
|
768
|
+
"instancedBufferAttribute",
|
|
769
|
+
{
|
|
770
|
+
attach: "geometry-attributes-instanceColor",
|
|
771
|
+
args: [x.instanceColor],
|
|
772
|
+
itemSize: 3,
|
|
773
|
+
count: r,
|
|
774
|
+
usage: p.DynamicDrawUsage
|
|
775
|
+
}
|
|
776
|
+
),
|
|
777
|
+
/* @__PURE__ */ R.jsx(
|
|
778
|
+
"instancedBufferAttribute",
|
|
779
|
+
{
|
|
780
|
+
attach: "geometry-attributes-instanceColorEnd",
|
|
781
|
+
args: [x.instanceColorEnd],
|
|
782
|
+
itemSize: 3,
|
|
783
|
+
count: r,
|
|
784
|
+
usage: p.DynamicDrawUsage
|
|
785
|
+
}
|
|
786
|
+
),
|
|
787
|
+
/* @__PURE__ */ R.jsx(
|
|
788
|
+
"instancedBufferAttribute",
|
|
789
|
+
{
|
|
790
|
+
attach: "geometry-attributes-instanceDirection",
|
|
791
|
+
args: [x.instanceDirection],
|
|
792
|
+
itemSize: 3,
|
|
793
|
+
count: r,
|
|
794
|
+
usage: p.DynamicDrawUsage
|
|
795
|
+
}
|
|
796
|
+
),
|
|
797
|
+
/* @__PURE__ */ R.jsx(
|
|
798
|
+
"instancedBufferAttribute",
|
|
799
|
+
{
|
|
800
|
+
attach: "geometry-attributes-instanceLifetime",
|
|
801
|
+
args: [x.instanceLifetime],
|
|
802
|
+
itemSize: 2,
|
|
803
|
+
count: r,
|
|
804
|
+
usage: p.DynamicDrawUsage
|
|
805
|
+
}
|
|
806
|
+
),
|
|
807
|
+
/* @__PURE__ */ R.jsx(
|
|
808
|
+
"instancedBufferAttribute",
|
|
809
|
+
{
|
|
810
|
+
attach: "geometry-attributes-instanceSpeed",
|
|
811
|
+
args: [x.instanceSpeed],
|
|
812
|
+
itemSize: 1,
|
|
813
|
+
count: r,
|
|
814
|
+
usage: p.DynamicDrawUsage
|
|
815
|
+
}
|
|
816
|
+
),
|
|
817
|
+
/* @__PURE__ */ R.jsx(
|
|
818
|
+
"instancedBufferAttribute",
|
|
819
|
+
{
|
|
820
|
+
attach: "geometry-attributes-instanceRotationSpeed",
|
|
821
|
+
args: [x.instanceRotationSpeed],
|
|
822
|
+
itemSize: 3,
|
|
823
|
+
count: r,
|
|
824
|
+
usage: p.DynamicDrawUsage
|
|
825
|
+
}
|
|
826
|
+
)
|
|
827
|
+
]
|
|
828
|
+
}
|
|
829
|
+
);
|
|
830
|
+
};
|
|
831
|
+
export {
|
|
832
|
+
Le as VFXEmitter,
|
|
833
|
+
Ie as VFXParticles
|
|
834
|
+
};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
(function(x,u){typeof exports=="object"&&typeof module<"u"?u(exports,require("react"),require("zustand"),require("@react-three/fiber"),require("three"),require("leva")):typeof define=="function"&&define.amd?define(["exports","react","zustand","@react-three/fiber","three","leva"],u):(x=typeof globalThis<"u"?globalThis:x||self,u(x.LazyVFX={},x.React,x.zustand,x.Fiber,x.THREE,x.leva))})(this,(function(x,u,ge,ie,Ee,C){"use strict";function be(n){const d=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(n){for(const a in n)if(a!=="default"){const o=Object.getOwnPropertyDescriptor(n,a);Object.defineProperty(d,a,o.get?o:{enumerable:!0,get:()=>n[a]})}}return d.default=n,Object.freeze(d)}const v=be(Ee);var q={exports:{}},G={};/**
|
|
2
|
+
* @license React
|
|
3
|
+
* react-jsx-runtime.production.js
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
6
|
+
*
|
|
7
|
+
* This source code is licensed under the MIT license found in the
|
|
8
|
+
* LICENSE file in the root directory of this source tree.
|
|
9
|
+
*/var se;function Se(){if(se)return G;se=1;var n=Symbol.for("react.transitional.element"),d=Symbol.for("react.fragment");function a(o,r,i){var S=null;if(i!==void 0&&(S=""+i),r.key!==void 0&&(S=""+r.key),"key"in r){i={};for(var l in r)l!=="key"&&(i[l]=r[l])}else i=r;return r=i.ref,{$$typeof:n,type:o,key:S,ref:r!==void 0?r:null,props:i}}return G.Fragment=d,G.jsx=a,G.jsxs=a,G}var H={};/**
|
|
10
|
+
* @license React
|
|
11
|
+
* react-jsx-runtime.development.js
|
|
12
|
+
*
|
|
13
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
14
|
+
*
|
|
15
|
+
* This source code is licensed under the MIT license found in the
|
|
16
|
+
* LICENSE file in the root directory of this source tree.
|
|
17
|
+
*/var ce;function ye(){return ce||(ce=1,process.env.NODE_ENV!=="production"&&(function(){function n(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===D?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case M:return"Fragment";case L:return"Profiler";case N:return"StrictMode";case m:return"Suspense";case J:return"SuspenseList";case k:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case w:return"Portal";case T:return e.displayName||"Context";case I:return(e._context.displayName||"Context")+".Consumer";case y:var t=e.render;return e=e.displayName,e||(e=t.displayName||t.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case Q:return t=e.displayName||null,t!==null?t:n(e.type)||"Memo";case A:t=e._payload,e=e._init;try{return n(e(t))}catch{}}return null}function d(e){return""+e}function a(e){try{d(e);var t=!1}catch{t=!0}if(t){t=console;var f=t.error,g=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return f.call(t,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",g),d(e)}}function o(e){if(e===M)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===A)return"<...>";try{var t=n(e);return t?"<"+t+">":"<...>"}catch{return"<...>"}}function r(){var e=U.A;return e===null?null:e.getOwner()}function i(){return Error("react-stack-top-frame")}function S(e){if(V.call(e,"key")){var t=Object.getOwnPropertyDescriptor(e,"key").get;if(t&&t.isReactWarning)return!1}return e.key!==void 0}function l(e,t){function f(){B||(B=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",t))}f.isReactWarning=!0,Object.defineProperty(e,"key",{get:f,configurable:!0})}function j(){var e=n(this.type);return Z[e]||(Z[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function _(e,t,f,g,te,oe){var E=f.ref;return e={$$typeof:P,type:e,key:t,props:f,_owner:g},(E!==void 0?E:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:j}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:te}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:oe}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function p(e,t,f,g,te,oe){var E=t.children;if(E!==void 0)if(g)if(Y(E)){for(g=0;g<E.length;g++)s(E[g]);Object.freeze&&Object.freeze(E)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else s(E);if(V.call(t,"key")){E=n(e);var W=Object.keys(t).filter(function(Te){return Te!=="key"});g=0<W.length?"{key: someKey, "+W.join(": ..., ")+": ...}":"{key: someKey}",z[E+g]||(W=0<W.length?"{"+W.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
|
|
18
|
+
let props = %s;
|
|
19
|
+
<%s {...props} />
|
|
20
|
+
React keys must be passed directly to JSX without using spread:
|
|
21
|
+
let props = %s;
|
|
22
|
+
<%s key={someKey} {...props} />`,g,E,W,E),z[E+g]=!0)}if(E=null,f!==void 0&&(a(f),E=""+f),S(t)&&(a(t.key),E=""+t.key),"key"in t){f={};for(var ae in t)ae!=="key"&&(f[ae]=t[ae])}else f=t;return E&&l(f,typeof e=="function"?e.displayName||e.name||"Unknown":e),_(e,E,f,r(),te,oe)}function s(e){h(e)?e._store&&(e._store.validated=1):typeof e=="object"&&e!==null&&e.$$typeof===A&&(e._payload.status==="fulfilled"?h(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function h(e){return typeof e=="object"&&e!==null&&e.$$typeof===P}var c=u,P=Symbol.for("react.transitional.element"),w=Symbol.for("react.portal"),M=Symbol.for("react.fragment"),N=Symbol.for("react.strict_mode"),L=Symbol.for("react.profiler"),I=Symbol.for("react.consumer"),T=Symbol.for("react.context"),y=Symbol.for("react.forward_ref"),m=Symbol.for("react.suspense"),J=Symbol.for("react.suspense_list"),Q=Symbol.for("react.memo"),A=Symbol.for("react.lazy"),k=Symbol.for("react.activity"),D=Symbol.for("react.client.reference"),U=c.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,V=Object.prototype.hasOwnProperty,Y=Array.isArray,X=console.createTask?console.createTask:function(){return null};c={react_stack_bottom_frame:function(e){return e()}};var B,Z={},F=c.react_stack_bottom_frame.bind(c,i)(),K=X(o(i)),z={};H.Fragment=M,H.jsx=function(e,t,f){var g=1e4>U.recentlyCreatedOwnerStacks++;return p(e,t,f,!1,g?Error("react-stack-top-frame"):F,g?X(o(e)):K)},H.jsxs=function(e,t,f){var g=1e4>U.recentlyCreatedOwnerStacks++;return p(e,t,f,!0,g?Error("react-stack-top-frame"):F,g?X(o(e)):K)}})()),H}var le;function xe(){return le||(le=1,process.env.NODE_ENV==="production"?q.exports=Se():q.exports=ye()),q.exports}var R=xe();const re=ge.create((n,d)=>({emitters:{},registerEmitter:(a,o)=>{if(d().emitters[a]){console.warn(`Emitter ${a} already exists`);return}n(r=>(r.emitters[a]=o,r))},unregisterEmitter:a=>{n(o=>(delete o.emitters[a],o))},emit:(a,...o)=>{const r=d().emitters[a];if(!r){console.warn(`Emitter ${a} not found`);return}r(...o)}}));function ue(n,d){return n+Math.floor(Math.random()*(d-n+1))}function b(n,d){return n+Math.random()*(d-n)}const Re=({settings:n,onChange:d,onRestart:a})=>{C.useControls("⚙️ Emitter Settings",{Restart:C.button(()=>a()),Export:C.button(()=>{const l=JSON.stringify(S.current);console.log("📋 Values saved to clipboard: ",l),navigator.clipboard.writeText(l)})});const[{...o},r]=C.useControls(()=>({"🪄 Emitter":C.folder({duration:4,delay:0,nbParticles:2e3,spawnMode:{options:["time","burst"],value:"time"},loop:!1,startPositionMin:{value:[-1,-1,-1],min:-10,max:10,step:.1,label:"startPositionMin"},startPositionMax:{value:[1,1,1],min:-10,max:10,step:.1,label:"startPositionMax"},startRotationMin:{value:[0,0,0],min:-Math.PI*2,max:Math.PI*2,step:.1,label:"startRotationMin"},startRotationMax:{value:[0,0,0],min:-Math.PI*2,max:Math.PI*2,step:.1,label:"startRotationMax"}}),"✨ Particles":C.folder({particlesLifetime:{value:[.1,1],min:0,max:10,step:.1,label:"lifetime"}}),"🌪 Forces":C.folder({speed:{value:[5,20],min:-100,max:100},directionMin:{value:[-1,-1,-1],min:-1,max:1,step:.1},directionMax:{value:[1,1,1],min:-1,max:1,step:.1},rotationSpeedMin:{value:[0,0,0],min:0,max:10,step:.1},rotationSpeedMax:{value:[0,0,0],min:0,max:10,step:.1}}),"🎨 Appearance":C.folder({nbColors:{options:[1,2,3]},colorStart:"#ffffff",colorEnd:"#ffffff",colorStart2:{value:"#ff0000",render:l=>l("🎨 Appearance.nbColors")>1},colorEnd2:{value:"#ffffff",render:l=>l("🎨 Appearance.nbColors")>1},colorStart3:{value:"#ff0000",render:l=>l("🎨 Appearance.nbColors")>2},colorEnd3:{value:"#ff0000",render:l=>l("🎨 Appearance.nbColors")>2},size:{value:[.01,1],min:0,max:5,step:.01,label:"size"}})})),i={...o,colorStart:[o.colorStart],colorEnd:[o.colorEnd]};delete i.nbColors,delete i.colorStart2,delete i.colorEnd2,delete i.colorStart3,delete i.colorEnd3,o.nbColors>1&&i.colorStart.push(o.colorStart2),o.nbColors>1&&i.colorEnd.push(o.colorEnd2),o.nbColors>2&&i.colorStart.push(o.colorStart3),o.nbColors>2&&i.colorEnd.push(o.colorEnd3);const S=u.useRef(i);S.current=i,u.useEffect(()=>{var l,j;if(n){const _={...n};for(let p=0;p<2;p++)((l=n.colorStart)==null?void 0:l.length)>p&&(_[p===0?"colorStart":`colorStart${p+1}`]=n.colorStart[p],_.nbColors=p+1),((j=n.colorEnd)==null?void 0:j.length)>p&&(_[p===0?"colorEnd":`colorEnd${p+1}`]=n.colorEnd[p]);r({..._})}},[n]),d(i)},$=new v.Vector3,ne=new v.Quaternion,he=new v.Euler,ee=new v.Euler,Pe=new v.Vector3,_e=u.forwardRef(({debug:n=!1,emitter:d,settings:a={},...o},r)=>{const[{duration:i=1,nParticles:S=1e3,spawnMode:l="time",loop:j=!1,delay:_=0,colorStart:p=["white","skyblue"],colorEnd:s=[],particlesLifetime:h=[.1,1],speed:c=[5,20],size:P=[.1,1],startPositionMin:w=[-1,-1,-1],startPositionMax:M=[1,1,1],startRotationMin:N=[0,0,0],startRotationMax:L=[0,0,0],rotationSpeedMin:I=[0,0,0],rotationSpeedMax:T=[0,0,0],directionMin:y=[0,0,0],directionMax:m=[0,0,0]},J]=u.useState(a),Q=re(Y=>Y.emit),A=u.useRef();u.useImperativeHandle(r,()=>A.current);const k=u.useRef(0),D=u.useRef(0);ie.useFrame(({clock:Y},X)=>{const B=Y.elapsedTime;if(D.current<S||j){if(!A)return;const F=(l==="burst"?S:Math.max(0,Math.floor((k.current-_)/i*S)))-D.current;F>0&&k.current>=_&&(Q(d,F,()=>{A.current.updateWorldMatrix(!0),A.current.matrixWorld.decompose($,ne,Pe),he.setFromQuaternion(ne),ee.setFromQuaternion(ne);const z=b(P[0],P[1]),e=p[ue(0,p.length-1)];return{position:[$.x+b(w[0],M[0]),$.y+b(w[1],M[1]),$.z+b(w[2],M[2])],direction:[b(y[0],m[0]),b(y[1],m[1]),b(y[2],m[2])],scale:[z,z,z],rotation:[ee.x+b(N[0],L[0]),ee.y+b(N[1],L[1]),ee.z+b(N[2],L[2])],rotationSpeed:[b(I[0],T[0]),b(I[1],T[1]),b(I[2],T[2])],lifetime:[B,b(h[0],h[1])],colorStart:e,colorEnd:s!=null&&s.length?s[ue(0,s.length-1)]:e,speed:[b(c[0],c[1])]}}),D.current+=F)}k.current+=X});const U=u.useCallback(()=>{D.current=0,k.current=0},[]),V=u.useMemo(()=>n?R.jsx(Re,{settings:a,onChange:J,onRestart:U}):null,[n]);return R.jsxs(R.Fragment,{children:[V,R.jsx("object3D",{...o,ref:A})]})});var Ae=`varying vec2 vUv;
|
|
23
|
+
varying vec3 vColor;
|
|
24
|
+
varying vec3 vColorEnd;
|
|
25
|
+
varying float vProgress;
|
|
26
|
+
|
|
27
|
+
uniform float uTime;
|
|
28
|
+
uniform vec2 uFadeSize;
|
|
29
|
+
uniform vec3 uGravity;
|
|
30
|
+
|
|
31
|
+
attribute vec3 instanceColor;
|
|
32
|
+
attribute vec3 instanceColorEnd;
|
|
33
|
+
attribute vec3 instanceDirection;
|
|
34
|
+
attribute vec2 instanceLifetime;
|
|
35
|
+
attribute float instanceSpeed;
|
|
36
|
+
attribute vec3 instanceRotationSpeed;
|
|
37
|
+
|
|
38
|
+
mat4 rotationX(float angle) {
|
|
39
|
+
float s = sin(angle);
|
|
40
|
+
float c = cos(angle);
|
|
41
|
+
return mat4(
|
|
42
|
+
1, 0, 0, 0,
|
|
43
|
+
0, c, -s, 0,
|
|
44
|
+
0, s, c, 0,
|
|
45
|
+
0, 0, 0, 1
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
mat4 rotationY(float angle) {
|
|
50
|
+
float s = sin(angle);
|
|
51
|
+
float c = cos(angle);
|
|
52
|
+
return mat4(
|
|
53
|
+
c, 0, s, 0,
|
|
54
|
+
0, 1, 0, 0,
|
|
55
|
+
-s, 0, c, 0,
|
|
56
|
+
0, 0, 0, 1
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
mat4 rotationZ(float angle) {
|
|
61
|
+
float s = sin(angle);
|
|
62
|
+
float c = cos(angle);
|
|
63
|
+
return mat4(
|
|
64
|
+
c, -s, 0, 0,
|
|
65
|
+
s, c, 0, 0,
|
|
66
|
+
0, 0, 1, 0,
|
|
67
|
+
0, 0, 0, 1
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
vec3 billboard(vec2 v, mat4 view) {
|
|
72
|
+
vec3 up = vec3(view[0][1], view[1][1], view[2][1]);
|
|
73
|
+
vec3 right = vec3(view[0][0], view[1][0], view[2][0]);
|
|
74
|
+
vec3 p = right * v.x + up * v.y;
|
|
75
|
+
return p;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
void main() {
|
|
80
|
+
float startTime = instanceLifetime.x;
|
|
81
|
+
float duration = instanceLifetime.y;
|
|
82
|
+
float age = uTime - startTime;
|
|
83
|
+
vProgress = age / duration;
|
|
84
|
+
|
|
85
|
+
if (vProgress < 0.0 || vProgress > 1.0) {
|
|
86
|
+
gl_Position = vec4(vec3(999.9), 1.0);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
float scale = smoothstep(0.0, uFadeSize.x, vProgress) * smoothstep(1.01, uFadeSize.y, vProgress);
|
|
91
|
+
vec3 gravity = 0.5 * uGravity * (age * age);
|
|
92
|
+
|
|
93
|
+
vec3 normalizedDirection = length(instanceDirection) > 0.0 ? normalize(instanceDirection) : vec3(0.0);
|
|
94
|
+
vec3 offset = normalizedDirection * age * instanceSpeed;
|
|
95
|
+
offset += gravity;
|
|
96
|
+
|
|
97
|
+
vec3 rotationSpeed = instanceRotationSpeed * age;
|
|
98
|
+
mat4 rotY = rotationY(rotationSpeed.y);
|
|
99
|
+
mat4 rotX = rotationX(rotationSpeed.x);
|
|
100
|
+
mat4 rotZ = rotationZ(rotationSpeed.z);
|
|
101
|
+
mat4 rotationMatrix = rotZ * rotX * rotX;
|
|
102
|
+
|
|
103
|
+
vec4 mvPosition;
|
|
104
|
+
#ifdef MESH_MODE
|
|
105
|
+
vec4 startPosition = modelMatrix * instanceMatrix * rotationMatrix * vec4(position * scale , 1.0);
|
|
106
|
+
|
|
107
|
+
vec3 instancePosition = startPosition.xyz;
|
|
108
|
+
|
|
109
|
+
vec3 finalPosition = instancePosition + offset;
|
|
110
|
+
mvPosition = modelViewMatrix * vec4(finalPosition, 1.0);
|
|
111
|
+
#endif
|
|
112
|
+
|
|
113
|
+
#ifdef BILLBOARD_MODE
|
|
114
|
+
vec4 localPos = vec4(position, 1.0);
|
|
115
|
+
localPos.xyz = billboard(position.xy, viewMatrix) * scale;
|
|
116
|
+
|
|
117
|
+
vec4 worldPos = modelMatrix * instanceMatrix * rotationMatrix * localPos;
|
|
118
|
+
worldPos.xyz += offset;
|
|
119
|
+
mvPosition = modelViewMatrix * worldPos;
|
|
120
|
+
#endif
|
|
121
|
+
|
|
122
|
+
gl_Position = projectionMatrix * mvPosition;
|
|
123
|
+
|
|
124
|
+
vUv = uv;
|
|
125
|
+
vColor = instanceColor;
|
|
126
|
+
vColorEnd = instanceColorEnd;
|
|
127
|
+
}`,we=`varying vec2 vUv;
|
|
128
|
+
varying vec3 vColor;
|
|
129
|
+
varying vec3 vColorEnd;
|
|
130
|
+
varying float vProgress;
|
|
131
|
+
|
|
132
|
+
uniform float uIntensity;
|
|
133
|
+
uniform vec2 uFadeAlpha;
|
|
134
|
+
|
|
135
|
+
uniform sampler2D uAlphaMap;
|
|
136
|
+
|
|
137
|
+
void main() {
|
|
138
|
+
if (vProgress < 0.0 || vProgress > 1.0) {
|
|
139
|
+
discard;
|
|
140
|
+
}
|
|
141
|
+
vec3 color = mix(vColor, vColorEnd, vProgress);
|
|
142
|
+
color *= uIntensity;
|
|
143
|
+
|
|
144
|
+
float alpha = smoothstep(0.0, uFadeAlpha.x, vProgress) * smoothstep(1.01, uFadeAlpha.y, vProgress);
|
|
145
|
+
|
|
146
|
+
#ifdef ALPHAMAP
|
|
147
|
+
vec4 tex = texture2D(uAlphaMap, vUv);
|
|
148
|
+
gl_FragColor = vec4(color, tex.a * alpha);
|
|
149
|
+
#else
|
|
150
|
+
gl_FragColor = vec4(color, alpha);
|
|
151
|
+
#endif
|
|
152
|
+
}`;const fe=new v.Vector3,de=new v.Euler,me=new v.Quaternion,ve=new v.Vector3(1,1,1),pe=new v.Matrix4,O=new v.Color,Me=({name:n,settings:d={},alphaMap:a,geometry:o})=>{const{nParticals:r=1e3,intensity:i=1,renderMode:S="mesh",fadeSize:l=[.1,.9],fadeAlpha:j=[0,1],gravity:_=[0,0,0]}=d,p=new v.PlaneGeometry,s=u.useRef(),[h]=u.useState({instanceColor:new Float32Array(r*3),instanceColorEnd:new Float32Array(r*3),instanceDirection:new Float32Array(r*3),instanceLifetime:new Float32Array(r*2),instanceSpeed:new Float32Array(r*1),instanceRotationSpeed:new Float32Array(r*3)}),c=u.useRef(0),P=u.useRef(0),w=u.useRef(!1),M=(y,m)=>{const J=s.current.geometry.getAttribute("instanceColor"),Q=s.current.geometry.getAttribute("instanceColorEnd"),A=s.current.geometry.getAttribute("instanceDirection"),k=s.current.geometry.getAttribute("instanceLifetime"),D=s.current.geometry.getAttribute("instanceSpeed"),U=s.current.geometry.getAttribute("instanceRotationSpeed");for(let V=0;V<y;V++){c.current>=r&&(c.current=0);const{scale:Y,rotation:X,rotationSpeed:B,position:Z,direction:F,lifetime:K,colorStart:z,colorEnd:e,speed:t}=m();fe.set(...Z),de.set(...X),me.setFromEuler(de),ve.set(...Y),pe.compose(fe,me,ve),O.set(z),O.set(e),A.set(F,c.current*3),k.set(K,c.current*2),D.set([t],c.current),U.set(B,c.current*3),J.set([O.r,O.g,O.b],c.current*3),Q.set([O.r,O.g,O.b],c.current*3),s.current.setMatrixAt(c.current,pe)}w.current=!0,c.current++,c.current=c.current%r},N=()=>{if(!w.current||!s.current)return;[s.current.instanceMatrix,s.current.geometry.getAttribute("instanceColor"),s.current.geometry.getAttribute("instanceColorEnd"),s.current.geometry.getAttribute("instanceDirection"),s.current.geometry.getAttribute("instanceLifetime"),s.current.geometry.getAttribute("instanceSpeed"),s.current.geometry.getAttribute("instanceRotationSpeed")].forEach(m=>{m.clearUpdateRanges(),P.current>c.current?(m.addUpdateRange(0,c.current*m.itemSize),m.addUpdateRange(P.current*m.itemSize,r*m.itemSize-P.current*m.itemSize)):m.addUpdateRange(P.current*m.itemSize,c.current*m.itemSize-P.current*m.itemSize),m.needsUpdate=!0}),P.current=c.current,w.current=!1},L=re(y=>y.registerEmitter),I=re(y=>y.unregisterEmitter);u.useEffect(()=>(L(n,M),()=>{I(n)}),[]);const T=u.useMemo(()=>({uTime:{value:0},uIntensity:{value:i},uFadeSize:{value:l},uFadeAlpha:{value:j},uGravity:{value:_},uAlphaMap:{value:a}}),[]);return ie.useFrame(({clock:y})=>{T&&(T.uTime.value=y.elapsedTime)}),R.jsxs("instancedMesh",{ref:s,args:[p,null,r],onBeforeRender:N,children:[o,R.jsx("shaderMaterial",{uniforms:T,vertexShader:Ae,fragmentShader:we,blending:v.AdditiveBlending,depthTest:!1,depthWrite:!1,transparent:!0,defines:{BILLBOARD_MODE:S==="billboard",MESH_MODE:S==="mesh",ALPHAMAP:!!a}}),R.jsx("instancedBufferAttribute",{attach:"geometry-attributes-instanceColor",args:[h.instanceColor],itemSize:3,count:r,usage:v.DynamicDrawUsage}),R.jsx("instancedBufferAttribute",{attach:"geometry-attributes-instanceColorEnd",args:[h.instanceColorEnd],itemSize:3,count:r,usage:v.DynamicDrawUsage}),R.jsx("instancedBufferAttribute",{attach:"geometry-attributes-instanceDirection",args:[h.instanceDirection],itemSize:3,count:r,usage:v.DynamicDrawUsage}),R.jsx("instancedBufferAttribute",{attach:"geometry-attributes-instanceLifetime",args:[h.instanceLifetime],itemSize:2,count:r,usage:v.DynamicDrawUsage}),R.jsx("instancedBufferAttribute",{attach:"geometry-attributes-instanceSpeed",args:[h.instanceSpeed],itemSize:1,count:r,usage:v.DynamicDrawUsage}),R.jsx("instancedBufferAttribute",{attach:"geometry-attributes-instanceRotationSpeed",args:[h.instanceRotationSpeed],itemSize:3,count:r,usage:v.DynamicDrawUsage})]})};x.VFXEmitter=_e,x.VFXParticles=Me,Object.defineProperty(x,Symbol.toStringTag,{value:"Module"})}));
|
package/dist/vite.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lazy-vfx",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Effortless high-end visual effects for React and Three.js",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react",
|
|
7
|
+
"three",
|
|
8
|
+
"react-three-fiber",
|
|
9
|
+
"r3f",
|
|
10
|
+
"vfx",
|
|
11
|
+
"particles",
|
|
12
|
+
"shaders",
|
|
13
|
+
"glsl",
|
|
14
|
+
"motion-design"
|
|
15
|
+
],
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "./dist/lazy-vfx.umd.js",
|
|
18
|
+
"module": "./dist/lazy-vfx.es.js",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"import": "./dist/lazy-vfx.es.js",
|
|
22
|
+
"require": "./dist/lazy-vfx.umd.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"dev": "vite",
|
|
30
|
+
"build": "vite build",
|
|
31
|
+
"preview": "vite preview",
|
|
32
|
+
"prepublishOnly": "pnpm build"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"react": ">=18.0.0",
|
|
36
|
+
"react-dom": ">=18.0.0",
|
|
37
|
+
"three": ">=0.150.0",
|
|
38
|
+
"@react-three/fiber": ">=8.0.0",
|
|
39
|
+
"@react-three/drei": ">=9.0.0"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@react-three/postprocessing": "^3.0.4",
|
|
43
|
+
"leva": "^0.10.1",
|
|
44
|
+
"zustand": "^5.0.12"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@react-three/drei": "^10.7.7",
|
|
48
|
+
"@react-three/fiber": "^9.5.0",
|
|
49
|
+
"@types/react": "^19.0.10",
|
|
50
|
+
"@types/react-dom": "^19.0.4",
|
|
51
|
+
"@vitejs/plugin-react": "^4.3.4",
|
|
52
|
+
"globals": "^15.15.0",
|
|
53
|
+
"react": "^19.0.0",
|
|
54
|
+
"react-dom": "^19.0.0",
|
|
55
|
+
"three": "^0.183.2",
|
|
56
|
+
"vite": "^6.2.0",
|
|
57
|
+
"vite-plugin-glsl": "^1.5.6",
|
|
58
|
+
"path": "^0.12.7"
|
|
59
|
+
},
|
|
60
|
+
"author": "Sameer Khan",
|
|
61
|
+
"license": "MIT"
|
|
62
|
+
}
|