interactive-bg 0.1.1 → 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.
Files changed (122) hide show
  1. package/README.md +55 -7
  2. package/dist/fluid/canvas2d.cjs +14 -0
  3. package/dist/fluid/canvas2d.cjs.map +1 -0
  4. package/dist/fluid/canvas2d.d.cts +5 -0
  5. package/dist/fluid/canvas2d.d.ts +5 -0
  6. package/dist/fluid/canvas2d.js +13 -0
  7. package/dist/fluid/canvas2d.js.map +1 -0
  8. package/dist/fluid/index.cjs +16 -0
  9. package/dist/fluid/index.cjs.map +1 -0
  10. package/dist/fluid/index.d.cts +5 -0
  11. package/dist/fluid/index.d.ts +5 -0
  12. package/dist/fluid/index.js +15 -0
  13. package/dist/fluid/index.js.map +1 -0
  14. package/dist/fluid/webgl.cjs +14 -0
  15. package/dist/fluid/webgl.cjs.map +1 -0
  16. package/dist/fluid/webgl.d.cts +5 -0
  17. package/dist/fluid/webgl.d.ts +5 -0
  18. package/dist/fluid/webgl.js +13 -0
  19. package/dist/fluid/webgl.js.map +1 -0
  20. package/dist/index.cjs +4 -0
  21. package/dist/index.d.cts +4 -0
  22. package/dist/index.d.ts +4 -0
  23. package/dist/index.js +3 -1
  24. package/dist/index.umd.js +255 -12
  25. package/dist/index.umd.js.map +1 -1
  26. package/dist/shimmer/canvas2d.cjs +14 -0
  27. package/dist/shimmer/canvas2d.cjs.map +1 -0
  28. package/dist/shimmer/canvas2d.d.cts +5 -0
  29. package/dist/shimmer/canvas2d.d.ts +5 -0
  30. package/dist/shimmer/canvas2d.js +13 -0
  31. package/dist/shimmer/canvas2d.js.map +1 -0
  32. package/dist/shimmer/index.cjs +16 -0
  33. package/dist/shimmer/index.cjs.map +1 -0
  34. package/dist/shimmer/index.d.cts +5 -0
  35. package/dist/shimmer/index.d.ts +5 -0
  36. package/dist/shimmer/index.js +15 -0
  37. package/dist/shimmer/index.js.map +1 -0
  38. package/dist/shimmer/webgl.cjs +14 -0
  39. package/dist/shimmer/webgl.cjs.map +1 -0
  40. package/dist/shimmer/webgl.d.cts +5 -0
  41. package/dist/shimmer/webgl.d.ts +5 -0
  42. package/dist/shimmer/webgl.js +13 -0
  43. package/dist/shimmer/webgl.js.map +1 -0
  44. package/dist/styles/fluid/canvas2d.cjs +155 -0
  45. package/dist/styles/fluid/canvas2d.cjs.map +1 -0
  46. package/dist/styles/fluid/canvas2d.d.cts +8 -0
  47. package/dist/styles/fluid/canvas2d.d.ts +8 -0
  48. package/dist/styles/fluid/canvas2d.js +155 -0
  49. package/dist/styles/fluid/canvas2d.js.map +1 -0
  50. package/dist/styles/fluid/color.cjs +40 -0
  51. package/dist/styles/fluid/color.cjs.map +1 -0
  52. package/dist/styles/fluid/color.d.cts +4 -0
  53. package/dist/styles/fluid/color.d.ts +4 -0
  54. package/dist/styles/fluid/color.js +40 -0
  55. package/dist/styles/fluid/color.js.map +1 -0
  56. package/dist/styles/fluid/definition.cjs +14 -0
  57. package/dist/styles/fluid/definition.cjs.map +1 -0
  58. package/dist/styles/fluid/definition.d.cts +8 -0
  59. package/dist/styles/fluid/definition.d.ts +8 -0
  60. package/dist/styles/fluid/definition.js +15 -0
  61. package/dist/styles/fluid/definition.js.map +1 -0
  62. package/dist/styles/fluid/options.cjs +29 -0
  63. package/dist/styles/fluid/options.cjs.map +1 -0
  64. package/dist/styles/fluid/options.d.cts +31 -0
  65. package/dist/styles/fluid/options.d.ts +31 -0
  66. package/dist/styles/fluid/options.js +28 -0
  67. package/dist/styles/fluid/options.js.map +1 -0
  68. package/dist/styles/fluid/settings.cjs +32 -0
  69. package/dist/styles/fluid/settings.cjs.map +1 -0
  70. package/dist/styles/fluid/settings.d.cts +24 -0
  71. package/dist/styles/fluid/settings.d.ts +24 -0
  72. package/dist/styles/fluid/settings.js +23 -0
  73. package/dist/styles/fluid/settings.js.map +1 -0
  74. package/dist/styles/fluid/simulation.cjs +183 -0
  75. package/dist/styles/fluid/simulation.cjs.map +1 -0
  76. package/dist/styles/fluid/simulation.d.cts +22 -0
  77. package/dist/styles/fluid/simulation.d.ts +22 -0
  78. package/dist/styles/fluid/simulation.js +183 -0
  79. package/dist/styles/fluid/simulation.js.map +1 -0
  80. package/dist/styles/fluid/size.cjs +17 -0
  81. package/dist/styles/fluid/size.cjs.map +1 -0
  82. package/dist/styles/fluid/size.d.cts +5 -0
  83. package/dist/styles/fluid/size.d.ts +5 -0
  84. package/dist/styles/fluid/size.js +17 -0
  85. package/dist/styles/fluid/size.js.map +1 -0
  86. package/dist/styles/fluid/webgl.cjs +607 -0
  87. package/dist/styles/fluid/webgl.cjs.map +1 -0
  88. package/dist/styles/fluid/webgl.d.cts +3 -0
  89. package/dist/styles/fluid/webgl.d.ts +3 -0
  90. package/dist/styles/fluid/webgl.js +607 -0
  91. package/dist/styles/fluid/webgl.js.map +1 -0
  92. package/dist/styles/shimmer/canvas2d.cjs +84 -0
  93. package/dist/styles/shimmer/canvas2d.cjs.map +1 -0
  94. package/dist/styles/shimmer/canvas2d.d.cts +3 -0
  95. package/dist/styles/shimmer/canvas2d.d.ts +3 -0
  96. package/dist/styles/shimmer/canvas2d.js +84 -0
  97. package/dist/styles/shimmer/canvas2d.js.map +1 -0
  98. package/dist/styles/shimmer/definition.cjs +15 -0
  99. package/dist/styles/shimmer/definition.cjs.map +1 -0
  100. package/dist/styles/shimmer/definition.d.cts +8 -0
  101. package/dist/styles/shimmer/definition.d.ts +8 -0
  102. package/dist/styles/shimmer/definition.js +16 -0
  103. package/dist/styles/shimmer/definition.js.map +1 -0
  104. package/dist/styles/shimmer/field.cjs +79 -0
  105. package/dist/styles/shimmer/field.cjs.map +1 -0
  106. package/dist/styles/shimmer/field.d.cts +11 -0
  107. package/dist/styles/shimmer/field.d.ts +11 -0
  108. package/dist/styles/shimmer/field.js +78 -0
  109. package/dist/styles/shimmer/field.js.map +1 -0
  110. package/dist/styles/shimmer/options.cjs +28 -0
  111. package/dist/styles/shimmer/options.cjs.map +1 -0
  112. package/dist/styles/shimmer/options.d.cts +22 -0
  113. package/dist/styles/shimmer/options.d.ts +22 -0
  114. package/dist/styles/shimmer/options.js +27 -0
  115. package/dist/styles/shimmer/options.js.map +1 -0
  116. package/dist/styles/shimmer/webgl.cjs +89 -0
  117. package/dist/styles/shimmer/webgl.cjs.map +1 -0
  118. package/dist/styles/shimmer/webgl.d.cts +4 -0
  119. package/dist/styles/shimmer/webgl.d.ts +4 -0
  120. package/dist/styles/shimmer/webgl.js +89 -0
  121. package/dist/styles/shimmer/webgl.js.map +1 -0
  122. package/package.json +75 -1
@@ -0,0 +1,607 @@
1
+ import { createProgram, getUniforms } from "../../core/webgl.js";
2
+ import { splatColor } from "./color.js";
3
+ import { resolveFluidOptions } from "./options.js";
4
+ import { BURST_DYE, BURST_FORCE, BURST_RADIUS, DYE_INTENSITY, IDLE_CLEAR, IDLE_DECAY, MAX_DYE_RESOLUTION, PRESSURE_RETENTION, VELOCITY_FADE } from "./settings.js";
5
+ import { simulationSize } from "./size.js";
6
+ // src/styles/fluid/webgl.ts
7
+ var TAU = Math.PI * 2;
8
+ var VERTEX = `#version 300 es
9
+ precision highp float;
10
+
11
+ uniform vec2 uTexelSize;
12
+
13
+ out vec2 vUv;
14
+ out vec2 vL;
15
+ out vec2 vR;
16
+ out vec2 vT;
17
+ out vec2 vB;
18
+
19
+ void main() {
20
+ vec2 p = vec2(float((gl_VertexID << 1) & 2), float(gl_VertexID & 2));
21
+ vUv = p;
22
+ vL = vUv - vec2(uTexelSize.x, 0.0);
23
+ vR = vUv + vec2(uTexelSize.x, 0.0);
24
+ vT = vUv + vec2(0.0, uTexelSize.y);
25
+ vB = vUv - vec2(0.0, uTexelSize.y);
26
+ gl_Position = vec4(p * 2.0 - 1.0, 0.0, 1.0);
27
+ }`;
28
+ var SPLAT = `#version 300 es
29
+ precision highp float;
30
+
31
+ uniform sampler2D uTarget;
32
+ uniform vec2 uPoint;
33
+ uniform vec3 uColor;
34
+ uniform float uRadius; // squared radius, in screens-heights
35
+ uniform float uAspect;
36
+
37
+ in vec2 vUv;
38
+ out vec4 outColor;
39
+
40
+ void main() {
41
+ vec2 p = vUv - uPoint;
42
+ p.x *= uAspect;
43
+ vec3 splat = exp(-dot(p, p) / uRadius) * uColor;
44
+ outColor = vec4(texture(uTarget, vUv).rgb + splat, 1.0);
45
+ }`;
46
+ var ADVECTION = `#version 300 es
47
+ precision highp float;
48
+
49
+ uniform sampler2D uVelocity;
50
+ uniform sampler2D uSource;
51
+ uniform vec2 uTexelSize;
52
+ uniform float uDt;
53
+ uniform float uDissipation;
54
+
55
+ in vec2 vUv;
56
+ out vec4 outColor;
57
+
58
+ void main() {
59
+ vec2 coord = vUv - uDt * texture(uVelocity, vUv).xy * uTexelSize;
60
+ outColor = texture(uSource, coord) / (1.0 + uDissipation * uDt);
61
+ }`;
62
+ var DIVERGENCE = `#version 300 es
63
+ precision highp float;
64
+
65
+ uniform sampler2D uVelocity;
66
+ uniform vec2 uTexelSize;
67
+
68
+ in vec2 vUv;
69
+ in vec2 vL;
70
+ in vec2 vR;
71
+ in vec2 vT;
72
+ in vec2 vB;
73
+ out vec4 outColor;
74
+
75
+ void main() {
76
+ float L = texture(uVelocity, vL).x;
77
+ float R = texture(uVelocity, vR).x;
78
+ float T = texture(uVelocity, vT).y;
79
+ float B = texture(uVelocity, vB).y;
80
+ vec2 C = texture(uVelocity, vUv).xy;
81
+ if (vL.x < 0.0) L = -C.x;
82
+ if (vR.x > 1.0) R = -C.x;
83
+ if (vT.y > 1.0) T = -C.y;
84
+ if (vB.y < 0.0) B = -C.y;
85
+ outColor = vec4(0.5 * (R - L + T - B), 0.0, 0.0, 1.0);
86
+ }`;
87
+ var CURL = `#version 300 es
88
+ precision highp float;
89
+
90
+ uniform sampler2D uVelocity;
91
+ uniform vec2 uTexelSize;
92
+
93
+ in vec2 vL;
94
+ in vec2 vR;
95
+ in vec2 vT;
96
+ in vec2 vB;
97
+ out vec4 outColor;
98
+
99
+ void main() {
100
+ float L = texture(uVelocity, vL).y;
101
+ float R = texture(uVelocity, vR).y;
102
+ float T = texture(uVelocity, vT).x;
103
+ float B = texture(uVelocity, vB).x;
104
+ outColor = vec4(0.5 * (R - L - T + B), 0.0, 0.0, 1.0);
105
+ }`;
106
+ var VORTICITY = `#version 300 es
107
+ precision highp float;
108
+
109
+ uniform sampler2D uVelocity;
110
+ uniform sampler2D uCurl;
111
+ uniform vec2 uTexelSize;
112
+ uniform float uDt;
113
+ uniform float uStrength;
114
+
115
+ in vec2 vUv;
116
+ in vec2 vL;
117
+ in vec2 vR;
118
+ in vec2 vT;
119
+ in vec2 vB;
120
+ out vec4 outColor;
121
+
122
+ void main() {
123
+ float L = texture(uCurl, vL).x;
124
+ float R = texture(uCurl, vR).x;
125
+ float T = texture(uCurl, vT).x;
126
+ float B = texture(uCurl, vB).x;
127
+ float C = texture(uCurl, vUv).x;
128
+ vec2 force = 0.5 * vec2(abs(T) - abs(B), abs(R) - abs(L));
129
+ force /= length(force) + 1e-4;
130
+ force *= uStrength * C;
131
+ force.y *= -1.0;
132
+ vec2 velocity = texture(uVelocity, vUv).xy + force * uDt;
133
+ outColor = vec4(clamp(velocity, vec2(-1000.0), vec2(1000.0)), 0.0, 1.0);
134
+ }`;
135
+ var PRESSURE = `#version 300 es
136
+ precision highp float;
137
+
138
+ uniform sampler2D uPressure;
139
+ uniform sampler2D uDivergence;
140
+ uniform vec2 uTexelSize;
141
+
142
+ in vec2 vUv;
143
+ in vec2 vL;
144
+ in vec2 vR;
145
+ in vec2 vT;
146
+ in vec2 vB;
147
+ out vec4 outColor;
148
+
149
+ void main() {
150
+ float L = texture(uPressure, vL).x;
151
+ float R = texture(uPressure, vR).x;
152
+ float T = texture(uPressure, vT).x;
153
+ float B = texture(uPressure, vB).x;
154
+ float divergence = texture(uDivergence, vUv).x;
155
+ outColor = vec4((L + R + T + B - divergence) * 0.25, 0.0, 0.0, 1.0);
156
+ }`;
157
+ var GRADIENT = `#version 300 es
158
+ precision highp float;
159
+
160
+ uniform sampler2D uPressure;
161
+ uniform sampler2D uVelocity;
162
+ uniform vec2 uTexelSize;
163
+
164
+ in vec2 vUv;
165
+ in vec2 vL;
166
+ in vec2 vR;
167
+ in vec2 vT;
168
+ in vec2 vB;
169
+ out vec4 outColor;
170
+
171
+ void main() {
172
+ float L = texture(uPressure, vL).x;
173
+ float R = texture(uPressure, vR).x;
174
+ float T = texture(uPressure, vT).x;
175
+ float B = texture(uPressure, vB).x;
176
+ vec2 velocity = texture(uVelocity, vUv).xy - vec2(R - L, T - B);
177
+ outColor = vec4(velocity, 0.0, 1.0);
178
+ }`;
179
+ var CLEAR = `#version 300 es
180
+ precision highp float;
181
+
182
+ uniform sampler2D uTexture;
183
+ uniform float uValue;
184
+
185
+ in vec2 vUv;
186
+ out vec4 outColor;
187
+
188
+ void main() {
189
+ outColor = vec4(uValue * texture(uTexture, vUv).rgb, 1.0);
190
+ }`;
191
+ var DISPLAY = `#version 300 es
192
+ precision highp float;
193
+
194
+ uniform sampler2D uDye;
195
+ uniform vec2 uTexelSize;
196
+ uniform float uOpacity;
197
+ uniform bool uShading;
198
+
199
+ in vec2 vUv;
200
+ in vec2 vL;
201
+ in vec2 vR;
202
+ in vec2 vT;
203
+ in vec2 vB;
204
+ out vec4 outColor;
205
+
206
+ void main() {
207
+ vec3 c = texture(uDye, vUv).rgb;
208
+ if (uShading) {
209
+ vec3 lc = texture(uDye, vL).rgb;
210
+ vec3 rc = texture(uDye, vR).rgb;
211
+ vec3 tc = texture(uDye, vT).rgb;
212
+ vec3 bc = texture(uDye, vB).rgb;
213
+ float dx = length(rc) - length(lc);
214
+ float dy = length(tc) - length(bc);
215
+ vec3 normal = normalize(vec3(dx, dy, length(uTexelSize)));
216
+ float diffuse = clamp(dot(normal, vec3(0.0, 0.0, 1.0)) + 0.7, 0.7, 1.0);
217
+ c *= diffuse;
218
+ }
219
+ vec3 colour = clamp(c, 0.0, 1.0);
220
+ float alpha = clamp(max(colour.r, max(colour.g, colour.b)) * uOpacity, 0.0, 1.0);
221
+ outColor = vec4(colour * uOpacity, alpha);
222
+ }`;
223
+ function createFluidWebGL(gl, initial) {
224
+ if (!gl.getExtension("EXT_color_buffer_float")) throw new Error("interactive-bg: fluid needs EXT_color_buffer_float");
225
+ let options = resolveFluidOptions(initial);
226
+ function makePass(fragment, names) {
227
+ const program = createProgram(gl, VERTEX, fragment);
228
+ if (!program) throw new Error("interactive-bg: fluid could not create a shader program");
229
+ return {
230
+ program,
231
+ uniforms: getUniforms(gl, program, names)
232
+ };
233
+ }
234
+ const splatPass = makePass(SPLAT, [
235
+ "uTarget",
236
+ "uPoint",
237
+ "uColor",
238
+ "uRadius",
239
+ "uAspect"
240
+ ]);
241
+ const advectionPass = makePass(ADVECTION, [
242
+ "uVelocity",
243
+ "uSource",
244
+ "uDt",
245
+ "uDissipation",
246
+ "uTexelSize"
247
+ ]);
248
+ const divergencePass = makePass(DIVERGENCE, ["uVelocity", "uTexelSize"]);
249
+ const curlPass = makePass(CURL, ["uVelocity", "uTexelSize"]);
250
+ const vorticityPass = makePass(VORTICITY, [
251
+ "uVelocity",
252
+ "uCurl",
253
+ "uDt",
254
+ "uStrength",
255
+ "uTexelSize"
256
+ ]);
257
+ const pressurePass = makePass(PRESSURE, [
258
+ "uPressure",
259
+ "uDivergence",
260
+ "uTexelSize"
261
+ ]);
262
+ const gradientPass = makePass(GRADIENT, [
263
+ "uPressure",
264
+ "uVelocity",
265
+ "uTexelSize"
266
+ ]);
267
+ const clearPass = makePass(CLEAR, ["uTexture", "uValue"]);
268
+ const displayPass = makePass(DISPLAY, [
269
+ "uDye",
270
+ "uOpacity",
271
+ "uShading",
272
+ "uTexelSize"
273
+ ]);
274
+ function createFBO(width, height) {
275
+ const texture = gl.createTexture();
276
+ const framebuffer = gl.createFramebuffer();
277
+ if (!texture || !framebuffer) throw new Error("interactive-bg: fluid could not allocate a render target");
278
+ gl.bindTexture(gl.TEXTURE_2D, texture);
279
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA16F, width, height, 0, gl.RGBA, gl.HALF_FLOAT, null);
280
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
281
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
282
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
283
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
284
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
285
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
286
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) throw new Error("interactive-bg: fluid render target is incomplete");
287
+ gl.viewport(0, 0, width, height);
288
+ gl.clearColor(0, 0, 0, 0);
289
+ gl.clear(gl.COLOR_BUFFER_BIT);
290
+ return {
291
+ texture,
292
+ framebuffer,
293
+ width,
294
+ height
295
+ };
296
+ }
297
+ function createDoubleFBO(width, height) {
298
+ const pair = {
299
+ read: createFBO(width, height),
300
+ write: createFBO(width, height),
301
+ swap() {
302
+ [pair.read, pair.write] = [pair.write, pair.read];
303
+ }
304
+ };
305
+ return pair;
306
+ }
307
+ function deleteFBO(target) {
308
+ gl.deleteTexture(target.texture);
309
+ gl.deleteFramebuffer(target.framebuffer);
310
+ }
311
+ let simWidth = 0;
312
+ let simHeight = 0;
313
+ let dyeWidth = 0;
314
+ let dyeHeight = 0;
315
+ let builtWidth = 0;
316
+ let builtHeight = 0;
317
+ let builtResolution = -1;
318
+ let velocity;
319
+ let dye;
320
+ let pressure;
321
+ let divergence;
322
+ let curl;
323
+ velocity = createDoubleFBO(1, 1);
324
+ dye = createDoubleFBO(1, 1);
325
+ pressure = createDoubleFBO(1, 1);
326
+ divergence = createFBO(1, 1);
327
+ curl = createFBO(1, 1);
328
+ function allocate(width, height) {
329
+ for (const target of [
330
+ velocity.read,
331
+ velocity.write,
332
+ dye.read,
333
+ dye.write,
334
+ pressure.read,
335
+ pressure.write,
336
+ divergence,
337
+ curl
338
+ ]) deleteFBO(target);
339
+ const grid = simulationSize(options.resolution, width, height);
340
+ const dyeGrid = simulationSize(Math.min(MAX_DYE_RESOLUTION, Math.max(256, options.resolution * 8)), width, height);
341
+ simWidth = grid.width;
342
+ simHeight = grid.height;
343
+ dyeWidth = dyeGrid.width;
344
+ dyeHeight = dyeGrid.height;
345
+ velocity = createDoubleFBO(simWidth, simHeight);
346
+ dye = createDoubleFBO(dyeWidth, dyeHeight);
347
+ pressure = createDoubleFBO(simWidth, simHeight);
348
+ divergence = createFBO(simWidth, simHeight);
349
+ curl = createFBO(simWidth, simHeight);
350
+ burstPending = true;
351
+ }
352
+ function draw(pass, target) {
353
+ gl.bindFramebuffer(gl.FRAMEBUFFER, target.framebuffer);
354
+ gl.viewport(0, 0, target.width, target.height);
355
+ gl.useProgram(pass.program);
356
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
357
+ }
358
+ function texture(unit, source) {
359
+ gl.activeTexture(gl.TEXTURE0 + unit);
360
+ gl.bindTexture(gl.TEXTURE_2D, source);
361
+ }
362
+ function splatVelocity(pointX, pointY, vx, vy, radius, aspect) {
363
+ const { uniforms, program } = splatPass;
364
+ texture(0, velocity.read.texture);
365
+ gl.useProgram(program);
366
+ gl.uniform1i(uniforms.uTarget, 0);
367
+ gl.uniform2f(uniforms.uPoint, pointX, pointY);
368
+ gl.uniform3f(uniforms.uColor, vx, vy, 0);
369
+ gl.uniform1f(uniforms.uRadius, radius * radius);
370
+ gl.uniform1f(uniforms.uAspect, aspect);
371
+ draw(splatPass, velocity.write);
372
+ velocity.swap();
373
+ }
374
+ function splatDye(pointX, pointY, colour, radius, aspect) {
375
+ const { uniforms, program } = splatPass;
376
+ texture(0, dye.read.texture);
377
+ gl.useProgram(program);
378
+ gl.uniform1i(uniforms.uTarget, 0);
379
+ gl.uniform2f(uniforms.uPoint, pointX, pointY);
380
+ gl.uniform3f(uniforms.uColor, colour[0] * DYE_INTENSITY, colour[1] * DYE_INTENSITY, colour[2] * DYE_INTENSITY);
381
+ gl.uniform1f(uniforms.uRadius, radius * radius);
382
+ gl.uniform1f(uniforms.uAspect, aspect);
383
+ draw(splatPass, dye.write);
384
+ dye.swap();
385
+ }
386
+ function splatAt(x, y, vx, vy, colour, radiusPx, aspect, height) {
387
+ const pointX = x / (height * aspect);
388
+ const pointY = 1 - y / height;
389
+ const radius = Math.max(5e-4, radiusPx / height);
390
+ splatVelocity(pointX, pointY, vx, -vy, radius, aspect);
391
+ splatDye(pointX, pointY, colour, radius, aspect);
392
+ }
393
+ function step(dt) {
394
+ gl.disable(gl.BLEND);
395
+ const idleBoost = idleTime > .5 ? 1 / IDLE_DECAY : 0;
396
+ gl.useProgram(curlPass.program);
397
+ texture(0, velocity.read.texture);
398
+ gl.uniform1i(curlPass.uniforms.uVelocity, 0);
399
+ gl.uniform2f(curlPass.uniforms.uTexelSize, 1 / simWidth, 1 / simHeight);
400
+ draw(curlPass, curl);
401
+ gl.useProgram(vorticityPass.program);
402
+ texture(0, velocity.read.texture);
403
+ texture(1, curl.texture);
404
+ gl.uniform1i(vorticityPass.uniforms.uVelocity, 0);
405
+ gl.uniform1i(vorticityPass.uniforms.uCurl, 1);
406
+ gl.uniform2f(vorticityPass.uniforms.uTexelSize, 1 / simWidth, 1 / simHeight);
407
+ gl.uniform1f(vorticityPass.uniforms.uDt, dt);
408
+ gl.uniform1f(vorticityPass.uniforms.uStrength, options.curl);
409
+ draw(vorticityPass, velocity.write);
410
+ velocity.swap();
411
+ gl.useProgram(divergencePass.program);
412
+ texture(0, velocity.read.texture);
413
+ gl.uniform1i(divergencePass.uniforms.uVelocity, 0);
414
+ gl.uniform2f(divergencePass.uniforms.uTexelSize, 1 / simWidth, 1 / simHeight);
415
+ draw(divergencePass, divergence);
416
+ gl.useProgram(clearPass.program);
417
+ texture(0, pressure.read.texture);
418
+ gl.uniform1i(clearPass.uniforms.uTexture, 0);
419
+ gl.uniform1f(clearPass.uniforms.uValue, PRESSURE_RETENTION);
420
+ draw(clearPass, pressure.write);
421
+ pressure.swap();
422
+ for (let iteration = 0; iteration < 20; iteration++) {
423
+ gl.useProgram(pressurePass.program);
424
+ texture(0, pressure.read.texture);
425
+ texture(1, divergence.texture);
426
+ gl.uniform1i(pressurePass.uniforms.uPressure, 0);
427
+ gl.uniform1i(pressurePass.uniforms.uDivergence, 1);
428
+ gl.uniform2f(pressurePass.uniforms.uTexelSize, 1 / simWidth, 1 / simHeight);
429
+ draw(pressurePass, pressure.write);
430
+ pressure.swap();
431
+ }
432
+ gl.useProgram(gradientPass.program);
433
+ texture(0, pressure.read.texture);
434
+ texture(1, velocity.read.texture);
435
+ gl.uniform1i(gradientPass.uniforms.uPressure, 0);
436
+ gl.uniform1i(gradientPass.uniforms.uVelocity, 1);
437
+ gl.uniform2f(gradientPass.uniforms.uTexelSize, 1 / simWidth, 1 / simHeight);
438
+ draw(gradientPass, velocity.write);
439
+ velocity.swap();
440
+ gl.useProgram(advectionPass.program);
441
+ gl.uniform1i(advectionPass.uniforms.uVelocity, 0);
442
+ gl.uniform1i(advectionPass.uniforms.uSource, 1);
443
+ gl.uniform1f(advectionPass.uniforms.uDt, dt);
444
+ gl.uniform2f(advectionPass.uniforms.uTexelSize, 1 / simWidth, 1 / simHeight);
445
+ texture(0, velocity.read.texture);
446
+ texture(1, velocity.read.texture);
447
+ gl.uniform1f(advectionPass.uniforms.uDissipation, 1 / VELOCITY_FADE);
448
+ draw(advectionPass, velocity.write);
449
+ velocity.swap();
450
+ gl.useProgram(advectionPass.program);
451
+ gl.uniform1i(advectionPass.uniforms.uVelocity, 0);
452
+ gl.uniform1i(advectionPass.uniforms.uSource, 1);
453
+ gl.uniform1f(advectionPass.uniforms.uDt, dt);
454
+ gl.uniform1f(advectionPass.uniforms.uDissipation, 1 / options.fade + idleBoost);
455
+ gl.uniform2f(advectionPass.uniforms.uTexelSize, 1 / simWidth, 1 / simHeight);
456
+ texture(0, velocity.read.texture);
457
+ texture(1, dye.read.texture);
458
+ draw(advectionPass, dye.write);
459
+ dye.swap();
460
+ }
461
+ let clock = 0;
462
+ let active = 0;
463
+ let idleTime = 0;
464
+ let lastX = 0;
465
+ let lastY = 0;
466
+ let wasInside = false;
467
+ let burstPending = true;
468
+ function wake() {
469
+ active = Math.max(active, IDLE_CLEAR + .5);
470
+ idleTime = 0;
471
+ }
472
+ function burst(x, y, radius, aspect, height) {
473
+ const colour = splatColor(options, clock);
474
+ const dye = [
475
+ colour[0] * BURST_DYE,
476
+ colour[1] * BURST_DYE,
477
+ colour[2] * BURST_DYE
478
+ ];
479
+ const angle = Math.random() * TAU;
480
+ const speed = options.force * BURST_FORCE;
481
+ splatAt(x, y, Math.cos(angle) * speed, Math.sin(angle) * speed, dye, radius, aspect, height);
482
+ }
483
+ function click(x, y, aspect, height) {
484
+ const colour = splatColor(options, clock);
485
+ const dye = [
486
+ colour[0] * 10,
487
+ colour[1] * 10,
488
+ colour[2] * 10
489
+ ];
490
+ splatAt(x, y, 10 * (Math.random() - .5), 30 * (Math.random() - .5), dye, options.radius, aspect, height);
491
+ wake();
492
+ }
493
+ function mountSize(width, height) {
494
+ if (width === builtWidth && height === builtHeight && options.resolution === builtResolution) return;
495
+ builtWidth = width;
496
+ builtHeight = height;
497
+ builtResolution = options.resolution;
498
+ allocate(width, height);
499
+ }
500
+ /** Clear both sides of a double buffer. */
501
+ function clearField(target) {
502
+ for (const fbo of [target.read, target.write]) {
503
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo.framebuffer);
504
+ gl.viewport(0, 0, fbo.width, fbo.height);
505
+ gl.clearColor(0, 0, 0, 0);
506
+ gl.clear(gl.COLOR_BUFFER_BIT);
507
+ }
508
+ }
509
+ function drawDye(frame) {
510
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
511
+ gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
512
+ gl.enable(gl.BLEND);
513
+ gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
514
+ gl.useProgram(displayPass.program);
515
+ texture(0, dye.read.texture);
516
+ gl.uniform1i(displayPass.uniforms.uDye, 0);
517
+ gl.uniform2f(displayPass.uniforms.uTexelSize, 1 / Math.max(1, frame.width * frame.dpr), 1 / Math.max(1, frame.height * frame.dpr));
518
+ gl.uniform1f(displayPass.uniforms.uOpacity, options.opacity);
519
+ gl.uniform1i(displayPass.uniforms.uShading, options.shading ? 1 : 0);
520
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
521
+ }
522
+ return {
523
+ update(next) {
524
+ options = resolveFluidOptions(next);
525
+ },
526
+ render(frame) {
527
+ mountSize(frame.width, frame.height);
528
+ if (frame.reducedMotion) {
529
+ if (burstPending) {
530
+ burstPending = false;
531
+ const aspect = frame.width / Math.max(1, frame.height);
532
+ burst(frame.width * (.34 + Math.random() * .18), frame.height * (.4 + Math.random() * .2), options.radius * BURST_RADIUS, aspect, frame.height);
533
+ }
534
+ drawDye(frame);
535
+ return false;
536
+ }
537
+ const dt = Math.min(frame.dt, 1 / 60);
538
+ const aspect = frame.width / Math.max(1, frame.height);
539
+ const { pointer } = frame;
540
+ if (burstPending) {
541
+ burstPending = false;
542
+ burst(frame.width * (.34 + Math.random() * .18), frame.height * (.4 + Math.random() * .2), options.radius * BURST_RADIUS, aspect, frame.height);
543
+ wake();
544
+ }
545
+ if (pointer.influence > 0) {
546
+ if (wasInside) {
547
+ const moveX = pointer.x - lastX;
548
+ const moveY = pointer.y - lastY;
549
+ const dx = moveX / Math.max(1, frame.width);
550
+ const dy = moveY / Math.max(1, frame.height);
551
+ if (Math.hypot(moveX, moveY) > .5) {
552
+ const colour = splatColor(options, clock);
553
+ const strength = options.force * pointer.influence;
554
+ splatAt(pointer.x, pointer.y, dx * strength, dy * strength, colour, options.radius, aspect, frame.height);
555
+ wake();
556
+ }
557
+ }
558
+ lastX = pointer.x;
559
+ lastY = pointer.y;
560
+ wasInside = true;
561
+ } else wasInside = false;
562
+ for (const clickPoint of frame.clicks) click(clickPoint.x, clickPoint.y, aspect, frame.height);
563
+ if (dt > 0) {
564
+ idleTime += dt;
565
+ if (idleTime >= 3.5) {
566
+ clearField(dye);
567
+ clearField(velocity);
568
+ idleTime = 0;
569
+ active = 0;
570
+ drawDye(frame);
571
+ return false;
572
+ }
573
+ step(dt);
574
+ clock += dt;
575
+ active = Math.max(0, active - dt);
576
+ }
577
+ drawDye(frame);
578
+ return active > 0;
579
+ },
580
+ destroy() {
581
+ for (const target of [
582
+ velocity.read,
583
+ velocity.write,
584
+ dye.read,
585
+ dye.write,
586
+ pressure.read,
587
+ pressure.write,
588
+ divergence,
589
+ curl
590
+ ]) deleteFBO(target);
591
+ for (const pass of [
592
+ splatPass,
593
+ advectionPass,
594
+ divergencePass,
595
+ curlPass,
596
+ vorticityPass,
597
+ pressurePass,
598
+ gradientPass,
599
+ clearPass,
600
+ displayPass
601
+ ]) gl.deleteProgram(pass.program);
602
+ }
603
+ };
604
+ }
605
+ export { createFluidWebGL };
606
+
607
+ //# sourceMappingURL=webgl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webgl.js","names":[],"sources":["../../../src/styles/fluid/webgl.ts"],"sourcesContent":["import type { Frame, StyleRenderer } from '../../core/style';\nimport { createProgram, getUniforms } from '../../core/webgl';\nimport { splatColor, type RGB } from './color';\nimport { resolveFluidOptions, type FluidOptions } from './options';\nimport {\n BURST_DYE,\n BURST_FORCE,\n BURST_RADIUS,\n DYE_INTENSITY,\n DYE_SCALE,\n IDLE_CLEAR,\n IDLE_DECAY,\n IDLE_DELAY,\n MAX_DYE_RESOLUTION,\n PRESSURE_ITERATIONS,\n PRESSURE_RETENTION,\n VELOCITY_FADE,\n} from './settings';\nimport { simulationSize } from './size';\n\nconst TAU = Math.PI * 2;\n\n// All passes are one full-screen triangle. Neighbouring texel coordinates are\n// worked out once in the vertex shader and interpolated.\nconst VERTEX = `#version 300 es\nprecision highp float;\n\nuniform vec2 uTexelSize;\n\nout vec2 vUv;\nout vec2 vL;\nout vec2 vR;\nout vec2 vT;\nout vec2 vB;\n\nvoid main() {\n vec2 p = vec2(float((gl_VertexID << 1) & 2), float(gl_VertexID & 2));\n vUv = p;\n vL = vUv - vec2(uTexelSize.x, 0.0);\n vR = vUv + vec2(uTexelSize.x, 0.0);\n vT = vUv + vec2(0.0, uTexelSize.y);\n vB = vUv - vec2(0.0, uTexelSize.y);\n gl_Position = vec4(p * 2.0 - 1.0, 0.0, 1.0);\n}`;\n\nconst SPLAT = `#version 300 es\nprecision highp float;\n\nuniform sampler2D uTarget;\nuniform vec2 uPoint;\nuniform vec3 uColor;\nuniform float uRadius; // squared radius, in screens-heights\nuniform float uAspect;\n\nin vec2 vUv;\nout vec4 outColor;\n\nvoid main() {\n vec2 p = vUv - uPoint;\n p.x *= uAspect;\n vec3 splat = exp(-dot(p, p) / uRadius) * uColor;\n outColor = vec4(texture(uTarget, vUv).rgb + splat, 1.0);\n}`;\n\nconst ADVECTION = `#version 300 es\nprecision highp float;\n\nuniform sampler2D uVelocity;\nuniform sampler2D uSource;\nuniform vec2 uTexelSize;\nuniform float uDt;\nuniform float uDissipation;\n\nin vec2 vUv;\nout vec4 outColor;\n\nvoid main() {\n vec2 coord = vUv - uDt * texture(uVelocity, vUv).xy * uTexelSize;\n outColor = texture(uSource, coord) / (1.0 + uDissipation * uDt);\n}`;\n\nconst DIVERGENCE = `#version 300 es\nprecision highp float;\n\nuniform sampler2D uVelocity;\nuniform vec2 uTexelSize;\n\nin vec2 vUv;\nin vec2 vL;\nin vec2 vR;\nin vec2 vT;\nin vec2 vB;\nout vec4 outColor;\n\nvoid main() {\n float L = texture(uVelocity, vL).x;\n float R = texture(uVelocity, vR).x;\n float T = texture(uVelocity, vT).y;\n float B = texture(uVelocity, vB).y;\n vec2 C = texture(uVelocity, vUv).xy;\n if (vL.x < 0.0) L = -C.x;\n if (vR.x > 1.0) R = -C.x;\n if (vT.y > 1.0) T = -C.y;\n if (vB.y < 0.0) B = -C.y;\n outColor = vec4(0.5 * (R - L + T - B), 0.0, 0.0, 1.0);\n}`;\n\nconst CURL = `#version 300 es\nprecision highp float;\n\nuniform sampler2D uVelocity;\nuniform vec2 uTexelSize;\n\nin vec2 vL;\nin vec2 vR;\nin vec2 vT;\nin vec2 vB;\nout vec4 outColor;\n\nvoid main() {\n float L = texture(uVelocity, vL).y;\n float R = texture(uVelocity, vR).y;\n float T = texture(uVelocity, vT).x;\n float B = texture(uVelocity, vB).x;\n outColor = vec4(0.5 * (R - L - T + B), 0.0, 0.0, 1.0);\n}`;\n\nconst VORTICITY = `#version 300 es\nprecision highp float;\n\nuniform sampler2D uVelocity;\nuniform sampler2D uCurl;\nuniform vec2 uTexelSize;\nuniform float uDt;\nuniform float uStrength;\n\nin vec2 vUv;\nin vec2 vL;\nin vec2 vR;\nin vec2 vT;\nin vec2 vB;\nout vec4 outColor;\n\nvoid main() {\n float L = texture(uCurl, vL).x;\n float R = texture(uCurl, vR).x;\n float T = texture(uCurl, vT).x;\n float B = texture(uCurl, vB).x;\n float C = texture(uCurl, vUv).x;\n vec2 force = 0.5 * vec2(abs(T) - abs(B), abs(R) - abs(L));\n force /= length(force) + 1e-4;\n force *= uStrength * C;\n force.y *= -1.0;\n vec2 velocity = texture(uVelocity, vUv).xy + force * uDt;\n outColor = vec4(clamp(velocity, vec2(-1000.0), vec2(1000.0)), 0.0, 1.0);\n}`;\n\nconst PRESSURE = `#version 300 es\nprecision highp float;\n\nuniform sampler2D uPressure;\nuniform sampler2D uDivergence;\nuniform vec2 uTexelSize;\n\nin vec2 vUv;\nin vec2 vL;\nin vec2 vR;\nin vec2 vT;\nin vec2 vB;\nout vec4 outColor;\n\nvoid main() {\n float L = texture(uPressure, vL).x;\n float R = texture(uPressure, vR).x;\n float T = texture(uPressure, vT).x;\n float B = texture(uPressure, vB).x;\n float divergence = texture(uDivergence, vUv).x;\n outColor = vec4((L + R + T + B - divergence) * 0.25, 0.0, 0.0, 1.0);\n}`;\n\nconst GRADIENT = `#version 300 es\nprecision highp float;\n\nuniform sampler2D uPressure;\nuniform sampler2D uVelocity;\nuniform vec2 uTexelSize;\n\nin vec2 vUv;\nin vec2 vL;\nin vec2 vR;\nin vec2 vT;\nin vec2 vB;\nout vec4 outColor;\n\nvoid main() {\n float L = texture(uPressure, vL).x;\n float R = texture(uPressure, vR).x;\n float T = texture(uPressure, vT).x;\n float B = texture(uPressure, vB).x;\n vec2 velocity = texture(uVelocity, vUv).xy - vec2(R - L, T - B);\n outColor = vec4(velocity, 0.0, 1.0);\n}`;\n\nconst CLEAR = `#version 300 es\nprecision highp float;\n\nuniform sampler2D uTexture;\nuniform float uValue;\n\nin vec2 vUv;\nout vec4 outColor;\n\nvoid main() {\n outColor = vec4(uValue * texture(uTexture, vUv).rgb, 1.0);\n}`;\n\nconst DISPLAY = `#version 300 es\nprecision highp float;\n\nuniform sampler2D uDye;\nuniform vec2 uTexelSize;\nuniform float uOpacity;\nuniform bool uShading;\n\nin vec2 vUv;\nin vec2 vL;\nin vec2 vR;\nin vec2 vT;\nin vec2 vB;\nout vec4 outColor;\n\nvoid main() {\n vec3 c = texture(uDye, vUv).rgb;\n if (uShading) {\n vec3 lc = texture(uDye, vL).rgb;\n vec3 rc = texture(uDye, vR).rgb;\n vec3 tc = texture(uDye, vT).rgb;\n vec3 bc = texture(uDye, vB).rgb;\n float dx = length(rc) - length(lc);\n float dy = length(tc) - length(bc);\n vec3 normal = normalize(vec3(dx, dy, length(uTexelSize)));\n float diffuse = clamp(dot(normal, vec3(0.0, 0.0, 1.0)) + 0.7, 0.7, 1.0);\n c *= diffuse;\n }\n vec3 colour = clamp(c, 0.0, 1.0);\n float alpha = clamp(max(colour.r, max(colour.g, colour.b)) * uOpacity, 0.0, 1.0);\n outColor = vec4(colour * uOpacity, alpha);\n}`;\n\ninterface FBO {\n texture: WebGLTexture;\n framebuffer: WebGLFramebuffer;\n width: number;\n height: number;\n}\n\ninterface DoubleFBO {\n read: FBO;\n write: FBO;\n swap(): void;\n}\n\ninterface Pass {\n program: WebGLProgram;\n uniforms: Record<string, WebGLUniformLocation | null>;\n}\n\nexport function createFluidWebGL(gl: WebGL2RenderingContext, initial: FluidOptions): StyleRenderer<FluidOptions> {\n if (!gl.getExtension('EXT_color_buffer_float')) {\n throw new Error('interactive-bg: fluid needs EXT_color_buffer_float');\n }\n\n let options = resolveFluidOptions(initial);\n\n function makePass(fragment: string, names: readonly string[]): Pass {\n const program = createProgram(gl, VERTEX, fragment);\n if (!program) throw new Error('interactive-bg: fluid could not create a shader program');\n return { program, uniforms: getUniforms(gl, program, names) };\n }\n\n const splatPass = makePass(SPLAT, ['uTarget', 'uPoint', 'uColor', 'uRadius', 'uAspect']);\n const advectionPass = makePass(ADVECTION, ['uVelocity', 'uSource', 'uDt', 'uDissipation', 'uTexelSize']);\n const divergencePass = makePass(DIVERGENCE, ['uVelocity', 'uTexelSize']);\n const curlPass = makePass(CURL, ['uVelocity', 'uTexelSize']);\n const vorticityPass = makePass(VORTICITY, ['uVelocity', 'uCurl', 'uDt', 'uStrength', 'uTexelSize']);\n const pressurePass = makePass(PRESSURE, ['uPressure', 'uDivergence', 'uTexelSize']);\n const gradientPass = makePass(GRADIENT, ['uPressure', 'uVelocity', 'uTexelSize']);\n const clearPass = makePass(CLEAR, ['uTexture', 'uValue']);\n const displayPass = makePass(DISPLAY, ['uDye', 'uOpacity', 'uShading', 'uTexelSize']);\n\n function createFBO(width: number, height: number): FBO {\n const texture = gl.createTexture();\n const framebuffer = gl.createFramebuffer();\n if (!texture || !framebuffer) throw new Error('interactive-bg: fluid could not allocate a render target');\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA16F, width, height, 0, gl.RGBA, gl.HALF_FLOAT, null);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);\n if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) {\n throw new Error('interactive-bg: fluid render target is incomplete');\n }\n gl.viewport(0, 0, width, height);\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n return { texture, framebuffer, width, height };\n }\n\n function createDoubleFBO(width: number, height: number): DoubleFBO {\n const a = createFBO(width, height);\n const b = createFBO(width, height);\n const pair = {\n read: a,\n write: b,\n swap() {\n [pair.read, pair.write] = [pair.write, pair.read];\n },\n };\n return pair;\n }\n\n function deleteFBO(target: FBO): void {\n gl.deleteTexture(target.texture);\n gl.deleteFramebuffer(target.framebuffer);\n }\n\n let simWidth = 0;\n let simHeight = 0;\n let dyeWidth = 0;\n let dyeHeight = 0;\n let builtWidth = 0;\n let builtHeight = 0;\n let builtResolution = -1;\n let velocity: DoubleFBO;\n let dye: DoubleFBO;\n let pressure: DoubleFBO;\n let divergence: FBO;\n let curl: FBO;\n\n // Initialised below by allocate().\n velocity = createDoubleFBO(1, 1);\n dye = createDoubleFBO(1, 1);\n pressure = createDoubleFBO(1, 1);\n divergence = createFBO(1, 1);\n curl = createFBO(1, 1);\n\n function allocate(width: number, height: number): void {\n for (const target of [velocity.read, velocity.write, dye.read, dye.write, pressure.read, pressure.write, divergence, curl]) {\n deleteFBO(target);\n }\n const grid = simulationSize(options.resolution, width, height);\n const dyeGrid = simulationSize(\n Math.min(MAX_DYE_RESOLUTION, Math.max(256, options.resolution * DYE_SCALE)),\n width,\n height,\n );\n simWidth = grid.width;\n simHeight = grid.height;\n dyeWidth = dyeGrid.width;\n dyeHeight = dyeGrid.height;\n velocity = createDoubleFBO(simWidth, simHeight);\n dye = createDoubleFBO(dyeWidth, dyeHeight);\n pressure = createDoubleFBO(simWidth, simHeight);\n divergence = createFBO(simWidth, simHeight);\n curl = createFBO(simWidth, simHeight);\n burstPending = true;\n }\n\n function draw(pass: Pass, target: FBO): void {\n gl.bindFramebuffer(gl.FRAMEBUFFER, target.framebuffer);\n gl.viewport(0, 0, target.width, target.height);\n gl.useProgram(pass.program);\n gl.drawArrays(gl.TRIANGLES, 0, 3);\n }\n\n function texture(unit: number, source: WebGLTexture): void {\n gl.activeTexture(gl.TEXTURE0 + unit);\n gl.bindTexture(gl.TEXTURE_2D, source);\n }\n\n function splatVelocity(pointX: number, pointY: number, vx: number, vy: number, radius: number, aspect: number): void {\n const { uniforms, program } = splatPass;\n texture(0, velocity.read.texture);\n gl.useProgram(program);\n gl.uniform1i(uniforms.uTarget, 0);\n gl.uniform2f(uniforms.uPoint, pointX, pointY);\n gl.uniform3f(uniforms.uColor, vx, vy, 0);\n gl.uniform1f(uniforms.uRadius, radius * radius);\n gl.uniform1f(uniforms.uAspect, aspect);\n draw(splatPass, velocity.write);\n velocity.swap();\n }\n\n function splatDye(pointX: number, pointY: number, colour: RGB, radius: number, aspect: number): void {\n const { uniforms, program } = splatPass;\n texture(0, dye.read.texture);\n gl.useProgram(program);\n gl.uniform1i(uniforms.uTarget, 0);\n gl.uniform2f(uniforms.uPoint, pointX, pointY);\n gl.uniform3f(uniforms.uColor, colour[0] * DYE_INTENSITY, colour[1] * DYE_INTENSITY, colour[2] * DYE_INTENSITY);\n gl.uniform1f(uniforms.uRadius, radius * radius);\n gl.uniform1f(uniforms.uAspect, aspect);\n draw(splatPass, dye.write);\n dye.swap();\n }\n\n function splatAt(\n x: number,\n y: number,\n vx: number,\n vy: number,\n colour: RGB,\n radiusPx: number,\n aspect: number,\n height: number,\n ): void {\n const pointX = x / (height * aspect);\n // Texture v points up; pointer y points down. Flip both the splash position\n // and the vertical velocity so the smoke follows the pointer's direction.\n const pointY = 1 - y / height;\n const radius = Math.max(0.0005, radiusPx / height);\n splatVelocity(pointX, pointY, vx, -vy, radius, aspect);\n splatDye(pointX, pointY, colour, radius, aspect);\n }\n\n function step(dt: number): void {\n gl.disable(gl.BLEND);\n const idleBoost = idleTime > IDLE_DELAY ? 1 / IDLE_DECAY : 0;\n // Vorticity confinement: the curl of the velocity becomes a force.\n gl.useProgram(curlPass.program);\n texture(0, velocity.read.texture);\n gl.uniform1i(curlPass.uniforms.uVelocity, 0);\n gl.uniform2f(curlPass.uniforms.uTexelSize, 1 / simWidth, 1 / simHeight);\n draw(curlPass, curl);\n\n gl.useProgram(vorticityPass.program);\n texture(0, velocity.read.texture);\n texture(1, curl.texture);\n gl.uniform1i(vorticityPass.uniforms.uVelocity, 0);\n gl.uniform1i(vorticityPass.uniforms.uCurl, 1);\n gl.uniform2f(vorticityPass.uniforms.uTexelSize, 1 / simWidth, 1 / simHeight);\n gl.uniform1f(vorticityPass.uniforms.uDt, dt);\n gl.uniform1f(vorticityPass.uniforms.uStrength, options.curl);\n draw(vorticityPass, velocity.write);\n velocity.swap();\n\n gl.useProgram(divergencePass.program);\n texture(0, velocity.read.texture);\n gl.uniform1i(divergencePass.uniforms.uVelocity, 0);\n gl.uniform2f(divergencePass.uniforms.uTexelSize, 1 / simWidth, 1 / simHeight);\n draw(divergencePass, divergence);\n\n gl.useProgram(clearPass.program);\n texture(0, pressure.read.texture);\n gl.uniform1i(clearPass.uniforms.uTexture, 0);\n gl.uniform1f(clearPass.uniforms.uValue, PRESSURE_RETENTION);\n draw(clearPass, pressure.write);\n pressure.swap();\n for (let iteration = 0; iteration < PRESSURE_ITERATIONS; iteration++) {\n gl.useProgram(pressurePass.program);\n texture(0, pressure.read.texture);\n texture(1, divergence.texture);\n gl.uniform1i(pressurePass.uniforms.uPressure, 0);\n gl.uniform1i(pressurePass.uniforms.uDivergence, 1);\n gl.uniform2f(pressurePass.uniforms.uTexelSize, 1 / simWidth, 1 / simHeight);\n draw(pressurePass, pressure.write);\n pressure.swap();\n }\n\n gl.useProgram(gradientPass.program);\n texture(0, pressure.read.texture);\n texture(1, velocity.read.texture);\n gl.uniform1i(gradientPass.uniforms.uPressure, 0);\n gl.uniform1i(gradientPass.uniforms.uVelocity, 1);\n gl.uniform2f(gradientPass.uniforms.uTexelSize, 1 / simWidth, 1 / simHeight);\n draw(gradientPass, velocity.write);\n velocity.swap();\n\n gl.useProgram(advectionPass.program);\n gl.uniform1i(advectionPass.uniforms.uVelocity, 0);\n gl.uniform1i(advectionPass.uniforms.uSource, 1);\n gl.uniform1f(advectionPass.uniforms.uDt, dt);\n gl.uniform2f(advectionPass.uniforms.uTexelSize, 1 / simWidth, 1 / simHeight);\n texture(0, velocity.read.texture);\n texture(1, velocity.read.texture);\n gl.uniform1f(advectionPass.uniforms.uDissipation, 1 / VELOCITY_FADE);\n draw(advectionPass, velocity.write);\n velocity.swap();\n\n gl.useProgram(advectionPass.program);\n gl.uniform1i(advectionPass.uniforms.uVelocity, 0);\n gl.uniform1i(advectionPass.uniforms.uSource, 1);\n gl.uniform1f(advectionPass.uniforms.uDt, dt);\n gl.uniform1f(advectionPass.uniforms.uDissipation, 1 / options.fade + idleBoost);\n gl.uniform2f(advectionPass.uniforms.uTexelSize, 1 / simWidth, 1 / simHeight);\n texture(0, velocity.read.texture);\n texture(1, dye.read.texture);\n draw(advectionPass, dye.write);\n dye.swap();\n }\n\n let clock = 0;\n let active = 0;\n let idleTime = 0;\n let lastX = 0;\n let lastY = 0;\n let wasInside = false;\n let burstPending = true;\n\n function wake(): void {\n active = Math.max(active, IDLE_CLEAR + 0.5);\n idleTime = 0;\n }\n\n function burst(x: number, y: number, radius: number, aspect: number, height: number): void {\n const colour = splatColor(options, clock);\n const dye: RGB = [colour[0] * BURST_DYE, colour[1] * BURST_DYE, colour[2] * BURST_DYE];\n const angle = Math.random() * TAU;\n const speed = options.force * BURST_FORCE;\n splatAt(x, y, Math.cos(angle) * speed, Math.sin(angle) * speed, dye, radius, aspect, height);\n }\n\n function click(x: number, y: number, aspect: number, height: number): void {\n const colour = splatColor(options, clock);\n const dye: RGB = [colour[0] * 10, colour[1] * 10, colour[2] * 10];\n const dx = 10 * (Math.random() - 0.5);\n const dy = 30 * (Math.random() - 0.5);\n splatAt(x, y, dx, dy, dye, options.radius, aspect, height);\n wake();\n }\n\n function mountSize(width: number, height: number): void {\n if (width === builtWidth && height === builtHeight && options.resolution === builtResolution) return;\n builtWidth = width;\n builtHeight = height;\n builtResolution = options.resolution;\n allocate(width, height);\n }\n\n /** Clear both sides of a double buffer. */\n function clearField(target: DoubleFBO): void {\n for (const fbo of [target.read, target.write]) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, fbo.framebuffer);\n gl.viewport(0, 0, fbo.width, fbo.height);\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n }\n }\n\n function drawDye(frame: Frame): void {\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);\n gl.enable(gl.BLEND);\n gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n gl.useProgram(displayPass.program);\n texture(0, dye.read.texture);\n gl.uniform1i(displayPass.uniforms.uDye, 0);\n gl.uniform2f(displayPass.uniforms.uTexelSize, 1 / Math.max(1, frame.width * frame.dpr), 1 / Math.max(1, frame.height * frame.dpr));\n gl.uniform1f(displayPass.uniforms.uOpacity, options.opacity);\n gl.uniform1i(displayPass.uniforms.uShading, options.shading ? 1 : 0);\n gl.drawArrays(gl.TRIANGLES, 0, 3);\n }\n\n return {\n update(next) {\n options = resolveFluidOptions(next);\n },\n render(frame: Frame) {\n mountSize(frame.width, frame.height);\n if (frame.reducedMotion) {\n // Hold the smoke still: one static splash, no simulation. The engine then stops.\n if (burstPending) {\n burstPending = false;\n const aspect = frame.width / Math.max(1, frame.height);\n const bx = frame.width * (0.34 + Math.random() * 0.18);\n const by = frame.height * (0.4 + Math.random() * 0.2);\n burst(bx, by, options.radius * BURST_RADIUS, aspect, frame.height);\n }\n drawDye(frame);\n return false;\n }\n\n const dt = Math.min(frame.dt, 1 / 60);\n const aspect = frame.width / Math.max(1, frame.height);\n const { pointer } = frame;\n\n if (burstPending) {\n burstPending = false;\n const bx = frame.width * (0.34 + Math.random() * 0.18);\n const by = frame.height * (0.4 + Math.random() * 0.2);\n burst(bx, by, options.radius * BURST_RADIUS, aspect, frame.height);\n wake();\n }\n\n if (pointer.influence > 0) {\n if (wasInside) {\n const moveX = pointer.x - lastX;\n const moveY = pointer.y - lastY;\n const dx = moveX / Math.max(1, frame.width);\n const dy = moveY / Math.max(1, frame.height);\n // Like a real mousemove stream: don't keep adding dye to a resting pointer.\n if (Math.hypot(moveX, moveY) > 0.5) {\n const colour = splatColor(options, clock);\n const strength = options.force * pointer.influence;\n splatAt(\n pointer.x,\n pointer.y,\n dx * strength,\n dy * strength,\n colour,\n options.radius,\n aspect,\n frame.height,\n );\n wake();\n }\n }\n lastX = pointer.x;\n lastY = pointer.y;\n wasInside = true;\n } else {\n wasInside = false;\n }\n\n for (const clickPoint of frame.clicks) click(clickPoint.x, clickPoint.y, aspect, frame.height);\n\n if (dt > 0) {\n idleTime += dt;\n if (idleTime >= IDLE_CLEAR) {\n clearField(dye);\n clearField(velocity);\n idleTime = 0;\n active = 0;\n drawDye(frame);\n return false;\n }\n step(dt);\n clock += dt;\n active = Math.max(0, active - dt);\n }\n\n drawDye(frame);\n return active > 0;\n },\n destroy() {\n for (const target of [\n velocity.read,\n velocity.write,\n dye.read,\n dye.write,\n pressure.read,\n pressure.write,\n divergence,\n curl,\n ]) {\n deleteFBO(target);\n }\n for (const pass of [\n splatPass,\n advectionPass,\n divergencePass,\n curlPass,\n vorticityPass,\n pressurePass,\n gradientPass,\n clearPass,\n displayPass,\n ]) {\n gl.deleteProgram(pass.program);\n }\n },\n };\n}\n"],"mappings":"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"}