[READ-ONLY] Mirror of https://github.com/flo-bit/webgl-text-flowy-background. flo-bit.dev/webgl-text-flowy-background/
0

Configure Feed

Select the types of activity you want to include in your feed.

first commit

Florian (Jul 29, 2025, 7:24 PM +0200) 4570a488

+1835
+50
.github/workflows/deploy.yml
··· 1 + name: Deploy to GitHub Pages 2 + 3 + on: 4 + push: 5 + branches: 6 + - main 7 + 8 + jobs: 9 + build_site: 10 + runs-on: ubuntu-latest 11 + steps: 12 + - name: Checkout 13 + uses: actions/checkout@v3 14 + 15 + - name: Install Node.js 16 + uses: actions/setup-node@v3 17 + with: 18 + node-version: 18 19 + cache: npm 20 + 21 + - name: Install dependencies 22 + run: npm ci 23 + 24 + - name: build 25 + env: 26 + BASE_PATH: '/${{ github.event.repository.name }}' 27 + run: | 28 + npm run build 29 + 30 + - name: Upload Artifacts 31 + uses: actions/upload-pages-artifact@v2 32 + with: 33 + path: 'dist/' 34 + 35 + deploy: 36 + needs: build_site 37 + runs-on: ubuntu-latest 38 + 39 + permissions: 40 + pages: write 41 + id-token: write 42 + 43 + environment: 44 + name: github-pages 45 + url: ${{ steps.deployment.outputs.page_url }} 46 + 47 + steps: 48 + - name: Deploy 49 + id: deployment 50 + uses: actions/deploy-pages@v2
+24
.gitignore
··· 1 + # Logs 2 + logs 3 + *.log 4 + npm-debug.log* 5 + yarn-debug.log* 6 + yarn-error.log* 7 + pnpm-debug.log* 8 + lerna-debug.log* 9 + 10 + node_modules 11 + dist 12 + dist-ssr 13 + *.local 14 + 15 + # Editor directories and files 16 + .vscode/* 17 + !.vscode/extensions.json 18 + .idea 19 + .DS_Store 20 + *.suo 21 + *.ntvs* 22 + *.njsproj 23 + *.sln 24 + *.sw?
+3
Readme.md
··· 1 + # flowing webgl gradient text 2 + 3 + adapted from https://alexharri.com/blog/webgl-gradients to work as a text background.
+75
index.html
··· 1 + <!doctype html> 2 + <html lang="en"> 3 + <head> 4 + <meta charset="UTF-8" /> 5 + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 + <title>Shader App</title> 7 + <style> 8 + body, 9 + html { 10 + margin: 0; 11 + padding: 0; 12 + width: 100%; 13 + height: 100%; 14 + overflow: hidden; 15 + } 16 + 17 + body { 18 + background: black; 19 + } 20 + 21 + .mask-wrapper { 22 + position: fixed; 23 + top: 25%; 24 + left: 0; 25 + width: 100vw; 26 + height: 60vh; 27 + /* apply the SVG mask we defined above: */ 28 + mask: url(#text-mask) no-repeat center / cover; 29 + -webkit-mask: url(#text-mask) no-repeat center / cover; 30 + /* fallback background outside the text: */ 31 + background: black; 32 + } 33 + 34 + .mask-wrapper canvas { 35 + position: absolute; 36 + top: 0; 37 + left: 0; 38 + width: 100%; 39 + height: 100%; 40 + } 41 + </style> 42 + </head> 43 + <body> 44 + <div class="mask-wrapper"> 45 + <svg width="100vw" height="50vh" style="position: absolute"> 46 + <defs> 47 + <mask 48 + id="text-mask" 49 + maskUnits="userSpaceOnUse" 50 + maskContentUnits="userSpaceOnUse" 51 + > 52 + <!-- black = transparent, white = opaque --> 53 + <rect x="0" y="0" width="100%" height="100%" fill="black" /> 54 + <text 55 + x="50%" 56 + y="50%" 57 + text-anchor="middle" 58 + dy=".35em" 59 + fill="white" 60 + font-family="'Arial Rounded MT Bold', 'Comic Sans MS', sans-serif" 61 + 62 + font-weight="1000" 63 + font-size="30vw" 64 + > 65 + flowy 66 + </text> 67 + </mask> 68 + </defs> 69 + </svg> 70 + 71 + <canvas id="glcanvas"></canvas> 72 + </div> 73 + <script type="module" src="/src/main.ts"></script> 74 + </body> 75 + </html>
+1030
package-lock.json
··· 1 + { 2 + "name": "webgl-blur-shader", 3 + "version": "0.0.0", 4 + "lockfileVersion": 3, 5 + "requires": true, 6 + "packages": { 7 + "": { 8 + "name": "webgl-blur-shader", 9 + "version": "0.0.0", 10 + "dependencies": { 11 + "vite-plugin-glsl": "^1.5.1" 12 + }, 13 + "devDependencies": { 14 + "typescript": "~5.8.3", 15 + "vite": "^7.0.4" 16 + } 17 + }, 18 + "node_modules/@esbuild/aix-ppc64": { 19 + "version": "0.25.8", 20 + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz", 21 + "integrity": "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==", 22 + "cpu": [ 23 + "ppc64" 24 + ], 25 + "license": "MIT", 26 + "optional": true, 27 + "os": [ 28 + "aix" 29 + ], 30 + "engines": { 31 + "node": ">=18" 32 + } 33 + }, 34 + "node_modules/@esbuild/android-arm": { 35 + "version": "0.25.8", 36 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.8.tgz", 37 + "integrity": "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==", 38 + "cpu": [ 39 + "arm" 40 + ], 41 + "license": "MIT", 42 + "optional": true, 43 + "os": [ 44 + "android" 45 + ], 46 + "engines": { 47 + "node": ">=18" 48 + } 49 + }, 50 + "node_modules/@esbuild/android-arm64": { 51 + "version": "0.25.8", 52 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz", 53 + "integrity": "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==", 54 + "cpu": [ 55 + "arm64" 56 + ], 57 + "license": "MIT", 58 + "optional": true, 59 + "os": [ 60 + "android" 61 + ], 62 + "engines": { 63 + "node": ">=18" 64 + } 65 + }, 66 + "node_modules/@esbuild/android-x64": { 67 + "version": "0.25.8", 68 + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.8.tgz", 69 + "integrity": "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==", 70 + "cpu": [ 71 + "x64" 72 + ], 73 + "license": "MIT", 74 + "optional": true, 75 + "os": [ 76 + "android" 77 + ], 78 + "engines": { 79 + "node": ">=18" 80 + } 81 + }, 82 + "node_modules/@esbuild/darwin-arm64": { 83 + "version": "0.25.8", 84 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz", 85 + "integrity": "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==", 86 + "cpu": [ 87 + "arm64" 88 + ], 89 + "license": "MIT", 90 + "optional": true, 91 + "os": [ 92 + "darwin" 93 + ], 94 + "engines": { 95 + "node": ">=18" 96 + } 97 + }, 98 + "node_modules/@esbuild/darwin-x64": { 99 + "version": "0.25.8", 100 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz", 101 + "integrity": "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==", 102 + "cpu": [ 103 + "x64" 104 + ], 105 + "license": "MIT", 106 + "optional": true, 107 + "os": [ 108 + "darwin" 109 + ], 110 + "engines": { 111 + "node": ">=18" 112 + } 113 + }, 114 + "node_modules/@esbuild/freebsd-arm64": { 115 + "version": "0.25.8", 116 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz", 117 + "integrity": "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==", 118 + "cpu": [ 119 + "arm64" 120 + ], 121 + "license": "MIT", 122 + "optional": true, 123 + "os": [ 124 + "freebsd" 125 + ], 126 + "engines": { 127 + "node": ">=18" 128 + } 129 + }, 130 + "node_modules/@esbuild/freebsd-x64": { 131 + "version": "0.25.8", 132 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz", 133 + "integrity": "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==", 134 + "cpu": [ 135 + "x64" 136 + ], 137 + "license": "MIT", 138 + "optional": true, 139 + "os": [ 140 + "freebsd" 141 + ], 142 + "engines": { 143 + "node": ">=18" 144 + } 145 + }, 146 + "node_modules/@esbuild/linux-arm": { 147 + "version": "0.25.8", 148 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz", 149 + "integrity": "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==", 150 + "cpu": [ 151 + "arm" 152 + ], 153 + "license": "MIT", 154 + "optional": true, 155 + "os": [ 156 + "linux" 157 + ], 158 + "engines": { 159 + "node": ">=18" 160 + } 161 + }, 162 + "node_modules/@esbuild/linux-arm64": { 163 + "version": "0.25.8", 164 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz", 165 + "integrity": "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==", 166 + "cpu": [ 167 + "arm64" 168 + ], 169 + "license": "MIT", 170 + "optional": true, 171 + "os": [ 172 + "linux" 173 + ], 174 + "engines": { 175 + "node": ">=18" 176 + } 177 + }, 178 + "node_modules/@esbuild/linux-ia32": { 179 + "version": "0.25.8", 180 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz", 181 + "integrity": "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==", 182 + "cpu": [ 183 + "ia32" 184 + ], 185 + "license": "MIT", 186 + "optional": true, 187 + "os": [ 188 + "linux" 189 + ], 190 + "engines": { 191 + "node": ">=18" 192 + } 193 + }, 194 + "node_modules/@esbuild/linux-loong64": { 195 + "version": "0.25.8", 196 + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz", 197 + "integrity": "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==", 198 + "cpu": [ 199 + "loong64" 200 + ], 201 + "license": "MIT", 202 + "optional": true, 203 + "os": [ 204 + "linux" 205 + ], 206 + "engines": { 207 + "node": ">=18" 208 + } 209 + }, 210 + "node_modules/@esbuild/linux-mips64el": { 211 + "version": "0.25.8", 212 + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz", 213 + "integrity": "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==", 214 + "cpu": [ 215 + "mips64el" 216 + ], 217 + "license": "MIT", 218 + "optional": true, 219 + "os": [ 220 + "linux" 221 + ], 222 + "engines": { 223 + "node": ">=18" 224 + } 225 + }, 226 + "node_modules/@esbuild/linux-ppc64": { 227 + "version": "0.25.8", 228 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz", 229 + "integrity": "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==", 230 + "cpu": [ 231 + "ppc64" 232 + ], 233 + "license": "MIT", 234 + "optional": true, 235 + "os": [ 236 + "linux" 237 + ], 238 + "engines": { 239 + "node": ">=18" 240 + } 241 + }, 242 + "node_modules/@esbuild/linux-riscv64": { 243 + "version": "0.25.8", 244 + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz", 245 + "integrity": "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==", 246 + "cpu": [ 247 + "riscv64" 248 + ], 249 + "license": "MIT", 250 + "optional": true, 251 + "os": [ 252 + "linux" 253 + ], 254 + "engines": { 255 + "node": ">=18" 256 + } 257 + }, 258 + "node_modules/@esbuild/linux-s390x": { 259 + "version": "0.25.8", 260 + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz", 261 + "integrity": "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==", 262 + "cpu": [ 263 + "s390x" 264 + ], 265 + "license": "MIT", 266 + "optional": true, 267 + "os": [ 268 + "linux" 269 + ], 270 + "engines": { 271 + "node": ">=18" 272 + } 273 + }, 274 + "node_modules/@esbuild/linux-x64": { 275 + "version": "0.25.8", 276 + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz", 277 + "integrity": "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==", 278 + "cpu": [ 279 + "x64" 280 + ], 281 + "license": "MIT", 282 + "optional": true, 283 + "os": [ 284 + "linux" 285 + ], 286 + "engines": { 287 + "node": ">=18" 288 + } 289 + }, 290 + "node_modules/@esbuild/netbsd-arm64": { 291 + "version": "0.25.8", 292 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz", 293 + "integrity": "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==", 294 + "cpu": [ 295 + "arm64" 296 + ], 297 + "license": "MIT", 298 + "optional": true, 299 + "os": [ 300 + "netbsd" 301 + ], 302 + "engines": { 303 + "node": ">=18" 304 + } 305 + }, 306 + "node_modules/@esbuild/netbsd-x64": { 307 + "version": "0.25.8", 308 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz", 309 + "integrity": "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==", 310 + "cpu": [ 311 + "x64" 312 + ], 313 + "license": "MIT", 314 + "optional": true, 315 + "os": [ 316 + "netbsd" 317 + ], 318 + "engines": { 319 + "node": ">=18" 320 + } 321 + }, 322 + "node_modules/@esbuild/openbsd-arm64": { 323 + "version": "0.25.8", 324 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz", 325 + "integrity": "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==", 326 + "cpu": [ 327 + "arm64" 328 + ], 329 + "license": "MIT", 330 + "optional": true, 331 + "os": [ 332 + "openbsd" 333 + ], 334 + "engines": { 335 + "node": ">=18" 336 + } 337 + }, 338 + "node_modules/@esbuild/openbsd-x64": { 339 + "version": "0.25.8", 340 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz", 341 + "integrity": "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==", 342 + "cpu": [ 343 + "x64" 344 + ], 345 + "license": "MIT", 346 + "optional": true, 347 + "os": [ 348 + "openbsd" 349 + ], 350 + "engines": { 351 + "node": ">=18" 352 + } 353 + }, 354 + "node_modules/@esbuild/openharmony-arm64": { 355 + "version": "0.25.8", 356 + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz", 357 + "integrity": "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==", 358 + "cpu": [ 359 + "arm64" 360 + ], 361 + "license": "MIT", 362 + "optional": true, 363 + "os": [ 364 + "openharmony" 365 + ], 366 + "engines": { 367 + "node": ">=18" 368 + } 369 + }, 370 + "node_modules/@esbuild/sunos-x64": { 371 + "version": "0.25.8", 372 + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz", 373 + "integrity": "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==", 374 + "cpu": [ 375 + "x64" 376 + ], 377 + "license": "MIT", 378 + "optional": true, 379 + "os": [ 380 + "sunos" 381 + ], 382 + "engines": { 383 + "node": ">=18" 384 + } 385 + }, 386 + "node_modules/@esbuild/win32-arm64": { 387 + "version": "0.25.8", 388 + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz", 389 + "integrity": "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==", 390 + "cpu": [ 391 + "arm64" 392 + ], 393 + "license": "MIT", 394 + "optional": true, 395 + "os": [ 396 + "win32" 397 + ], 398 + "engines": { 399 + "node": ">=18" 400 + } 401 + }, 402 + "node_modules/@esbuild/win32-ia32": { 403 + "version": "0.25.8", 404 + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz", 405 + "integrity": "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==", 406 + "cpu": [ 407 + "ia32" 408 + ], 409 + "license": "MIT", 410 + "optional": true, 411 + "os": [ 412 + "win32" 413 + ], 414 + "engines": { 415 + "node": ">=18" 416 + } 417 + }, 418 + "node_modules/@esbuild/win32-x64": { 419 + "version": "0.25.8", 420 + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz", 421 + "integrity": "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==", 422 + "cpu": [ 423 + "x64" 424 + ], 425 + "license": "MIT", 426 + "optional": true, 427 + "os": [ 428 + "win32" 429 + ], 430 + "engines": { 431 + "node": ">=18" 432 + } 433 + }, 434 + "node_modules/@rollup/pluginutils": { 435 + "version": "5.2.0", 436 + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.2.0.tgz", 437 + "integrity": "sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==", 438 + "license": "MIT", 439 + "dependencies": { 440 + "@types/estree": "^1.0.0", 441 + "estree-walker": "^2.0.2", 442 + "picomatch": "^4.0.2" 443 + }, 444 + "engines": { 445 + "node": ">=14.0.0" 446 + }, 447 + "peerDependencies": { 448 + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" 449 + }, 450 + "peerDependenciesMeta": { 451 + "rollup": { 452 + "optional": true 453 + } 454 + } 455 + }, 456 + "node_modules/@rollup/rollup-android-arm-eabi": { 457 + "version": "4.45.1", 458 + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.45.1.tgz", 459 + "integrity": "sha512-NEySIFvMY0ZQO+utJkgoMiCAjMrGvnbDLHvcmlA33UXJpYBCvlBEbMMtV837uCkS+plG2umfhn0T5mMAxGrlRA==", 460 + "cpu": [ 461 + "arm" 462 + ], 463 + "license": "MIT", 464 + "optional": true, 465 + "os": [ 466 + "android" 467 + ] 468 + }, 469 + "node_modules/@rollup/rollup-android-arm64": { 470 + "version": "4.45.1", 471 + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.45.1.tgz", 472 + "integrity": "sha512-ujQ+sMXJkg4LRJaYreaVx7Z/VMgBBd89wGS4qMrdtfUFZ+TSY5Rs9asgjitLwzeIbhwdEhyj29zhst3L1lKsRQ==", 473 + "cpu": [ 474 + "arm64" 475 + ], 476 + "license": "MIT", 477 + "optional": true, 478 + "os": [ 479 + "android" 480 + ] 481 + }, 482 + "node_modules/@rollup/rollup-darwin-arm64": { 483 + "version": "4.45.1", 484 + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.45.1.tgz", 485 + "integrity": "sha512-FSncqHvqTm3lC6Y13xncsdOYfxGSLnP+73k815EfNmpewPs+EyM49haPS105Rh4aF5mJKywk9X0ogzLXZzN9lA==", 486 + "cpu": [ 487 + "arm64" 488 + ], 489 + "license": "MIT", 490 + "optional": true, 491 + "os": [ 492 + "darwin" 493 + ] 494 + }, 495 + "node_modules/@rollup/rollup-darwin-x64": { 496 + "version": "4.45.1", 497 + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.45.1.tgz", 498 + "integrity": "sha512-2/vVn/husP5XI7Fsf/RlhDaQJ7x9zjvC81anIVbr4b/f0xtSmXQTFcGIQ/B1cXIYM6h2nAhJkdMHTnD7OtQ9Og==", 499 + "cpu": [ 500 + "x64" 501 + ], 502 + "license": "MIT", 503 + "optional": true, 504 + "os": [ 505 + "darwin" 506 + ] 507 + }, 508 + "node_modules/@rollup/rollup-freebsd-arm64": { 509 + "version": "4.45.1", 510 + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.45.1.tgz", 511 + "integrity": "sha512-4g1kaDxQItZsrkVTdYQ0bxu4ZIQ32cotoQbmsAnW1jAE4XCMbcBPDirX5fyUzdhVCKgPcrwWuucI8yrVRBw2+g==", 512 + "cpu": [ 513 + "arm64" 514 + ], 515 + "license": "MIT", 516 + "optional": true, 517 + "os": [ 518 + "freebsd" 519 + ] 520 + }, 521 + "node_modules/@rollup/rollup-freebsd-x64": { 522 + "version": "4.45.1", 523 + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.45.1.tgz", 524 + "integrity": "sha512-L/6JsfiL74i3uK1Ti2ZFSNsp5NMiM4/kbbGEcOCps99aZx3g8SJMO1/9Y0n/qKlWZfn6sScf98lEOUe2mBvW9A==", 525 + "cpu": [ 526 + "x64" 527 + ], 528 + "license": "MIT", 529 + "optional": true, 530 + "os": [ 531 + "freebsd" 532 + ] 533 + }, 534 + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 535 + "version": "4.45.1", 536 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.45.1.tgz", 537 + "integrity": "sha512-RkdOTu2jK7brlu+ZwjMIZfdV2sSYHK2qR08FUWcIoqJC2eywHbXr0L8T/pONFwkGukQqERDheaGTeedG+rra6Q==", 538 + "cpu": [ 539 + "arm" 540 + ], 541 + "license": "MIT", 542 + "optional": true, 543 + "os": [ 544 + "linux" 545 + ] 546 + }, 547 + "node_modules/@rollup/rollup-linux-arm-musleabihf": { 548 + "version": "4.45.1", 549 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.45.1.tgz", 550 + "integrity": "sha512-3kJ8pgfBt6CIIr1o+HQA7OZ9mp/zDk3ctekGl9qn/pRBgrRgfwiffaUmqioUGN9hv0OHv2gxmvdKOkARCtRb8Q==", 551 + "cpu": [ 552 + "arm" 553 + ], 554 + "license": "MIT", 555 + "optional": true, 556 + "os": [ 557 + "linux" 558 + ] 559 + }, 560 + "node_modules/@rollup/rollup-linux-arm64-gnu": { 561 + "version": "4.45.1", 562 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.45.1.tgz", 563 + "integrity": "sha512-k3dOKCfIVixWjG7OXTCOmDfJj3vbdhN0QYEqB+OuGArOChek22hn7Uy5A/gTDNAcCy5v2YcXRJ/Qcnm4/ma1xw==", 564 + "cpu": [ 565 + "arm64" 566 + ], 567 + "license": "MIT", 568 + "optional": true, 569 + "os": [ 570 + "linux" 571 + ] 572 + }, 573 + "node_modules/@rollup/rollup-linux-arm64-musl": { 574 + "version": "4.45.1", 575 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.45.1.tgz", 576 + "integrity": "sha512-PmI1vxQetnM58ZmDFl9/Uk2lpBBby6B6rF4muJc65uZbxCs0EA7hhKCk2PKlmZKuyVSHAyIw3+/SiuMLxKxWog==", 577 + "cpu": [ 578 + "arm64" 579 + ], 580 + "license": "MIT", 581 + "optional": true, 582 + "os": [ 583 + "linux" 584 + ] 585 + }, 586 + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { 587 + "version": "4.45.1", 588 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.45.1.tgz", 589 + "integrity": "sha512-9UmI0VzGmNJ28ibHW2GpE2nF0PBQqsyiS4kcJ5vK+wuwGnV5RlqdczVocDSUfGX/Na7/XINRVoUgJyFIgipoRg==", 590 + "cpu": [ 591 + "loong64" 592 + ], 593 + "license": "MIT", 594 + "optional": true, 595 + "os": [ 596 + "linux" 597 + ] 598 + }, 599 + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { 600 + "version": "4.45.1", 601 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.45.1.tgz", 602 + "integrity": "sha512-7nR2KY8oEOUTD3pBAxIBBbZr0U7U+R9HDTPNy+5nVVHDXI4ikYniH1oxQz9VoB5PbBU1CZuDGHkLJkd3zLMWsg==", 603 + "cpu": [ 604 + "ppc64" 605 + ], 606 + "license": "MIT", 607 + "optional": true, 608 + "os": [ 609 + "linux" 610 + ] 611 + }, 612 + "node_modules/@rollup/rollup-linux-riscv64-gnu": { 613 + "version": "4.45.1", 614 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.45.1.tgz", 615 + "integrity": "sha512-nlcl3jgUultKROfZijKjRQLUu9Ma0PeNv/VFHkZiKbXTBQXhpytS8CIj5/NfBeECZtY2FJQubm6ltIxm/ftxpw==", 616 + "cpu": [ 617 + "riscv64" 618 + ], 619 + "license": "MIT", 620 + "optional": true, 621 + "os": [ 622 + "linux" 623 + ] 624 + }, 625 + "node_modules/@rollup/rollup-linux-riscv64-musl": { 626 + "version": "4.45.1", 627 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.45.1.tgz", 628 + "integrity": "sha512-HJV65KLS51rW0VY6rvZkiieiBnurSzpzore1bMKAhunQiECPuxsROvyeaot/tcK3A3aGnI+qTHqisrpSgQrpgA==", 629 + "cpu": [ 630 + "riscv64" 631 + ], 632 + "license": "MIT", 633 + "optional": true, 634 + "os": [ 635 + "linux" 636 + ] 637 + }, 638 + "node_modules/@rollup/rollup-linux-s390x-gnu": { 639 + "version": "4.45.1", 640 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.45.1.tgz", 641 + "integrity": "sha512-NITBOCv3Qqc6hhwFt7jLV78VEO/il4YcBzoMGGNxznLgRQf43VQDae0aAzKiBeEPIxnDrACiMgbqjuihx08OOw==", 642 + "cpu": [ 643 + "s390x" 644 + ], 645 + "license": "MIT", 646 + "optional": true, 647 + "os": [ 648 + "linux" 649 + ] 650 + }, 651 + "node_modules/@rollup/rollup-linux-x64-gnu": { 652 + "version": "4.45.1", 653 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.45.1.tgz", 654 + "integrity": "sha512-+E/lYl6qu1zqgPEnTrs4WysQtvc/Sh4fC2nByfFExqgYrqkKWp1tWIbe+ELhixnenSpBbLXNi6vbEEJ8M7fiHw==", 655 + "cpu": [ 656 + "x64" 657 + ], 658 + "license": "MIT", 659 + "optional": true, 660 + "os": [ 661 + "linux" 662 + ] 663 + }, 664 + "node_modules/@rollup/rollup-linux-x64-musl": { 665 + "version": "4.45.1", 666 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.45.1.tgz", 667 + "integrity": "sha512-a6WIAp89p3kpNoYStITT9RbTbTnqarU7D8N8F2CV+4Cl9fwCOZraLVuVFvlpsW0SbIiYtEnhCZBPLoNdRkjQFw==", 668 + "cpu": [ 669 + "x64" 670 + ], 671 + "license": "MIT", 672 + "optional": true, 673 + "os": [ 674 + "linux" 675 + ] 676 + }, 677 + "node_modules/@rollup/rollup-win32-arm64-msvc": { 678 + "version": "4.45.1", 679 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.45.1.tgz", 680 + "integrity": "sha512-T5Bi/NS3fQiJeYdGvRpTAP5P02kqSOpqiopwhj0uaXB6nzs5JVi2XMJb18JUSKhCOX8+UE1UKQufyD6Or48dJg==", 681 + "cpu": [ 682 + "arm64" 683 + ], 684 + "license": "MIT", 685 + "optional": true, 686 + "os": [ 687 + "win32" 688 + ] 689 + }, 690 + "node_modules/@rollup/rollup-win32-ia32-msvc": { 691 + "version": "4.45.1", 692 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.45.1.tgz", 693 + "integrity": "sha512-lxV2Pako3ujjuUe9jiU3/s7KSrDfH6IgTSQOnDWr9aJ92YsFd7EurmClK0ly/t8dzMkDtd04g60WX6yl0sGfdw==", 694 + "cpu": [ 695 + "ia32" 696 + ], 697 + "license": "MIT", 698 + "optional": true, 699 + "os": [ 700 + "win32" 701 + ] 702 + }, 703 + "node_modules/@rollup/rollup-win32-x64-msvc": { 704 + "version": "4.45.1", 705 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.45.1.tgz", 706 + "integrity": "sha512-M/fKi4sasCdM8i0aWJjCSFm2qEnYRR8AMLG2kxp6wD13+tMGA4Z1tVAuHkNRjud5SW2EM3naLuK35w9twvf6aA==", 707 + "cpu": [ 708 + "x64" 709 + ], 710 + "license": "MIT", 711 + "optional": true, 712 + "os": [ 713 + "win32" 714 + ] 715 + }, 716 + "node_modules/@types/estree": { 717 + "version": "1.0.8", 718 + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", 719 + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", 720 + "license": "MIT" 721 + }, 722 + "node_modules/esbuild": { 723 + "version": "0.25.8", 724 + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz", 725 + "integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==", 726 + "hasInstallScript": true, 727 + "license": "MIT", 728 + "bin": { 729 + "esbuild": "bin/esbuild" 730 + }, 731 + "engines": { 732 + "node": ">=18" 733 + }, 734 + "optionalDependencies": { 735 + "@esbuild/aix-ppc64": "0.25.8", 736 + "@esbuild/android-arm": "0.25.8", 737 + "@esbuild/android-arm64": "0.25.8", 738 + "@esbuild/android-x64": "0.25.8", 739 + "@esbuild/darwin-arm64": "0.25.8", 740 + "@esbuild/darwin-x64": "0.25.8", 741 + "@esbuild/freebsd-arm64": "0.25.8", 742 + "@esbuild/freebsd-x64": "0.25.8", 743 + "@esbuild/linux-arm": "0.25.8", 744 + "@esbuild/linux-arm64": "0.25.8", 745 + "@esbuild/linux-ia32": "0.25.8", 746 + "@esbuild/linux-loong64": "0.25.8", 747 + "@esbuild/linux-mips64el": "0.25.8", 748 + "@esbuild/linux-ppc64": "0.25.8", 749 + "@esbuild/linux-riscv64": "0.25.8", 750 + "@esbuild/linux-s390x": "0.25.8", 751 + "@esbuild/linux-x64": "0.25.8", 752 + "@esbuild/netbsd-arm64": "0.25.8", 753 + "@esbuild/netbsd-x64": "0.25.8", 754 + "@esbuild/openbsd-arm64": "0.25.8", 755 + "@esbuild/openbsd-x64": "0.25.8", 756 + "@esbuild/openharmony-arm64": "0.25.8", 757 + "@esbuild/sunos-x64": "0.25.8", 758 + "@esbuild/win32-arm64": "0.25.8", 759 + "@esbuild/win32-ia32": "0.25.8", 760 + "@esbuild/win32-x64": "0.25.8" 761 + } 762 + }, 763 + "node_modules/estree-walker": { 764 + "version": "2.0.2", 765 + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", 766 + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", 767 + "license": "MIT" 768 + }, 769 + "node_modules/fdir": { 770 + "version": "6.4.6", 771 + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", 772 + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", 773 + "license": "MIT", 774 + "peerDependencies": { 775 + "picomatch": "^3 || ^4" 776 + }, 777 + "peerDependenciesMeta": { 778 + "picomatch": { 779 + "optional": true 780 + } 781 + } 782 + }, 783 + "node_modules/fsevents": { 784 + "version": "2.3.3", 785 + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 786 + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 787 + "hasInstallScript": true, 788 + "license": "MIT", 789 + "optional": true, 790 + "os": [ 791 + "darwin" 792 + ], 793 + "engines": { 794 + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 795 + } 796 + }, 797 + "node_modules/nanoid": { 798 + "version": "3.3.11", 799 + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", 800 + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", 801 + "funding": [ 802 + { 803 + "type": "github", 804 + "url": "https://github.com/sponsors/ai" 805 + } 806 + ], 807 + "license": "MIT", 808 + "bin": { 809 + "nanoid": "bin/nanoid.cjs" 810 + }, 811 + "engines": { 812 + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 813 + } 814 + }, 815 + "node_modules/picocolors": { 816 + "version": "1.1.1", 817 + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 818 + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 819 + "license": "ISC" 820 + }, 821 + "node_modules/picomatch": { 822 + "version": "4.0.3", 823 + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", 824 + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", 825 + "license": "MIT", 826 + "engines": { 827 + "node": ">=12" 828 + }, 829 + "funding": { 830 + "url": "https://github.com/sponsors/jonschlinkert" 831 + } 832 + }, 833 + "node_modules/postcss": { 834 + "version": "8.5.6", 835 + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", 836 + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", 837 + "funding": [ 838 + { 839 + "type": "opencollective", 840 + "url": "https://opencollective.com/postcss/" 841 + }, 842 + { 843 + "type": "tidelift", 844 + "url": "https://tidelift.com/funding/github/npm/postcss" 845 + }, 846 + { 847 + "type": "github", 848 + "url": "https://github.com/sponsors/ai" 849 + } 850 + ], 851 + "license": "MIT", 852 + "dependencies": { 853 + "nanoid": "^3.3.11", 854 + "picocolors": "^1.1.1", 855 + "source-map-js": "^1.2.1" 856 + }, 857 + "engines": { 858 + "node": "^10 || ^12 || >=14" 859 + } 860 + }, 861 + "node_modules/rollup": { 862 + "version": "4.45.1", 863 + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.45.1.tgz", 864 + "integrity": "sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw==", 865 + "license": "MIT", 866 + "dependencies": { 867 + "@types/estree": "1.0.8" 868 + }, 869 + "bin": { 870 + "rollup": "dist/bin/rollup" 871 + }, 872 + "engines": { 873 + "node": ">=18.0.0", 874 + "npm": ">=8.0.0" 875 + }, 876 + "optionalDependencies": { 877 + "@rollup/rollup-android-arm-eabi": "4.45.1", 878 + "@rollup/rollup-android-arm64": "4.45.1", 879 + "@rollup/rollup-darwin-arm64": "4.45.1", 880 + "@rollup/rollup-darwin-x64": "4.45.1", 881 + "@rollup/rollup-freebsd-arm64": "4.45.1", 882 + "@rollup/rollup-freebsd-x64": "4.45.1", 883 + "@rollup/rollup-linux-arm-gnueabihf": "4.45.1", 884 + "@rollup/rollup-linux-arm-musleabihf": "4.45.1", 885 + "@rollup/rollup-linux-arm64-gnu": "4.45.1", 886 + "@rollup/rollup-linux-arm64-musl": "4.45.1", 887 + "@rollup/rollup-linux-loongarch64-gnu": "4.45.1", 888 + "@rollup/rollup-linux-powerpc64le-gnu": "4.45.1", 889 + "@rollup/rollup-linux-riscv64-gnu": "4.45.1", 890 + "@rollup/rollup-linux-riscv64-musl": "4.45.1", 891 + "@rollup/rollup-linux-s390x-gnu": "4.45.1", 892 + "@rollup/rollup-linux-x64-gnu": "4.45.1", 893 + "@rollup/rollup-linux-x64-musl": "4.45.1", 894 + "@rollup/rollup-win32-arm64-msvc": "4.45.1", 895 + "@rollup/rollup-win32-ia32-msvc": "4.45.1", 896 + "@rollup/rollup-win32-x64-msvc": "4.45.1", 897 + "fsevents": "~2.3.2" 898 + } 899 + }, 900 + "node_modules/source-map-js": { 901 + "version": "1.2.1", 902 + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", 903 + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", 904 + "license": "BSD-3-Clause", 905 + "engines": { 906 + "node": ">=0.10.0" 907 + } 908 + }, 909 + "node_modules/tinyglobby": { 910 + "version": "0.2.14", 911 + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", 912 + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", 913 + "license": "MIT", 914 + "dependencies": { 915 + "fdir": "^6.4.4", 916 + "picomatch": "^4.0.2" 917 + }, 918 + "engines": { 919 + "node": ">=12.0.0" 920 + }, 921 + "funding": { 922 + "url": "https://github.com/sponsors/SuperchupuDev" 923 + } 924 + }, 925 + "node_modules/typescript": { 926 + "version": "5.8.3", 927 + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", 928 + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", 929 + "dev": true, 930 + "license": "Apache-2.0", 931 + "bin": { 932 + "tsc": "bin/tsc", 933 + "tsserver": "bin/tsserver" 934 + }, 935 + "engines": { 936 + "node": ">=14.17" 937 + } 938 + }, 939 + "node_modules/vite": { 940 + "version": "7.0.6", 941 + "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.6.tgz", 942 + "integrity": "sha512-MHFiOENNBd+Bd9uvc8GEsIzdkn1JxMmEeYX35tI3fv0sJBUTfW5tQsoaOwuY4KhBI09A3dUJ/DXf2yxPVPUceg==", 943 + "license": "MIT", 944 + "dependencies": { 945 + "esbuild": "^0.25.0", 946 + "fdir": "^6.4.6", 947 + "picomatch": "^4.0.3", 948 + "postcss": "^8.5.6", 949 + "rollup": "^4.40.0", 950 + "tinyglobby": "^0.2.14" 951 + }, 952 + "bin": { 953 + "vite": "bin/vite.js" 954 + }, 955 + "engines": { 956 + "node": "^20.19.0 || >=22.12.0" 957 + }, 958 + "funding": { 959 + "url": "https://github.com/vitejs/vite?sponsor=1" 960 + }, 961 + "optionalDependencies": { 962 + "fsevents": "~2.3.3" 963 + }, 964 + "peerDependencies": { 965 + "@types/node": "^20.19.0 || >=22.12.0", 966 + "jiti": ">=1.21.0", 967 + "less": "^4.0.0", 968 + "lightningcss": "^1.21.0", 969 + "sass": "^1.70.0", 970 + "sass-embedded": "^1.70.0", 971 + "stylus": ">=0.54.8", 972 + "sugarss": "^5.0.0", 973 + "terser": "^5.16.0", 974 + "tsx": "^4.8.1", 975 + "yaml": "^2.4.2" 976 + }, 977 + "peerDependenciesMeta": { 978 + "@types/node": { 979 + "optional": true 980 + }, 981 + "jiti": { 982 + "optional": true 983 + }, 984 + "less": { 985 + "optional": true 986 + }, 987 + "lightningcss": { 988 + "optional": true 989 + }, 990 + "sass": { 991 + "optional": true 992 + }, 993 + "sass-embedded": { 994 + "optional": true 995 + }, 996 + "stylus": { 997 + "optional": true 998 + }, 999 + "sugarss": { 1000 + "optional": true 1001 + }, 1002 + "terser": { 1003 + "optional": true 1004 + }, 1005 + "tsx": { 1006 + "optional": true 1007 + }, 1008 + "yaml": { 1009 + "optional": true 1010 + } 1011 + } 1012 + }, 1013 + "node_modules/vite-plugin-glsl": { 1014 + "version": "1.5.1", 1015 + "resolved": "https://registry.npmjs.org/vite-plugin-glsl/-/vite-plugin-glsl-1.5.1.tgz", 1016 + "integrity": "sha512-kFI8rUItruG2Dfltyhr6tP3jlgCBGda2TnIvUodBHbpdQ7KT0NWyKpS1EqV47DoAl4woKzer7GWd1fiEvzf4nQ==", 1017 + "license": "MIT", 1018 + "dependencies": { 1019 + "@rollup/pluginutils": "^5.1.4" 1020 + }, 1021 + "engines": { 1022 + "node": ">= 20.17.0", 1023 + "npm": ">= 10.8.3" 1024 + }, 1025 + "peerDependencies": { 1026 + "vite": ">= 3.x" 1027 + } 1028 + } 1029 + } 1030 + }
+18
package.json
··· 1 + { 2 + "name": "webgl-blur-shader", 3 + "private": true, 4 + "version": "0.0.0", 5 + "type": "module", 6 + "scripts": { 7 + "dev": "vite", 8 + "build": "tsc && vite build", 9 + "preview": "vite preview" 10 + }, 11 + "devDependencies": { 12 + "typescript": "~5.8.3", 13 + "vite": "^7.0.4" 14 + }, 15 + "dependencies": { 16 + "vite-plugin-glsl": "^1.5.1" 17 + } 18 + }
+166
src/WebGLRenderer.ts
··· 1 + import type { ColorConfiguration } from "./colorConfigurations"; 2 + import { colorConfigurations } from "./colorConfigurations"; 3 + 4 + const N_TIME_VALUES = 2; 5 + function timeKey(index: number) { 6 + return index > 0 ? `u_time${index + 1}` : "u_time"; 7 + } 8 + 9 + interface TimeState { 10 + seed: number; 11 + lastTime: number; 12 + elapsed: number; 13 + timeSpeed: number; 14 + } 15 + 16 + export class WebGLRenderer { 17 + readonly gl: WebGLRenderingContext; 18 + readonly program: WebGLProgram; 19 + readonly positionBuffer: WebGLBuffer; 20 + readonly gradientTexture: WebGLTexture; 21 + readonly timeStates: TimeState[]; 22 + readonly uniformLocations = new Map<string, WebGLUniformLocation>(); 23 + 24 + constructor( 25 + canvas: HTMLCanvasElement, 26 + vertexSrc: string, 27 + fragmentSrc: string, 28 + config: ColorConfiguration, 29 + seed?: number, 30 + ) { 31 + const gl = canvas.getContext("webgl")!; 32 + this.gl = gl; 33 + this.program = WebGLRenderer.createProgram(gl, vertexSrc, fragmentSrc); 34 + this.positionBuffer = gl.createBuffer()!; 35 + this.gradientTexture = gl.createTexture()!; 36 + gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer); 37 + this.setPositions(); 38 + 39 + seed = seed ?? Math.random() * 100_000; 40 + this.timeStates = Array(N_TIME_VALUES) 41 + .fill(0) 42 + .map(() => ({ 43 + seed: seed, 44 + lastTime: Date.now(), 45 + elapsed: 0, 46 + timeSpeed: 1, 47 + })); 48 + this.setColorConfig(config); 49 + gl.useProgram(this.program); 50 + } 51 + 52 + private setPositions() { 53 + const gl = this.gl; 54 + gl.bufferData( 55 + gl.ARRAY_BUFFER, 56 + new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]), 57 + gl.STATIC_DRAW, 58 + ); 59 + } 60 + 61 + public setColorConfig(name: ColorConfiguration) { 62 + const gradient = colorConfigurations[name].gradient; 63 + WebGLRenderer.writeGradientToTexture( 64 + this.gl, 65 + gradient, 66 + this.gradientTexture, 67 + 1000, 68 + 2, 69 + ); 70 + } 71 + 72 + public render() { 73 + const gl = this.gl; 74 + const now = Date.now(); 75 + gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); 76 + gl.useProgram(this.program); 77 + 78 + // update time uniforms 79 + this.timeStates.forEach((st, i) => { 80 + const dt = now - st.lastTime; 81 + st.elapsed += dt * st.timeSpeed; 82 + st.lastTime = now; 83 + gl.uniform1f(this.getLoc(timeKey(i)), st.seed + st.elapsed * 0.001); 84 + }); 85 + 86 + gl.uniform1f(this.getLoc("u_w"), gl.canvas.width); 87 + gl.uniform1f(this.getLoc("u_h"), gl.canvas.height); 88 + 89 + // bind gradient 90 + gl.activeTexture(gl.TEXTURE0); 91 + gl.bindTexture(gl.TEXTURE_2D, this.gradientTexture); 92 + gl.uniform1i(this.getLoc("u_gradient"), 0); 93 + 94 + gl.enableVertexAttribArray( 95 + gl.getAttribLocation(this.program, "a_position"), 96 + ); 97 + gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer); 98 + gl.vertexAttribPointer( 99 + gl.getAttribLocation(this.program, "a_position"), 100 + 2, 101 + gl.FLOAT, 102 + false, 103 + 0, 104 + 0, 105 + ); 106 + 107 + gl.clearColor(0, 0, 0, 0); 108 + gl.clear(gl.COLOR_BUFFER_BIT); 109 + gl.drawArrays(gl.TRIANGLES, 0, 6); 110 + } 111 + 112 + private getLoc(name: string) { 113 + if (!this.uniformLocations.has(name)) { 114 + this.uniformLocations.set( 115 + name, 116 + this.gl.getUniformLocation(this.program, name)!, 117 + ); 118 + } 119 + return this.uniformLocations.get(name)!; 120 + } 121 + 122 + private static writeGradientToTexture( 123 + gl: WebGLRenderingContext, 124 + stops: string[], 125 + tex: WebGLTexture, 126 + w: number, 127 + h: number, 128 + ) { 129 + const cvs = document.createElement("canvas"); 130 + cvs.width = w; 131 + cvs.height = h; 132 + const ctx = cvs.getContext("2d")!; 133 + const grad = ctx.createLinearGradient(0, 0, w, 0); 134 + stops.forEach((c, i) => grad.addColorStop(i / (stops.length - 1), c)); 135 + ctx.fillStyle = grad; 136 + ctx.fillRect(0, 0, w, h); 137 + 138 + gl.bindTexture(gl.TEXTURE_2D, tex); 139 + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, cvs); 140 + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 141 + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 142 + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 143 + } 144 + 145 + private static createProgram( 146 + gl: WebGLRenderingContext, 147 + vs: string, 148 + fs: string, 149 + ) { 150 + const compile = (type: number, src: string) => { 151 + const s = gl.createShader(type)!; 152 + gl.shaderSource(s, src); 153 + gl.compileShader(s); 154 + if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) 155 + throw new Error(gl.getShaderInfoLog(s)!); 156 + return s; 157 + }; 158 + const prog = gl.createProgram(); 159 + gl.attachShader(prog, compile(gl.VERTEX_SHADER, vs)); 160 + gl.attachShader(prog, compile(gl.FRAGMENT_SHADER, fs)); 161 + gl.linkProgram(prog); 162 + if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) 163 + throw new Error(gl.getProgramInfoLog(prog)!); 164 + return prog; 165 + } 166 + }
+73
src/colorConfigurations.ts
··· 1 + export type ColorConfiguration = keyof typeof colorConfigurations; 2 + 3 + export const colorConfigurations = { 4 + default: { 5 + gradient: [ 6 + "hsl(240deg 100% 20%)", 7 + "hsl(281deg 100% 21%)", 8 + "hsl(304deg 100% 23%)", 9 + "hsl(319deg 100% 30%)", 10 + "hsl(329deg 100% 36%)", 11 + "hsl(336deg 100% 41%)", 12 + "hsl(346deg 83% 51%)", 13 + "hsl(3deg 95% 61%)", 14 + "hsl(17deg 100% 59%)", 15 + "hsl(30deg 100% 55%)", 16 + "hsl(40deg 100% 50%)", 17 + "hsl(48deg 100% 50%)", 18 + "hsl(55deg 100% 50%)", 19 + ], 20 + }, 21 + 22 + black_white: { 23 + gradient: ["hsl(0deg 0% 0%)", "hsl(0deg 0% 100%)"], 24 + }, 25 + 26 + orange: { 27 + gradient: [ 28 + "hsl(345deg 100% 37%)", 29 + "hsl(1deg 67% 48%)", 30 + "hsl(13deg 75% 48%)", 31 + "hsl(23deg 86% 47%)", 32 + "hsl(31deg 100% 45%)", 33 + "hsl(36deg 100% 46%)", 34 + "hsl(42deg 100% 46%)", 35 + "hsl(49deg 100% 45%)", 36 + "hsl(56deg 100% 44%)", 37 + "hsl(64deg 84% 50%)", 38 + "hsl(75deg 100% 61%)", 39 + ], 40 + }, 41 + 42 + green: { 43 + gradient: [ 44 + "hsl(170deg 31% 19%)", 45 + "hsl(163deg 48% 24%)", 46 + "hsl(152deg 49% 30%)", 47 + "hsl(133deg 38% 40%)", 48 + "hsl(105deg 39% 47%)", 49 + "hsl(83deg 52% 49%)", 50 + "hsl(68deg 68% 49%)", 51 + "hsl(56deg 100% 48%)", 52 + "hsl(54deg 95% 63%)", 53 + "hsl(53deg 99% 71%)", 54 + "hsl(52deg 100% 77%)", 55 + ], 56 + }, 57 + 58 + pastel: { 59 + gradient: ["hsl(141 75% 72%)", "hsl(41 90% 62%)", "hsl(358 64% 50%)"], 60 + }, 61 + 62 + blue_to_yellow: { 63 + gradient: [ 64 + "hsl(204deg 100% 22%)", 65 + "hsl(199deg 100% 29%)", 66 + "hsl(189deg 100% 32%)", 67 + "hsl(173deg 100% 33%)", 68 + "hsl(154deg 100% 39%)", 69 + "hsl( 89deg 70% 56%)", 70 + "hsl( 55deg 100% 50%)", 71 + ], 72 + }, 73 + };
+158
src/fragment.ts
··· 1 + import { noiseUtils } from "./noiseUtils"; 2 + import { simplex_noise } from "./simplexNoise"; 3 + import type { CreateFragmentShader, FragmentShaderUniforms } from "./types"; 4 + 5 + const createFragmentShader: CreateFragmentShader = (options) => { 6 + const { 7 + blurAmount = 345, 8 + blurQuality = 7, 9 + blurExponentRange = [0.9, 1.2], 10 + } = options as Partial<{ 11 + blurAmount: number; 12 + blurQuality: number; 13 + blurExponentRange: [number, number]; 14 + }>; 15 + 16 + const uniforms: FragmentShaderUniforms = {}; 17 + 18 + const shader = /* glsl */ ` 19 + precision mediump float; 20 + 21 + uniform float u_time; // Time in seconds 22 + uniform float u_h; 23 + uniform float u_w; 24 + uniform sampler2D u_gradient; 25 + 26 + const float PI = 3.14159; 27 + 28 + const float speed = 2.0; 29 + 30 + float WAVE1_Y = 0.45 * u_h, WAVE2_Y = 0.9 * u_h; 31 + float WAVE1_HEIGHT = 0.195 * u_h, WAVE2_HEIGHT = 0.144 * u_h; 32 + 33 + ${noiseUtils} 34 + ${simplex_noise} 35 + 36 + float get_x() { 37 + return 900.0 + gl_FragCoord.x - u_w / 2.0; 38 + } 39 + 40 + // Various utility functions 41 + float smoothstep(float t) 42 + { return t * t * t * (t * (6.0 * t - 15.0) + 10.0); } 43 + 44 + float lerp(float a, float b, float t) 45 + { return a * (1.0 - t) + b * t; } 46 + 47 + float ease_in(float x) 48 + { return 1.0 - cos((x * PI) * 0.5); } 49 + 50 + float wave_alpha_part(float dist, float blur_fac, float t) { 51 + float exp = mix(${blurExponentRange[0].toFixed(5)}, ${blurExponentRange[1].toFixed(5)}, t); 52 + float v = pow(blur_fac, exp); 53 + v = ease_in(v); 54 + v = smoothstep(v); 55 + v = clamp(v, 0.008, 1.0); 56 + v *= ${blurAmount.toFixed(1)}; 57 + float alpha = clamp(0.5 + dist / v, 0.0, 1.0); 58 + alpha = smoothstep(alpha); 59 + return alpha; 60 + } 61 + 62 + float background_noise(float offset) { 63 + const float S = 0.064; 64 + const float L = 0.00085; 65 + const float L1 = 1.5, L2 = 0.9, L3 = 0.6; 66 + const float LY1 = 1.00, LY2 = 0.85, LY3 = 0.70; 67 + const float F = 0.04; 68 + const float Y_SCALE = 1.0 / 0.27; 69 + 70 + float x = get_x() * L; 71 + float y = gl_FragCoord.y * L * Y_SCALE; 72 + float time = (u_time * speed) + offset; 73 + float x_shift = time * F; 74 + float sum = 0.5; 75 + sum += simplex_noise(vec3(x * L1 + x_shift * 1.1, y * L1 * LY1, time * S)) * 0.30; 76 + sum += simplex_noise(vec3(x * L2 + -x_shift * 0.6, y * L2 * LY2, time * S)) * 0.25; 77 + sum += simplex_noise(vec3(x * L3 + x_shift * 0.8, y * L3 * LY3, time * S)) * 0.20; 78 + return sum; 79 + } 80 + 81 + float wave_y_noise(float offset) { 82 + const float L = 0.000845; 83 + const float S = 0.075; 84 + const float F = 0.026; 85 + 86 + float time = (u_time * speed) + offset; 87 + float x = get_x() * 0.000845; 88 + float y = time * S; 89 + float x_shift = time * 0.026; 90 + 91 + float sum = 0.0; 92 + sum += simplex_noise(vec2(x * 1.30 + x_shift, y * 0.54)) * 0.85; 93 + sum += simplex_noise(vec2(x * 1.00 + x_shift, y * 0.68)) * 1.15; 94 + sum += simplex_noise(vec2(x * 0.70 + x_shift, y * 0.59)) * 0.60; 95 + sum += simplex_noise(vec2(x * 0.40 + x_shift, y * 0.48)) * 0.40; 96 + return sum; 97 + } 98 + 99 + float calc_blur_bias() { 100 + const float S = 0.261; 101 + float bias_t = (sin((u_time * speed) * S) + 1.0) * 0.5; 102 + return lerp(-0.17, -0.04, bias_t); 103 + } 104 + 105 + float calc_blur(float offset) { 106 + const float L = 0.0011; 107 + const float S = 0.07; 108 + const float F = 0.03; 109 + 110 + float time = (u_time * speed) + offset; 111 + 112 + float x = get_x() * L; 113 + float blur_fac = calc_blur_bias(); 114 + blur_fac += simplex_noise(vec2(x * 0.60 + time * F * 1.0, time * S * 0.7)) * 0.5; 115 + blur_fac += simplex_noise(vec2(x * 1.30 + time * F * -0.8, time * S * 1.0)) * 0.4; 116 + blur_fac = (blur_fac + 1.0) * 0.5; 117 + blur_fac = clamp(blur_fac, 0.0, 1.0); 118 + return blur_fac; 119 + } 120 + 121 + float wave_alpha(float Y, float wave_height, float offset) { 122 + float wave_y = Y + wave_y_noise(offset) * wave_height; 123 + float dist = wave_y - gl_FragCoord.y; 124 + float blur_fac = calc_blur(offset); 125 + 126 + const float PART = 1.0 / float(${blurQuality.toFixed(1)}); 127 + float sum = 0.0; 128 + for (int i = 0; i < ${blurQuality}; i++) { 129 + float t = ${blurQuality} == 1 ? 0.5 : PART * float(i); 130 + sum += wave_alpha_part(dist, blur_fac, t) * PART; 131 + } 132 + return sum; 133 + } 134 + 135 + vec3 calc_color(float lightness) { 136 + lightness = clamp(lightness, 0.0, 1.0); 137 + return vec3(texture2D(u_gradient, vec2(lightness, 0.5))); 138 + } 139 + 140 + void main() { 141 + float bg_lightness = background_noise(-192.4); 142 + float w1_lightness = background_noise( 273.3); 143 + float w2_lightness = background_noise( 623.1); 144 + 145 + float w1_alpha = wave_alpha(WAVE1_Y, WAVE1_HEIGHT, 112.5 * 48.75); 146 + float w2_alpha = wave_alpha(WAVE2_Y, WAVE2_HEIGHT, 225.0 * 36.00); 147 + 148 + float lightness = bg_lightness; 149 + lightness = lerp(lightness, w2_lightness, w2_alpha); 150 + lightness = lerp(lightness, w1_lightness, w1_alpha); 151 + 152 + gl_FragColor = vec4(calc_color(lightness), 1.0); 153 + } 154 + `; 155 + return { shader, uniforms }; 156 + }; 157 + 158 + export default createFragmentShader;
+32
src/main.ts
··· 1 + import { WebGLRenderer } from "./WebGLRenderer"; 2 + import createFragmentShader from "./fragment"; 3 + import type { ColorConfiguration } from "./colorConfigurations"; 4 + 5 + const canvas = document.getElementById("glcanvas") as HTMLCanvasElement; 6 + const parent = canvas.parentElement; 7 + 8 + function resize() { 9 + canvas.width = parent!.clientWidth; 10 + canvas.height = parent!.clientHeight; 11 + } 12 + window.addEventListener("resize", resize); 13 + resize(); 14 + 15 + const fsModule = createFragmentShader({}); 16 + const fragmentSrc = fsModule.shader; 17 + 18 + // choose your color preset here: 19 + const preset: ColorConfiguration = "blue_to_yellow"; 20 + 21 + const renderer = new WebGLRenderer(canvas, `precision mediump float; 22 + attribute vec2 a_position; 23 + 24 + void main() { 25 + gl_Position = vec4(a_position, 0.0, 1.0); 26 + }`, fragmentSrc, preset); 27 + 28 + tick(); 29 + function tick() { 30 + requestAnimationFrame(tick); 31 + renderer.render(); 32 + }
+36
src/noiseUtils.ts
··· 1 + export const noiseUtils = /* glsl */ ` 2 + // 3 + // Description : Array and textureless GLSL 2D/3D/4D simplex 4 + // noise functions. 5 + // Author : Ian McEwan, Ashima Arts. 6 + // Maintainer : stegu 7 + // Lastmod : 20201014 (stegu) 8 + // License : Copyright (C) 2011 Ashima Arts. All rights reserved. 9 + // Distributed under the MIT License. See LICENSE file. 10 + // https://github.com/ashima/webgl-noise 11 + // https://github.com/stegu/webgl-noise 12 + // 13 + vec2 mod289(vec2 x) { 14 + return x - floor(x * (1.0 / 289.0)) * 289.0; 15 + } 16 + 17 + vec3 mod289(vec3 x) { 18 + return x - floor(x * (1.0 / 289.0)) * 289.0; 19 + } 20 + 21 + vec4 mod289(vec4 x) { 22 + return x - floor(x * (1.0 / 289.0)) * 289.0; 23 + } 24 + 25 + vec4 permute(vec4 x) { 26 + return mod289(((x * 34.0) + 1.0) * x); 27 + } 28 + 29 + vec3 permute(vec3 x) { 30 + return mod289(((x * 34.0) + 10.0) * x); 31 + } 32 + 33 + vec4 taylorInvSqrt(vec4 r) { 34 + return 1.79284291400159 - 0.85373472095314 * r; 35 + } 36 + `;
+120
src/simplexNoise.ts
··· 1 + export const simplex_noise = /* glsl */ ` 2 + // 3 + // Description : Array and textureless GLSL 2D/3D/4D simplex 4 + // noise functions. 5 + // Author : Ian McEwan, Ashima Arts. 6 + // Maintainer : stegu 7 + // Lastmod : 20201014 (stegu) 8 + // License : Copyright (C) 2011 Ashima Arts. All rights reserved. 9 + // Distributed under the MIT License. See LICENSE file. 10 + // https://github.com/ashima/webgl-noise 11 + // https://github.com/stegu/webgl-noise 12 + // 13 + float simplex_noise(vec3 v) 14 + { 15 + const vec2 C = vec2(1.0/6.0, 1.0/3.0) ; 16 + const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); 17 + 18 + // First corner 19 + vec3 i = floor(v + dot(v, C.yyy) ); 20 + vec3 x0 = v - i + dot(i, C.xxx) ; 21 + 22 + // Other corners 23 + vec3 g = step(x0.yzx, x0.xyz); 24 + vec3 l = 1.0 - g; 25 + vec3 i1 = min( g.xyz, l.zxy ); 26 + vec3 i2 = max( g.xyz, l.zxy ); 27 + 28 + vec3 x1 = x0 - i1 + C.xxx; 29 + vec3 x2 = x0 - i2 + C.yyy; 30 + vec3 x3 = x0 - D.yyy; 31 + 32 + // Permutations 33 + i = mod289(i); 34 + vec4 p = permute( permute( permute( 35 + i.z + vec4(0.0, i1.z, i2.z, 1.0 )) 36 + + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) 37 + + i.x + vec4(0.0, i1.x, i2.x, 1.0 )); 38 + 39 + // Gradients: 7x7 points over a square, mapped onto an octahedron. 40 + // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) 41 + float n_ = 0.142857142857; // 1.0/7.0 42 + vec3 ns = n_ * D.wyz - D.xzx; 43 + 44 + vec4 j = p - 49.0 * floor(p * ns.z * ns.z); 45 + 46 + vec4 x_ = floor(j * ns.z); 47 + vec4 y_ = floor(j - 7.0 * x_ ); 48 + 49 + vec4 x = x_ *ns.x + ns.yyyy; 50 + vec4 y = y_ *ns.x + ns.yyyy; 51 + vec4 h = 1.0 - abs(x) - abs(y); 52 + 53 + vec4 b0 = vec4( x.xy, y.xy ); 54 + vec4 b1 = vec4( x.zw, y.zw ); 55 + 56 + vec4 s0 = floor(b0)*2.0 + 1.0; 57 + vec4 s1 = floor(b1)*2.0 + 1.0; 58 + vec4 sh = -step(h, vec4(0.0)); 59 + 60 + vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ; 61 + vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ; 62 + 63 + vec3 p0 = vec3(a0.xy,h.x); 64 + vec3 p1 = vec3(a0.zw,h.y); 65 + vec3 p2 = vec3(a1.xy,h.z); 66 + vec3 p3 = vec3(a1.zw,h.w); 67 + 68 + // Normalise gradients 69 + vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); 70 + p0 *= norm.x; 71 + p1 *= norm.y; 72 + p2 *= norm.z; 73 + p3 *= norm.w; 74 + 75 + // Mix final noise value 76 + vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); 77 + m = m * m; 78 + return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), 79 + dot(p2,x2), dot(p3,x3) ) ); 80 + } 81 + 82 + float simplex_noise(vec2 v) { 83 + const vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439); 84 + // First corner 85 + vec2 i = floor(v + dot(v, C.yy) ); 86 + vec2 x0 = v - i + dot(i, C.xx); 87 + 88 + // Other corners 89 + vec2 i1; 90 + i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); 91 + vec4 x12 = x0.xyxy + C.xxzz; 92 + x12.xy -= i1; 93 + 94 + // Permutations 95 + i = mod289(i); // Avoid truncation effects in permutation 96 + vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 )) 97 + + i.x + vec3(0.0, i1.x, 1.0 )); 98 + 99 + vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0); 100 + m = m*m ; 101 + m = m*m ; 102 + 103 + // Gradients: 41 points uniformly over a line, mapped onto a diamond. 104 + // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) 105 + vec3 x = 2.0 * fract(p * C.www) - 1.0; 106 + vec3 h = abs(x) - 0.5; 107 + vec3 ox = floor(x + 0.5); 108 + vec3 a0 = x - ox; 109 + 110 + // Normalise gradients implicitly by scaling m 111 + // Approximation of: m *= inversesqrt( a0*a0 + h*h ); 112 + m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h ); 113 + 114 + // Compute final noise value at P 115 + vec3 g; 116 + g.x = a0.x * x0.x + h.x * x0.y; 117 + g.yz = a0.yz * x12.xz + h.yz * x12.yw; 118 + return 130.0 * dot(m, g); 119 + } 120 + `;
+18
src/types.ts
··· 1 + export interface FragmentShaderUniform { 2 + label?: string; 3 + value: number; 4 + range: [number, number]; 5 + step?: number; 6 + format?: "number" | "percent" | "multiplier"; 7 + } 8 + 9 + export type FragmentShaderUniforms = Record<string, FragmentShaderUniform>; 10 + 11 + export type FragmentShader = { 12 + shader: string; 13 + uniforms: FragmentShaderUniforms; 14 + }; 15 + 16 + export type CreateFragmentShader = ( 17 + options: Partial<Record<string, unknown>>, 18 + ) => FragmentShader;
+25
tsconfig.json
··· 1 + { 2 + "compilerOptions": { 3 + "target": "ES2022", 4 + "useDefineForClassFields": true, 5 + "module": "ESNext", 6 + "lib": ["ES2022", "DOM", "DOM.Iterable"], 7 + "skipLibCheck": true, 8 + 9 + /* Bundler mode */ 10 + "moduleResolution": "bundler", 11 + "allowImportingTsExtensions": true, 12 + "verbatimModuleSyntax": true, 13 + "moduleDetection": "force", 14 + "noEmit": true, 15 + 16 + /* Linting */ 17 + "strict": true, 18 + "noUnusedLocals": true, 19 + "noUnusedParameters": true, 20 + "erasableSyntaxOnly": true, 21 + "noFallthroughCasesInSwitch": true, 22 + "noUncheckedSideEffectImports": true 23 + }, 24 + "include": ["src"] 25 + }
+7
vite.config.ts
··· 1 + import { defineConfig } from "vite"; 2 + 3 + export default defineConfig({ 4 + plugins: [], 5 + resolve: { alias: { "@": "/src" } }, 6 + base: "/webgl-text-flowy-background" 7 + });