react-smokey-fluid-cursor 2.1.0 → 2.2.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 +6 -0
- package/dist/index.d.mts +3 -376
- package/dist/index.d.ts +3 -376
- package/dist/index.js +1 -194
- package/dist/index.mjs +1 -194
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -81,6 +81,12 @@ bun add react-smokey-fluid-cursor
|
|
|
81
81
|
|
|
82
82
|
**Peer dependencies:** `react >= 17`, `react-dom >= 17`.
|
|
83
83
|
|
|
84
|
+
The WebGL engine comes from
|
|
85
|
+
[`smokey-fluid-cursor`](https://github.com/faraasat/smokey-fluid-cursor), which
|
|
86
|
+
is installed automatically as a dependency. This package is the React binding
|
|
87
|
+
for it — everything that package exports (`initFluid`, `presets`, the types) is
|
|
88
|
+
re-exported here, so you never need to import both.
|
|
89
|
+
|
|
84
90
|
## Quick start
|
|
85
91
|
|
|
86
92
|
```tsx
|
package/dist/index.d.mts
CHANGED
|
@@ -1,379 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* This file defines the foundational TypeScript interfaces
|
|
5
|
-
* and type aliases used throughout the Smokey Fluid simulation engine.
|
|
6
|
-
*
|
|
7
|
-
* It abstracts WebGL object types (FBOs, textures, uniforms, etc.)
|
|
8
|
-
* to provide clear, type-safe contracts for interacting with GPU resources.
|
|
9
|
-
*
|
|
10
|
-
* Developers integrating or extending this package should primarily
|
|
11
|
-
* adjust configuration options defined in `ISmokeyFluidConfig`.
|
|
12
|
-
*/
|
|
13
|
-
/**
|
|
14
|
-
* Generic alias for either WebGL1 or WebGL2 rendering contexts.
|
|
15
|
-
*
|
|
16
|
-
* - WebGLRenderingContext → legacy WebGL1 API
|
|
17
|
-
* - WebGL2RenderingContext → modern API with extended texture formats and MRT support
|
|
18
|
-
*
|
|
19
|
-
* This alias allows code to remain compatible across both WebGL versions.
|
|
20
|
-
*/
|
|
21
|
-
type GL = WebGLRenderingContext | WebGL2RenderingContext;
|
|
22
|
-
/**
|
|
23
|
-
* Describes a format pair used for texture or renderbuffer configuration.
|
|
24
|
-
*
|
|
25
|
-
* - `internalFormat`: how GPU stores the texture internally (e.g., RGBA16F)
|
|
26
|
-
* - `format`: how the data is laid out when uploading pixels (e.g., RGBA)
|
|
27
|
-
*
|
|
28
|
-
* Used for compatibility mapping between WebGL1 and WebGL2.
|
|
29
|
-
*/
|
|
30
|
-
interface GLFormat {
|
|
31
|
-
internalFormat: number;
|
|
32
|
-
format: number;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Represents detected WebGL extension and format capabilities
|
|
36
|
-
* for the current context. This allows the engine to dynamically
|
|
37
|
-
* choose the optimal texture formats and filtering modes.
|
|
38
|
-
*
|
|
39
|
-
* Usually populated at initialization after checking for extensions like:
|
|
40
|
-
* - OES_texture_half_float
|
|
41
|
-
* - OES_texture_float_linear
|
|
42
|
-
* - EXT_color_buffer_float
|
|
43
|
-
*/
|
|
44
|
-
interface GLExtInfo {
|
|
45
|
-
/** Supported RGBA floating-point texture format */
|
|
46
|
-
formatRGBA: GLFormat | null;
|
|
47
|
-
/** Supported RG (two-channel) texture format (WebGL2 only) */
|
|
48
|
-
formatRG: GLFormat | null;
|
|
49
|
-
/** Supported R (single-channel) texture format (WebGL2 only) */
|
|
50
|
-
formatR: GLFormat | null;
|
|
51
|
-
/** GL constant for HALF_FLOAT type (e.g., gl.HALF_FLOAT_OES) */
|
|
52
|
-
halfFloatTexType: number;
|
|
53
|
-
/** Whether linear filtering (smooth interpolation) for float textures is available */
|
|
54
|
-
supportLinearFiltering: boolean;
|
|
55
|
-
/** True if running on WebGL2 (vs WebGL1 + extensions) */
|
|
56
|
-
isWebGL2: boolean;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Framebuffer Object (FBO) descriptor — wraps a texture and its framebuffer target.
|
|
60
|
-
*
|
|
61
|
-
* Each FBO represents a GPU render target that can store color or data fields
|
|
62
|
-
* (such as velocity, pressure, or density in fluid simulation).
|
|
63
|
-
*/
|
|
64
|
-
interface FBO {
|
|
65
|
-
/** GPU texture attached to the framebuffer */
|
|
66
|
-
texture: WebGLTexture | null;
|
|
67
|
-
/** The framebuffer object itself */
|
|
68
|
-
fbo: WebGLFramebuffer | null;
|
|
69
|
-
/** Width of the texture in pixels */
|
|
70
|
-
width: number;
|
|
71
|
-
/** Height of the texture in pixels */
|
|
72
|
-
height: number;
|
|
73
|
-
/** Normalized texel size (1 / width) */
|
|
74
|
-
texelSizeX: number;
|
|
75
|
-
/** Normalized texel size (1 / height) */
|
|
76
|
-
texelSizeY: number;
|
|
77
|
-
/**
|
|
78
|
-
* Binds this FBO's texture to a given texture unit (slot).
|
|
79
|
-
* Returns the bound texture unit index for convenience.
|
|
80
|
-
*
|
|
81
|
-
* Example:
|
|
82
|
-
* ```ts
|
|
83
|
-
* const unit = velocityFBO.attach(0); // binds to TEXTURE0
|
|
84
|
-
* gl.uniform1i(uniforms.uVelocity, unit);
|
|
85
|
-
* ```
|
|
86
|
-
*/
|
|
87
|
-
attach(id: number): number;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Represents a double-buffered framebuffer system.
|
|
91
|
-
*
|
|
92
|
-
* Used heavily in fluid simulations to "ping-pong" between two framebuffers:
|
|
93
|
-
* - One for reading previous state
|
|
94
|
-
* - One for writing the next frame
|
|
95
|
-
*
|
|
96
|
-
* After each simulation step, `swap()` is called to exchange them.
|
|
97
|
-
*/
|
|
98
|
-
interface DoubleFBO {
|
|
99
|
-
/** Buffer width in pixels */
|
|
100
|
-
width: number;
|
|
101
|
-
/** Buffer height in pixels */
|
|
102
|
-
height: number;
|
|
103
|
-
/** Normalized texel size (1 / width) */
|
|
104
|
-
texelSizeX: number;
|
|
105
|
-
/** Normalized texel size (1 / height) */
|
|
106
|
-
texelSizeY: number;
|
|
107
|
-
/** Framebuffer currently used for reading */
|
|
108
|
-
read: FBO;
|
|
109
|
-
/** Framebuffer currently used for writing */
|
|
110
|
-
write: FBO;
|
|
111
|
-
/** Swaps read/write buffers for next iteration */
|
|
112
|
-
swap(): void;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* ---------------------------------------------------------
|
|
116
|
-
* 🔧 Smokey Fluid Configuration
|
|
117
|
-
* ---------------------------------------------------------
|
|
118
|
-
*
|
|
119
|
-
* This interface defines **all configurable simulation parameters**
|
|
120
|
-
* that can be customized externally (e.g., by UI, app settings, or user code).
|
|
121
|
-
*
|
|
122
|
-
* Each property controls a different aspect of the fluid’s physics,
|
|
123
|
-
* rendering behavior, or visual appearance.
|
|
124
|
-
*/
|
|
125
|
-
interface ISmokeyFluidConfig {
|
|
126
|
-
/** Simulation grid resolution for velocity/pressure fields (lower = faster but coarser) */
|
|
127
|
-
simResolution: number;
|
|
128
|
-
/** Visual color/dye buffer resolution (affects rendering detail) */
|
|
129
|
-
dyeResolution: number;
|
|
130
|
-
/** Resolution used for high-quality screenshots or recording */
|
|
131
|
-
captureResolution: number;
|
|
132
|
-
/** Rate at which color fades from the fluid (higher = faster fade) */
|
|
133
|
-
densityDissipation: number;
|
|
134
|
-
/** Rate at which velocity energy dissipates (higher = faster slowdown) */
|
|
135
|
-
velocityDissipation: number;
|
|
136
|
-
/** Initial pressure clear multiplier (affects stability of solver) */
|
|
137
|
-
pressure: number;
|
|
138
|
-
/** Number of Jacobi iterations when solving pressure (higher = more accurate but slower) */
|
|
139
|
-
pressureIteration: number;
|
|
140
|
-
/** Strength of vorticity confinement (adds swirling, curl-like motion) */
|
|
141
|
-
curl: number;
|
|
142
|
-
/** Base normalized radius of user splats (0–1 range relative to screen size) */
|
|
143
|
-
splatRadius: number;
|
|
144
|
-
/** Force multiplier applied when user interacts (e.g., mouse/touch input) */
|
|
145
|
-
splatForce: number;
|
|
146
|
-
/** Enable or disable lighting/shading effects for visual depth */
|
|
147
|
-
shading: boolean;
|
|
148
|
-
/** Speed at which the dynamic color palette rotates during simulation */
|
|
149
|
-
colorUpdateSpeed: number;
|
|
150
|
-
/** If true, pauses the main simulation loop (used for debugging or static rendering) */
|
|
151
|
-
paused: boolean;
|
|
152
|
-
/**
|
|
153
|
-
* Canvas background color (can be in 0–1 normalized range or 0–255)
|
|
154
|
-
* Example: `{ r: 0, g: 0, b: 0 }` for black.
|
|
155
|
-
*/
|
|
156
|
-
backColor: {
|
|
157
|
-
r: number;
|
|
158
|
-
g: number;
|
|
159
|
-
b: number;
|
|
160
|
-
};
|
|
161
|
-
/**
|
|
162
|
-
* Determines whether the canvas should preserve alpha transparency.
|
|
163
|
-
* If `true`, blending with HTML backgrounds is allowed.
|
|
164
|
-
*/
|
|
165
|
-
transparent: boolean;
|
|
166
|
-
/**
|
|
167
|
-
* ID assigned to the canvas element.
|
|
168
|
-
* Default is "smokey-fluid-canvas".
|
|
169
|
-
*/
|
|
170
|
-
id: string;
|
|
171
|
-
/**
|
|
172
|
-
* An existing canvas to render into — an element, or a CSS selector.
|
|
173
|
-
*
|
|
174
|
-
* Takes precedence over `id` and `container`. Use this when the canvas is
|
|
175
|
-
* already part of your markup or managed by a framework.
|
|
176
|
-
*/
|
|
177
|
-
canvas?: HTMLCanvasElement | string | null;
|
|
178
|
-
/**
|
|
179
|
-
* Element (or CSS selector) to create the canvas inside, when no canvas
|
|
180
|
-
* matches `canvas`/`id` yet.
|
|
181
|
-
*
|
|
182
|
-
* Defaults to `document.body`, which with `position: "fixed"` gives the
|
|
183
|
-
* classic full-viewport effect. Point it at a section to scope the effect
|
|
184
|
-
* to just that area.
|
|
185
|
-
*/
|
|
186
|
-
container?: HTMLElement | string | null;
|
|
187
|
-
/**
|
|
188
|
-
* CSS position for the canvas. Use `"absolute"` to confine the effect to a
|
|
189
|
-
* positioned container; `"fixed"` covers the viewport. Default `"fixed"`.
|
|
190
|
-
*/
|
|
191
|
-
position: "fixed" | "absolute" | "static" | "relative";
|
|
192
|
-
/** Stacking order of the canvas. Default `-9999` (behind page content). */
|
|
193
|
-
zIndex: number;
|
|
194
|
-
/**
|
|
195
|
-
* Whether the canvas receives pointer events. Default `false`, so clicks
|
|
196
|
-
* pass straight through to your UI.
|
|
197
|
-
*/
|
|
198
|
-
pointerEvents: boolean;
|
|
199
|
-
/** Extra class name applied to the canvas element. */
|
|
200
|
-
className?: string;
|
|
201
|
-
/**
|
|
202
|
-
* Upper bound on the device pixel ratio used for the render buffers.
|
|
203
|
-
*
|
|
204
|
-
* Default `2`. Uncapped, a 3x phone renders nine times the pixels of a 1x
|
|
205
|
-
* display for a purely decorative effect, which drains battery and drops
|
|
206
|
-
* frame rate.
|
|
207
|
-
*/
|
|
208
|
-
maxDpr: number;
|
|
209
|
-
/**
|
|
210
|
-
* Pause the simulation while the page is hidden (background tab). Default
|
|
211
|
-
* `true` — an invisible animation should not burn CPU or battery.
|
|
212
|
-
*/
|
|
213
|
-
pauseOnHidden: boolean;
|
|
214
|
-
/**
|
|
215
|
-
* Honour the `prefers-reduced-motion` media query. When the visitor has
|
|
216
|
-
* asked for reduced motion the simulation starts paused. Default `true`.
|
|
217
|
-
*/
|
|
218
|
-
respectReducedMotion: boolean;
|
|
219
|
-
/**
|
|
220
|
-
* Colour palette for the fluid, as CSS hex strings (e.g. `["#ff4ecd"]`).
|
|
221
|
-
*
|
|
222
|
-
* When omitted, colours are generated randomly across the full hue range,
|
|
223
|
-
* which is the original behaviour.
|
|
224
|
-
*/
|
|
225
|
-
palette?: string[] | null;
|
|
226
|
-
/**
|
|
227
|
-
* Brightness multiplier applied to generated colours. Default `0.15`;
|
|
228
|
-
* raise it for a more saturated, higher-contrast trail.
|
|
229
|
-
*/
|
|
230
|
-
colorIntensity: number;
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Controls returned by {@link initFluid}.
|
|
234
|
-
*/
|
|
235
|
-
interface FluidHandle {
|
|
236
|
-
/** Stop the render loop, detach listeners and release the GL context. */
|
|
237
|
-
dispose(): void;
|
|
238
|
-
/** Pause the simulation, leaving the canvas in place. */
|
|
239
|
-
pause(): void;
|
|
240
|
-
/** Resume after {@link FluidHandle.pause}. */
|
|
241
|
-
resume(): void;
|
|
242
|
-
/** Whether the simulation is currently paused. */
|
|
243
|
-
isPaused(): boolean;
|
|
244
|
-
/**
|
|
245
|
-
* Update tunable options in place, without tearing the simulation down.
|
|
246
|
-
*
|
|
247
|
-
* Resolution options (`simResolution`, `dyeResolution`) reallocate the
|
|
248
|
-
* framebuffers; everything else applies on the next frame.
|
|
249
|
-
*/
|
|
250
|
-
setConfig(partial: Partial<ISmokeyFluidConfig>): void;
|
|
251
|
-
/**
|
|
252
|
-
* Inject a splash at a point, in CSS pixels relative to the canvas.
|
|
253
|
-
* Useful for driving the effect from something other than the pointer.
|
|
254
|
-
*/
|
|
255
|
-
splat(x: number, y: number, color?: {
|
|
256
|
-
r: number;
|
|
257
|
-
g: number;
|
|
258
|
-
b: number;
|
|
259
|
-
}): void;
|
|
260
|
-
/** The canvas being rendered into. */
|
|
261
|
-
readonly canvas: HTMLCanvasElement | null;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Initializes and starts the fluid simulation
|
|
266
|
-
* @param incomingConfig - Partial configuration object to override default settings
|
|
267
|
-
*/
|
|
268
|
-
declare const initFluid: (incomingConfig?: Partial<ISmokeyFluidConfig>) => FluidHandle;
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* A named, ready-made configuration.
|
|
272
|
-
*
|
|
273
|
-
* Presets only set appearance and physics — never mounting or placement — so
|
|
274
|
-
* they compose with whatever `canvas`, `container` or `zIndex` you pass.
|
|
275
|
-
*/
|
|
276
|
-
type Preset = Pick<Partial<ISmokeyFluidConfig>, "palette" | "colorIntensity" | "colorUpdateSpeed" | "curl" | "splatForce" | "splatRadius" | "densityDissipation" | "velocityDissipation" | "pressure" | "pressureIteration" | "shading">;
|
|
277
|
-
/**
|
|
278
|
-
* The colour side of a preset.
|
|
279
|
-
*
|
|
280
|
-
* `null` means "no palette": hues are generated across the full spectrum,
|
|
281
|
-
* which is the library's default behaviour.
|
|
282
|
-
*/
|
|
283
|
-
declare const palettes: {
|
|
284
|
-
readonly Spectrum: null;
|
|
285
|
-
readonly Sunset: readonly ["#ff4ecd", "#ff8a4e", "#ffd24e"];
|
|
286
|
-
readonly Ocean: readonly ["#4ea8ff", "#4effd2", "#7c4dff"];
|
|
287
|
-
readonly Mono: readonly ["#ffffff"];
|
|
288
|
-
readonly Aurora: readonly ["#3affa3", "#38d9ff", "#8f7bff"];
|
|
289
|
-
readonly Ember: readonly ["#ff5722", "#ff9100", "#ffc400"];
|
|
290
|
-
readonly Lagoon: readonly ["#00c2a8", "#00a3ff", "#0057d9"];
|
|
291
|
-
readonly Candy: readonly ["#ff8fd0", "#ffa9f0", "#c79bff"];
|
|
292
|
-
readonly Toxic: readonly ["#b6ff00", "#4dff88", "#00ffc8"];
|
|
293
|
-
readonly Royal: readonly ["#5b2bff", "#8f4dff", "#c44dff"];
|
|
294
|
-
readonly Sakura: readonly ["#ffc2dd", "#ff8fb1", "#ff6f91"];
|
|
295
|
-
readonly Mint: readonly ["#9cffd6", "#5ef2c0", "#2fd6a5"];
|
|
296
|
-
readonly Copper: readonly ["#ff9a5a", "#e2703a", "#b34700"];
|
|
297
|
-
readonly Ultraviolet: readonly ["#7b2cff", "#b429ff", "#ff29f0"];
|
|
298
|
-
readonly Ice: readonly ["#c9f0ff", "#8ad4ff", "#4fb3ff"];
|
|
299
|
-
readonly Magma: readonly ["#ff2d2d", "#ff6a00", "#ffb300"];
|
|
300
|
-
readonly Forest: readonly ["#2f9e44", "#69db7c", "#a9e34b"];
|
|
301
|
-
readonly Dusk: readonly ["#3b3b98", "#7158e2", "#cd84f1"];
|
|
302
|
-
readonly Cyber: readonly ["#00fff0", "#ff00e0", "#fffb00"];
|
|
303
|
-
readonly Pastel: readonly ["#ffd6e0", "#c7ceea", "#b5ead7"];
|
|
304
|
-
};
|
|
305
|
-
/**
|
|
306
|
-
* The motion side of a preset — how the fluid moves, independent of colour.
|
|
307
|
-
*/
|
|
308
|
-
declare const characters: {
|
|
309
|
-
readonly Calm: {
|
|
310
|
-
readonly curl: 3;
|
|
311
|
-
readonly splatForce: 4200;
|
|
312
|
-
readonly splatRadius: 0.45;
|
|
313
|
-
readonly densityDissipation: 4.6;
|
|
314
|
-
readonly velocityDissipation: 2.6;
|
|
315
|
-
readonly pressureIteration: 16;
|
|
316
|
-
readonly colorUpdateSpeed: 6;
|
|
317
|
-
};
|
|
318
|
-
readonly Flow: {
|
|
319
|
-
readonly curl: 10;
|
|
320
|
-
readonly splatForce: 6000;
|
|
321
|
-
readonly splatRadius: 0.5;
|
|
322
|
-
readonly densityDissipation: 3.5;
|
|
323
|
-
readonly velocityDissipation: 2;
|
|
324
|
-
readonly pressureIteration: 20;
|
|
325
|
-
readonly colorUpdateSpeed: 10;
|
|
326
|
-
};
|
|
327
|
-
readonly Swirl: {
|
|
328
|
-
readonly curl: 24;
|
|
329
|
-
readonly splatForce: 7200;
|
|
330
|
-
readonly splatRadius: 0.55;
|
|
331
|
-
readonly densityDissipation: 3;
|
|
332
|
-
readonly velocityDissipation: 1.6;
|
|
333
|
-
readonly pressureIteration: 24;
|
|
334
|
-
readonly colorUpdateSpeed: 12;
|
|
335
|
-
};
|
|
336
|
-
readonly Storm: {
|
|
337
|
-
readonly curl: 40;
|
|
338
|
-
readonly splatForce: 9500;
|
|
339
|
-
readonly splatRadius: 0.65;
|
|
340
|
-
readonly densityDissipation: 2.2;
|
|
341
|
-
readonly velocityDissipation: 1.2;
|
|
342
|
-
readonly pressureIteration: 28;
|
|
343
|
-
readonly colorUpdateSpeed: 16;
|
|
344
|
-
};
|
|
345
|
-
readonly Wisp: {
|
|
346
|
-
readonly curl: 6;
|
|
347
|
-
readonly splatForce: 3200;
|
|
348
|
-
readonly splatRadius: 0.32;
|
|
349
|
-
readonly densityDissipation: 6.5;
|
|
350
|
-
readonly velocityDissipation: 3.4;
|
|
351
|
-
readonly pressureIteration: 12;
|
|
352
|
-
readonly colorUpdateSpeed: 8;
|
|
353
|
-
};
|
|
354
|
-
};
|
|
355
|
-
type PaletteName = keyof typeof palettes;
|
|
356
|
-
type CharacterName = keyof typeof characters;
|
|
357
|
-
type PresetName = `${PaletteName} ${CharacterName}`;
|
|
358
|
-
/**
|
|
359
|
-
* 100 ready-made looks: every colour palette crossed with every motion
|
|
360
|
-
* character, named `"<Palette> <Character>"` — e.g. `"Ocean Swirl"`.
|
|
361
|
-
*
|
|
362
|
-
* ```ts
|
|
363
|
-
* import { initFluid, presets } from "smokey-fluid-cursor";
|
|
364
|
-
*
|
|
365
|
-
* initFluid(presets["Ocean Swirl"]);
|
|
366
|
-
* ```
|
|
367
|
-
*/
|
|
368
|
-
declare const presets: Record<PresetName, Preset>;
|
|
369
|
-
/** Every preset name, in definition order. */
|
|
370
|
-
declare const presetNames: PresetName[];
|
|
371
|
-
/** The palette names presets are built from. */
|
|
372
|
-
declare const paletteNames: PaletteName[];
|
|
373
|
-
/** The motion characters presets are built from. */
|
|
374
|
-
declare const characterNames: CharacterName[];
|
|
375
|
-
/** Looks up a preset by name, returning `undefined` when it does not exist. */
|
|
376
|
-
declare const getPreset: (name: string) => Preset | undefined;
|
|
2
|
+
import { ISmokeyFluidConfig, FluidHandle } from 'smokey-fluid-cursor';
|
|
3
|
+
export { CharacterName, DoubleFBO, FBO, FluidHandle, GL, GLExtInfo, ISmokeyFluidConfig, PaletteName, Preset, PresetName, characterNames, getPreset, initFluid, paletteNames, presetNames, presets } from 'smokey-fluid-cursor';
|
|
377
4
|
|
|
378
5
|
interface SmokeyFluidCursorProps {
|
|
379
6
|
/** Simulation options. See ISmokeyFluidConfig. */
|
|
@@ -406,4 +33,4 @@ declare function useSmokeyFluidCursor(config?: Partial<ISmokeyFluidConfig>, cont
|
|
|
406
33
|
*/
|
|
407
34
|
declare const SmokeyFluidCursor: React.ForwardRefExoticComponent<SmokeyFluidCursorProps & React.RefAttributes<FluidHandle>>;
|
|
408
35
|
|
|
409
|
-
export {
|
|
36
|
+
export { SmokeyFluidCursor, type SmokeyFluidCursorProps, useSmokeyFluidCursor };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,379 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* This file defines the foundational TypeScript interfaces
|
|
5
|
-
* and type aliases used throughout the Smokey Fluid simulation engine.
|
|
6
|
-
*
|
|
7
|
-
* It abstracts WebGL object types (FBOs, textures, uniforms, etc.)
|
|
8
|
-
* to provide clear, type-safe contracts for interacting with GPU resources.
|
|
9
|
-
*
|
|
10
|
-
* Developers integrating or extending this package should primarily
|
|
11
|
-
* adjust configuration options defined in `ISmokeyFluidConfig`.
|
|
12
|
-
*/
|
|
13
|
-
/**
|
|
14
|
-
* Generic alias for either WebGL1 or WebGL2 rendering contexts.
|
|
15
|
-
*
|
|
16
|
-
* - WebGLRenderingContext → legacy WebGL1 API
|
|
17
|
-
* - WebGL2RenderingContext → modern API with extended texture formats and MRT support
|
|
18
|
-
*
|
|
19
|
-
* This alias allows code to remain compatible across both WebGL versions.
|
|
20
|
-
*/
|
|
21
|
-
type GL = WebGLRenderingContext | WebGL2RenderingContext;
|
|
22
|
-
/**
|
|
23
|
-
* Describes a format pair used for texture or renderbuffer configuration.
|
|
24
|
-
*
|
|
25
|
-
* - `internalFormat`: how GPU stores the texture internally (e.g., RGBA16F)
|
|
26
|
-
* - `format`: how the data is laid out when uploading pixels (e.g., RGBA)
|
|
27
|
-
*
|
|
28
|
-
* Used for compatibility mapping between WebGL1 and WebGL2.
|
|
29
|
-
*/
|
|
30
|
-
interface GLFormat {
|
|
31
|
-
internalFormat: number;
|
|
32
|
-
format: number;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Represents detected WebGL extension and format capabilities
|
|
36
|
-
* for the current context. This allows the engine to dynamically
|
|
37
|
-
* choose the optimal texture formats and filtering modes.
|
|
38
|
-
*
|
|
39
|
-
* Usually populated at initialization after checking for extensions like:
|
|
40
|
-
* - OES_texture_half_float
|
|
41
|
-
* - OES_texture_float_linear
|
|
42
|
-
* - EXT_color_buffer_float
|
|
43
|
-
*/
|
|
44
|
-
interface GLExtInfo {
|
|
45
|
-
/** Supported RGBA floating-point texture format */
|
|
46
|
-
formatRGBA: GLFormat | null;
|
|
47
|
-
/** Supported RG (two-channel) texture format (WebGL2 only) */
|
|
48
|
-
formatRG: GLFormat | null;
|
|
49
|
-
/** Supported R (single-channel) texture format (WebGL2 only) */
|
|
50
|
-
formatR: GLFormat | null;
|
|
51
|
-
/** GL constant for HALF_FLOAT type (e.g., gl.HALF_FLOAT_OES) */
|
|
52
|
-
halfFloatTexType: number;
|
|
53
|
-
/** Whether linear filtering (smooth interpolation) for float textures is available */
|
|
54
|
-
supportLinearFiltering: boolean;
|
|
55
|
-
/** True if running on WebGL2 (vs WebGL1 + extensions) */
|
|
56
|
-
isWebGL2: boolean;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Framebuffer Object (FBO) descriptor — wraps a texture and its framebuffer target.
|
|
60
|
-
*
|
|
61
|
-
* Each FBO represents a GPU render target that can store color or data fields
|
|
62
|
-
* (such as velocity, pressure, or density in fluid simulation).
|
|
63
|
-
*/
|
|
64
|
-
interface FBO {
|
|
65
|
-
/** GPU texture attached to the framebuffer */
|
|
66
|
-
texture: WebGLTexture | null;
|
|
67
|
-
/** The framebuffer object itself */
|
|
68
|
-
fbo: WebGLFramebuffer | null;
|
|
69
|
-
/** Width of the texture in pixels */
|
|
70
|
-
width: number;
|
|
71
|
-
/** Height of the texture in pixels */
|
|
72
|
-
height: number;
|
|
73
|
-
/** Normalized texel size (1 / width) */
|
|
74
|
-
texelSizeX: number;
|
|
75
|
-
/** Normalized texel size (1 / height) */
|
|
76
|
-
texelSizeY: number;
|
|
77
|
-
/**
|
|
78
|
-
* Binds this FBO's texture to a given texture unit (slot).
|
|
79
|
-
* Returns the bound texture unit index for convenience.
|
|
80
|
-
*
|
|
81
|
-
* Example:
|
|
82
|
-
* ```ts
|
|
83
|
-
* const unit = velocityFBO.attach(0); // binds to TEXTURE0
|
|
84
|
-
* gl.uniform1i(uniforms.uVelocity, unit);
|
|
85
|
-
* ```
|
|
86
|
-
*/
|
|
87
|
-
attach(id: number): number;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Represents a double-buffered framebuffer system.
|
|
91
|
-
*
|
|
92
|
-
* Used heavily in fluid simulations to "ping-pong" between two framebuffers:
|
|
93
|
-
* - One for reading previous state
|
|
94
|
-
* - One for writing the next frame
|
|
95
|
-
*
|
|
96
|
-
* After each simulation step, `swap()` is called to exchange them.
|
|
97
|
-
*/
|
|
98
|
-
interface DoubleFBO {
|
|
99
|
-
/** Buffer width in pixels */
|
|
100
|
-
width: number;
|
|
101
|
-
/** Buffer height in pixels */
|
|
102
|
-
height: number;
|
|
103
|
-
/** Normalized texel size (1 / width) */
|
|
104
|
-
texelSizeX: number;
|
|
105
|
-
/** Normalized texel size (1 / height) */
|
|
106
|
-
texelSizeY: number;
|
|
107
|
-
/** Framebuffer currently used for reading */
|
|
108
|
-
read: FBO;
|
|
109
|
-
/** Framebuffer currently used for writing */
|
|
110
|
-
write: FBO;
|
|
111
|
-
/** Swaps read/write buffers for next iteration */
|
|
112
|
-
swap(): void;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* ---------------------------------------------------------
|
|
116
|
-
* 🔧 Smokey Fluid Configuration
|
|
117
|
-
* ---------------------------------------------------------
|
|
118
|
-
*
|
|
119
|
-
* This interface defines **all configurable simulation parameters**
|
|
120
|
-
* that can be customized externally (e.g., by UI, app settings, or user code).
|
|
121
|
-
*
|
|
122
|
-
* Each property controls a different aspect of the fluid’s physics,
|
|
123
|
-
* rendering behavior, or visual appearance.
|
|
124
|
-
*/
|
|
125
|
-
interface ISmokeyFluidConfig {
|
|
126
|
-
/** Simulation grid resolution for velocity/pressure fields (lower = faster but coarser) */
|
|
127
|
-
simResolution: number;
|
|
128
|
-
/** Visual color/dye buffer resolution (affects rendering detail) */
|
|
129
|
-
dyeResolution: number;
|
|
130
|
-
/** Resolution used for high-quality screenshots or recording */
|
|
131
|
-
captureResolution: number;
|
|
132
|
-
/** Rate at which color fades from the fluid (higher = faster fade) */
|
|
133
|
-
densityDissipation: number;
|
|
134
|
-
/** Rate at which velocity energy dissipates (higher = faster slowdown) */
|
|
135
|
-
velocityDissipation: number;
|
|
136
|
-
/** Initial pressure clear multiplier (affects stability of solver) */
|
|
137
|
-
pressure: number;
|
|
138
|
-
/** Number of Jacobi iterations when solving pressure (higher = more accurate but slower) */
|
|
139
|
-
pressureIteration: number;
|
|
140
|
-
/** Strength of vorticity confinement (adds swirling, curl-like motion) */
|
|
141
|
-
curl: number;
|
|
142
|
-
/** Base normalized radius of user splats (0–1 range relative to screen size) */
|
|
143
|
-
splatRadius: number;
|
|
144
|
-
/** Force multiplier applied when user interacts (e.g., mouse/touch input) */
|
|
145
|
-
splatForce: number;
|
|
146
|
-
/** Enable or disable lighting/shading effects for visual depth */
|
|
147
|
-
shading: boolean;
|
|
148
|
-
/** Speed at which the dynamic color palette rotates during simulation */
|
|
149
|
-
colorUpdateSpeed: number;
|
|
150
|
-
/** If true, pauses the main simulation loop (used for debugging or static rendering) */
|
|
151
|
-
paused: boolean;
|
|
152
|
-
/**
|
|
153
|
-
* Canvas background color (can be in 0–1 normalized range or 0–255)
|
|
154
|
-
* Example: `{ r: 0, g: 0, b: 0 }` for black.
|
|
155
|
-
*/
|
|
156
|
-
backColor: {
|
|
157
|
-
r: number;
|
|
158
|
-
g: number;
|
|
159
|
-
b: number;
|
|
160
|
-
};
|
|
161
|
-
/**
|
|
162
|
-
* Determines whether the canvas should preserve alpha transparency.
|
|
163
|
-
* If `true`, blending with HTML backgrounds is allowed.
|
|
164
|
-
*/
|
|
165
|
-
transparent: boolean;
|
|
166
|
-
/**
|
|
167
|
-
* ID assigned to the canvas element.
|
|
168
|
-
* Default is "smokey-fluid-canvas".
|
|
169
|
-
*/
|
|
170
|
-
id: string;
|
|
171
|
-
/**
|
|
172
|
-
* An existing canvas to render into — an element, or a CSS selector.
|
|
173
|
-
*
|
|
174
|
-
* Takes precedence over `id` and `container`. Use this when the canvas is
|
|
175
|
-
* already part of your markup or managed by a framework.
|
|
176
|
-
*/
|
|
177
|
-
canvas?: HTMLCanvasElement | string | null;
|
|
178
|
-
/**
|
|
179
|
-
* Element (or CSS selector) to create the canvas inside, when no canvas
|
|
180
|
-
* matches `canvas`/`id` yet.
|
|
181
|
-
*
|
|
182
|
-
* Defaults to `document.body`, which with `position: "fixed"` gives the
|
|
183
|
-
* classic full-viewport effect. Point it at a section to scope the effect
|
|
184
|
-
* to just that area.
|
|
185
|
-
*/
|
|
186
|
-
container?: HTMLElement | string | null;
|
|
187
|
-
/**
|
|
188
|
-
* CSS position for the canvas. Use `"absolute"` to confine the effect to a
|
|
189
|
-
* positioned container; `"fixed"` covers the viewport. Default `"fixed"`.
|
|
190
|
-
*/
|
|
191
|
-
position: "fixed" | "absolute" | "static" | "relative";
|
|
192
|
-
/** Stacking order of the canvas. Default `-9999` (behind page content). */
|
|
193
|
-
zIndex: number;
|
|
194
|
-
/**
|
|
195
|
-
* Whether the canvas receives pointer events. Default `false`, so clicks
|
|
196
|
-
* pass straight through to your UI.
|
|
197
|
-
*/
|
|
198
|
-
pointerEvents: boolean;
|
|
199
|
-
/** Extra class name applied to the canvas element. */
|
|
200
|
-
className?: string;
|
|
201
|
-
/**
|
|
202
|
-
* Upper bound on the device pixel ratio used for the render buffers.
|
|
203
|
-
*
|
|
204
|
-
* Default `2`. Uncapped, a 3x phone renders nine times the pixels of a 1x
|
|
205
|
-
* display for a purely decorative effect, which drains battery and drops
|
|
206
|
-
* frame rate.
|
|
207
|
-
*/
|
|
208
|
-
maxDpr: number;
|
|
209
|
-
/**
|
|
210
|
-
* Pause the simulation while the page is hidden (background tab). Default
|
|
211
|
-
* `true` — an invisible animation should not burn CPU or battery.
|
|
212
|
-
*/
|
|
213
|
-
pauseOnHidden: boolean;
|
|
214
|
-
/**
|
|
215
|
-
* Honour the `prefers-reduced-motion` media query. When the visitor has
|
|
216
|
-
* asked for reduced motion the simulation starts paused. Default `true`.
|
|
217
|
-
*/
|
|
218
|
-
respectReducedMotion: boolean;
|
|
219
|
-
/**
|
|
220
|
-
* Colour palette for the fluid, as CSS hex strings (e.g. `["#ff4ecd"]`).
|
|
221
|
-
*
|
|
222
|
-
* When omitted, colours are generated randomly across the full hue range,
|
|
223
|
-
* which is the original behaviour.
|
|
224
|
-
*/
|
|
225
|
-
palette?: string[] | null;
|
|
226
|
-
/**
|
|
227
|
-
* Brightness multiplier applied to generated colours. Default `0.15`;
|
|
228
|
-
* raise it for a more saturated, higher-contrast trail.
|
|
229
|
-
*/
|
|
230
|
-
colorIntensity: number;
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Controls returned by {@link initFluid}.
|
|
234
|
-
*/
|
|
235
|
-
interface FluidHandle {
|
|
236
|
-
/** Stop the render loop, detach listeners and release the GL context. */
|
|
237
|
-
dispose(): void;
|
|
238
|
-
/** Pause the simulation, leaving the canvas in place. */
|
|
239
|
-
pause(): void;
|
|
240
|
-
/** Resume after {@link FluidHandle.pause}. */
|
|
241
|
-
resume(): void;
|
|
242
|
-
/** Whether the simulation is currently paused. */
|
|
243
|
-
isPaused(): boolean;
|
|
244
|
-
/**
|
|
245
|
-
* Update tunable options in place, without tearing the simulation down.
|
|
246
|
-
*
|
|
247
|
-
* Resolution options (`simResolution`, `dyeResolution`) reallocate the
|
|
248
|
-
* framebuffers; everything else applies on the next frame.
|
|
249
|
-
*/
|
|
250
|
-
setConfig(partial: Partial<ISmokeyFluidConfig>): void;
|
|
251
|
-
/**
|
|
252
|
-
* Inject a splash at a point, in CSS pixels relative to the canvas.
|
|
253
|
-
* Useful for driving the effect from something other than the pointer.
|
|
254
|
-
*/
|
|
255
|
-
splat(x: number, y: number, color?: {
|
|
256
|
-
r: number;
|
|
257
|
-
g: number;
|
|
258
|
-
b: number;
|
|
259
|
-
}): void;
|
|
260
|
-
/** The canvas being rendered into. */
|
|
261
|
-
readonly canvas: HTMLCanvasElement | null;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Initializes and starts the fluid simulation
|
|
266
|
-
* @param incomingConfig - Partial configuration object to override default settings
|
|
267
|
-
*/
|
|
268
|
-
declare const initFluid: (incomingConfig?: Partial<ISmokeyFluidConfig>) => FluidHandle;
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* A named, ready-made configuration.
|
|
272
|
-
*
|
|
273
|
-
* Presets only set appearance and physics — never mounting or placement — so
|
|
274
|
-
* they compose with whatever `canvas`, `container` or `zIndex` you pass.
|
|
275
|
-
*/
|
|
276
|
-
type Preset = Pick<Partial<ISmokeyFluidConfig>, "palette" | "colorIntensity" | "colorUpdateSpeed" | "curl" | "splatForce" | "splatRadius" | "densityDissipation" | "velocityDissipation" | "pressure" | "pressureIteration" | "shading">;
|
|
277
|
-
/**
|
|
278
|
-
* The colour side of a preset.
|
|
279
|
-
*
|
|
280
|
-
* `null` means "no palette": hues are generated across the full spectrum,
|
|
281
|
-
* which is the library's default behaviour.
|
|
282
|
-
*/
|
|
283
|
-
declare const palettes: {
|
|
284
|
-
readonly Spectrum: null;
|
|
285
|
-
readonly Sunset: readonly ["#ff4ecd", "#ff8a4e", "#ffd24e"];
|
|
286
|
-
readonly Ocean: readonly ["#4ea8ff", "#4effd2", "#7c4dff"];
|
|
287
|
-
readonly Mono: readonly ["#ffffff"];
|
|
288
|
-
readonly Aurora: readonly ["#3affa3", "#38d9ff", "#8f7bff"];
|
|
289
|
-
readonly Ember: readonly ["#ff5722", "#ff9100", "#ffc400"];
|
|
290
|
-
readonly Lagoon: readonly ["#00c2a8", "#00a3ff", "#0057d9"];
|
|
291
|
-
readonly Candy: readonly ["#ff8fd0", "#ffa9f0", "#c79bff"];
|
|
292
|
-
readonly Toxic: readonly ["#b6ff00", "#4dff88", "#00ffc8"];
|
|
293
|
-
readonly Royal: readonly ["#5b2bff", "#8f4dff", "#c44dff"];
|
|
294
|
-
readonly Sakura: readonly ["#ffc2dd", "#ff8fb1", "#ff6f91"];
|
|
295
|
-
readonly Mint: readonly ["#9cffd6", "#5ef2c0", "#2fd6a5"];
|
|
296
|
-
readonly Copper: readonly ["#ff9a5a", "#e2703a", "#b34700"];
|
|
297
|
-
readonly Ultraviolet: readonly ["#7b2cff", "#b429ff", "#ff29f0"];
|
|
298
|
-
readonly Ice: readonly ["#c9f0ff", "#8ad4ff", "#4fb3ff"];
|
|
299
|
-
readonly Magma: readonly ["#ff2d2d", "#ff6a00", "#ffb300"];
|
|
300
|
-
readonly Forest: readonly ["#2f9e44", "#69db7c", "#a9e34b"];
|
|
301
|
-
readonly Dusk: readonly ["#3b3b98", "#7158e2", "#cd84f1"];
|
|
302
|
-
readonly Cyber: readonly ["#00fff0", "#ff00e0", "#fffb00"];
|
|
303
|
-
readonly Pastel: readonly ["#ffd6e0", "#c7ceea", "#b5ead7"];
|
|
304
|
-
};
|
|
305
|
-
/**
|
|
306
|
-
* The motion side of a preset — how the fluid moves, independent of colour.
|
|
307
|
-
*/
|
|
308
|
-
declare const characters: {
|
|
309
|
-
readonly Calm: {
|
|
310
|
-
readonly curl: 3;
|
|
311
|
-
readonly splatForce: 4200;
|
|
312
|
-
readonly splatRadius: 0.45;
|
|
313
|
-
readonly densityDissipation: 4.6;
|
|
314
|
-
readonly velocityDissipation: 2.6;
|
|
315
|
-
readonly pressureIteration: 16;
|
|
316
|
-
readonly colorUpdateSpeed: 6;
|
|
317
|
-
};
|
|
318
|
-
readonly Flow: {
|
|
319
|
-
readonly curl: 10;
|
|
320
|
-
readonly splatForce: 6000;
|
|
321
|
-
readonly splatRadius: 0.5;
|
|
322
|
-
readonly densityDissipation: 3.5;
|
|
323
|
-
readonly velocityDissipation: 2;
|
|
324
|
-
readonly pressureIteration: 20;
|
|
325
|
-
readonly colorUpdateSpeed: 10;
|
|
326
|
-
};
|
|
327
|
-
readonly Swirl: {
|
|
328
|
-
readonly curl: 24;
|
|
329
|
-
readonly splatForce: 7200;
|
|
330
|
-
readonly splatRadius: 0.55;
|
|
331
|
-
readonly densityDissipation: 3;
|
|
332
|
-
readonly velocityDissipation: 1.6;
|
|
333
|
-
readonly pressureIteration: 24;
|
|
334
|
-
readonly colorUpdateSpeed: 12;
|
|
335
|
-
};
|
|
336
|
-
readonly Storm: {
|
|
337
|
-
readonly curl: 40;
|
|
338
|
-
readonly splatForce: 9500;
|
|
339
|
-
readonly splatRadius: 0.65;
|
|
340
|
-
readonly densityDissipation: 2.2;
|
|
341
|
-
readonly velocityDissipation: 1.2;
|
|
342
|
-
readonly pressureIteration: 28;
|
|
343
|
-
readonly colorUpdateSpeed: 16;
|
|
344
|
-
};
|
|
345
|
-
readonly Wisp: {
|
|
346
|
-
readonly curl: 6;
|
|
347
|
-
readonly splatForce: 3200;
|
|
348
|
-
readonly splatRadius: 0.32;
|
|
349
|
-
readonly densityDissipation: 6.5;
|
|
350
|
-
readonly velocityDissipation: 3.4;
|
|
351
|
-
readonly pressureIteration: 12;
|
|
352
|
-
readonly colorUpdateSpeed: 8;
|
|
353
|
-
};
|
|
354
|
-
};
|
|
355
|
-
type PaletteName = keyof typeof palettes;
|
|
356
|
-
type CharacterName = keyof typeof characters;
|
|
357
|
-
type PresetName = `${PaletteName} ${CharacterName}`;
|
|
358
|
-
/**
|
|
359
|
-
* 100 ready-made looks: every colour palette crossed with every motion
|
|
360
|
-
* character, named `"<Palette> <Character>"` — e.g. `"Ocean Swirl"`.
|
|
361
|
-
*
|
|
362
|
-
* ```ts
|
|
363
|
-
* import { initFluid, presets } from "smokey-fluid-cursor";
|
|
364
|
-
*
|
|
365
|
-
* initFluid(presets["Ocean Swirl"]);
|
|
366
|
-
* ```
|
|
367
|
-
*/
|
|
368
|
-
declare const presets: Record<PresetName, Preset>;
|
|
369
|
-
/** Every preset name, in definition order. */
|
|
370
|
-
declare const presetNames: PresetName[];
|
|
371
|
-
/** The palette names presets are built from. */
|
|
372
|
-
declare const paletteNames: PaletteName[];
|
|
373
|
-
/** The motion characters presets are built from. */
|
|
374
|
-
declare const characterNames: CharacterName[];
|
|
375
|
-
/** Looks up a preset by name, returning `undefined` when it does not exist. */
|
|
376
|
-
declare const getPreset: (name: string) => Preset | undefined;
|
|
2
|
+
import { ISmokeyFluidConfig, FluidHandle } from 'smokey-fluid-cursor';
|
|
3
|
+
export { CharacterName, DoubleFBO, FBO, FluidHandle, GL, GLExtInfo, ISmokeyFluidConfig, PaletteName, Preset, PresetName, characterNames, getPreset, initFluid, paletteNames, presetNames, presets } from 'smokey-fluid-cursor';
|
|
377
4
|
|
|
378
5
|
interface SmokeyFluidCursorProps {
|
|
379
6
|
/** Simulation options. See ISmokeyFluidConfig. */
|
|
@@ -406,4 +33,4 @@ declare function useSmokeyFluidCursor(config?: Partial<ISmokeyFluidConfig>, cont
|
|
|
406
33
|
*/
|
|
407
34
|
declare const SmokeyFluidCursor: React.ForwardRefExoticComponent<SmokeyFluidCursorProps & React.RefAttributes<FluidHandle>>;
|
|
408
35
|
|
|
409
|
-
export {
|
|
36
|
+
export { SmokeyFluidCursor, type SmokeyFluidCursorProps, useSmokeyFluidCursor };
|
package/dist/index.js
CHANGED
|
@@ -1,195 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
"use strict";var
|
|
3
|
-
Move the background to <html>, or give the canvas a zIndex above your background.`)},Lt=()=>typeof window!="undefined"&&typeof window.matchMedia=="function"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,ue={dispose:()=>{},pause:()=>{},resume:()=>{},isPaused:()=>!0,setConfig:()=>{},splat:()=>{},canvas:null},ce=(a={})=>{var Ce,_e,Be;let i={...Ft,...a};if(typeof document=="undefined")return ue;let m=!1,u=(Ce=Ue(i.canvas))!=null?Ce:document.getElementById(i.id);if(!u){let e=(_e=Ue(i.container))!=null?_e:document.body;if(!e)return ue;u=document.createElement("canvas"),u.id=i.id,e.appendChild(u),m=!0}i.className&&u.classList.add(...i.className.split(/\s+/));let g=i.position==="fixed"||i.position==="absolute";Object.assign(u.style,{position:i.position,...g?{top:"0",left:"0",width:"100%",height:"100%"}:{},display:"block",pointerEvents:i.pointerEvents?"auto":"none",zIndex:String(i.zIndex)}),Dt(i.zIndex),N();class S{constructor(){this.id=-1;this.texcoordX=0;this.texcoordY=0;this.prevTexcoordX=0;this.prevTexcoordY=0;this.deltaX=0;this.deltaY=0;this.down=!1;this.moved=!1;this.color=[30,0,300]}}let R=[];R.push(new S);let t,h;try{({gl:t,ext:h}=v(u))}catch(e){typeof console!="undefined"&&console.warn("[smokey-fluid-cursor] WebGL is unavailable; the cursor effect is disabled.",e);let r=u,n=m;return{...ue,dispose:()=>{n&&r.remove()},setConfig:o=>{o.zIndex!==void 0&&(r.style.zIndex=String(o.zIndex)),o.pointerEvents!==void 0&&(r.style.pointerEvents=o.pointerEvents?"auto":"none")},get canvas(){return r}}}h.supportLinearFiltering||(i.dyeResolution=512,i.shading=!1);function v(e){let r={alpha:!0,depth:!1,stencil:!1,antialias:!1,preserveDrawingBuffer:!1},n=e.getContext("webgl2",r),o=!!n;if(o||(n=e.getContext("webgl",r)||e.getContext("experimental-webgl",r)),!n)throw new Error("WebGL not supported");let s=null,l,c;if(o){let d=n;d.getExtension("EXT_color_buffer_float"),l=!!d.getExtension("OES_texture_float_linear"),c=d.HALF_FLOAT}else{let d=n;if(s=d.getExtension("OES_texture_half_float"),l=!!d.getExtension("OES_texture_half_float_linear"),!s)throw new Error("OES_texture_half_float not supported on WebGL1");c=s.HALF_FLOAT_OES}n.clearColor(0,0,0,1);let p=null,b=null,C=null;if(o){let d=n;p=x(d,d.RGBA16F,d.RGBA,c),b=x(d,d.RG16F,d.RG,c),C=x(d,d.R16F,d.RED,c)}else{let d=n;p=x(d,d.RGBA,d.RGBA,c),b=x(d,d.RGBA,d.RGBA,c),C=x(d,d.RGBA,d.RGBA,c)}return{gl:n,ext:{formatRGBA:p,formatRG:b,formatR:C,halfFloatTexType:c,supportLinearFiltering:l,isWebGL2:o}}}function x(e,r,n,o){if(!$(e,r,n,o)){if(e.RGBA16F!==void 0){let s=e;switch(r){case s.R16F:return x(s,s.RG16F,s.RG,o);case s.RG16F:return x(s,s.RGBA16F,s.RGBA,o);default:return null}}return null}return{internalFormat:r,format:n}}function $(e,r,n,o){let s=e.createTexture();if(!s)return!1;e.bindTexture(e.TEXTURE_2D,s),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texImage2D(e.TEXTURE_2D,0,r,4,4,0,n,o,null);let l=e.createFramebuffer();if(!l)return!1;e.bindFramebuffer(e.FRAMEBUFFER,l),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,s,0);let c=e.checkFramebufferStatus(e.FRAMEBUFFER);return e.bindFramebuffer(e.FRAMEBUFFER,null),e.deleteFramebuffer(l),e.deleteTexture(s),c===e.FRAMEBUFFER_COMPLETE}class z{constructor(r,n){this.vertexShader=r,this.fragmentShaderSource=n,this.programs={},this.activeProgram=null,this.uniforms={}}setKeywords(r){let n=0;for(let s=0;s<r.length;s++)n+=vt(r[s]);let o=this.programs[n];if(!o){let s=D(t,t.FRAGMENT_SHADER,de(this.fragmentShaderSource,r));o=le(t,this.vertexShader,s),this.programs[n]=o}o!==this.activeProgram&&(this.uniforms=fe(t,o),this.activeProgram=o)}bind(){this.activeProgram&&t.useProgram(this.activeProgram)}}class P{constructor(r,n){this.program=le(t,r,n),this.uniforms=fe(t,this.program)}bind(){this.program&&t.useProgram(this.program)}}function le(e,r,n){let o=e.createProgram();return e.attachShader(o,r),e.attachShader(o,n),e.bindAttribLocation(o,0,"aPosition"),e.linkProgram(o),e.getProgramParameter(o,e.LINK_STATUS)||console.trace(e.getProgramInfoLog(o)),o}function fe(e,r){let n={},o=e.getProgramParameter(r,e.ACTIVE_UNIFORMS);for(let s=0;s<o;s++){let l=e.getActiveUniform(r,s);if(!l)continue;let c=l.name,p=e.getUniformLocation(r,c);p&&(n[c]=p)}return n}function D(e,r,n){let o=e.createShader(r);return e.shaderSource(o,n),e.compileShader(o),e.getShaderParameter(o,e.COMPILE_STATUS)||console.trace(e.getShaderInfoLog(o)),o}function de(e,r){if(!r||r.length===0)return e;let n="";return r.forEach(o=>{n+="#define "+o+`
|
|
4
|
-
`}),n+e}let w=D(t,t.VERTEX_SHADER,`precision highp float;
|
|
5
|
-
attribute vec2 aPosition;
|
|
6
|
-
varying vec2 vUv;
|
|
7
|
-
varying vec2 vL;
|
|
8
|
-
varying vec2 vR;
|
|
9
|
-
varying vec2 vT;
|
|
10
|
-
varying vec2 vB;
|
|
11
|
-
uniform vec2 texelSize;
|
|
12
|
-
void main () {
|
|
13
|
-
vUv = aPosition * 0.5 + 0.5;
|
|
14
|
-
vL = vUv - vec2(texelSize.x, 0.0);
|
|
15
|
-
vR = vUv + vec2(texelSize.x, 0.0);
|
|
16
|
-
vT = vUv + vec2(0.0, texelSize.y);
|
|
17
|
-
vB = vUv - vec2(0.0, texelSize.y);
|
|
18
|
-
gl_Position = vec4(aPosition, 0.0, 1.0);
|
|
19
|
-
}`),He=D(t,t.FRAGMENT_SHADER,`precision mediump float;
|
|
20
|
-
precision mediump sampler2D;
|
|
21
|
-
varying highp vec2 vUv;
|
|
22
|
-
uniform sampler2D uTexture;
|
|
23
|
-
void main () {
|
|
24
|
-
gl_FragColor = texture2D(uTexture, vUv);
|
|
25
|
-
}`),Ye=D(t,t.FRAGMENT_SHADER,`precision mediump float;
|
|
26
|
-
precision mediump sampler2D;
|
|
27
|
-
varying highp vec2 vUv;
|
|
28
|
-
uniform sampler2D uTexture;
|
|
29
|
-
uniform float value;
|
|
30
|
-
void main () {
|
|
31
|
-
gl_FragColor = value * texture2D(uTexture, vUv);
|
|
32
|
-
}`),We=`precision highp float;
|
|
33
|
-
precision highp sampler2D;
|
|
34
|
-
varying vec2 vUv;
|
|
35
|
-
varying vec2 vL;
|
|
36
|
-
varying vec2 vR;
|
|
37
|
-
varying vec2 vT;
|
|
38
|
-
varying vec2 vB;
|
|
39
|
-
uniform sampler2D uTexture;
|
|
40
|
-
uniform vec2 texelSize;
|
|
41
|
-
void main () {
|
|
42
|
-
vec3 c = texture2D(uTexture, vUv).rgb;
|
|
43
|
-
#ifdef shading
|
|
44
|
-
vec3 lc = texture2D(uTexture, vL).rgb;
|
|
45
|
-
vec3 rc = texture2D(uTexture, vR).rgb;
|
|
46
|
-
vec3 tc = texture2D(uTexture, vT).rgb;
|
|
47
|
-
vec3 bc = texture2D(uTexture, vB).rgb;
|
|
48
|
-
float dx = length(rc) - length(lc);
|
|
49
|
-
float dy = length(tc) - length(bc);
|
|
50
|
-
vec3 n = normalize(vec3(dx, dy, length(texelSize)));
|
|
51
|
-
vec3 l = vec3(0.0, 0.0, 1.0);
|
|
52
|
-
float diffuse = clamp(dot(n, l) + 0.7, 0.7, 1.0);
|
|
53
|
-
c *= diffuse;
|
|
54
|
-
#endif
|
|
55
|
-
float a = max(c.r, max(c.g, c.b));
|
|
56
|
-
gl_FragColor = vec4(c, a);
|
|
57
|
-
}`,Ve=D(t,t.FRAGMENT_SHADER,`precision highp float;
|
|
58
|
-
precision highp sampler2D;
|
|
59
|
-
varying vec2 vUv;
|
|
60
|
-
uniform sampler2D uTarget;
|
|
61
|
-
uniform float aspectRatio;
|
|
62
|
-
uniform vec3 color;
|
|
63
|
-
uniform vec2 point;
|
|
64
|
-
uniform float radius;
|
|
65
|
-
void main () {
|
|
66
|
-
vec2 p = vUv - point.xy;
|
|
67
|
-
p.x *= aspectRatio;
|
|
68
|
-
vec3 splat = exp(-dot(p, p) / radius) * color;
|
|
69
|
-
vec3 base = texture2D(uTarget, vUv).xyz;
|
|
70
|
-
gl_FragColor = vec4(base + splat, 1.0);
|
|
71
|
-
}`),je=D(t,t.FRAGMENT_SHADER,de(`precision highp float;
|
|
72
|
-
precision highp sampler2D;
|
|
73
|
-
varying vec2 vUv;
|
|
74
|
-
uniform sampler2D uVelocity;
|
|
75
|
-
uniform sampler2D uSource;
|
|
76
|
-
uniform vec2 texelSize;
|
|
77
|
-
uniform vec2 dyeTexelSize;
|
|
78
|
-
uniform float dt;
|
|
79
|
-
uniform float dissipation;
|
|
80
|
-
vec4 bilerp (sampler2D sam, vec2 uv, vec2 tsize) {
|
|
81
|
-
vec2 st = uv / tsize - 0.5;
|
|
82
|
-
vec2 iuv = floor(st);
|
|
83
|
-
vec2 fuv = fract(st);
|
|
84
|
-
vec4 a = texture2D(sam, (iuv + vec2(0.5, 0.5)) * tsize);
|
|
85
|
-
vec4 b = texture2D(sam, (iuv + vec2(1.5, 0.5)) * tsize);
|
|
86
|
-
vec4 c = texture2D(sam, (iuv + vec2(0.5, 1.5)) * tsize);
|
|
87
|
-
vec4 d = texture2D(sam, (iuv + vec2(1.5, 1.5)) * tsize);
|
|
88
|
-
return mix(mix(a, b, fuv.x), mix(c, d, fuv.x), fuv.y);
|
|
89
|
-
}
|
|
90
|
-
void main () {
|
|
91
|
-
#ifdef MANUAL_FILTERING
|
|
92
|
-
vec2 coord = vUv - dt * bilerp(uVelocity, vUv, texelSize).xy * texelSize;
|
|
93
|
-
vec4 result = bilerp(uSource, coord, dyeTexelSize);
|
|
94
|
-
#else
|
|
95
|
-
vec2 coord = vUv - dt * texture2D(uVelocity, vUv).xy * texelSize;
|
|
96
|
-
vec4 result = texture2D(uSource, coord);
|
|
97
|
-
#endif
|
|
98
|
-
float decay = 1.0 + dissipation * dt;
|
|
99
|
-
gl_FragColor = result / decay;
|
|
100
|
-
}`,h.supportLinearFiltering?null:["MANUAL_FILTERING"])),qe=D(t,t.FRAGMENT_SHADER,`precision mediump float;
|
|
101
|
-
precision mediump sampler2D;
|
|
102
|
-
varying highp vec2 vUv;
|
|
103
|
-
varying highp vec2 vL;
|
|
104
|
-
varying highp vec2 vR;
|
|
105
|
-
varying highp vec2 vT;
|
|
106
|
-
varying highp vec2 vB;
|
|
107
|
-
uniform sampler2D uVelocity;
|
|
108
|
-
void main () {
|
|
109
|
-
float L = texture2D(uVelocity, vL).x;
|
|
110
|
-
float R = texture2D(uVelocity, vR).x;
|
|
111
|
-
float T = texture2D(uVelocity, vT).y;
|
|
112
|
-
float B = texture2D(uVelocity, vB).y;
|
|
113
|
-
vec2 C = texture2D(uVelocity, vUv).xy;
|
|
114
|
-
if (vL.x < 0.0) { L = -C.x; }
|
|
115
|
-
if (vR.x > 1.0) { R = -C.x; }
|
|
116
|
-
if (vT.y > 1.0) { T = -C.y; }
|
|
117
|
-
if (vB.y < 0.0) { B = -C.y; }
|
|
118
|
-
float div = 0.5 * (R - L + T - B);
|
|
119
|
-
gl_FragColor = vec4(div, 0.0, 0.0, 1.0);
|
|
120
|
-
}`),Ke=D(t,t.FRAGMENT_SHADER,`precision mediump float;
|
|
121
|
-
precision mediump sampler2D;
|
|
122
|
-
varying highp vec2 vUv;
|
|
123
|
-
varying highp vec2 vL;
|
|
124
|
-
varying highp vec2 vR;
|
|
125
|
-
varying highp vec2 vT;
|
|
126
|
-
varying highp vec2 vB;
|
|
127
|
-
uniform sampler2D uVelocity;
|
|
128
|
-
void main () {
|
|
129
|
-
float L = texture2D(uVelocity, vL).y;
|
|
130
|
-
float R = texture2D(uVelocity, vR).y;
|
|
131
|
-
float T = texture2D(uVelocity, vT).x;
|
|
132
|
-
float B = texture2D(uVelocity, vB).x;
|
|
133
|
-
float vorticity = R - L - T + B;
|
|
134
|
-
gl_FragColor = vec4(0.5 * vorticity, 0.0, 0.0, 1.0);
|
|
135
|
-
}`),$e=D(t,t.FRAGMENT_SHADER,`precision highp float;
|
|
136
|
-
precision highp sampler2D;
|
|
137
|
-
varying vec2 vUv;
|
|
138
|
-
varying vec2 vL;
|
|
139
|
-
varying vec2 vR;
|
|
140
|
-
varying vec2 vT;
|
|
141
|
-
varying vec2 vB;
|
|
142
|
-
uniform sampler2D uVelocity;
|
|
143
|
-
uniform sampler2D uCurl;
|
|
144
|
-
uniform float curl;
|
|
145
|
-
uniform float dt;
|
|
146
|
-
void main () {
|
|
147
|
-
float L = texture2D(uCurl, vL).x;
|
|
148
|
-
float R = texture2D(uCurl, vR).x;
|
|
149
|
-
float T = texture2D(uCurl, vT).x;
|
|
150
|
-
float B = texture2D(uCurl, vB).x;
|
|
151
|
-
float C = texture2D(uCurl, vUv).x;
|
|
152
|
-
vec2 force = 0.5 * vec2(abs(T) - abs(B), abs(R) - abs(L));
|
|
153
|
-
force /= length(force) + 0.0001;
|
|
154
|
-
force *= curl * C;
|
|
155
|
-
force.y *= -1.0;
|
|
156
|
-
vec2 velocity = texture2D(uVelocity, vUv).xy;
|
|
157
|
-
velocity += force * dt;
|
|
158
|
-
velocity = min(max(velocity, -1000.0), 1000.0);
|
|
159
|
-
gl_FragColor = vec4(velocity, 0.0, 1.0);
|
|
160
|
-
}`),Je=D(t,t.FRAGMENT_SHADER,`precision mediump float;
|
|
161
|
-
precision mediump sampler2D;
|
|
162
|
-
varying highp vec2 vUv;
|
|
163
|
-
varying highp vec2 vL;
|
|
164
|
-
varying highp vec2 vR;
|
|
165
|
-
varying highp vec2 vT;
|
|
166
|
-
varying highp vec2 vB;
|
|
167
|
-
uniform sampler2D uPressure;
|
|
168
|
-
uniform sampler2D uDivergence;
|
|
169
|
-
void main () {
|
|
170
|
-
float L = texture2D(uPressure, vL).x;
|
|
171
|
-
float R = texture2D(uPressure, vR).x;
|
|
172
|
-
float T = texture2D(uPressure, vT).x;
|
|
173
|
-
float B = texture2D(uPressure, vB).x;
|
|
174
|
-
float C = texture2D(uPressure, vUv).x;
|
|
175
|
-
float divergence = texture2D(uDivergence, vUv).x;
|
|
176
|
-
float pressure = (L + R + B + T - divergence) * 0.25;
|
|
177
|
-
gl_FragColor = vec4(pressure, 0.0, 0.0, 1.0);
|
|
178
|
-
}`),Ze=D(t,t.FRAGMENT_SHADER,`precision mediump float;
|
|
179
|
-
precision mediump sampler2D;
|
|
180
|
-
varying highp vec2 vUv;
|
|
181
|
-
varying highp vec2 vL;
|
|
182
|
-
varying highp vec2 vR;
|
|
183
|
-
varying highp vec2 vT;
|
|
184
|
-
varying highp vec2 vB;
|
|
185
|
-
uniform sampler2D uPressure;
|
|
186
|
-
uniform sampler2D uVelocity;
|
|
187
|
-
void main () {
|
|
188
|
-
float L = texture2D(uPressure, vL).x;
|
|
189
|
-
float R = texture2D(uPressure, vR).x;
|
|
190
|
-
float T = texture2D(uPressure, vT).x;
|
|
191
|
-
float B = texture2D(uPressure, vB).x;
|
|
192
|
-
vec2 velocity = texture2D(uVelocity, vUv).xy;
|
|
193
|
-
velocity.xy -= vec2(R - L, T - B);
|
|
194
|
-
gl_FragColor = vec4(velocity, 0.0, 1.0);
|
|
195
|
-
}`),T=(()=>{let e=t.createBuffer();t.bindBuffer(t.ARRAY_BUFFER,e),t.bufferData(t.ARRAY_BUFFER,new Float32Array([-1,-1,-1,1,1,1,1,-1]),t.STATIC_DRAW);let r=t.createBuffer();return t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,r),t.bufferData(t.ELEMENT_ARRAY_BUFFER,new Uint16Array([0,1,2,0,2,3]),t.STATIC_DRAW),t.vertexAttribPointer(0,2,t.FLOAT,!1,0,0),t.enableVertexAttribArray(0),(n,o=!1)=>{n==null?(t.viewport(0,0,t.drawingBufferWidth,t.drawingBufferHeight),t.bindFramebuffer(t.FRAMEBUFFER,null)):(t.viewport(0,0,n.width,n.height),t.bindFramebuffer(t.FRAMEBUFFER,n.fbo)),o&&(t.clearColor(0,0,0,1),t.clear(t.COLOR_BUFFER_BIT)),t.drawElements(t.TRIANGLES,6,t.UNSIGNED_SHORT,0)}})(),y,f,J,Z,_,me=new P(w,He),Q=new P(w,Ye),B=new P(w,Ve),L=new P(w,je),ee=new P(w,qe),te=new P(w,Ke),U=new P(w,$e),O=new P(w,Je),X=new P(w,Ze),k=new z(w,We);function re(){let e=De(i.simResolution),r=De(i.dyeResolution),n=h.halfFloatTexType,o=h.formatRGBA,s=h.formatRG,l=h.formatR,c=h.supportLinearFiltering?t.LINEAR:t.NEAREST;t.disable(t.BLEND),y==null?y=ne(r.width,r.height,o.internalFormat,o.format,n,c):y=ve(y,r.width,r.height,o.internalFormat,o.format,n,c),f==null?f=ne(e.width,e.height,s.internalFormat,s.format,n,c):f=ve(f,e.width,e.height,s.internalFormat,s.format,n,c),J=G(e.width,e.height,l.internalFormat,l.format,n,t.NEAREST),Z=G(e.width,e.height,l.internalFormat,l.format,n,t.NEAREST),_=ne(e.width,e.height,l.internalFormat,l.format,n,t.NEAREST)}function G(e,r,n,o,s,l){t.activeTexture(t.TEXTURE0);let c=t.createTexture();t.bindTexture(t.TEXTURE_2D,c),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,l),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,l),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texImage2D(t.TEXTURE_2D,0,n,e,r,0,o,s,null);let p=t.createFramebuffer();t.bindFramebuffer(t.FRAMEBUFFER,p),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,c,0),t.viewport(0,0,e,r),t.clear(t.COLOR_BUFFER_BIT);let b=1/e,C=1/r;return{texture:c,fbo:p,width:e,height:r,texelSizeX:b,texelSizeY:C,attach(d){return t.activeTexture(t.TEXTURE0+d),t.bindTexture(t.TEXTURE_2D,c),d}}}function ne(e,r,n,o,s,l){let c=G(e,r,n,o,s,l),p=G(e,r,n,o,s,l);return{width:e,height:r,texelSizeX:c.texelSizeX,texelSizeY:c.texelSizeY,get read(){return c},set read(b){c=b},get write(){return p},set write(b){p=b},swap(){let b=c;c=p,p=b}}}function Qe(e,r,n,o,s,l,c){let p=G(r,n,o,s,l,c);return me.bind(),t.uniform1i(me.uniforms.uTexture,e.attach(0)),T(p),p}function ve(e,r,n,o,s,l,c){return e.width===r&&e.height===n||(e.read=Qe(e.read,r,n,o,s,l,c),e.write=G(r,n,o,s,l,c),e.width=r,e.height=n,e.texelSizeX=1/r,e.texelSizeY=1/n),e}function et(){let e=[];i.shading&&e.push("shading"),k.setKeywords(e)}et(),re();let oe=Date.now(),H=0,ie=0;function pe(){let e=tt();N()&&re(),rt(e),nt(),i.paused||ot(e),he(null),ie=requestAnimationFrame(pe)}function tt(){let e=Date.now(),r=(e-oe)/1e3;return r=Math.min(r,.016666),oe=e,r}function N(){let e=F(u.clientWidth),r=F(u.clientHeight);return u.width!==e||u.height!==r?(u.width=e,u.height=r,!0):!1}function rt(e){H+=e*i.colorUpdateSpeed,H>=1&&(H=mt(H,0,1),R.forEach(r=>{r.color=Se(Y())}))}function nt(){R.forEach(e=>{e.moved&&(e.moved=!1,st(e))})}function ot(e){t.disable(t.BLEND),te.bind(),t.uniform2f(te.uniforms.texelSize,f.texelSizeX,f.texelSizeY),t.uniform1i(te.uniforms.uVelocity,f.read.attach(0)),T(Z),U.bind(),t.uniform2f(U.uniforms.texelSize,f.texelSizeX,f.texelSizeY),t.uniform1i(U.uniforms.uVelocity,f.read.attach(0)),t.uniform1i(U.uniforms.uCurl,Z.attach(1)),t.uniform1f(U.uniforms.curl,i.curl),t.uniform1f(U.uniforms.dt,e),T(f.write),f.swap(),ee.bind(),t.uniform2f(ee.uniforms.texelSize,f.texelSizeX,f.texelSizeY),t.uniform1i(ee.uniforms.uVelocity,f.read.attach(0)),T(J),Q.bind(),t.uniform1i(Q.uniforms.uTexture,_.read.attach(0)),t.uniform1f(Q.uniforms.value,i.pressure),T(_.write),_.swap(),O.bind(),t.uniform2f(O.uniforms.texelSize,f.texelSizeX,f.texelSizeY),t.uniform1i(O.uniforms.uDivergence,J.attach(0));for(let n=0;n<i.pressureIteration;n++)t.uniform1i(O.uniforms.uPressure,_.read.attach(1)),T(_.write),_.swap();X.bind(),t.uniform2f(X.uniforms.texelSize,f.texelSizeX,f.texelSizeY),t.uniform1i(X.uniforms.uPressure,_.read.attach(0)),t.uniform1i(X.uniforms.uVelocity,f.read.attach(1)),T(f.write),f.swap(),L.bind(),t.uniform2f(L.uniforms.texelSize,f.texelSizeX,f.texelSizeY),h.supportLinearFiltering||t.uniform2f(L.uniforms.dyeTexelSize,f.texelSizeX,f.texelSizeY);let r=f.read.attach(0);t.uniform1i(L.uniforms.uVelocity,r),t.uniform1i(L.uniforms.uSource,r),t.uniform1f(L.uniforms.dt,e),t.uniform1f(L.uniforms.dissipation,i.velocityDissipation),T(f.write),f.swap(),h.supportLinearFiltering||t.uniform2f(L.uniforms.dyeTexelSize,y.texelSizeX,y.texelSizeY),t.uniform1i(L.uniforms.uVelocity,f.read.attach(0)),t.uniform1i(L.uniforms.uSource,y.read.attach(1)),t.uniform1f(L.uniforms.dissipation,i.densityDissipation),T(y.write),y.swap()}function he(e){t.blendFunc(t.ONE,t.ONE_MINUS_SRC_ALPHA),t.enable(t.BLEND),it(e)}function it(e){let r=e==null?t.drawingBufferWidth:e.width,n=e==null?t.drawingBufferHeight:e.height;k.bind(),i.shading&&t.uniform2f(k.uniforms.texelSize,1/r,1/n),t.uniform1i(k.uniforms.uTexture,y.read.attach(0)),T(e)}function st(e){let r=e.deltaX*i.splatForce,n=e.deltaY*i.splatForce,o=ft(e.color);se(e.texcoordX,e.texcoordY,r,n,o)}function xe(e){let r=Y();r.r*=10,r.g*=10,r.b*=10;let n=10*(Math.random()-.5),o=30*(Math.random()-.5);se(e.texcoordX,e.texcoordY,n,o,r)}function se(e,r,n,o,s){B.bind(),t.uniform1i(B.uniforms.uTarget,f.read.attach(0)),t.uniform1f(B.uniforms.aspectRatio,u.width/u.height),t.uniform2f(B.uniforms.point,e,r),t.uniform3f(B.uniforms.color,n,o,0),t.uniform1f(B.uniforms.radius,at(i.splatRadius/100)),T(f.write),f.swap(),t.uniform1i(B.uniforms.uTarget,y.read.attach(0)),t.uniform3f(B.uniforms.color,s.r,s.g,s.b),T(y.write),y.swap()}function at(e){let r=u.width/u.height;return r>1&&(e*=r),e}let be=e=>{let r=R[0],n=u.getBoundingClientRect(),o=F(e.clientX-n.left),s=F(e.clientY-n.top);Te(r,-1,o,s),xe(r)},ge=e=>{let r=R[0],n=u.getBoundingClientRect(),o=F(e.clientX-n.left),s=F(e.clientY-n.top),l=r.color;Fe(r,o,s,l)},Re=e=>{let r=e.targetTouches,n=u.getBoundingClientRect(),o=R[0];for(let s=0;s<r.length;s++){let l=F(r[s].clientX-n.left),c=F(r[s].clientY-n.top);Te(o,r[s].identifier,l,c),xe(o)}},ye=e=>{e.preventDefault();let r=e.targetTouches,n=u.getBoundingClientRect(),o=R[0];for(let s=0;s<r.length;s++){let l=F(r[s].clientX-n.left),c=F(r[s].clientY-n.top);Fe(o,l,c,o.color)}},Ee=e=>{let r=e.changedTouches,n=R[0];for(let o=0;o<r.length;o++)ut(n)};window.addEventListener("mousedown",be),window.addEventListener("mousemove",ge),window.addEventListener("touchstart",Re),window.addEventListener("touchmove",ye,{passive:!1}),window.addEventListener("touchend",Ee);function Te(e,r,n,o){e.id=r,e.down=!0,e.moved=!1,e.texcoordX=n/u.width,e.texcoordY=1-o/u.height,e.prevTexcoordX=e.texcoordX,e.prevTexcoordY=e.texcoordY,e.deltaX=0,e.deltaY=0,e.color=Se(Y())}function Fe(e,r,n,o){e.prevTexcoordX=e.texcoordX,e.prevTexcoordY=e.texcoordY,e.texcoordX=r/u.width,e.texcoordY=1-n/u.height,e.deltaX=ct(e.texcoordX-e.prevTexcoordX),e.deltaY=lt(e.texcoordY-e.prevTexcoordY),e.moved=Math.abs(e.deltaX)>0||Math.abs(e.deltaY)>0,e.color=o}function ut(e){e.down=!1}function ct(e){let r=u.width/u.height;return r<1&&(e*=r),e}function lt(e){let r=u.width/u.height;return r>1&&(e/=r),e}function Y(){let e=i.colorIntensity,r=i.palette;if(r&&r.length>0){let o=r[Math.floor(Math.random()*r.length)],s=St(o);if(s)return{r:s.r*e,g:s.g*e,b:s.b*e}}let n=dt(Math.random(),1,1);return n.r*=e,n.g*=e,n.b*=e,n}function Se(e){return[e.r,e.g,e.b]}function ft(e){return{r:e[0],g:e[1],b:e[2]}}function dt(e,r,n){let o=0,s=0,l=0,c=Math.floor(e*6),p=e*6-c,b=n*(1-r),C=n*(1-p*r),d=n*(1-(1-p)*r);switch(c%6){case 0:o=n,s=d,l=b;break;case 1:o=C,s=n,l=b;break;case 2:o=b,s=n,l=d;break;case 3:o=b,s=C,l=n;break;case 4:o=d,s=b,l=n;break;case 5:o=n,s=b,l=C;break}return{r:o,g:s,b:l}}function mt(e,r,n){let o=n-r;return o===0?r:(e-r)%o+r}function De(e){let r=t.drawingBufferWidth/t.drawingBufferHeight;r<1&&(r=1/r);let n=Math.round(e),o=Math.round(e*r);return t.drawingBufferWidth>t.drawingBufferHeight?{width:o,height:n}:{width:n,height:o}}function F(e){let r=Math.min(window.devicePixelRatio||1,Math.max(1,i.maxDpr));return Math.floor(e*r)}function vt(e){if(e.length===0)return 0;let r=0;for(let n=0;n<e.length;n++)r=(r<<5)-r+e.charCodeAt(n),r|=0;return r}function pt(){var e,r;ae||(ae=!0,j(),window.removeEventListener("mousedown",be),window.removeEventListener("mousemove",ge),window.removeEventListener("touchstart",Re),window.removeEventListener("touchmove",ye),window.removeEventListener("touchend",Ee),window.removeEventListener("resize",we),document.removeEventListener("visibilitychange",Le),(e=E==null?void 0:E.removeEventListener)==null||e.call(E,"change",Pe),M==null||M.disconnect(),m&&(u==null||u.remove()),(r=t.getExtension("WEBGL_lose_context"))==null||r.loseContext())}let ae=!1,W=!1;function V(){W||ae||(W=!0,oe=Date.now(),ie=requestAnimationFrame(pe))}function j(){W=!1,cancelAnimationFrame(ie)}let Le=()=>{i.pauseOnHidden&&(document.hidden?j():I||V())},we=()=>N(),M=typeof ResizeObserver!="undefined"?new ResizeObserver(()=>N()):null;M==null||M.observe(u);let E=typeof window.matchMedia=="function"?window.matchMedia("(prefers-reduced-motion: reduce)"):null,Pe=()=>{i.respectReducedMotion&&(E!=null&&E.matches?j():I||V())},I=!1;return window.addEventListener("resize",we),document.addEventListener("visibilitychange",Le),(Be=E==null?void 0:E.addEventListener)==null||Be.call(E,"change",Pe),i.respectReducedMotion&&Lt()?(I=!0,he(null)):V(),{dispose:pt,pause(){I=!0,j()},resume(){I=!1,V()},isPaused:()=>I||!W,setConfig(e){let r=e.simResolution!==void 0&&e.simResolution!==i.simResolution||e.dyeResolution!==void 0&&e.dyeResolution!==i.dyeResolution;Object.assign(i,e),e.maxDpr!==void 0&&N(),r&&re(),e.zIndex!==void 0&&(u.style.zIndex=String(e.zIndex)),e.pointerEvents!==void 0&&(u.style.pointerEvents=e.pointerEvents?"auto":"none")},splat(e,r,n){let o=u.getBoundingClientRect(),s=F(e),l=F(r),c=n!=null?n:Y();se(s,u.height-l,0,0,c)},get canvas(){return u}}};var Ge={Spectrum:null,Sunset:["#ff4ecd","#ff8a4e","#ffd24e"],Ocean:["#4ea8ff","#4effd2","#7c4dff"],Mono:["#ffffff"],Aurora:["#3affa3","#38d9ff","#8f7bff"],Ember:["#ff5722","#ff9100","#ffc400"],Lagoon:["#00c2a8","#00a3ff","#0057d9"],Candy:["#ff8fd0","#ffa9f0","#c79bff"],Toxic:["#b6ff00","#4dff88","#00ffc8"],Royal:["#5b2bff","#8f4dff","#c44dff"],Sakura:["#ffc2dd","#ff8fb1","#ff6f91"],Mint:["#9cffd6","#5ef2c0","#2fd6a5"],Copper:["#ff9a5a","#e2703a","#b34700"],Ultraviolet:["#7b2cff","#b429ff","#ff29f0"],Ice:["#c9f0ff","#8ad4ff","#4fb3ff"],Magma:["#ff2d2d","#ff6a00","#ffb300"],Forest:["#2f9e44","#69db7c","#a9e34b"],Dusk:["#3b3b98","#7158e2","#cd84f1"],Cyber:["#00fff0","#ff00e0","#fffb00"],Pastel:["#ffd6e0","#c7ceea","#b5ead7"]},Me={Calm:{curl:3,splatForce:4200,splatRadius:.45,densityDissipation:4.6,velocityDissipation:2.6,pressureIteration:16,colorUpdateSpeed:6},Flow:{curl:10,splatForce:6e3,splatRadius:.5,densityDissipation:3.5,velocityDissipation:2,pressureIteration:20,colorUpdateSpeed:10},Swirl:{curl:24,splatForce:7200,splatRadius:.55,densityDissipation:3,velocityDissipation:1.6,pressureIteration:24,colorUpdateSpeed:12},Storm:{curl:40,splatForce:9500,splatRadius:.65,densityDissipation:2.2,velocityDissipation:1.2,pressureIteration:28,colorUpdateSpeed:16},Wisp:{curl:6,splatForce:3200,splatRadius:.32,densityDissipation:6.5,velocityDissipation:3.4,pressureIteration:12,colorUpdateSpeed:8}},wt=()=>{let a={};for(let[i,m]of Object.entries(Ge))for(let[u,g]of Object.entries(Me)){let S=`${i} ${u}`;a[S]={...g,palette:m?[...m]:null,colorIntensity:m===null?.15:.18}}return a},K=wt(),Ie=Object.keys(K),Ne=Object.keys(Ge),ze=Object.keys(Me),Oe=a=>K[a];var ke=require("react/jsx-runtime"),Pt=["densityDissipation","velocityDissipation","pressure","pressureIteration","curl","splatRadius","splatForce","shading","colorUpdateSpeed","paused","transparent","backColor","palette","colorIntensity","zIndex","pointerEvents","maxDpr","pauseOnHidden","respectReducedMotion"],Ct=a=>JSON.stringify([a==null?void 0:a.id,a==null?void 0:a.position,a==null?void 0:a.className,a==null?void 0:a.simResolution,a==null?void 0:a.dyeResolution,a==null?void 0:a.captureResolution]);function Xe(a,i){let m=A.default.useRef(null),u=A.default.useRef(a);u.current=a;let g=Ct(a);return A.default.useEffect(()=>{let S=ce({...u.current,...i!=null&&i.current?{container:i.current}:{}});return m.current=S,()=>{S.dispose(),m.current=null}},[g,i]),A.default.useEffect(()=>{let S=m.current;if(!S||!a)return;let R={};for(let t of Pt)a[t]!==void 0&&(R[t]=a[t]);S.setConfig(R)}),m}var _t=A.default.forwardRef(function({config:i,scoped:m=!1,className:u,style:g,children:S},R){let t=A.default.useRef(null),h=Xe(i,m?t:void 0);return A.default.useImperativeHandle(R,()=>({dispose:()=>{var v;return(v=h.current)==null?void 0:v.dispose()},pause:()=>{var v;return(v=h.current)==null?void 0:v.pause()},resume:()=>{var v;return(v=h.current)==null?void 0:v.resume()},isPaused:()=>{var v,x;return(x=(v=h.current)==null?void 0:v.isPaused())!=null?x:!0},setConfig:v=>{var x;return(x=h.current)==null?void 0:x.setConfig(v)},splat:(v,x,$)=>{var z;return(z=h.current)==null?void 0:z.splat(v,x,$)},get canvas(){var v,x;return(x=(v=h.current)==null?void 0:v.canvas)!=null?x:null}}),[h]),m?(0,ke.jsx)("div",{ref:t,className:u,style:{position:"relative",overflow:"hidden",...g},children:S}):null});0&&(module.exports={SmokeyFluidCursor,characterNames,getPreset,initFluid,paletteNames,presetNames,presets,useSmokeyFluidCursor});
|
|
2
|
+
"use strict";var I=Object.create;var y=Object.defineProperty;var P=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var f=Object.getPrototypeOf,h=Object.prototype.hasOwnProperty;var v=(e,r)=>{for(var s in r)y(e,s,{get:r[s],enumerable:!0})},F=(e,r,s,d)=>{if(r&&typeof r=="object"||typeof r=="function")for(let a of N(r))!h.call(e,a)&&a!==s&&y(e,a,{get:()=>r[a],enumerable:!(d=P(r,a))||d.enumerable});return e};var H=(e,r,s)=>(s=e!=null?I(f(e)):{},F(r||!e||!e.__esModule?y(s,"default",{value:e,enumerable:!0}):s,e)),E=e=>F(y({},"__esModule",{value:!0}),e);var b={};v(b,{SmokeyFluidCursor:()=>O,characterNames:()=>u.characterNames,getPreset:()=>u.getPreset,initFluid:()=>u.initFluid,paletteNames:()=>u.paletteNames,presetNames:()=>u.presetNames,presets:()=>u.presets,useSmokeyFluidCursor:()=>C});module.exports=E(b);var n=H(require("react")),k=require("smokey-fluid-cursor"),u=require("smokey-fluid-cursor"),R=require("react/jsx-runtime"),x=["densityDissipation","velocityDissipation","pressure","pressureIteration","curl","splatRadius","splatForce","shading","colorUpdateSpeed","paused","transparent","backColor","palette","colorIntensity","zIndex","pointerEvents","maxDpr","pauseOnHidden","respectReducedMotion"],L=e=>JSON.stringify([e==null?void 0:e.id,e==null?void 0:e.position,e==null?void 0:e.className,e==null?void 0:e.simResolution,e==null?void 0:e.dyeResolution,e==null?void 0:e.captureResolution]);function C(e,r){let s=n.default.useRef(null),d=n.default.useRef(e);d.current=e;let a=L(e);return n.default.useEffect(()=>{let i=(0,k.initFluid)({...d.current,...r!=null&&r.current?{container:r.current}:{}});return s.current=i,()=>{i.dispose(),s.current=null}},[a,r]),n.default.useEffect(()=>{let i=s.current;if(!i||!e)return;let m={};for(let p of x)e[p]!==void 0&&(m[p]=e[p]);i.setConfig(m)}),s}var O=n.default.forwardRef(function({config:r,scoped:s=!1,className:d,style:a,children:i},m){let p=n.default.useRef(null),o=C(r,s?p:void 0);return n.default.useImperativeHandle(m,()=>({dispose:()=>{var t;return(t=o.current)==null?void 0:t.dispose()},pause:()=>{var t;return(t=o.current)==null?void 0:t.pause()},resume:()=>{var t;return(t=o.current)==null?void 0:t.resume()},isPaused:()=>{var t,l;return(l=(t=o.current)==null?void 0:t.isPaused())!=null?l:!0},setConfig:t=>{var l;return(l=o.current)==null?void 0:l.setConfig(t)},splat:(t,l,S)=>{var c;return(c=o.current)==null?void 0:c.splat(t,l,S)},get canvas(){var t,l;return(l=(t=o.current)==null?void 0:t.canvas)!=null?l:null}}),[o]),s?(0,R.jsx)("div",{ref:p,className:d,style:{position:"relative",overflow:"hidden",...a},children:i}):null});0&&(module.exports={SmokeyFluidCursor,characterNames,getPreset,initFluid,paletteNames,presetNames,presets,useSmokeyFluidCursor});
|
package/dist/index.mjs
CHANGED
|
@@ -1,195 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import
|
|
3
|
-
Move the background to <html>, or give the canvas a zIndex above your background.`)},ft=()=>typeof window!="undefined"&&typeof window.matchMedia=="function"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,se={dispose:()=>{},pause:()=>{},resume:()=>{},isPaused:()=>!0,setConfig:()=>{},splat:()=>{},canvas:null},Be=(c={})=>{var we,Pe,Ce;let s={...ut,...c};if(typeof document=="undefined")return se;let b=!1,a=(we=_e(s.canvas))!=null?we:document.getElementById(s.id);if(!a){let e=(Pe=_e(s.container))!=null?Pe:document.body;if(!e)return se;a=document.createElement("canvas"),a.id=s.id,e.appendChild(a),b=!0}s.className&&a.classList.add(...s.className.split(/\s+/));let B=s.position==="fixed"||s.position==="absolute";Object.assign(a.style,{position:s.position,...B?{top:"0",left:"0",width:"100%",height:"100%"}:{},display:"block",pointerEvents:s.pointerEvents?"auto":"none",zIndex:String(s.zIndex)}),lt(s.zIndex),N();class F{constructor(){this.id=-1;this.texcoordX=0;this.texcoordY=0;this.prevTexcoordX=0;this.prevTexcoordY=0;this.deltaX=0;this.deltaY=0;this.down=!1;this.moved=!1;this.color=[30,0,300]}}let g=[];g.push(new F);let t,p;try{({gl:t,ext:p}=m(a))}catch(e){typeof console!="undefined"&&console.warn("[smokey-fluid-cursor] WebGL is unavailable; the cursor effect is disabled.",e);let r=a,n=b;return{...se,dispose:()=>{n&&r.remove()},setConfig:o=>{o.zIndex!==void 0&&(r.style.zIndex=String(o.zIndex)),o.pointerEvents!==void 0&&(r.style.pointerEvents=o.pointerEvents?"auto":"none")},get canvas(){return r}}}p.supportLinearFiltering||(s.dyeResolution=512,s.shading=!1);function m(e){let r={alpha:!0,depth:!1,stencil:!1,antialias:!1,preserveDrawingBuffer:!1},n=e.getContext("webgl2",r),o=!!n;if(o||(n=e.getContext("webgl",r)||e.getContext("experimental-webgl",r)),!n)throw new Error("WebGL not supported");let i=null,l,u;if(o){let d=n;d.getExtension("EXT_color_buffer_float"),l=!!d.getExtension("OES_texture_float_linear"),u=d.HALF_FLOAT}else{let d=n;if(i=d.getExtension("OES_texture_half_float"),l=!!d.getExtension("OES_texture_half_float_linear"),!i)throw new Error("OES_texture_half_float not supported on WebGL1");u=i.HALF_FLOAT_OES}n.clearColor(0,0,0,1);let v=null,x=null,P=null;if(o){let d=n;v=h(d,d.RGBA16F,d.RGBA,u),x=h(d,d.RG16F,d.RG,u),P=h(d,d.R16F,d.RED,u)}else{let d=n;v=h(d,d.RGBA,d.RGBA,u),x=h(d,d.RGBA,d.RGBA,u),P=h(d,d.RGBA,d.RGBA,u)}return{gl:n,ext:{formatRGBA:v,formatRG:x,formatR:P,halfFloatTexType:u,supportLinearFiltering:l,isWebGL2:o}}}function h(e,r,n,o){if(!q(e,r,n,o)){if(e.RGBA16F!==void 0){let i=e;switch(r){case i.R16F:return h(i,i.RG16F,i.RG,o);case i.RG16F:return h(i,i.RGBA16F,i.RGBA,o);default:return null}}return null}return{internalFormat:r,format:n}}function q(e,r,n,o){let i=e.createTexture();if(!i)return!1;e.bindTexture(e.TEXTURE_2D,i),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texImage2D(e.TEXTURE_2D,0,r,4,4,0,n,o,null);let l=e.createFramebuffer();if(!l)return!1;e.bindFramebuffer(e.FRAMEBUFFER,l),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,i,0);let u=e.checkFramebufferStatus(e.FRAMEBUFFER);return e.bindFramebuffer(e.FRAMEBUFFER,null),e.deleteFramebuffer(l),e.deleteTexture(i),u===e.FRAMEBUFFER_COMPLETE}class z{constructor(r,n){this.vertexShader=r,this.fragmentShaderSource=n,this.programs={},this.activeProgram=null,this.uniforms={}}setKeywords(r){let n=0;for(let i=0;i<r.length;i++)n+=st(r[i]);let o=this.programs[n];if(!o){let i=S(t,t.FRAGMENT_SHADER,le(this.fragmentShaderSource,r));o=ue(t,this.vertexShader,i),this.programs[n]=o}o!==this.activeProgram&&(this.uniforms=ce(t,o),this.activeProgram=o)}bind(){this.activeProgram&&t.useProgram(this.activeProgram)}}class w{constructor(r,n){this.program=ue(t,r,n),this.uniforms=ce(t,this.program)}bind(){this.program&&t.useProgram(this.program)}}function ue(e,r,n){let o=e.createProgram();return e.attachShader(o,r),e.attachShader(o,n),e.bindAttribLocation(o,0,"aPosition"),e.linkProgram(o),e.getProgramParameter(o,e.LINK_STATUS)||console.trace(e.getProgramInfoLog(o)),o}function ce(e,r){let n={},o=e.getProgramParameter(r,e.ACTIVE_UNIFORMS);for(let i=0;i<o;i++){let l=e.getActiveUniform(r,i);if(!l)continue;let u=l.name,v=e.getUniformLocation(r,u);v&&(n[u]=v)}return n}function S(e,r,n){let o=e.createShader(r);return e.shaderSource(o,n),e.compileShader(o),e.getShaderParameter(o,e.COMPILE_STATUS)||console.trace(e.getShaderInfoLog(o)),o}function le(e,r){if(!r||r.length===0)return e;let n="";return r.forEach(o=>{n+="#define "+o+`
|
|
4
|
-
`}),n+e}let L=S(t,t.VERTEX_SHADER,`precision highp float;
|
|
5
|
-
attribute vec2 aPosition;
|
|
6
|
-
varying vec2 vUv;
|
|
7
|
-
varying vec2 vL;
|
|
8
|
-
varying vec2 vR;
|
|
9
|
-
varying vec2 vT;
|
|
10
|
-
varying vec2 vB;
|
|
11
|
-
uniform vec2 texelSize;
|
|
12
|
-
void main () {
|
|
13
|
-
vUv = aPosition * 0.5 + 0.5;
|
|
14
|
-
vL = vUv - vec2(texelSize.x, 0.0);
|
|
15
|
-
vR = vUv + vec2(texelSize.x, 0.0);
|
|
16
|
-
vT = vUv + vec2(0.0, texelSize.y);
|
|
17
|
-
vB = vUv - vec2(0.0, texelSize.y);
|
|
18
|
-
gl_Position = vec4(aPosition, 0.0, 1.0);
|
|
19
|
-
}`),Ge=S(t,t.FRAGMENT_SHADER,`precision mediump float;
|
|
20
|
-
precision mediump sampler2D;
|
|
21
|
-
varying highp vec2 vUv;
|
|
22
|
-
uniform sampler2D uTexture;
|
|
23
|
-
void main () {
|
|
24
|
-
gl_FragColor = texture2D(uTexture, vUv);
|
|
25
|
-
}`),Me=S(t,t.FRAGMENT_SHADER,`precision mediump float;
|
|
26
|
-
precision mediump sampler2D;
|
|
27
|
-
varying highp vec2 vUv;
|
|
28
|
-
uniform sampler2D uTexture;
|
|
29
|
-
uniform float value;
|
|
30
|
-
void main () {
|
|
31
|
-
gl_FragColor = value * texture2D(uTexture, vUv);
|
|
32
|
-
}`),Ie=`precision highp float;
|
|
33
|
-
precision highp sampler2D;
|
|
34
|
-
varying vec2 vUv;
|
|
35
|
-
varying vec2 vL;
|
|
36
|
-
varying vec2 vR;
|
|
37
|
-
varying vec2 vT;
|
|
38
|
-
varying vec2 vB;
|
|
39
|
-
uniform sampler2D uTexture;
|
|
40
|
-
uniform vec2 texelSize;
|
|
41
|
-
void main () {
|
|
42
|
-
vec3 c = texture2D(uTexture, vUv).rgb;
|
|
43
|
-
#ifdef shading
|
|
44
|
-
vec3 lc = texture2D(uTexture, vL).rgb;
|
|
45
|
-
vec3 rc = texture2D(uTexture, vR).rgb;
|
|
46
|
-
vec3 tc = texture2D(uTexture, vT).rgb;
|
|
47
|
-
vec3 bc = texture2D(uTexture, vB).rgb;
|
|
48
|
-
float dx = length(rc) - length(lc);
|
|
49
|
-
float dy = length(tc) - length(bc);
|
|
50
|
-
vec3 n = normalize(vec3(dx, dy, length(texelSize)));
|
|
51
|
-
vec3 l = vec3(0.0, 0.0, 1.0);
|
|
52
|
-
float diffuse = clamp(dot(n, l) + 0.7, 0.7, 1.0);
|
|
53
|
-
c *= diffuse;
|
|
54
|
-
#endif
|
|
55
|
-
float a = max(c.r, max(c.g, c.b));
|
|
56
|
-
gl_FragColor = vec4(c, a);
|
|
57
|
-
}`,Ne=S(t,t.FRAGMENT_SHADER,`precision highp float;
|
|
58
|
-
precision highp sampler2D;
|
|
59
|
-
varying vec2 vUv;
|
|
60
|
-
uniform sampler2D uTarget;
|
|
61
|
-
uniform float aspectRatio;
|
|
62
|
-
uniform vec3 color;
|
|
63
|
-
uniform vec2 point;
|
|
64
|
-
uniform float radius;
|
|
65
|
-
void main () {
|
|
66
|
-
vec2 p = vUv - point.xy;
|
|
67
|
-
p.x *= aspectRatio;
|
|
68
|
-
vec3 splat = exp(-dot(p, p) / radius) * color;
|
|
69
|
-
vec3 base = texture2D(uTarget, vUv).xyz;
|
|
70
|
-
gl_FragColor = vec4(base + splat, 1.0);
|
|
71
|
-
}`),ze=S(t,t.FRAGMENT_SHADER,le(`precision highp float;
|
|
72
|
-
precision highp sampler2D;
|
|
73
|
-
varying vec2 vUv;
|
|
74
|
-
uniform sampler2D uVelocity;
|
|
75
|
-
uniform sampler2D uSource;
|
|
76
|
-
uniform vec2 texelSize;
|
|
77
|
-
uniform vec2 dyeTexelSize;
|
|
78
|
-
uniform float dt;
|
|
79
|
-
uniform float dissipation;
|
|
80
|
-
vec4 bilerp (sampler2D sam, vec2 uv, vec2 tsize) {
|
|
81
|
-
vec2 st = uv / tsize - 0.5;
|
|
82
|
-
vec2 iuv = floor(st);
|
|
83
|
-
vec2 fuv = fract(st);
|
|
84
|
-
vec4 a = texture2D(sam, (iuv + vec2(0.5, 0.5)) * tsize);
|
|
85
|
-
vec4 b = texture2D(sam, (iuv + vec2(1.5, 0.5)) * tsize);
|
|
86
|
-
vec4 c = texture2D(sam, (iuv + vec2(0.5, 1.5)) * tsize);
|
|
87
|
-
vec4 d = texture2D(sam, (iuv + vec2(1.5, 1.5)) * tsize);
|
|
88
|
-
return mix(mix(a, b, fuv.x), mix(c, d, fuv.x), fuv.y);
|
|
89
|
-
}
|
|
90
|
-
void main () {
|
|
91
|
-
#ifdef MANUAL_FILTERING
|
|
92
|
-
vec2 coord = vUv - dt * bilerp(uVelocity, vUv, texelSize).xy * texelSize;
|
|
93
|
-
vec4 result = bilerp(uSource, coord, dyeTexelSize);
|
|
94
|
-
#else
|
|
95
|
-
vec2 coord = vUv - dt * texture2D(uVelocity, vUv).xy * texelSize;
|
|
96
|
-
vec4 result = texture2D(uSource, coord);
|
|
97
|
-
#endif
|
|
98
|
-
float decay = 1.0 + dissipation * dt;
|
|
99
|
-
gl_FragColor = result / decay;
|
|
100
|
-
}`,p.supportLinearFiltering?null:["MANUAL_FILTERING"])),Oe=S(t,t.FRAGMENT_SHADER,`precision mediump float;
|
|
101
|
-
precision mediump sampler2D;
|
|
102
|
-
varying highp vec2 vUv;
|
|
103
|
-
varying highp vec2 vL;
|
|
104
|
-
varying highp vec2 vR;
|
|
105
|
-
varying highp vec2 vT;
|
|
106
|
-
varying highp vec2 vB;
|
|
107
|
-
uniform sampler2D uVelocity;
|
|
108
|
-
void main () {
|
|
109
|
-
float L = texture2D(uVelocity, vL).x;
|
|
110
|
-
float R = texture2D(uVelocity, vR).x;
|
|
111
|
-
float T = texture2D(uVelocity, vT).y;
|
|
112
|
-
float B = texture2D(uVelocity, vB).y;
|
|
113
|
-
vec2 C = texture2D(uVelocity, vUv).xy;
|
|
114
|
-
if (vL.x < 0.0) { L = -C.x; }
|
|
115
|
-
if (vR.x > 1.0) { R = -C.x; }
|
|
116
|
-
if (vT.y > 1.0) { T = -C.y; }
|
|
117
|
-
if (vB.y < 0.0) { B = -C.y; }
|
|
118
|
-
float div = 0.5 * (R - L + T - B);
|
|
119
|
-
gl_FragColor = vec4(div, 0.0, 0.0, 1.0);
|
|
120
|
-
}`),Xe=S(t,t.FRAGMENT_SHADER,`precision mediump float;
|
|
121
|
-
precision mediump sampler2D;
|
|
122
|
-
varying highp vec2 vUv;
|
|
123
|
-
varying highp vec2 vL;
|
|
124
|
-
varying highp vec2 vR;
|
|
125
|
-
varying highp vec2 vT;
|
|
126
|
-
varying highp vec2 vB;
|
|
127
|
-
uniform sampler2D uVelocity;
|
|
128
|
-
void main () {
|
|
129
|
-
float L = texture2D(uVelocity, vL).y;
|
|
130
|
-
float R = texture2D(uVelocity, vR).y;
|
|
131
|
-
float T = texture2D(uVelocity, vT).x;
|
|
132
|
-
float B = texture2D(uVelocity, vB).x;
|
|
133
|
-
float vorticity = R - L - T + B;
|
|
134
|
-
gl_FragColor = vec4(0.5 * vorticity, 0.0, 0.0, 1.0);
|
|
135
|
-
}`),ke=S(t,t.FRAGMENT_SHADER,`precision highp float;
|
|
136
|
-
precision highp sampler2D;
|
|
137
|
-
varying vec2 vUv;
|
|
138
|
-
varying vec2 vL;
|
|
139
|
-
varying vec2 vR;
|
|
140
|
-
varying vec2 vT;
|
|
141
|
-
varying vec2 vB;
|
|
142
|
-
uniform sampler2D uVelocity;
|
|
143
|
-
uniform sampler2D uCurl;
|
|
144
|
-
uniform float curl;
|
|
145
|
-
uniform float dt;
|
|
146
|
-
void main () {
|
|
147
|
-
float L = texture2D(uCurl, vL).x;
|
|
148
|
-
float R = texture2D(uCurl, vR).x;
|
|
149
|
-
float T = texture2D(uCurl, vT).x;
|
|
150
|
-
float B = texture2D(uCurl, vB).x;
|
|
151
|
-
float C = texture2D(uCurl, vUv).x;
|
|
152
|
-
vec2 force = 0.5 * vec2(abs(T) - abs(B), abs(R) - abs(L));
|
|
153
|
-
force /= length(force) + 0.0001;
|
|
154
|
-
force *= curl * C;
|
|
155
|
-
force.y *= -1.0;
|
|
156
|
-
vec2 velocity = texture2D(uVelocity, vUv).xy;
|
|
157
|
-
velocity += force * dt;
|
|
158
|
-
velocity = min(max(velocity, -1000.0), 1000.0);
|
|
159
|
-
gl_FragColor = vec4(velocity, 0.0, 1.0);
|
|
160
|
-
}`),He=S(t,t.FRAGMENT_SHADER,`precision mediump float;
|
|
161
|
-
precision mediump sampler2D;
|
|
162
|
-
varying highp vec2 vUv;
|
|
163
|
-
varying highp vec2 vL;
|
|
164
|
-
varying highp vec2 vR;
|
|
165
|
-
varying highp vec2 vT;
|
|
166
|
-
varying highp vec2 vB;
|
|
167
|
-
uniform sampler2D uPressure;
|
|
168
|
-
uniform sampler2D uDivergence;
|
|
169
|
-
void main () {
|
|
170
|
-
float L = texture2D(uPressure, vL).x;
|
|
171
|
-
float R = texture2D(uPressure, vR).x;
|
|
172
|
-
float T = texture2D(uPressure, vT).x;
|
|
173
|
-
float B = texture2D(uPressure, vB).x;
|
|
174
|
-
float C = texture2D(uPressure, vUv).x;
|
|
175
|
-
float divergence = texture2D(uDivergence, vUv).x;
|
|
176
|
-
float pressure = (L + R + B + T - divergence) * 0.25;
|
|
177
|
-
gl_FragColor = vec4(pressure, 0.0, 0.0, 1.0);
|
|
178
|
-
}`),Ye=S(t,t.FRAGMENT_SHADER,`precision mediump float;
|
|
179
|
-
precision mediump sampler2D;
|
|
180
|
-
varying highp vec2 vUv;
|
|
181
|
-
varying highp vec2 vL;
|
|
182
|
-
varying highp vec2 vR;
|
|
183
|
-
varying highp vec2 vT;
|
|
184
|
-
varying highp vec2 vB;
|
|
185
|
-
uniform sampler2D uPressure;
|
|
186
|
-
uniform sampler2D uVelocity;
|
|
187
|
-
void main () {
|
|
188
|
-
float L = texture2D(uPressure, vL).x;
|
|
189
|
-
float R = texture2D(uPressure, vR).x;
|
|
190
|
-
float T = texture2D(uPressure, vT).x;
|
|
191
|
-
float B = texture2D(uPressure, vB).x;
|
|
192
|
-
vec2 velocity = texture2D(uVelocity, vUv).xy;
|
|
193
|
-
velocity.xy -= vec2(R - L, T - B);
|
|
194
|
-
gl_FragColor = vec4(velocity, 0.0, 1.0);
|
|
195
|
-
}`),E=(()=>{let e=t.createBuffer();t.bindBuffer(t.ARRAY_BUFFER,e),t.bufferData(t.ARRAY_BUFFER,new Float32Array([-1,-1,-1,1,1,1,1,-1]),t.STATIC_DRAW);let r=t.createBuffer();return t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,r),t.bufferData(t.ELEMENT_ARRAY_BUFFER,new Uint16Array([0,1,2,0,2,3]),t.STATIC_DRAW),t.vertexAttribPointer(0,2,t.FLOAT,!1,0,0),t.enableVertexAttribArray(0),(n,o=!1)=>{n==null?(t.viewport(0,0,t.drawingBufferWidth,t.drawingBufferHeight),t.bindFramebuffer(t.FRAMEBUFFER,null)):(t.viewport(0,0,n.width,n.height),t.bindFramebuffer(t.FRAMEBUFFER,n.fbo)),o&&(t.clearColor(0,0,0,1),t.clear(t.COLOR_BUFFER_BIT)),t.drawElements(t.TRIANGLES,6,t.UNSIGNED_SHORT,0)}})(),R,f,K,$,C,fe=new w(L,Ge),J=new w(L,Me),_=new w(L,Ne),D=new w(L,ze),Z=new w(L,Oe),Q=new w(L,Xe),U=new w(L,ke),O=new w(L,He),X=new w(L,Ye),k=new z(L,Ie);function ee(){let e=Fe(s.simResolution),r=Fe(s.dyeResolution),n=p.halfFloatTexType,o=p.formatRGBA,i=p.formatRG,l=p.formatR,u=p.supportLinearFiltering?t.LINEAR:t.NEAREST;t.disable(t.BLEND),R==null?R=te(r.width,r.height,o.internalFormat,o.format,n,u):R=de(R,r.width,r.height,o.internalFormat,o.format,n,u),f==null?f=te(e.width,e.height,i.internalFormat,i.format,n,u):f=de(f,e.width,e.height,i.internalFormat,i.format,n,u),K=G(e.width,e.height,l.internalFormat,l.format,n,t.NEAREST),$=G(e.width,e.height,l.internalFormat,l.format,n,t.NEAREST),C=te(e.width,e.height,l.internalFormat,l.format,n,t.NEAREST)}function G(e,r,n,o,i,l){t.activeTexture(t.TEXTURE0);let u=t.createTexture();t.bindTexture(t.TEXTURE_2D,u),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,l),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,l),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texImage2D(t.TEXTURE_2D,0,n,e,r,0,o,i,null);let v=t.createFramebuffer();t.bindFramebuffer(t.FRAMEBUFFER,v),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,u,0),t.viewport(0,0,e,r),t.clear(t.COLOR_BUFFER_BIT);let x=1/e,P=1/r;return{texture:u,fbo:v,width:e,height:r,texelSizeX:x,texelSizeY:P,attach(d){return t.activeTexture(t.TEXTURE0+d),t.bindTexture(t.TEXTURE_2D,u),d}}}function te(e,r,n,o,i,l){let u=G(e,r,n,o,i,l),v=G(e,r,n,o,i,l);return{width:e,height:r,texelSizeX:u.texelSizeX,texelSizeY:u.texelSizeY,get read(){return u},set read(x){u=x},get write(){return v},set write(x){v=x},swap(){let x=u;u=v,v=x}}}function We(e,r,n,o,i,l,u){let v=G(r,n,o,i,l,u);return fe.bind(),t.uniform1i(fe.uniforms.uTexture,e.attach(0)),E(v),v}function de(e,r,n,o,i,l,u){return e.width===r&&e.height===n||(e.read=We(e.read,r,n,o,i,l,u),e.write=G(r,n,o,i,l,u),e.width=r,e.height=n,e.texelSizeX=1/r,e.texelSizeY=1/n),e}function Ve(){let e=[];s.shading&&e.push("shading"),k.setKeywords(e)}Ve(),ee();let re=Date.now(),H=0,ne=0;function me(){let e=je();N()&&ee(),qe(e),Ke(),s.paused||$e(e),ve(null),ne=requestAnimationFrame(me)}function je(){let e=Date.now(),r=(e-re)/1e3;return r=Math.min(r,.016666),re=e,r}function N(){let e=T(a.clientWidth),r=T(a.clientHeight);return a.width!==e||a.height!==r?(a.width=e,a.height=r,!0):!1}function qe(e){H+=e*s.colorUpdateSpeed,H>=1&&(H=it(H,0,1),g.forEach(r=>{r.color=Te(Y())}))}function Ke(){g.forEach(e=>{e.moved&&(e.moved=!1,Ze(e))})}function $e(e){t.disable(t.BLEND),Q.bind(),t.uniform2f(Q.uniforms.texelSize,f.texelSizeX,f.texelSizeY),t.uniform1i(Q.uniforms.uVelocity,f.read.attach(0)),E($),U.bind(),t.uniform2f(U.uniforms.texelSize,f.texelSizeX,f.texelSizeY),t.uniform1i(U.uniforms.uVelocity,f.read.attach(0)),t.uniform1i(U.uniforms.uCurl,$.attach(1)),t.uniform1f(U.uniforms.curl,s.curl),t.uniform1f(U.uniforms.dt,e),E(f.write),f.swap(),Z.bind(),t.uniform2f(Z.uniforms.texelSize,f.texelSizeX,f.texelSizeY),t.uniform1i(Z.uniforms.uVelocity,f.read.attach(0)),E(K),J.bind(),t.uniform1i(J.uniforms.uTexture,C.read.attach(0)),t.uniform1f(J.uniforms.value,s.pressure),E(C.write),C.swap(),O.bind(),t.uniform2f(O.uniforms.texelSize,f.texelSizeX,f.texelSizeY),t.uniform1i(O.uniforms.uDivergence,K.attach(0));for(let n=0;n<s.pressureIteration;n++)t.uniform1i(O.uniforms.uPressure,C.read.attach(1)),E(C.write),C.swap();X.bind(),t.uniform2f(X.uniforms.texelSize,f.texelSizeX,f.texelSizeY),t.uniform1i(X.uniforms.uPressure,C.read.attach(0)),t.uniform1i(X.uniforms.uVelocity,f.read.attach(1)),E(f.write),f.swap(),D.bind(),t.uniform2f(D.uniforms.texelSize,f.texelSizeX,f.texelSizeY),p.supportLinearFiltering||t.uniform2f(D.uniforms.dyeTexelSize,f.texelSizeX,f.texelSizeY);let r=f.read.attach(0);t.uniform1i(D.uniforms.uVelocity,r),t.uniform1i(D.uniforms.uSource,r),t.uniform1f(D.uniforms.dt,e),t.uniform1f(D.uniforms.dissipation,s.velocityDissipation),E(f.write),f.swap(),p.supportLinearFiltering||t.uniform2f(D.uniforms.dyeTexelSize,R.texelSizeX,R.texelSizeY),t.uniform1i(D.uniforms.uVelocity,f.read.attach(0)),t.uniform1i(D.uniforms.uSource,R.read.attach(1)),t.uniform1f(D.uniforms.dissipation,s.densityDissipation),E(R.write),R.swap()}function ve(e){t.blendFunc(t.ONE,t.ONE_MINUS_SRC_ALPHA),t.enable(t.BLEND),Je(e)}function Je(e){let r=e==null?t.drawingBufferWidth:e.width,n=e==null?t.drawingBufferHeight:e.height;k.bind(),s.shading&&t.uniform2f(k.uniforms.texelSize,1/r,1/n),t.uniform1i(k.uniforms.uTexture,R.read.attach(0)),E(e)}function Ze(e){let r=e.deltaX*s.splatForce,n=e.deltaY*s.splatForce,o=nt(e.color);oe(e.texcoordX,e.texcoordY,r,n,o)}function pe(e){let r=Y();r.r*=10,r.g*=10,r.b*=10;let n=10*(Math.random()-.5),o=30*(Math.random()-.5);oe(e.texcoordX,e.texcoordY,n,o,r)}function oe(e,r,n,o,i){_.bind(),t.uniform1i(_.uniforms.uTarget,f.read.attach(0)),t.uniform1f(_.uniforms.aspectRatio,a.width/a.height),t.uniform2f(_.uniforms.point,e,r),t.uniform3f(_.uniforms.color,n,o,0),t.uniform1f(_.uniforms.radius,Qe(s.splatRadius/100)),E(f.write),f.swap(),t.uniform1i(_.uniforms.uTarget,R.read.attach(0)),t.uniform3f(_.uniforms.color,i.r,i.g,i.b),E(R.write),R.swap()}function Qe(e){let r=a.width/a.height;return r>1&&(e*=r),e}let he=e=>{let r=g[0],n=a.getBoundingClientRect(),o=T(e.clientX-n.left),i=T(e.clientY-n.top);ye(r,-1,o,i),pe(r)},xe=e=>{let r=g[0],n=a.getBoundingClientRect(),o=T(e.clientX-n.left),i=T(e.clientY-n.top),l=r.color;Ee(r,o,i,l)},be=e=>{let r=e.targetTouches,n=a.getBoundingClientRect(),o=g[0];for(let i=0;i<r.length;i++){let l=T(r[i].clientX-n.left),u=T(r[i].clientY-n.top);ye(o,r[i].identifier,l,u),pe(o)}},ge=e=>{e.preventDefault();let r=e.targetTouches,n=a.getBoundingClientRect(),o=g[0];for(let i=0;i<r.length;i++){let l=T(r[i].clientX-n.left),u=T(r[i].clientY-n.top);Ee(o,l,u,o.color)}},Re=e=>{let r=e.changedTouches,n=g[0];for(let o=0;o<r.length;o++)et(n)};window.addEventListener("mousedown",he),window.addEventListener("mousemove",xe),window.addEventListener("touchstart",be),window.addEventListener("touchmove",ge,{passive:!1}),window.addEventListener("touchend",Re);function ye(e,r,n,o){e.id=r,e.down=!0,e.moved=!1,e.texcoordX=n/a.width,e.texcoordY=1-o/a.height,e.prevTexcoordX=e.texcoordX,e.prevTexcoordY=e.texcoordY,e.deltaX=0,e.deltaY=0,e.color=Te(Y())}function Ee(e,r,n,o){e.prevTexcoordX=e.texcoordX,e.prevTexcoordY=e.texcoordY,e.texcoordX=r/a.width,e.texcoordY=1-n/a.height,e.deltaX=tt(e.texcoordX-e.prevTexcoordX),e.deltaY=rt(e.texcoordY-e.prevTexcoordY),e.moved=Math.abs(e.deltaX)>0||Math.abs(e.deltaY)>0,e.color=o}function et(e){e.down=!1}function tt(e){let r=a.width/a.height;return r<1&&(e*=r),e}function rt(e){let r=a.width/a.height;return r>1&&(e/=r),e}function Y(){let e=s.colorIntensity,r=s.palette;if(r&&r.length>0){let o=r[Math.floor(Math.random()*r.length)],i=ct(o);if(i)return{r:i.r*e,g:i.g*e,b:i.b*e}}let n=ot(Math.random(),1,1);return n.r*=e,n.g*=e,n.b*=e,n}function Te(e){return[e.r,e.g,e.b]}function nt(e){return{r:e[0],g:e[1],b:e[2]}}function ot(e,r,n){let o=0,i=0,l=0,u=Math.floor(e*6),v=e*6-u,x=n*(1-r),P=n*(1-v*r),d=n*(1-(1-v)*r);switch(u%6){case 0:o=n,i=d,l=x;break;case 1:o=P,i=n,l=x;break;case 2:o=x,i=n,l=d;break;case 3:o=x,i=P,l=n;break;case 4:o=d,i=x,l=n;break;case 5:o=n,i=x,l=P;break}return{r:o,g:i,b:l}}function it(e,r,n){let o=n-r;return o===0?r:(e-r)%o+r}function Fe(e){let r=t.drawingBufferWidth/t.drawingBufferHeight;r<1&&(r=1/r);let n=Math.round(e),o=Math.round(e*r);return t.drawingBufferWidth>t.drawingBufferHeight?{width:o,height:n}:{width:n,height:o}}function T(e){let r=Math.min(window.devicePixelRatio||1,Math.max(1,s.maxDpr));return Math.floor(e*r)}function st(e){if(e.length===0)return 0;let r=0;for(let n=0;n<e.length;n++)r=(r<<5)-r+e.charCodeAt(n),r|=0;return r}function at(){var e,r;ie||(ie=!0,j(),window.removeEventListener("mousedown",he),window.removeEventListener("mousemove",xe),window.removeEventListener("touchstart",be),window.removeEventListener("touchmove",ge),window.removeEventListener("touchend",Re),window.removeEventListener("resize",De),document.removeEventListener("visibilitychange",Se),(e=y==null?void 0:y.removeEventListener)==null||e.call(y,"change",Le),M==null||M.disconnect(),b&&(a==null||a.remove()),(r=t.getExtension("WEBGL_lose_context"))==null||r.loseContext())}let ie=!1,W=!1;function V(){W||ie||(W=!0,re=Date.now(),ne=requestAnimationFrame(me))}function j(){W=!1,cancelAnimationFrame(ne)}let Se=()=>{s.pauseOnHidden&&(document.hidden?j():I||V())},De=()=>N(),M=typeof ResizeObserver!="undefined"?new ResizeObserver(()=>N()):null;M==null||M.observe(a);let y=typeof window.matchMedia=="function"?window.matchMedia("(prefers-reduced-motion: reduce)"):null,Le=()=>{s.respectReducedMotion&&(y!=null&&y.matches?j():I||V())},I=!1;return window.addEventListener("resize",De),document.addEventListener("visibilitychange",Se),(Ce=y==null?void 0:y.addEventListener)==null||Ce.call(y,"change",Le),s.respectReducedMotion&&ft()?(I=!0,ve(null)):V(),{dispose:at,pause(){I=!0,j()},resume(){I=!1,V()},isPaused:()=>I||!W,setConfig(e){let r=e.simResolution!==void 0&&e.simResolution!==s.simResolution||e.dyeResolution!==void 0&&e.dyeResolution!==s.dyeResolution;Object.assign(s,e),e.maxDpr!==void 0&&N(),r&&ee(),e.zIndex!==void 0&&(a.style.zIndex=String(e.zIndex)),e.pointerEvents!==void 0&&(a.style.pointerEvents=e.pointerEvents?"auto":"none")},splat(e,r,n){let o=a.getBoundingClientRect(),i=T(e),l=T(r),u=n!=null?n:Y();oe(i,a.height-l,0,0,u)},get canvas(){return a}}};var Ae={Spectrum:null,Sunset:["#ff4ecd","#ff8a4e","#ffd24e"],Ocean:["#4ea8ff","#4effd2","#7c4dff"],Mono:["#ffffff"],Aurora:["#3affa3","#38d9ff","#8f7bff"],Ember:["#ff5722","#ff9100","#ffc400"],Lagoon:["#00c2a8","#00a3ff","#0057d9"],Candy:["#ff8fd0","#ffa9f0","#c79bff"],Toxic:["#b6ff00","#4dff88","#00ffc8"],Royal:["#5b2bff","#8f4dff","#c44dff"],Sakura:["#ffc2dd","#ff8fb1","#ff6f91"],Mint:["#9cffd6","#5ef2c0","#2fd6a5"],Copper:["#ff9a5a","#e2703a","#b34700"],Ultraviolet:["#7b2cff","#b429ff","#ff29f0"],Ice:["#c9f0ff","#8ad4ff","#4fb3ff"],Magma:["#ff2d2d","#ff6a00","#ffb300"],Forest:["#2f9e44","#69db7c","#a9e34b"],Dusk:["#3b3b98","#7158e2","#cd84f1"],Cyber:["#00fff0","#ff00e0","#fffb00"],Pastel:["#ffd6e0","#c7ceea","#b5ead7"]},Ue={Calm:{curl:3,splatForce:4200,splatRadius:.45,densityDissipation:4.6,velocityDissipation:2.6,pressureIteration:16,colorUpdateSpeed:6},Flow:{curl:10,splatForce:6e3,splatRadius:.5,densityDissipation:3.5,velocityDissipation:2,pressureIteration:20,colorUpdateSpeed:10},Swirl:{curl:24,splatForce:7200,splatRadius:.55,densityDissipation:3,velocityDissipation:1.6,pressureIteration:24,colorUpdateSpeed:12},Storm:{curl:40,splatForce:9500,splatRadius:.65,densityDissipation:2.2,velocityDissipation:1.2,pressureIteration:28,colorUpdateSpeed:16},Wisp:{curl:6,splatForce:3200,splatRadius:.32,densityDissipation:6.5,velocityDissipation:3.4,pressureIteration:12,colorUpdateSpeed:8}},dt=()=>{let c={};for(let[s,b]of Object.entries(Ae))for(let[a,B]of Object.entries(Ue)){let F=`${s} ${a}`;c[F]={...B,palette:b?[...b]:null,colorIntensity:b===null?.15:.18}}return c},ae=dt(),mt=Object.keys(ae),vt=Object.keys(Ae),pt=Object.keys(Ue),ht=c=>ae[c];import{jsx as Rt}from"react/jsx-runtime";var xt=["densityDissipation","velocityDissipation","pressure","pressureIteration","curl","splatRadius","splatForce","shading","colorUpdateSpeed","paused","transparent","backColor","palette","colorIntensity","zIndex","pointerEvents","maxDpr","pauseOnHidden","respectReducedMotion"],bt=c=>JSON.stringify([c==null?void 0:c.id,c==null?void 0:c.position,c==null?void 0:c.className,c==null?void 0:c.simResolution,c==null?void 0:c.dyeResolution,c==null?void 0:c.captureResolution]);function gt(c,s){let b=A.useRef(null),a=A.useRef(c);a.current=c;let B=bt(c);return A.useEffect(()=>{let F=Be({...a.current,...s!=null&&s.current?{container:s.current}:{}});return b.current=F,()=>{F.dispose(),b.current=null}},[B,s]),A.useEffect(()=>{let F=b.current;if(!F||!c)return;let g={};for(let t of xt)c[t]!==void 0&&(g[t]=c[t]);F.setConfig(g)}),b}var Dt=A.forwardRef(function({config:s,scoped:b=!1,className:a,style:B,children:F},g){let t=A.useRef(null),p=gt(s,b?t:void 0);return A.useImperativeHandle(g,()=>({dispose:()=>{var m;return(m=p.current)==null?void 0:m.dispose()},pause:()=>{var m;return(m=p.current)==null?void 0:m.pause()},resume:()=>{var m;return(m=p.current)==null?void 0:m.resume()},isPaused:()=>{var m,h;return(h=(m=p.current)==null?void 0:m.isPaused())!=null?h:!0},setConfig:m=>{var h;return(h=p.current)==null?void 0:h.setConfig(m)},splat:(m,h,q)=>{var z;return(z=p.current)==null?void 0:z.splat(m,h,q)},get canvas(){var m,h;return(h=(m=p.current)==null?void 0:m.canvas)!=null?h:null}}),[p]),b?Rt("div",{ref:t,className:a,style:{position:"relative",overflow:"hidden",...B},children:F}):null});export{Dt as SmokeyFluidCursor,pt as characterNames,ht as getPreset,Be as initFluid,vt as paletteNames,mt as presetNames,ae as presets,gt as useSmokeyFluidCursor};
|
|
2
|
+
import o from"react";import{initFluid as c}from"smokey-fluid-cursor";import{initFluid as h,presets as v,presetNames as H,paletteNames as E,characterNames as x,getPreset as L}from"smokey-fluid-cursor";import{jsx as R}from"react/jsx-runtime";var F=["densityDissipation","velocityDissipation","pressure","pressureIteration","curl","splatRadius","splatForce","shading","colorUpdateSpeed","paused","transparent","backColor","palette","colorIntensity","zIndex","pointerEvents","maxDpr","pauseOnHidden","respectReducedMotion"],k=e=>JSON.stringify([e==null?void 0:e.id,e==null?void 0:e.position,e==null?void 0:e.className,e==null?void 0:e.simResolution,e==null?void 0:e.dyeResolution,e==null?void 0:e.captureResolution]);function C(e,u){let l=o.useRef(null),d=o.useRef(e);d.current=e;let p=k(e);return o.useEffect(()=>{let a=c({...d.current,...u!=null&&u.current?{container:u.current}:{}});return l.current=a,()=>{a.dispose(),l.current=null}},[p,u]),o.useEffect(()=>{let a=l.current;if(!a||!e)return;let i={};for(let n of F)e[n]!==void 0&&(i[n]=e[n]);a.setConfig(i)}),l}var P=o.forwardRef(function({config:u,scoped:l=!1,className:d,style:p,children:a},i){let n=o.useRef(null),s=C(u,l?n:void 0);return o.useImperativeHandle(i,()=>({dispose:()=>{var r;return(r=s.current)==null?void 0:r.dispose()},pause:()=>{var r;return(r=s.current)==null?void 0:r.pause()},resume:()=>{var r;return(r=s.current)==null?void 0:r.resume()},isPaused:()=>{var r,t;return(t=(r=s.current)==null?void 0:r.isPaused())!=null?t:!0},setConfig:r=>{var t;return(t=s.current)==null?void 0:t.setConfig(r)},splat:(r,t,y)=>{var m;return(m=s.current)==null?void 0:m.splat(r,t,y)},get canvas(){var r,t;return(t=(r=s.current)==null?void 0:r.canvas)!=null?t:null}}),[s]),l?R("div",{ref:n,className:d,style:{position:"relative",overflow:"hidden",...p},children:a}):null});export{P as SmokeyFluidCursor,x as characterNames,L as getPreset,h as initFluid,E as paletteNames,H as presetNames,v as presets,C as useSmokeyFluidCursor};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-smokey-fluid-cursor",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "A customizable fluid cursor effect for React & Next.js Apps running on the web. Enhance user experience with smooth, interactive cursor animations. Perfect for modern web designs.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -97,5 +97,8 @@
|
|
|
97
97
|
"publishConfig": {
|
|
98
98
|
"access": "public",
|
|
99
99
|
"provenance": true
|
|
100
|
+
},
|
|
101
|
+
"dependencies": {
|
|
102
|
+
"smokey-fluid-cursor": "^2.1.0"
|
|
100
103
|
}
|
|
101
104
|
}
|