interactive-bg 0.1.0 → 0.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 +55 -7
- package/dist/fluid/canvas2d.cjs +14 -0
- package/dist/fluid/canvas2d.cjs.map +1 -0
- package/dist/fluid/canvas2d.d.cts +5 -0
- package/dist/fluid/canvas2d.d.ts +5 -0
- package/dist/fluid/canvas2d.js +13 -0
- package/dist/fluid/canvas2d.js.map +1 -0
- package/dist/fluid/index.cjs +16 -0
- package/dist/fluid/index.cjs.map +1 -0
- package/dist/fluid/index.d.cts +5 -0
- package/dist/fluid/index.d.ts +5 -0
- package/dist/fluid/index.js +15 -0
- package/dist/fluid/index.js.map +1 -0
- package/dist/fluid/webgl.cjs +14 -0
- package/dist/fluid/webgl.cjs.map +1 -0
- package/dist/fluid/webgl.d.cts +5 -0
- package/dist/fluid/webgl.d.ts +5 -0
- package/dist/fluid/webgl.js +13 -0
- package/dist/fluid/webgl.js.map +1 -0
- package/dist/index.cjs +4 -0
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -1
- package/dist/index.umd.js +255 -12
- package/dist/index.umd.js.map +1 -1
- package/dist/shimmer/canvas2d.cjs +14 -0
- package/dist/shimmer/canvas2d.cjs.map +1 -0
- package/dist/shimmer/canvas2d.d.cts +5 -0
- package/dist/shimmer/canvas2d.d.ts +5 -0
- package/dist/shimmer/canvas2d.js +13 -0
- package/dist/shimmer/canvas2d.js.map +1 -0
- package/dist/shimmer/index.cjs +16 -0
- package/dist/shimmer/index.cjs.map +1 -0
- package/dist/shimmer/index.d.cts +5 -0
- package/dist/shimmer/index.d.ts +5 -0
- package/dist/shimmer/index.js +15 -0
- package/dist/shimmer/index.js.map +1 -0
- package/dist/shimmer/webgl.cjs +14 -0
- package/dist/shimmer/webgl.cjs.map +1 -0
- package/dist/shimmer/webgl.d.cts +5 -0
- package/dist/shimmer/webgl.d.ts +5 -0
- package/dist/shimmer/webgl.js +13 -0
- package/dist/shimmer/webgl.js.map +1 -0
- package/dist/styles/fluid/canvas2d.cjs +155 -0
- package/dist/styles/fluid/canvas2d.cjs.map +1 -0
- package/dist/styles/fluid/canvas2d.d.cts +8 -0
- package/dist/styles/fluid/canvas2d.d.ts +8 -0
- package/dist/styles/fluid/canvas2d.js +155 -0
- package/dist/styles/fluid/canvas2d.js.map +1 -0
- package/dist/styles/fluid/color.cjs +40 -0
- package/dist/styles/fluid/color.cjs.map +1 -0
- package/dist/styles/fluid/color.d.cts +4 -0
- package/dist/styles/fluid/color.d.ts +4 -0
- package/dist/styles/fluid/color.js +40 -0
- package/dist/styles/fluid/color.js.map +1 -0
- package/dist/styles/fluid/definition.cjs +14 -0
- package/dist/styles/fluid/definition.cjs.map +1 -0
- package/dist/styles/fluid/definition.d.cts +8 -0
- package/dist/styles/fluid/definition.d.ts +8 -0
- package/dist/styles/fluid/definition.js +15 -0
- package/dist/styles/fluid/definition.js.map +1 -0
- package/dist/styles/fluid/options.cjs +29 -0
- package/dist/styles/fluid/options.cjs.map +1 -0
- package/dist/styles/fluid/options.d.cts +31 -0
- package/dist/styles/fluid/options.d.ts +31 -0
- package/dist/styles/fluid/options.js +28 -0
- package/dist/styles/fluid/options.js.map +1 -0
- package/dist/styles/fluid/settings.cjs +32 -0
- package/dist/styles/fluid/settings.cjs.map +1 -0
- package/dist/styles/fluid/settings.d.cts +24 -0
- package/dist/styles/fluid/settings.d.ts +24 -0
- package/dist/styles/fluid/settings.js +23 -0
- package/dist/styles/fluid/settings.js.map +1 -0
- package/dist/styles/fluid/simulation.cjs +183 -0
- package/dist/styles/fluid/simulation.cjs.map +1 -0
- package/dist/styles/fluid/simulation.d.cts +22 -0
- package/dist/styles/fluid/simulation.d.ts +22 -0
- package/dist/styles/fluid/simulation.js +183 -0
- package/dist/styles/fluid/simulation.js.map +1 -0
- package/dist/styles/fluid/size.cjs +17 -0
- package/dist/styles/fluid/size.cjs.map +1 -0
- package/dist/styles/fluid/size.d.cts +5 -0
- package/dist/styles/fluid/size.d.ts +5 -0
- package/dist/styles/fluid/size.js +17 -0
- package/dist/styles/fluid/size.js.map +1 -0
- package/dist/styles/fluid/webgl.cjs +607 -0
- package/dist/styles/fluid/webgl.cjs.map +1 -0
- package/dist/styles/fluid/webgl.d.cts +3 -0
- package/dist/styles/fluid/webgl.d.ts +3 -0
- package/dist/styles/fluid/webgl.js +607 -0
- package/dist/styles/fluid/webgl.js.map +1 -0
- package/dist/styles/shimmer/canvas2d.cjs +84 -0
- package/dist/styles/shimmer/canvas2d.cjs.map +1 -0
- package/dist/styles/shimmer/canvas2d.d.cts +3 -0
- package/dist/styles/shimmer/canvas2d.d.ts +3 -0
- package/dist/styles/shimmer/canvas2d.js +84 -0
- package/dist/styles/shimmer/canvas2d.js.map +1 -0
- package/dist/styles/shimmer/definition.cjs +15 -0
- package/dist/styles/shimmer/definition.cjs.map +1 -0
- package/dist/styles/shimmer/definition.d.cts +8 -0
- package/dist/styles/shimmer/definition.d.ts +8 -0
- package/dist/styles/shimmer/definition.js +16 -0
- package/dist/styles/shimmer/definition.js.map +1 -0
- package/dist/styles/shimmer/field.cjs +79 -0
- package/dist/styles/shimmer/field.cjs.map +1 -0
- package/dist/styles/shimmer/field.d.cts +11 -0
- package/dist/styles/shimmer/field.d.ts +11 -0
- package/dist/styles/shimmer/field.js +78 -0
- package/dist/styles/shimmer/field.js.map +1 -0
- package/dist/styles/shimmer/options.cjs +28 -0
- package/dist/styles/shimmer/options.cjs.map +1 -0
- package/dist/styles/shimmer/options.d.cts +22 -0
- package/dist/styles/shimmer/options.d.ts +22 -0
- package/dist/styles/shimmer/options.js +27 -0
- package/dist/styles/shimmer/options.js.map +1 -0
- package/dist/styles/shimmer/webgl.cjs +89 -0
- package/dist/styles/shimmer/webgl.cjs.map +1 -0
- package/dist/styles/shimmer/webgl.d.cts +4 -0
- package/dist/styles/shimmer/webgl.d.ts +4 -0
- package/dist/styles/shimmer/webgl.js +89 -0
- package/dist/styles/shimmer/webgl.js.map +1 -0
- package/package.json +76 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.js","names":[],"sources":["../../../src/styles/fluid/color.ts"],"sourcesContent":["import { parseColor } from '../../core/color';\nimport type { ResolvedFluidOptions } from './options';\n\nexport type RGB = readonly [number, number, number];\n\n/** HSL (all in 0–1) to straight RGB. */\nfunction hslToRgb(h: number, s: number, l: number): RGB {\n if (s === 0) return [l, l, l];\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const p = 2 * l - q;\n const channel = (t: number) => {\n let k = t % 1;\n if (k < 0) k += 1;\n if (k < 1 / 6) return p + (q - p) * 6 * k;\n if (k < 1 / 2) return q;\n if (k < 2 / 3) return p + (q - p) * (2 / 3 - k) * 6;\n return p;\n };\n return [channel(h + 1 / 3), channel(h), channel(h - 1 / 3)];\n}\n\n/** The colour of a splash made at `clock` seconds: the fixed colour, or the cycling hue. */\nexport function splatColor(options: ResolvedFluidOptions, clock: number): RGB {\n if (options.color) {\n const [r, g, b, a] = parseColor(options.color);\n return [r * a, g * a, b * a];\n }\n const step = Math.floor(clock * options.colorSpeed);\n const hue = (((0.55 + step * 0.61803398875) % 1) + 1) % 1;\n return hslToRgb(hue, 1, 0.5);\n}\n"],"mappings":";;;AAMA,SAAS,SAAS,GAAW,GAAW,GAAgB;CACtD,IAAI,MAAM,GAAG,OAAO;EAAC;EAAG;EAAG;CAAC;CAC5B,MAAM,IAAI,IAAI,KAAM,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI;CAC9C,MAAM,IAAI,IAAI,IAAI;CAClB,MAAM,WAAW,MAAc;EAC7B,IAAI,IAAI,IAAI;EACZ,IAAI,IAAI,GAAG,KAAK;EAChB,IAAI,IAAI,IAAI,GAAG,OAAO,KAAK,IAAI,KAAK,IAAI;EACxC,IAAI,IAAI,IAAI,GAAG,OAAO;EACtB,IAAI,IAAI,IAAI,GAAG,OAAO,KAAK,IAAI,MAAM,IAAI,IAAI,KAAK;EAClD,OAAO;CACT;CACA,OAAO;EAAC,QAAQ,IAAI,IAAI,CAAC;EAAG,QAAQ,CAAC;EAAG,QAAQ,IAAI,IAAI,CAAC;CAAC;AAC5D;;AAGA,SAAgB,WAAW,SAA+B,OAAoB;CAC5E,IAAI,QAAQ,OAAO;EACjB,MAAM,CAAC,GAAG,GAAG,GAAG,KAAK,WAAW,QAAQ,KAAK;EAC7C,OAAO;GAAC,IAAI;GAAG,IAAI;GAAG,IAAI;EAAC;CAC7B;CAGA,OAAO,WADQ,MADF,KAAK,MAAM,QAAQ,QAAQ,UAClB,IAAO,gBAAiB,IAAK,KAAK,GACnC,GAAG,EAAG;AAC7B"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// src/styles/fluid/definition.ts
|
|
2
|
+
/**
|
|
3
|
+
* A GPU fluid simulation: pointer movement injects velocity and dye, the dye is
|
|
4
|
+
* advected into curling plumes, and clicks send out a burst. A gentle splash
|
|
5
|
+
* plays when the background appears; otherwise it is still until stirred.
|
|
6
|
+
*/
|
|
7
|
+
var fluidStyle = {
|
|
8
|
+
name: "fluid",
|
|
9
|
+
defaults: require("./options.cjs").fluidDefaults,
|
|
10
|
+
animates: () => false
|
|
11
|
+
};
|
|
12
|
+
exports.fluidStyle = fluidStyle;
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=definition.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definition.cjs","names":["fluidDefaults"],"sources":["../../../src/styles/fluid/definition.ts"],"sourcesContent":["import type { StyleBase } from '../../core/style';\nimport { fluidDefaults, type FluidOptions } from './options';\n\n/**\n * A GPU fluid simulation: pointer movement injects velocity and dye, the dye is\n * advected into curling plumes, and clicks send out a burst. A gentle splash\n * plays when the background appears; otherwise it is still until stirred.\n */\nexport const fluidStyle: StyleBase<FluidOptions> = {\n name: 'fluid',\n defaults: fluidDefaults,\n // Nothing animates on its own: the initial burst and every reaction keep the\n // engine awake by returning true from render() until the smoke has settled.\n animates: () => false,\n};\n"],"mappings":";;;;;;AAQA,IAAa,aAAsC;CACjD,MAAM;CACN,U,uBAAUA,CAAAA,CAAAA;CAGV,gBAAgB;AAClB"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { StyleBase } from '../../core/style.cjs';
|
|
2
|
+
import { type FluidOptions } from './options.cjs';
|
|
3
|
+
/**
|
|
4
|
+
* A GPU fluid simulation: pointer movement injects velocity and dye, the dye is
|
|
5
|
+
* advected into curling plumes, and clicks send out a burst. A gentle splash
|
|
6
|
+
* plays when the background appears; otherwise it is still until stirred.
|
|
7
|
+
*/
|
|
8
|
+
export declare const fluidStyle: StyleBase<FluidOptions>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { StyleBase } from '../../core/style.js';
|
|
2
|
+
import { type FluidOptions } from './options.js';
|
|
3
|
+
/**
|
|
4
|
+
* A GPU fluid simulation: pointer movement injects velocity and dye, the dye is
|
|
5
|
+
* advected into curling plumes, and clicks send out a burst. A gentle splash
|
|
6
|
+
* plays when the background appears; otherwise it is still until stirred.
|
|
7
|
+
*/
|
|
8
|
+
export declare const fluidStyle: StyleBase<FluidOptions>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { fluidDefaults } from "./options.js";
|
|
2
|
+
// src/styles/fluid/definition.ts
|
|
3
|
+
/**
|
|
4
|
+
* A GPU fluid simulation: pointer movement injects velocity and dye, the dye is
|
|
5
|
+
* advected into curling plumes, and clicks send out a burst. A gentle splash
|
|
6
|
+
* plays when the background appears; otherwise it is still until stirred.
|
|
7
|
+
*/
|
|
8
|
+
var fluidStyle = {
|
|
9
|
+
name: "fluid",
|
|
10
|
+
defaults: fluidDefaults,
|
|
11
|
+
animates: () => false
|
|
12
|
+
};
|
|
13
|
+
export { fluidStyle };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=definition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definition.js","names":[],"sources":["../../../src/styles/fluid/definition.ts"],"sourcesContent":["import type { StyleBase } from '../../core/style';\nimport { fluidDefaults, type FluidOptions } from './options';\n\n/**\n * A GPU fluid simulation: pointer movement injects velocity and dye, the dye is\n * advected into curling plumes, and clicks send out a burst. A gentle splash\n * plays when the background appears; otherwise it is still until stirred.\n */\nexport const fluidStyle: StyleBase<FluidOptions> = {\n name: 'fluid',\n defaults: fluidDefaults,\n // Nothing animates on its own: the initial burst and every reaction keep the\n // engine awake by returning true from render() until the smoke has settled.\n animates: () => false,\n};\n"],"mappings":";;;;;;;AAQA,IAAa,aAAsC;CACjD,MAAM;CACN,UAAU;CAGV,gBAAgB;AAClB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/styles/fluid/options.ts
|
|
2
|
+
var fluidDefaults = Object.freeze({
|
|
3
|
+
color: null,
|
|
4
|
+
colorSpeed: 10,
|
|
5
|
+
opacity: .85,
|
|
6
|
+
curl: 10,
|
|
7
|
+
force: 6e3,
|
|
8
|
+
radius: 75,
|
|
9
|
+
fade: .3,
|
|
10
|
+
resolution: 128,
|
|
11
|
+
shading: true
|
|
12
|
+
});
|
|
13
|
+
var clamp = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
14
|
+
function resolveFluidOptions(options) {
|
|
15
|
+
return {
|
|
16
|
+
...options,
|
|
17
|
+
colorSpeed: Math.max(0, options.colorSpeed),
|
|
18
|
+
opacity: clamp(options.opacity, 0, 1),
|
|
19
|
+
curl: clamp(options.curl, 0, 100),
|
|
20
|
+
force: Math.max(0, options.force),
|
|
21
|
+
radius: Math.max(2, options.radius),
|
|
22
|
+
fade: Math.max(.2, options.fade),
|
|
23
|
+
resolution: Math.round(clamp(options.resolution, 48, 192))
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
exports.fluidDefaults = fluidDefaults;
|
|
27
|
+
exports.resolveFluidOptions = resolveFluidOptions;
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=options.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.cjs","names":[],"sources":["../../../src/styles/fluid/options.ts"],"sourcesContent":["export interface FluidOptions {\n /**\n * Colour of the smoke, as any CSS colour. `null` (the default) cycles through\n * hues over time; set a colour to keep every splat that colour.\n */\n color: string | null;\n /** How many times per second the smoke picks a new hue while `color` is `null`. */\n colorSpeed: number;\n /** Opacity of the smoke, from `0` to `1`. Multiplies any alpha in `color`. */\n opacity: number;\n /** How strongly the fluid curls back on itself: vorticity confinement. `0` = no swirl. */\n curl: number;\n /** How hard pointer movement stirs the fluid. `0` = the pointer only adds dye. */\n force: number;\n /** Radius of each splash, in CSS pixels. */\n radius: number;\n /** Roughly how long the smoke takes to fade out, in seconds. */\n fade: number;\n /**\n * Simulation grid size: the longer side of the velocity/dye field, in cells.\n * Higher is smoother and more detailed, at more CPU or GPU cost. The Canvas 2D\n * fallback runs the whole simulation at this resolution.\n */\n resolution: number;\n /** Light the smoke from the dye's own gradients, for a sense of depth. */\n shading: boolean;\n}\n\nexport const fluidDefaults: Readonly<FluidOptions> = Object.freeze({\n color: null,\n colorSpeed: 10,\n opacity: 0.85,\n curl: 10,\n force: 6000,\n radius: 75,\n fade: 0.3,\n resolution: 128,\n shading: true,\n});\n\n/** Options after clamping: what the simulation and the renderers consume. */\nexport type ResolvedFluidOptions = FluidOptions;\n\nconst clamp = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value));\n\nexport function resolveFluidOptions(options: FluidOptions): ResolvedFluidOptions {\n return {\n ...options,\n colorSpeed: Math.max(0, options.colorSpeed),\n opacity: clamp(options.opacity, 0, 1),\n curl: clamp(options.curl, 0, 100),\n force: Math.max(0, options.force),\n radius: Math.max(2, options.radius),\n fade: Math.max(0.2, options.fade),\n resolution: Math.round(clamp(options.resolution, 48, 192)),\n };\n}\n"],"mappings":";AA4BA,IAAa,gBAAwC,OAAO,OAAO;CACjE,OAAO;CACP,YAAY;CACZ,SAAS;CACT,MAAM;CACN,OAAO;CACP,QAAQ;CACR,MAAM;CACN,YAAY;CACZ,SAAS;AACX,CAAC;AAKD,IAAM,SAAS,OAAe,KAAa,QAAgB,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,CAAC;AAE7F,SAAgB,oBAAoB,SAA6C;CAC/E,OAAO;EACL,GAAG;EACH,YAAY,KAAK,IAAI,GAAG,QAAQ,UAAU;EAC1C,SAAS,MAAM,QAAQ,SAAS,GAAG,CAAC;EACpC,MAAM,MAAM,QAAQ,MAAM,GAAG,GAAG;EAChC,OAAO,KAAK,IAAI,GAAG,QAAQ,KAAK;EAChC,QAAQ,KAAK,IAAI,GAAG,QAAQ,MAAM;EAClC,MAAM,KAAK,IAAI,IAAK,QAAQ,IAAI;EAChC,YAAY,KAAK,MAAM,MAAM,QAAQ,YAAY,IAAI,GAAG,CAAC;CAC3D;AACF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface FluidOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Colour of the smoke, as any CSS colour. `null` (the default) cycles through
|
|
4
|
+
* hues over time; set a colour to keep every splat that colour.
|
|
5
|
+
*/
|
|
6
|
+
color: string | null;
|
|
7
|
+
/** How many times per second the smoke picks a new hue while `color` is `null`. */
|
|
8
|
+
colorSpeed: number;
|
|
9
|
+
/** Opacity of the smoke, from `0` to `1`. Multiplies any alpha in `color`. */
|
|
10
|
+
opacity: number;
|
|
11
|
+
/** How strongly the fluid curls back on itself: vorticity confinement. `0` = no swirl. */
|
|
12
|
+
curl: number;
|
|
13
|
+
/** How hard pointer movement stirs the fluid. `0` = the pointer only adds dye. */
|
|
14
|
+
force: number;
|
|
15
|
+
/** Radius of each splash, in CSS pixels. */
|
|
16
|
+
radius: number;
|
|
17
|
+
/** Roughly how long the smoke takes to fade out, in seconds. */
|
|
18
|
+
fade: number;
|
|
19
|
+
/**
|
|
20
|
+
* Simulation grid size: the longer side of the velocity/dye field, in cells.
|
|
21
|
+
* Higher is smoother and more detailed, at more CPU or GPU cost. The Canvas 2D
|
|
22
|
+
* fallback runs the whole simulation at this resolution.
|
|
23
|
+
*/
|
|
24
|
+
resolution: number;
|
|
25
|
+
/** Light the smoke from the dye's own gradients, for a sense of depth. */
|
|
26
|
+
shading: boolean;
|
|
27
|
+
}
|
|
28
|
+
export declare const fluidDefaults: Readonly<FluidOptions>;
|
|
29
|
+
/** Options after clamping: what the simulation and the renderers consume. */
|
|
30
|
+
export type ResolvedFluidOptions = FluidOptions;
|
|
31
|
+
export declare function resolveFluidOptions(options: FluidOptions): ResolvedFluidOptions;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface FluidOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Colour of the smoke, as any CSS colour. `null` (the default) cycles through
|
|
4
|
+
* hues over time; set a colour to keep every splat that colour.
|
|
5
|
+
*/
|
|
6
|
+
color: string | null;
|
|
7
|
+
/** How many times per second the smoke picks a new hue while `color` is `null`. */
|
|
8
|
+
colorSpeed: number;
|
|
9
|
+
/** Opacity of the smoke, from `0` to `1`. Multiplies any alpha in `color`. */
|
|
10
|
+
opacity: number;
|
|
11
|
+
/** How strongly the fluid curls back on itself: vorticity confinement. `0` = no swirl. */
|
|
12
|
+
curl: number;
|
|
13
|
+
/** How hard pointer movement stirs the fluid. `0` = the pointer only adds dye. */
|
|
14
|
+
force: number;
|
|
15
|
+
/** Radius of each splash, in CSS pixels. */
|
|
16
|
+
radius: number;
|
|
17
|
+
/** Roughly how long the smoke takes to fade out, in seconds. */
|
|
18
|
+
fade: number;
|
|
19
|
+
/**
|
|
20
|
+
* Simulation grid size: the longer side of the velocity/dye field, in cells.
|
|
21
|
+
* Higher is smoother and more detailed, at more CPU or GPU cost. The Canvas 2D
|
|
22
|
+
* fallback runs the whole simulation at this resolution.
|
|
23
|
+
*/
|
|
24
|
+
resolution: number;
|
|
25
|
+
/** Light the smoke from the dye's own gradients, for a sense of depth. */
|
|
26
|
+
shading: boolean;
|
|
27
|
+
}
|
|
28
|
+
export declare const fluidDefaults: Readonly<FluidOptions>;
|
|
29
|
+
/** Options after clamping: what the simulation and the renderers consume. */
|
|
30
|
+
export type ResolvedFluidOptions = FluidOptions;
|
|
31
|
+
export declare function resolveFluidOptions(options: FluidOptions): ResolvedFluidOptions;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// src/styles/fluid/options.ts
|
|
2
|
+
var fluidDefaults = Object.freeze({
|
|
3
|
+
color: null,
|
|
4
|
+
colorSpeed: 10,
|
|
5
|
+
opacity: .85,
|
|
6
|
+
curl: 10,
|
|
7
|
+
force: 6e3,
|
|
8
|
+
radius: 75,
|
|
9
|
+
fade: .3,
|
|
10
|
+
resolution: 128,
|
|
11
|
+
shading: true
|
|
12
|
+
});
|
|
13
|
+
var clamp = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
14
|
+
function resolveFluidOptions(options) {
|
|
15
|
+
return {
|
|
16
|
+
...options,
|
|
17
|
+
colorSpeed: Math.max(0, options.colorSpeed),
|
|
18
|
+
opacity: clamp(options.opacity, 0, 1),
|
|
19
|
+
curl: clamp(options.curl, 0, 100),
|
|
20
|
+
force: Math.max(0, options.force),
|
|
21
|
+
radius: Math.max(2, options.radius),
|
|
22
|
+
fade: Math.max(.2, options.fade),
|
|
23
|
+
resolution: Math.round(clamp(options.resolution, 48, 192))
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export { fluidDefaults, resolveFluidOptions };
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.js","names":[],"sources":["../../../src/styles/fluid/options.ts"],"sourcesContent":["export interface FluidOptions {\n /**\n * Colour of the smoke, as any CSS colour. `null` (the default) cycles through\n * hues over time; set a colour to keep every splat that colour.\n */\n color: string | null;\n /** How many times per second the smoke picks a new hue while `color` is `null`. */\n colorSpeed: number;\n /** Opacity of the smoke, from `0` to `1`. Multiplies any alpha in `color`. */\n opacity: number;\n /** How strongly the fluid curls back on itself: vorticity confinement. `0` = no swirl. */\n curl: number;\n /** How hard pointer movement stirs the fluid. `0` = the pointer only adds dye. */\n force: number;\n /** Radius of each splash, in CSS pixels. */\n radius: number;\n /** Roughly how long the smoke takes to fade out, in seconds. */\n fade: number;\n /**\n * Simulation grid size: the longer side of the velocity/dye field, in cells.\n * Higher is smoother and more detailed, at more CPU or GPU cost. The Canvas 2D\n * fallback runs the whole simulation at this resolution.\n */\n resolution: number;\n /** Light the smoke from the dye's own gradients, for a sense of depth. */\n shading: boolean;\n}\n\nexport const fluidDefaults: Readonly<FluidOptions> = Object.freeze({\n color: null,\n colorSpeed: 10,\n opacity: 0.85,\n curl: 10,\n force: 6000,\n radius: 75,\n fade: 0.3,\n resolution: 128,\n shading: true,\n});\n\n/** Options after clamping: what the simulation and the renderers consume. */\nexport type ResolvedFluidOptions = FluidOptions;\n\nconst clamp = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value));\n\nexport function resolveFluidOptions(options: FluidOptions): ResolvedFluidOptions {\n return {\n ...options,\n colorSpeed: Math.max(0, options.colorSpeed),\n opacity: clamp(options.opacity, 0, 1),\n curl: clamp(options.curl, 0, 100),\n force: Math.max(0, options.force),\n radius: Math.max(2, options.radius),\n fade: Math.max(0.2, options.fade),\n resolution: Math.round(clamp(options.resolution, 48, 192)),\n };\n}\n"],"mappings":";AA4BA,IAAa,gBAAwC,OAAO,OAAO;CACjE,OAAO;CACP,YAAY;CACZ,SAAS;CACT,MAAM;CACN,OAAO;CACP,QAAQ;CACR,MAAM;CACN,YAAY;CACZ,SAAS;AACX,CAAC;AAKD,IAAM,SAAS,OAAe,KAAa,QAAgB,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,CAAC;AAE7F,SAAgB,oBAAoB,SAA6C;CAC/E,OAAO;EACL,GAAG;EACH,YAAY,KAAK,IAAI,GAAG,QAAQ,UAAU;EAC1C,SAAS,MAAM,QAAQ,SAAS,GAAG,CAAC;EACpC,MAAM,MAAM,QAAQ,MAAM,GAAG,GAAG;EAChC,OAAO,KAAK,IAAI,GAAG,QAAQ,KAAK;EAChC,QAAQ,KAAK,IAAI,GAAG,QAAQ,MAAM;EAClC,MAAM,KAAK,IAAI,IAAK,QAAQ,IAAI;EAChC,YAAY,KAAK,MAAM,MAAM,QAAQ,YAAY,IAAI,GAAG,CAAC;CAC3D;AACF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// src/styles/fluid/settings.ts
|
|
2
|
+
/** How much dye one splash adds at its centre. */
|
|
3
|
+
var DYE_INTENSITY = .15;
|
|
4
|
+
/** Seconds for the velocity field to lose about two thirds of its strength. */
|
|
5
|
+
var VELOCITY_FADE = .5;
|
|
6
|
+
/** How much of the previous pressure field is kept between frames, as in the reference. */
|
|
7
|
+
var PRESSURE_RETENTION = .1;
|
|
8
|
+
/** The initial burst is this fraction of the pointer force: just enough to set the smoke moving. */
|
|
9
|
+
var BURST_FORCE = .003;
|
|
10
|
+
/** The initial burst covers this many times the pointer splash radius. */
|
|
11
|
+
var BURST_RADIUS = 2.2;
|
|
12
|
+
/** The initial burst adds this many times the usual dye, so it reads on an otherwise empty canvas. */
|
|
13
|
+
var BURST_DYE = 2.2;
|
|
14
|
+
/** Seconds after the last splash before the extra idle fade begins. */
|
|
15
|
+
var IDLE_DELAY = .5;
|
|
16
|
+
/** Effective dye fade time while the pointer is idle, in seconds. */
|
|
17
|
+
var IDLE_DECAY = .7;
|
|
18
|
+
/** Seconds after the last splash when the field is cleared completely. */
|
|
19
|
+
var IDLE_CLEAR = 3.5;
|
|
20
|
+
var MAX_DYE_RESOLUTION = 1440;
|
|
21
|
+
exports.BURST_DYE = BURST_DYE;
|
|
22
|
+
exports.BURST_FORCE = BURST_FORCE;
|
|
23
|
+
exports.BURST_RADIUS = BURST_RADIUS;
|
|
24
|
+
exports.DYE_INTENSITY = DYE_INTENSITY;
|
|
25
|
+
exports.IDLE_CLEAR = IDLE_CLEAR;
|
|
26
|
+
exports.IDLE_DECAY = IDLE_DECAY;
|
|
27
|
+
exports.IDLE_DELAY = IDLE_DELAY;
|
|
28
|
+
exports.MAX_DYE_RESOLUTION = MAX_DYE_RESOLUTION;
|
|
29
|
+
exports.PRESSURE_RETENTION = PRESSURE_RETENTION;
|
|
30
|
+
exports.VELOCITY_FADE = VELOCITY_FADE;
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=settings.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.cjs","names":[],"sources":["../../../src/styles/fluid/settings.ts"],"sourcesContent":["// Shared by the GPU and CPU simulations, so both produce the same kind of smoke.\n\n/** How much dye one splash adds at its centre. */\nexport const DYE_INTENSITY = 0.15;\n/** Seconds for the velocity field to lose about two thirds of its strength. */\nexport const VELOCITY_FADE = 0.5;\n/** How much of the previous pressure field is kept between frames, as in the reference. */\nexport const PRESSURE_RETENTION = 0.1;\n/** Pressure solve iterations (the CPU fallback uses fewer to stay cheap). */\nexport const PRESSURE_ITERATIONS = 20;\nexport const CPU_PRESSURE_ITERATIONS = 14;\n/** The initial burst is this fraction of the pointer force: just enough to set the smoke moving. */\nexport const BURST_FORCE = 0.003;\n/** The initial burst covers this many times the pointer splash radius. */\nexport const BURST_RADIUS = 2.2;\n/** The initial burst adds this many times the usual dye, so it reads on an otherwise empty canvas. */\nexport const BURST_DYE = 2.2;\n/** Seconds after the last splash before the extra idle fade begins. */\nexport const IDLE_DELAY = 0.5;\n/** Effective dye fade time while the pointer is idle, in seconds. */\nexport const IDLE_DECAY = 0.7;\n/** Seconds after the last splash when the field is cleared completely. */\nexport const IDLE_CLEAR = 3.5;\n\n/** The dye texture is this many times the simulation grid, up to a cap. */\nexport const DYE_SCALE = 8;\nexport const MAX_DYE_RESOLUTION = 1440;\n"],"mappings":";;AAGA,IAAa,gBAAgB;;AAE7B,IAAa,gBAAgB;;AAE7B,IAAa,qBAAqB;;AAKlC,IAAa,cAAc;;AAE3B,IAAa,eAAe;;AAE5B,IAAa,YAAY;;AAEzB,IAAa,aAAa;;AAE1B,IAAa,aAAa;;AAE1B,IAAa,aAAa;AAI1B,IAAa,qBAAqB"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** How much dye one splash adds at its centre. */
|
|
2
|
+
export declare const DYE_INTENSITY = 0.15;
|
|
3
|
+
/** Seconds for the velocity field to lose about two thirds of its strength. */
|
|
4
|
+
export declare const VELOCITY_FADE = 0.5;
|
|
5
|
+
/** How much of the previous pressure field is kept between frames, as in the reference. */
|
|
6
|
+
export declare const PRESSURE_RETENTION = 0.1;
|
|
7
|
+
/** Pressure solve iterations (the CPU fallback uses fewer to stay cheap). */
|
|
8
|
+
export declare const PRESSURE_ITERATIONS = 20;
|
|
9
|
+
export declare const CPU_PRESSURE_ITERATIONS = 14;
|
|
10
|
+
/** The initial burst is this fraction of the pointer force: just enough to set the smoke moving. */
|
|
11
|
+
export declare const BURST_FORCE = 0.003;
|
|
12
|
+
/** The initial burst covers this many times the pointer splash radius. */
|
|
13
|
+
export declare const BURST_RADIUS = 2.2;
|
|
14
|
+
/** The initial burst adds this many times the usual dye, so it reads on an otherwise empty canvas. */
|
|
15
|
+
export declare const BURST_DYE = 2.2;
|
|
16
|
+
/** Seconds after the last splash before the extra idle fade begins. */
|
|
17
|
+
export declare const IDLE_DELAY = 0.5;
|
|
18
|
+
/** Effective dye fade time while the pointer is idle, in seconds. */
|
|
19
|
+
export declare const IDLE_DECAY = 0.7;
|
|
20
|
+
/** Seconds after the last splash when the field is cleared completely. */
|
|
21
|
+
export declare const IDLE_CLEAR = 3.5;
|
|
22
|
+
/** The dye texture is this many times the simulation grid, up to a cap. */
|
|
23
|
+
export declare const DYE_SCALE = 8;
|
|
24
|
+
export declare const MAX_DYE_RESOLUTION = 1440;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** How much dye one splash adds at its centre. */
|
|
2
|
+
export declare const DYE_INTENSITY = 0.15;
|
|
3
|
+
/** Seconds for the velocity field to lose about two thirds of its strength. */
|
|
4
|
+
export declare const VELOCITY_FADE = 0.5;
|
|
5
|
+
/** How much of the previous pressure field is kept between frames, as in the reference. */
|
|
6
|
+
export declare const PRESSURE_RETENTION = 0.1;
|
|
7
|
+
/** Pressure solve iterations (the CPU fallback uses fewer to stay cheap). */
|
|
8
|
+
export declare const PRESSURE_ITERATIONS = 20;
|
|
9
|
+
export declare const CPU_PRESSURE_ITERATIONS = 14;
|
|
10
|
+
/** The initial burst is this fraction of the pointer force: just enough to set the smoke moving. */
|
|
11
|
+
export declare const BURST_FORCE = 0.003;
|
|
12
|
+
/** The initial burst covers this many times the pointer splash radius. */
|
|
13
|
+
export declare const BURST_RADIUS = 2.2;
|
|
14
|
+
/** The initial burst adds this many times the usual dye, so it reads on an otherwise empty canvas. */
|
|
15
|
+
export declare const BURST_DYE = 2.2;
|
|
16
|
+
/** Seconds after the last splash before the extra idle fade begins. */
|
|
17
|
+
export declare const IDLE_DELAY = 0.5;
|
|
18
|
+
/** Effective dye fade time while the pointer is idle, in seconds. */
|
|
19
|
+
export declare const IDLE_DECAY = 0.7;
|
|
20
|
+
/** Seconds after the last splash when the field is cleared completely. */
|
|
21
|
+
export declare const IDLE_CLEAR = 3.5;
|
|
22
|
+
/** The dye texture is this many times the simulation grid, up to a cap. */
|
|
23
|
+
export declare const DYE_SCALE = 8;
|
|
24
|
+
export declare const MAX_DYE_RESOLUTION = 1440;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// src/styles/fluid/settings.ts
|
|
2
|
+
/** How much dye one splash adds at its centre. */
|
|
3
|
+
var DYE_INTENSITY = .15;
|
|
4
|
+
/** Seconds for the velocity field to lose about two thirds of its strength. */
|
|
5
|
+
var VELOCITY_FADE = .5;
|
|
6
|
+
/** How much of the previous pressure field is kept between frames, as in the reference. */
|
|
7
|
+
var PRESSURE_RETENTION = .1;
|
|
8
|
+
/** The initial burst is this fraction of the pointer force: just enough to set the smoke moving. */
|
|
9
|
+
var BURST_FORCE = .003;
|
|
10
|
+
/** The initial burst covers this many times the pointer splash radius. */
|
|
11
|
+
var BURST_RADIUS = 2.2;
|
|
12
|
+
/** The initial burst adds this many times the usual dye, so it reads on an otherwise empty canvas. */
|
|
13
|
+
var BURST_DYE = 2.2;
|
|
14
|
+
/** Seconds after the last splash before the extra idle fade begins. */
|
|
15
|
+
var IDLE_DELAY = .5;
|
|
16
|
+
/** Effective dye fade time while the pointer is idle, in seconds. */
|
|
17
|
+
var IDLE_DECAY = .7;
|
|
18
|
+
/** Seconds after the last splash when the field is cleared completely. */
|
|
19
|
+
var IDLE_CLEAR = 3.5;
|
|
20
|
+
var MAX_DYE_RESOLUTION = 1440;
|
|
21
|
+
export { BURST_DYE, BURST_FORCE, BURST_RADIUS, DYE_INTENSITY, IDLE_CLEAR, IDLE_DECAY, IDLE_DELAY, MAX_DYE_RESOLUTION, PRESSURE_RETENTION, VELOCITY_FADE };
|
|
22
|
+
|
|
23
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","names":[],"sources":["../../../src/styles/fluid/settings.ts"],"sourcesContent":["// Shared by the GPU and CPU simulations, so both produce the same kind of smoke.\n\n/** How much dye one splash adds at its centre. */\nexport const DYE_INTENSITY = 0.15;\n/** Seconds for the velocity field to lose about two thirds of its strength. */\nexport const VELOCITY_FADE = 0.5;\n/** How much of the previous pressure field is kept between frames, as in the reference. */\nexport const PRESSURE_RETENTION = 0.1;\n/** Pressure solve iterations (the CPU fallback uses fewer to stay cheap). */\nexport const PRESSURE_ITERATIONS = 20;\nexport const CPU_PRESSURE_ITERATIONS = 14;\n/** The initial burst is this fraction of the pointer force: just enough to set the smoke moving. */\nexport const BURST_FORCE = 0.003;\n/** The initial burst covers this many times the pointer splash radius. */\nexport const BURST_RADIUS = 2.2;\n/** The initial burst adds this many times the usual dye, so it reads on an otherwise empty canvas. */\nexport const BURST_DYE = 2.2;\n/** Seconds after the last splash before the extra idle fade begins. */\nexport const IDLE_DELAY = 0.5;\n/** Effective dye fade time while the pointer is idle, in seconds. */\nexport const IDLE_DECAY = 0.7;\n/** Seconds after the last splash when the field is cleared completely. */\nexport const IDLE_CLEAR = 3.5;\n\n/** The dye texture is this many times the simulation grid, up to a cap. */\nexport const DYE_SCALE = 8;\nexport const MAX_DYE_RESOLUTION = 1440;\n"],"mappings":";;AAGA,IAAa,gBAAgB;;AAE7B,IAAa,gBAAgB;;AAE7B,IAAa,qBAAqB;;AAKlC,IAAa,cAAc;;AAE3B,IAAa,eAAe;;AAE5B,IAAa,YAAY;;AAEzB,IAAa,aAAa;;AAE1B,IAAa,aAAa;;AAE1B,IAAa,aAAa;AAI1B,IAAa,qBAAqB"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
const require_settings = require("./settings.cjs");
|
|
2
|
+
// src/styles/fluid/simulation.ts
|
|
3
|
+
var clamp = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
4
|
+
function createFluidSimulation(width, height) {
|
|
5
|
+
const w = width;
|
|
6
|
+
const h = height;
|
|
7
|
+
const cells = w * h;
|
|
8
|
+
let u = new Float32Array(cells);
|
|
9
|
+
let v = new Float32Array(cells);
|
|
10
|
+
let uNext = new Float32Array(cells);
|
|
11
|
+
let vNext = new Float32Array(cells);
|
|
12
|
+
let dyeR = new Float32Array(cells);
|
|
13
|
+
let dyeG = new Float32Array(cells);
|
|
14
|
+
let dyeB = new Float32Array(cells);
|
|
15
|
+
let dyeRNext = new Float32Array(cells);
|
|
16
|
+
let dyeGNext = new Float32Array(cells);
|
|
17
|
+
let dyeBNext = new Float32Array(cells);
|
|
18
|
+
const divergence = new Float32Array(cells);
|
|
19
|
+
const curl = new Float32Array(cells);
|
|
20
|
+
let pressure = new Float32Array(cells);
|
|
21
|
+
let pressureNext = new Float32Array(cells);
|
|
22
|
+
/** Bilinear sample of a field at grid coordinates, clamped at the edges. */
|
|
23
|
+
function sample(field, x, y) {
|
|
24
|
+
const gx = clamp(x, 0, w - 1);
|
|
25
|
+
const gy = clamp(y, 0, h - 1);
|
|
26
|
+
const i0 = Math.floor(gx);
|
|
27
|
+
const j0 = Math.floor(gy);
|
|
28
|
+
const i1 = Math.min(i0 + 1, w - 1);
|
|
29
|
+
const j1 = Math.min(j0 + 1, h - 1);
|
|
30
|
+
const fx = gx - i0;
|
|
31
|
+
const fy = gy - j0;
|
|
32
|
+
const top = field[j0 * w + i0] * (1 - fx) + field[j0 * w + i1] * fx;
|
|
33
|
+
const bottom = field[j1 * w + i0] * (1 - fx) + field[j1 * w + i1] * fx;
|
|
34
|
+
return top * (1 - fy) + bottom * fy;
|
|
35
|
+
}
|
|
36
|
+
/** Zero the velocity along the walls, so the field doesn't leak. */
|
|
37
|
+
function walls() {
|
|
38
|
+
for (let i = 0; i < w; i++) {
|
|
39
|
+
u[i] = 0;
|
|
40
|
+
u[(h - 1) * w + i] = 0;
|
|
41
|
+
v[i] = 0;
|
|
42
|
+
v[(h - 1) * w + i] = 0;
|
|
43
|
+
}
|
|
44
|
+
for (let j = 0; j < h; j++) {
|
|
45
|
+
u[j * w] = 0;
|
|
46
|
+
u[j * w + w - 1] = 0;
|
|
47
|
+
v[j * w] = 0;
|
|
48
|
+
v[j * w + w - 1] = 0;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function addCurl(dt, amount) {
|
|
52
|
+
for (let j = 1; j < h - 1; j++) for (let i = 1; i < w - 1; i++) {
|
|
53
|
+
const k = j * w + i;
|
|
54
|
+
curl[k] = .5 * (v[k + 1] - v[k - 1] - (u[k + w] - u[k - w]));
|
|
55
|
+
}
|
|
56
|
+
for (let j = 1; j < h - 1; j++) for (let i = 1; i < w - 1; i++) {
|
|
57
|
+
const k = j * w + i;
|
|
58
|
+
const forceX = .5 * (Math.abs(curl[k + 1]) - Math.abs(curl[k - 1]));
|
|
59
|
+
const forceY = .5 * (Math.abs(curl[k - w]) - Math.abs(curl[k + w]));
|
|
60
|
+
const length = Math.hypot(forceX, forceY) + 1e-4;
|
|
61
|
+
const strength = amount * curl[k] * dt / length;
|
|
62
|
+
u[k] = clamp(u[k] + forceX * strength, -1e3, 1e3);
|
|
63
|
+
v[k] = clamp(v[k] + forceY * strength, -1e3, 1e3);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function project(dt, options) {
|
|
67
|
+
if (options.curl > 0) addCurl(dt, options.curl);
|
|
68
|
+
for (let j = 1; j < h - 1; j++) for (let i = 1; i < w - 1; i++) {
|
|
69
|
+
const k = j * w + i;
|
|
70
|
+
divergence[k] = .5 * (u[k + 1] - u[k - 1] + v[k + w] - v[k - w]);
|
|
71
|
+
}
|
|
72
|
+
pressure.fill(0);
|
|
73
|
+
for (let iteration = 0; iteration < 14; iteration++) {
|
|
74
|
+
for (let j = 1; j < h - 1; j++) for (let i = 1; i < w - 1; i++) {
|
|
75
|
+
const k = j * w + i;
|
|
76
|
+
pressureNext[k] = (pressure[k - 1] + pressure[k + 1] + pressure[k - w] + pressure[k + w] - divergence[k]) * .25;
|
|
77
|
+
}
|
|
78
|
+
[pressure, pressureNext] = [pressureNext, pressure];
|
|
79
|
+
}
|
|
80
|
+
for (let j = 1; j < h - 1; j++) for (let i = 1; i < w - 1; i++) {
|
|
81
|
+
const k = j * w + i;
|
|
82
|
+
u[k] -= .5 * (pressure[k + 1] - pressure[k - 1]);
|
|
83
|
+
v[k] -= .5 * (pressure[k + w] - pressure[k - w]);
|
|
84
|
+
}
|
|
85
|
+
walls();
|
|
86
|
+
}
|
|
87
|
+
function advectVelocity(dt, decay) {
|
|
88
|
+
for (let j = 0; j < h; j++) for (let i = 0; i < w; i++) {
|
|
89
|
+
const k = j * w + i;
|
|
90
|
+
const sx = i - u[k] * dt;
|
|
91
|
+
const sy = j - v[k] * dt;
|
|
92
|
+
uNext[k] = sample(u, sx, sy) * decay;
|
|
93
|
+
vNext[k] = sample(v, sx, sy) * decay;
|
|
94
|
+
}
|
|
95
|
+
[u, uNext] = [uNext, u];
|
|
96
|
+
[v, vNext] = [vNext, v];
|
|
97
|
+
walls();
|
|
98
|
+
}
|
|
99
|
+
function advectDye(dt, decay) {
|
|
100
|
+
for (let j = 0; j < h; j++) for (let i = 0; i < w; i++) {
|
|
101
|
+
const k = j * w + i;
|
|
102
|
+
const sx = i - u[k] * dt;
|
|
103
|
+
const sy = j - v[k] * dt;
|
|
104
|
+
dyeRNext[k] = sample(dyeR, sx, sy) * decay;
|
|
105
|
+
dyeGNext[k] = sample(dyeG, sx, sy) * decay;
|
|
106
|
+
dyeBNext[k] = sample(dyeB, sx, sy) * decay;
|
|
107
|
+
}
|
|
108
|
+
[dyeR, dyeRNext] = [dyeRNext, dyeR];
|
|
109
|
+
[dyeG, dyeGNext] = [dyeGNext, dyeG];
|
|
110
|
+
[dyeB, dyeBNext] = [dyeBNext, dyeB];
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
width: w,
|
|
114
|
+
height: h,
|
|
115
|
+
get dyeR() {
|
|
116
|
+
return dyeR;
|
|
117
|
+
},
|
|
118
|
+
get dyeG() {
|
|
119
|
+
return dyeG;
|
|
120
|
+
},
|
|
121
|
+
get dyeB() {
|
|
122
|
+
return dyeB;
|
|
123
|
+
},
|
|
124
|
+
splat(x, y, vx, vy, color, radius, viewWidth, viewHeight) {
|
|
125
|
+
const aspect = Math.max(1, viewWidth) / Math.max(1, viewHeight);
|
|
126
|
+
const sigma = Math.max(5e-4, radius / viewHeight);
|
|
127
|
+
const cx = x / Math.max(1, viewWidth);
|
|
128
|
+
const cy = y / Math.max(1, viewHeight);
|
|
129
|
+
const reachX = sigma / aspect * w * 3;
|
|
130
|
+
const reachY = sigma * h * 3;
|
|
131
|
+
const x0 = Math.max(0, Math.floor(cx * w - reachX));
|
|
132
|
+
const x1 = Math.min(w - 1, Math.ceil(cx * w + reachX));
|
|
133
|
+
const y0 = Math.max(0, Math.floor(cy * h - reachY));
|
|
134
|
+
const y1 = Math.min(h - 1, Math.ceil(cy * h + reachY));
|
|
135
|
+
const velocityX = clamp(vx, -1e3, 1e3);
|
|
136
|
+
const velocityY = clamp(vy, -1e3, 1e3);
|
|
137
|
+
const sigma2 = sigma * sigma;
|
|
138
|
+
for (let j = y0; j <= y1; j++) {
|
|
139
|
+
const dy = (j + .5) / h - cy;
|
|
140
|
+
for (let i = x0; i <= x1; i++) {
|
|
141
|
+
const dx = ((i + .5) / w - cx) * aspect;
|
|
142
|
+
const distance = dx * dx + dy * dy;
|
|
143
|
+
if (distance > sigma2 * 9) continue;
|
|
144
|
+
const falloff = Math.exp(-distance / sigma2);
|
|
145
|
+
const k = j * w + i;
|
|
146
|
+
u[k] = clamp(u[k] + velocityX * falloff, -1e3, 1e3);
|
|
147
|
+
v[k] = clamp(v[k] + velocityY * falloff, -1e3, 1e3);
|
|
148
|
+
dyeR[k] += color[0] * require_settings.DYE_INTENSITY * falloff;
|
|
149
|
+
dyeG[k] += color[1] * require_settings.DYE_INTENSITY * falloff;
|
|
150
|
+
dyeB[k] += color[2] * require_settings.DYE_INTENSITY * falloff;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
step(dt, options) {
|
|
155
|
+
const stepTime = Math.min(dt, 1 / 30);
|
|
156
|
+
if (stepTime <= 0) return;
|
|
157
|
+
project(stepTime, options);
|
|
158
|
+
advectVelocity(stepTime, 1 / (1 + stepTime / require_settings.VELOCITY_FADE));
|
|
159
|
+
advectDye(stepTime, 1 / (1 + stepTime / options.fade));
|
|
160
|
+
},
|
|
161
|
+
clear() {
|
|
162
|
+
for (const field of [
|
|
163
|
+
u,
|
|
164
|
+
v,
|
|
165
|
+
uNext,
|
|
166
|
+
vNext,
|
|
167
|
+
dyeR,
|
|
168
|
+
dyeG,
|
|
169
|
+
dyeB,
|
|
170
|
+
dyeRNext,
|
|
171
|
+
dyeGNext,
|
|
172
|
+
dyeBNext,
|
|
173
|
+
pressure,
|
|
174
|
+
pressureNext,
|
|
175
|
+
divergence,
|
|
176
|
+
curl
|
|
177
|
+
]) field.fill(0);
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
exports.createFluidSimulation = createFluidSimulation;
|
|
182
|
+
|
|
183
|
+
//# sourceMappingURL=simulation.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simulation.cjs","names":["DYE_INTENSITY","VELOCITY_FADE"],"sources":["../../../src/styles/fluid/simulation.ts"],"sourcesContent":["import type { RGB } from './color';\nimport type { ResolvedFluidOptions } from './options';\nimport { CPU_PRESSURE_ITERATIONS, DYE_INTENSITY, VELOCITY_FADE } from './settings';\n\n/**\n * The CPU fluid field: a stable-fluids solver at `resolution` cells on its longer\n * side. The Canvas 2D renderer draws it upscaled; the WebGL renderer runs the\n * same steps in shaders instead. Velocities are in grid cells per second; dye\n * channels are straight colour densities.\n */\nexport interface FluidSimulation {\n readonly width: number;\n readonly height: number;\n readonly dyeR: Float32Array;\n readonly dyeG: Float32Array;\n readonly dyeB: Float32Array;\n /** Add a splash of colour and velocity at `(x, y)`, in CSS pixels of a view of `viewWidth` × `viewHeight`. */\n splat(\n x: number,\n y: number,\n vx: number,\n vy: number,\n color: RGB,\n radius: number,\n viewWidth: number,\n viewHeight: number,\n ): void;\n /** Advance the simulation by `dt` seconds. */\n step(dt: number, options: ResolvedFluidOptions): void;\n /** Clear the velocity and dye fields. */\n clear(): void;\n}\n\nconst clamp = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value));\n\nexport function createFluidSimulation(width: number, height: number): FluidSimulation {\n const w = width;\n const h = height;\n const cells = w * h;\n\n let u = new Float32Array(cells);\n let v = new Float32Array(cells);\n let uNext = new Float32Array(cells);\n let vNext = new Float32Array(cells);\n let dyeR = new Float32Array(cells);\n let dyeG = new Float32Array(cells);\n let dyeB = new Float32Array(cells);\n let dyeRNext = new Float32Array(cells);\n let dyeGNext = new Float32Array(cells);\n let dyeBNext = new Float32Array(cells);\n const divergence = new Float32Array(cells);\n const curl = new Float32Array(cells);\n let pressure = new Float32Array(cells);\n let pressureNext = new Float32Array(cells);\n\n /** Bilinear sample of a field at grid coordinates, clamped at the edges. */\n function sample(field: Float32Array, x: number, y: number): number {\n const gx = clamp(x, 0, w - 1);\n const gy = clamp(y, 0, h - 1);\n const i0 = Math.floor(gx);\n const j0 = Math.floor(gy);\n const i1 = Math.min(i0 + 1, w - 1);\n const j1 = Math.min(j0 + 1, h - 1);\n const fx = gx - i0;\n const fy = gy - j0;\n const top = field[j0 * w + i0] * (1 - fx) + field[j0 * w + i1] * fx;\n const bottom = field[j1 * w + i0] * (1 - fx) + field[j1 * w + i1] * fx;\n return top * (1 - fy) + bottom * fy;\n }\n\n /** Zero the velocity along the walls, so the field doesn't leak. */\n function walls(): void {\n for (let i = 0; i < w; i++) {\n u[i] = 0;\n u[(h - 1) * w + i] = 0;\n v[i] = 0;\n v[(h - 1) * w + i] = 0;\n }\n for (let j = 0; j < h; j++) {\n u[j * w] = 0;\n u[j * w + w - 1] = 0;\n v[j * w] = 0;\n v[j * w + w - 1] = 0;\n }\n }\n\n function addCurl(dt: number, amount: number): void {\n for (let j = 1; j < h - 1; j++) {\n for (let i = 1; i < w - 1; i++) {\n const k = j * w + i;\n curl[k] = 0.5 * (v[k + 1] - v[k - 1] - (u[k + w] - u[k - w]));\n }\n }\n for (let j = 1; j < h - 1; j++) {\n for (let i = 1; i < w - 1; i++) {\n const k = j * w + i;\n const forceX = 0.5 * (Math.abs(curl[k + 1]) - Math.abs(curl[k - 1]));\n const forceY = 0.5 * (Math.abs(curl[k - w]) - Math.abs(curl[k + w]));\n const length = Math.hypot(forceX, forceY) + 1e-4;\n const strength = (amount * curl[k] * dt) / length;\n u[k] = clamp(u[k] + forceX * strength, -1000, 1000);\n v[k] = clamp(v[k] + forceY * strength, -1000, 1000);\n }\n }\n }\n\n function project(dt: number, options: ResolvedFluidOptions): void {\n if (options.curl > 0) addCurl(dt, options.curl);\n for (let j = 1; j < h - 1; j++) {\n for (let i = 1; i < w - 1; i++) {\n const k = j * w + i;\n divergence[k] = 0.5 * (u[k + 1] - u[k - 1] + v[k + w] - v[k - w]);\n }\n }\n pressure.fill(0);\n for (let iteration = 0; iteration < CPU_PRESSURE_ITERATIONS; iteration++) {\n for (let j = 1; j < h - 1; j++) {\n for (let i = 1; i < w - 1; i++) {\n const k = j * w + i;\n pressureNext[k] =\n (pressure[k - 1] + pressure[k + 1] + pressure[k - w] + pressure[k + w] - divergence[k]) * 0.25;\n }\n }\n [pressure, pressureNext] = [pressureNext, pressure];\n }\n for (let j = 1; j < h - 1; j++) {\n for (let i = 1; i < w - 1; i++) {\n const k = j * w + i;\n u[k] -= 0.5 * (pressure[k + 1] - pressure[k - 1]);\n v[k] -= 0.5 * (pressure[k + w] - pressure[k - w]);\n }\n }\n walls();\n }\n\n function advectVelocity(dt: number, decay: number): void {\n for (let j = 0; j < h; j++) {\n for (let i = 0; i < w; i++) {\n const k = j * w + i;\n const sx = i - u[k] * dt;\n const sy = j - v[k] * dt;\n uNext[k] = sample(u, sx, sy) * decay;\n vNext[k] = sample(v, sx, sy) * decay;\n }\n }\n [u, uNext] = [uNext, u];\n [v, vNext] = [vNext, v];\n walls();\n }\n\n function advectDye(dt: number, decay: number): void {\n for (let j = 0; j < h; j++) {\n for (let i = 0; i < w; i++) {\n const k = j * w + i;\n const sx = i - u[k] * dt;\n const sy = j - v[k] * dt;\n dyeRNext[k] = sample(dyeR, sx, sy) * decay;\n dyeGNext[k] = sample(dyeG, sx, sy) * decay;\n dyeBNext[k] = sample(dyeB, sx, sy) * decay;\n }\n }\n [dyeR, dyeRNext] = [dyeRNext, dyeR];\n [dyeG, dyeGNext] = [dyeGNext, dyeG];\n [dyeB, dyeBNext] = [dyeBNext, dyeB];\n }\n\n return {\n width: w,\n height: h,\n get dyeR() {\n return dyeR;\n },\n get dyeG() {\n return dyeG;\n },\n get dyeB() {\n return dyeB;\n },\n splat(x, y, vx, vy, color, radius, viewWidth, viewHeight) {\n const aspect = Math.max(1, viewWidth) / Math.max(1, viewHeight);\n const sigma = Math.max(0.0005, radius / viewHeight);\n const cx = x / Math.max(1, viewWidth);\n const cy = y / Math.max(1, viewHeight);\n const reachX = (sigma / aspect) * w * 3;\n const reachY = sigma * h * 3;\n const x0 = Math.max(0, Math.floor(cx * w - reachX));\n const x1 = Math.min(w - 1, Math.ceil(cx * w + reachX));\n const y0 = Math.max(0, Math.floor(cy * h - reachY));\n const y1 = Math.min(h - 1, Math.ceil(cy * h + reachY));\n // Velocities are in simulation texels per second, which is cells per second here.\n const velocityX = clamp(vx, -1000, 1000);\n const velocityY = clamp(vy, -1000, 1000);\n const sigma2 = sigma * sigma;\n for (let j = y0; j <= y1; j++) {\n const ny = (j + 0.5) / h;\n const dy = ny - cy;\n for (let i = x0; i <= x1; i++) {\n const nx = (i + 0.5) / w;\n const dx = (nx - cx) * aspect;\n const distance = dx * dx + dy * dy;\n if (distance > sigma2 * 9) continue;\n const falloff = Math.exp(-distance / sigma2);\n const k = j * w + i;\n u[k] = clamp(u[k] + velocityX * falloff, -1000, 1000);\n v[k] = clamp(v[k] + velocityY * falloff, -1000, 1000);\n dyeR[k] += color[0] * DYE_INTENSITY * falloff;\n dyeG[k] += color[1] * DYE_INTENSITY * falloff;\n dyeB[k] += color[2] * DYE_INTENSITY * falloff;\n }\n }\n },\n step(dt, options) {\n const stepTime = Math.min(dt, 1 / 30);\n if (stepTime <= 0) return;\n project(stepTime, options);\n advectVelocity(stepTime, 1 / (1 + stepTime / VELOCITY_FADE));\n advectDye(stepTime, 1 / (1 + stepTime / options.fade));\n },\n clear() {\n for (const field of [u, v, uNext, vNext, dyeR, dyeG, dyeB, dyeRNext, dyeGNext, dyeBNext, pressure, pressureNext, divergence, curl]) {\n field.fill(0);\n }\n },\n };\n}\n"],"mappings":";;AAiCA,IAAM,SAAS,OAAe,KAAa,QAAgB,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,CAAC;AAE7F,SAAgB,sBAAsB,OAAe,QAAiC;CACpF,MAAM,IAAI;CACV,MAAM,IAAI;CACV,MAAM,QAAQ,IAAI;CAElB,IAAI,IAAI,IAAI,aAAa,KAAK;CAC9B,IAAI,IAAI,IAAI,aAAa,KAAK;CAC9B,IAAI,QAAQ,IAAI,aAAa,KAAK;CAClC,IAAI,QAAQ,IAAI,aAAa,KAAK;CAClC,IAAI,OAAO,IAAI,aAAa,KAAK;CACjC,IAAI,OAAO,IAAI,aAAa,KAAK;CACjC,IAAI,OAAO,IAAI,aAAa,KAAK;CACjC,IAAI,WAAW,IAAI,aAAa,KAAK;CACrC,IAAI,WAAW,IAAI,aAAa,KAAK;CACrC,IAAI,WAAW,IAAI,aAAa,KAAK;CACrC,MAAM,aAAa,IAAI,aAAa,KAAK;CACzC,MAAM,OAAO,IAAI,aAAa,KAAK;CACnC,IAAI,WAAW,IAAI,aAAa,KAAK;CACrC,IAAI,eAAe,IAAI,aAAa,KAAK;;CAGzC,SAAS,OAAO,OAAqB,GAAW,GAAmB;EACjE,MAAM,KAAK,MAAM,GAAG,GAAG,IAAI,CAAC;EAC5B,MAAM,KAAK,MAAM,GAAG,GAAG,IAAI,CAAC;EAC5B,MAAM,KAAK,KAAK,MAAM,EAAE;EACxB,MAAM,KAAK,KAAK,MAAM,EAAE;EACxB,MAAM,KAAK,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC;EACjC,MAAM,KAAK,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC;EACjC,MAAM,KAAK,KAAK;EAChB,MAAM,KAAK,KAAK;EAChB,MAAM,MAAM,MAAM,KAAK,IAAI,OAAO,IAAI,MAAM,MAAM,KAAK,IAAI,MAAM;EACjE,MAAM,SAAS,MAAM,KAAK,IAAI,OAAO,IAAI,MAAM,MAAM,KAAK,IAAI,MAAM;EACpE,OAAO,OAAO,IAAI,MAAM,SAAS;CACnC;;CAGA,SAAS,QAAc;EACrB,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;GAC1B,EAAE,KAAK;GACP,GAAG,IAAI,KAAK,IAAI,KAAK;GACrB,EAAE,KAAK;GACP,GAAG,IAAI,KAAK,IAAI,KAAK;EACvB;EACA,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;GAC1B,EAAE,IAAI,KAAK;GACX,EAAE,IAAI,IAAI,IAAI,KAAK;GACnB,EAAE,IAAI,KAAK;GACX,EAAE,IAAI,IAAI,IAAI,KAAK;EACrB;CACF;CAEA,SAAS,QAAQ,IAAY,QAAsB;EACjD,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,KACzB,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,KAAK;GAC9B,MAAM,IAAI,IAAI,IAAI;GAClB,KAAK,KAAK,MAAO,EAAE,IAAI,KAAK,EAAE,IAAI,MAAM,EAAE,IAAI,KAAK,EAAE,IAAI;EAC3D;EAEF,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,KACzB,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,KAAK;GAC9B,MAAM,IAAI,IAAI,IAAI;GAClB,MAAM,SAAS,MAAO,KAAK,IAAI,KAAK,IAAI,EAAE,IAAI,KAAK,IAAI,KAAK,IAAI,EAAE;GAClE,MAAM,SAAS,MAAO,KAAK,IAAI,KAAK,IAAI,EAAE,IAAI,KAAK,IAAI,KAAK,IAAI,EAAE;GAClE,MAAM,SAAS,KAAK,MAAM,QAAQ,MAAM,IAAI;GAC5C,MAAM,WAAY,SAAS,KAAK,KAAK,KAAM;GAC3C,EAAE,KAAK,MAAM,EAAE,KAAK,SAAS,UAAU,MAAO,GAAI;GAClD,EAAE,KAAK,MAAM,EAAE,KAAK,SAAS,UAAU,MAAO,GAAI;EACpD;CAEJ;CAEA,SAAS,QAAQ,IAAY,SAAqC;EAChE,IAAI,QAAQ,OAAO,GAAG,QAAQ,IAAI,QAAQ,IAAI;EAC9C,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,KACzB,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,KAAK;GAC9B,MAAM,IAAI,IAAI,IAAI;GAClB,WAAW,KAAK,MAAO,EAAE,IAAI,KAAK,EAAE,IAAI,KAAK,EAAE,IAAI,KAAK,EAAE,IAAI;EAChE;EAEF,SAAS,KAAK,CAAC;EACf,KAAK,IAAI,YAAY,GAAG,YAAA,IAAqC,aAAa;GACxE,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,KACzB,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,KAAK;IAC9B,MAAM,IAAI,IAAI,IAAI;IAClB,aAAa,MACV,SAAS,IAAI,KAAK,SAAS,IAAI,KAAK,SAAS,IAAI,KAAK,SAAS,IAAI,KAAK,WAAW,MAAM;GAC9F;GAEF,CAAC,UAAU,gBAAgB,CAAC,cAAc,QAAQ;EACpD;EACA,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,KACzB,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,KAAK;GAC9B,MAAM,IAAI,IAAI,IAAI;GAClB,EAAE,MAAM,MAAO,SAAS,IAAI,KAAK,SAAS,IAAI;GAC9C,EAAE,MAAM,MAAO,SAAS,IAAI,KAAK,SAAS,IAAI;EAChD;EAEF,MAAM;CACR;CAEA,SAAS,eAAe,IAAY,OAAqB;EACvD,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;GAC1B,MAAM,IAAI,IAAI,IAAI;GAClB,MAAM,KAAK,IAAI,EAAE,KAAK;GACtB,MAAM,KAAK,IAAI,EAAE,KAAK;GACtB,MAAM,KAAK,OAAO,GAAG,IAAI,EAAE,IAAI;GAC/B,MAAM,KAAK,OAAO,GAAG,IAAI,EAAE,IAAI;EACjC;EAEF,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC;EACtB,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC;EACtB,MAAM;CACR;CAEA,SAAS,UAAU,IAAY,OAAqB;EAClD,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;GAC1B,MAAM,IAAI,IAAI,IAAI;GAClB,MAAM,KAAK,IAAI,EAAE,KAAK;GACtB,MAAM,KAAK,IAAI,EAAE,KAAK;GACtB,SAAS,KAAK,OAAO,MAAM,IAAI,EAAE,IAAI;GACrC,SAAS,KAAK,OAAO,MAAM,IAAI,EAAE,IAAI;GACrC,SAAS,KAAK,OAAO,MAAM,IAAI,EAAE,IAAI;EACvC;EAEF,CAAC,MAAM,YAAY,CAAC,UAAU,IAAI;EAClC,CAAC,MAAM,YAAY,CAAC,UAAU,IAAI;EAClC,CAAC,MAAM,YAAY,CAAC,UAAU,IAAI;CACpC;CAEA,OAAO;EACL,OAAO;EACP,QAAQ;EACR,IAAI,OAAO;GACT,OAAO;EACT;EACA,IAAI,OAAO;GACT,OAAO;EACT;EACA,IAAI,OAAO;GACT,OAAO;EACT;EACA,MAAM,GAAG,GAAG,IAAI,IAAI,OAAO,QAAQ,WAAW,YAAY;GACxD,MAAM,SAAS,KAAK,IAAI,GAAG,SAAS,IAAI,KAAK,IAAI,GAAG,UAAU;GAC9D,MAAM,QAAQ,KAAK,IAAI,MAAQ,SAAS,UAAU;GAClD,MAAM,KAAK,IAAI,KAAK,IAAI,GAAG,SAAS;GACpC,MAAM,KAAK,IAAI,KAAK,IAAI,GAAG,UAAU;GACrC,MAAM,SAAU,QAAQ,SAAU,IAAI;GACtC,MAAM,SAAS,QAAQ,IAAI;GAC3B,MAAM,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC;GAClD,MAAM,KAAK,KAAK,IAAI,IAAI,GAAG,KAAK,KAAK,KAAK,IAAI,MAAM,CAAC;GACrD,MAAM,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC;GAClD,MAAM,KAAK,KAAK,IAAI,IAAI,GAAG,KAAK,KAAK,KAAK,IAAI,MAAM,CAAC;GAErD,MAAM,YAAY,MAAM,IAAI,MAAO,GAAI;GACvC,MAAM,YAAY,MAAM,IAAI,MAAO,GAAI;GACvC,MAAM,SAAS,QAAQ;GACvB,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK;IAE7B,MAAM,MADM,IAAI,MAAO,IACP;IAChB,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK;KAE7B,MAAM,OADM,IAAI,MAAO,IACN,MAAM;KACvB,MAAM,WAAW,KAAK,KAAK,KAAK;KAChC,IAAI,WAAW,SAAS,GAAG;KAC3B,MAAM,UAAU,KAAK,IAAI,CAAC,WAAW,MAAM;KAC3C,MAAM,IAAI,IAAI,IAAI;KAClB,EAAE,KAAK,MAAM,EAAE,KAAK,YAAY,SAAS,MAAO,GAAI;KACpD,EAAE,KAAK,MAAM,EAAE,KAAK,YAAY,SAAS,MAAO,GAAI;KACpD,KAAK,MAAM,MAAM,KAAKA,iBAAAA,gBAAgB;KACtC,KAAK,MAAM,MAAM,KAAKA,iBAAAA,gBAAgB;KACtC,KAAK,MAAM,MAAM,KAAKA,iBAAAA,gBAAgB;IACxC;GACF;EACF;EACA,KAAK,IAAI,SAAS;GAChB,MAAM,WAAW,KAAK,IAAI,IAAI,IAAI,EAAE;GACpC,IAAI,YAAY,GAAG;GACnB,QAAQ,UAAU,OAAO;GACzB,eAAe,UAAU,KAAK,IAAI,WAAWC,iBAAAA,cAAc;GAC3D,UAAU,UAAU,KAAK,IAAI,WAAW,QAAQ,KAAK;EACvD;EACA,QAAQ;GACN,KAAK,MAAM,SAAS;IAAC;IAAG;IAAG;IAAO;IAAO;IAAM;IAAM;IAAM;IAAU;IAAU;IAAU;IAAU;IAAc;IAAY;GAAI,GAC/H,MAAM,KAAK,CAAC;EAEhB;CACF;AACF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { RGB } from './color.cjs';
|
|
2
|
+
import type { ResolvedFluidOptions } from './options.cjs';
|
|
3
|
+
/**
|
|
4
|
+
* The CPU fluid field: a stable-fluids solver at `resolution` cells on its longer
|
|
5
|
+
* side. The Canvas 2D renderer draws it upscaled; the WebGL renderer runs the
|
|
6
|
+
* same steps in shaders instead. Velocities are in grid cells per second; dye
|
|
7
|
+
* channels are straight colour densities.
|
|
8
|
+
*/
|
|
9
|
+
export interface FluidSimulation {
|
|
10
|
+
readonly width: number;
|
|
11
|
+
readonly height: number;
|
|
12
|
+
readonly dyeR: Float32Array;
|
|
13
|
+
readonly dyeG: Float32Array;
|
|
14
|
+
readonly dyeB: Float32Array;
|
|
15
|
+
/** Add a splash of colour and velocity at `(x, y)`, in CSS pixels of a view of `viewWidth` × `viewHeight`. */
|
|
16
|
+
splat(x: number, y: number, vx: number, vy: number, color: RGB, radius: number, viewWidth: number, viewHeight: number): void;
|
|
17
|
+
/** Advance the simulation by `dt` seconds. */
|
|
18
|
+
step(dt: number, options: ResolvedFluidOptions): void;
|
|
19
|
+
/** Clear the velocity and dye fields. */
|
|
20
|
+
clear(): void;
|
|
21
|
+
}
|
|
22
|
+
export declare function createFluidSimulation(width: number, height: number): FluidSimulation;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { RGB } from './color.js';
|
|
2
|
+
import type { ResolvedFluidOptions } from './options.js';
|
|
3
|
+
/**
|
|
4
|
+
* The CPU fluid field: a stable-fluids solver at `resolution` cells on its longer
|
|
5
|
+
* side. The Canvas 2D renderer draws it upscaled; the WebGL renderer runs the
|
|
6
|
+
* same steps in shaders instead. Velocities are in grid cells per second; dye
|
|
7
|
+
* channels are straight colour densities.
|
|
8
|
+
*/
|
|
9
|
+
export interface FluidSimulation {
|
|
10
|
+
readonly width: number;
|
|
11
|
+
readonly height: number;
|
|
12
|
+
readonly dyeR: Float32Array;
|
|
13
|
+
readonly dyeG: Float32Array;
|
|
14
|
+
readonly dyeB: Float32Array;
|
|
15
|
+
/** Add a splash of colour and velocity at `(x, y)`, in CSS pixels of a view of `viewWidth` × `viewHeight`. */
|
|
16
|
+
splat(x: number, y: number, vx: number, vy: number, color: RGB, radius: number, viewWidth: number, viewHeight: number): void;
|
|
17
|
+
/** Advance the simulation by `dt` seconds. */
|
|
18
|
+
step(dt: number, options: ResolvedFluidOptions): void;
|
|
19
|
+
/** Clear the velocity and dye fields. */
|
|
20
|
+
clear(): void;
|
|
21
|
+
}
|
|
22
|
+
export declare function createFluidSimulation(width: number, height: number): FluidSimulation;
|