fancy-ui-svelte 0.2.1

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 (418) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +198 -0
  3. package/dist/fancy-ui/_template/Component.svelte +110 -0
  4. package/dist/fancy-ui/_template/Component.svelte.d.ts +16 -0
  5. package/dist/fancy-ui/_template/README.md +279 -0
  6. package/dist/fancy-ui/_template/index.d.ts +13 -0
  7. package/dist/fancy-ui/_template/index.js +27 -0
  8. package/dist/fancy-ui/_template/types.d.ts +53 -0
  9. package/dist/fancy-ui/_template/types.js +12 -0
  10. package/dist/fancy-ui/animated-beam/AnimatedBeam.svelte +166 -0
  11. package/dist/fancy-ui/animated-beam/AnimatedBeam.svelte.d.ts +4 -0
  12. package/dist/fancy-ui/animated-beam/AnimatedBeam.test.d.ts +1 -0
  13. package/dist/fancy-ui/animated-beam/AnimatedBeam.test.js +49 -0
  14. package/dist/fancy-ui/animated-beam/README.md +38 -0
  15. package/dist/fancy-ui/animated-beam/index.d.ts +2 -0
  16. package/dist/fancy-ui/animated-beam/index.js +1 -0
  17. package/dist/fancy-ui/animated-beam/types.d.ts +19 -0
  18. package/dist/fancy-ui/animated-beam/types.js +1 -0
  19. package/dist/fancy-ui/animated-testimonials/AnimatedTestimonials.svelte +196 -0
  20. package/dist/fancy-ui/animated-testimonials/AnimatedTestimonials.svelte.d.ts +29 -0
  21. package/dist/fancy-ui/animated-testimonials/AnimatedTestimonials.test.d.ts +1 -0
  22. package/dist/fancy-ui/animated-testimonials/AnimatedTestimonials.test.js +92 -0
  23. package/dist/fancy-ui/animated-testimonials/index.d.ts +2 -0
  24. package/dist/fancy-ui/animated-testimonials/index.js +1 -0
  25. package/dist/fancy-ui/animated-tooltip/AnimatedTooltip.svelte +97 -0
  26. package/dist/fancy-ui/animated-tooltip/AnimatedTooltip.svelte.d.ts +15 -0
  27. package/dist/fancy-ui/animated-tooltip/AnimatedTooltip.test.d.ts +1 -0
  28. package/dist/fancy-ui/animated-tooltip/AnimatedTooltip.test.js +67 -0
  29. package/dist/fancy-ui/animated-tooltip/index.d.ts +2 -0
  30. package/dist/fancy-ui/animated-tooltip/index.js +1 -0
  31. package/dist/fancy-ui/apple-card-carousel/AppleCard.svelte +226 -0
  32. package/dist/fancy-ui/apple-card-carousel/AppleCard.svelte.d.ts +27 -0
  33. package/dist/fancy-ui/apple-card-carousel/AppleCardCarousel.svelte +49 -0
  34. package/dist/fancy-ui/apple-card-carousel/AppleCardCarousel.svelte.d.ts +11 -0
  35. package/dist/fancy-ui/apple-card-carousel/AppleCardCarousel.test.d.ts +1 -0
  36. package/dist/fancy-ui/apple-card-carousel/AppleCardCarousel.test.js +85 -0
  37. package/dist/fancy-ui/apple-card-carousel/index.d.ts +3 -0
  38. package/dist/fancy-ui/apple-card-carousel/index.js +2 -0
  39. package/dist/fancy-ui/bento-grid/BentoGrid.svelte +21 -0
  40. package/dist/fancy-ui/bento-grid/BentoGrid.svelte.d.ts +7 -0
  41. package/dist/fancy-ui/bento-grid/BentoGridCard.svelte +70 -0
  42. package/dist/fancy-ui/bento-grid/BentoGridCard.svelte.d.ts +12 -0
  43. package/dist/fancy-ui/bento-grid/BentoGridItem.svelte +39 -0
  44. package/dist/fancy-ui/bento-grid/BentoGridItem.svelte.d.ts +10 -0
  45. package/dist/fancy-ui/bento-grid/README.md +51 -0
  46. package/dist/fancy-ui/bento-grid/index.d.ts +3 -0
  47. package/dist/fancy-ui/bento-grid/index.js +3 -0
  48. package/dist/fancy-ui/bg-falling-stars/FallingStarsBg.svelte +163 -0
  49. package/dist/fancy-ui/bg-falling-stars/FallingStarsBg.svelte.d.ts +11 -0
  50. package/dist/fancy-ui/bg-falling-stars/FallingStarsBg.test.d.ts +1 -0
  51. package/dist/fancy-ui/bg-falling-stars/FallingStarsBg.test.js +50 -0
  52. package/dist/fancy-ui/bg-falling-stars/README.md +22 -0
  53. package/dist/fancy-ui/bg-falling-stars/index.d.ts +2 -0
  54. package/dist/fancy-ui/bg-falling-stars/index.js +1 -0
  55. package/dist/fancy-ui/bg-stars/README.md +41 -0
  56. package/dist/fancy-ui/bg-stars/StarsBackground.svelte +205 -0
  57. package/dist/fancy-ui/bg-stars/StarsBackground.svelte.d.ts +33 -0
  58. package/dist/fancy-ui/bg-stars/StarsBackground.test.d.ts +1 -0
  59. package/dist/fancy-ui/bg-stars/StarsBackground.test.js +46 -0
  60. package/dist/fancy-ui/bg-stars/index.d.ts +1 -0
  61. package/dist/fancy-ui/bg-stars/index.js +1 -0
  62. package/dist/fancy-ui/blur-reveal/BlurReveal.svelte +126 -0
  63. package/dist/fancy-ui/blur-reveal/BlurReveal.svelte.d.ts +18 -0
  64. package/dist/fancy-ui/blur-reveal/BlurReveal.test.d.ts +1 -0
  65. package/dist/fancy-ui/blur-reveal/BlurReveal.test.js +47 -0
  66. package/dist/fancy-ui/blur-reveal/README.md +41 -0
  67. package/dist/fancy-ui/blur-reveal/index.d.ts +2 -0
  68. package/dist/fancy-ui/blur-reveal/index.js +2 -0
  69. package/dist/fancy-ui/book/Book.svelte +89 -0
  70. package/dist/fancy-ui/book/Book.svelte.d.ts +15 -0
  71. package/dist/fancy-ui/book/Book.test.d.ts +1 -0
  72. package/dist/fancy-ui/book/Book.test.js +47 -0
  73. package/dist/fancy-ui/book/BookDescription.svelte +17 -0
  74. package/dist/fancy-ui/book/BookDescription.svelte.d.ts +8 -0
  75. package/dist/fancy-ui/book/BookHeader.svelte +17 -0
  76. package/dist/fancy-ui/book/BookHeader.svelte.d.ts +8 -0
  77. package/dist/fancy-ui/book/BookTitle.svelte +17 -0
  78. package/dist/fancy-ui/book/BookTitle.svelte.d.ts +8 -0
  79. package/dist/fancy-ui/book/README.md +34 -0
  80. package/dist/fancy-ui/book/index.d.ts +128 -0
  81. package/dist/fancy-ui/book/index.js +46 -0
  82. package/dist/fancy-ui/border-beam/BorderBeam.svelte +85 -0
  83. package/dist/fancy-ui/border-beam/BorderBeam.svelte.d.ts +27 -0
  84. package/dist/fancy-ui/border-beam/BorderBeam.test.d.ts +1 -0
  85. package/dist/fancy-ui/border-beam/BorderBeam.test.js +64 -0
  86. package/dist/fancy-ui/border-beam/index.d.ts +2 -0
  87. package/dist/fancy-ui/border-beam/index.js +2 -0
  88. package/dist/fancy-ui/box-reveal/BoxReveal.svelte +73 -0
  89. package/dist/fancy-ui/box-reveal/BoxReveal.svelte.d.ts +24 -0
  90. package/dist/fancy-ui/box-reveal/BoxReveal.test.d.ts +1 -0
  91. package/dist/fancy-ui/box-reveal/BoxReveal.test.js +66 -0
  92. package/dist/fancy-ui/box-reveal/README.md +24 -0
  93. package/dist/fancy-ui/box-reveal/index.d.ts +2 -0
  94. package/dist/fancy-ui/box-reveal/index.js +2 -0
  95. package/dist/fancy-ui/card-3d/CardBody.svelte +16 -0
  96. package/dist/fancy-ui/card-3d/CardBody.svelte.d.ts +7 -0
  97. package/dist/fancy-ui/card-3d/CardContainer.svelte +53 -0
  98. package/dist/fancy-ui/card-3d/CardContainer.svelte.d.ts +8 -0
  99. package/dist/fancy-ui/card-3d/CardItem.svelte +49 -0
  100. package/dist/fancy-ui/card-3d/CardItem.svelte.d.ts +14 -0
  101. package/dist/fancy-ui/card-3d/README.md +52 -0
  102. package/dist/fancy-ui/card-3d/index.d.ts +3 -0
  103. package/dist/fancy-ui/card-3d/index.js +3 -0
  104. package/dist/fancy-ui/card-spotlight/CardSpotlight.svelte +59 -0
  105. package/dist/fancy-ui/card-spotlight/CardSpotlight.svelte.d.ts +11 -0
  106. package/dist/fancy-ui/card-spotlight/README.md +24 -0
  107. package/dist/fancy-ui/card-spotlight/index.d.ts +1 -0
  108. package/dist/fancy-ui/card-spotlight/index.js +1 -0
  109. package/dist/fancy-ui/colourful-text/ColourfulText.svelte +78 -0
  110. package/dist/fancy-ui/colourful-text/ColourfulText.svelte.d.ts +22 -0
  111. package/dist/fancy-ui/colourful-text/ColourfulText.test.d.ts +1 -0
  112. package/dist/fancy-ui/colourful-text/ColourfulText.test.js +53 -0
  113. package/dist/fancy-ui/colourful-text/README.md +21 -0
  114. package/dist/fancy-ui/colourful-text/index.d.ts +2 -0
  115. package/dist/fancy-ui/colourful-text/index.js +2 -0
  116. package/dist/fancy-ui/compare/Compare.svelte +304 -0
  117. package/dist/fancy-ui/compare/Compare.svelte.d.ts +25 -0
  118. package/dist/fancy-ui/compare/Compare.test.d.ts +1 -0
  119. package/dist/fancy-ui/compare/Compare.test.js +57 -0
  120. package/dist/fancy-ui/compare/README.md +97 -0
  121. package/dist/fancy-ui/compare/StarField.svelte +108 -0
  122. package/dist/fancy-ui/compare/StarField.svelte.d.ts +7 -0
  123. package/dist/fancy-ui/compare/index.d.ts +2 -0
  124. package/dist/fancy-ui/compare/index.js +2 -0
  125. package/dist/fancy-ui/confetti/Confetti.svelte +60 -0
  126. package/dist/fancy-ui/confetti/Confetti.svelte.d.ts +14 -0
  127. package/dist/fancy-ui/confetti/Confetti.test.d.ts +1 -0
  128. package/dist/fancy-ui/confetti/Confetti.test.js +39 -0
  129. package/dist/fancy-ui/confetti/ConfettiButton.svelte +41 -0
  130. package/dist/fancy-ui/confetti/ConfettiButton.svelte.d.ts +9 -0
  131. package/dist/fancy-ui/confetti/README.md +22 -0
  132. package/dist/fancy-ui/confetti/index.d.ts +2 -0
  133. package/dist/fancy-ui/confetti/index.js +2 -0
  134. package/dist/fancy-ui/container-scroll/ContainerScroll.svelte +82 -0
  135. package/dist/fancy-ui/container-scroll/ContainerScroll.svelte.d.ts +9 -0
  136. package/dist/fancy-ui/container-scroll/ContainerScroll.test.d.ts +1 -0
  137. package/dist/fancy-ui/container-scroll/ContainerScroll.test.js +34 -0
  138. package/dist/fancy-ui/container-scroll/README.md +28 -0
  139. package/dist/fancy-ui/container-scroll/index.d.ts +1 -0
  140. package/dist/fancy-ui/container-scroll/index.js +1 -0
  141. package/dist/fancy-ui/container-text-flip/ContainerTextFlip.svelte +78 -0
  142. package/dist/fancy-ui/container-text-flip/ContainerTextFlip.svelte.d.ts +10 -0
  143. package/dist/fancy-ui/container-text-flip/ContainerTextFlip.test.d.ts +1 -0
  144. package/dist/fancy-ui/container-text-flip/ContainerTextFlip.test.js +46 -0
  145. package/dist/fancy-ui/container-text-flip/README.md +22 -0
  146. package/dist/fancy-ui/container-text-flip/index.d.ts +1 -0
  147. package/dist/fancy-ui/container-text-flip/index.js +1 -0
  148. package/dist/fancy-ui/direction-aware-hover/DirectionAwareHover.svelte +232 -0
  149. package/dist/fancy-ui/direction-aware-hover/DirectionAwareHover.svelte.d.ts +11 -0
  150. package/dist/fancy-ui/direction-aware-hover/DirectionAwareHover.test.d.ts +1 -0
  151. package/dist/fancy-ui/direction-aware-hover/DirectionAwareHover.test.js +78 -0
  152. package/dist/fancy-ui/direction-aware-hover/README.md +47 -0
  153. package/dist/fancy-ui/direction-aware-hover/index.d.ts +1 -0
  154. package/dist/fancy-ui/direction-aware-hover/index.js +1 -0
  155. package/dist/fancy-ui/displacement-text/DisplacementText.svelte +224 -0
  156. package/dist/fancy-ui/displacement-text/DisplacementText.svelte.d.ts +19 -0
  157. package/dist/fancy-ui/displacement-text/DisplacementText.test.d.ts +1 -0
  158. package/dist/fancy-ui/displacement-text/DisplacementText.test.js +144 -0
  159. package/dist/fancy-ui/displacement-text/index.d.ts +2 -0
  160. package/dist/fancy-ui/displacement-text/index.js +1 -0
  161. package/dist/fancy-ui/dock/Dock.svelte +87 -0
  162. package/dist/fancy-ui/dock/Dock.svelte.d.ts +12 -0
  163. package/dist/fancy-ui/dock/Dock.test.d.ts +1 -0
  164. package/dist/fancy-ui/dock/Dock.test.js +51 -0
  165. package/dist/fancy-ui/dock/DockIcon.svelte +50 -0
  166. package/dist/fancy-ui/dock/DockIcon.svelte.d.ts +7 -0
  167. package/dist/fancy-ui/dock/DockSeparator.svelte +21 -0
  168. package/dist/fancy-ui/dock/DockSeparator.svelte.d.ts +6 -0
  169. package/dist/fancy-ui/dock/README.md +57 -0
  170. package/dist/fancy-ui/dock/index.d.ts +4 -0
  171. package/dist/fancy-ui/dock/index.js +4 -0
  172. package/dist/fancy-ui/dock/types.d.ts +14 -0
  173. package/dist/fancy-ui/dock/types.js +1 -0
  174. package/dist/fancy-ui/flickering-grid/FlickeringGrid.svelte +154 -0
  175. package/dist/fancy-ui/flickering-grid/FlickeringGrid.svelte.d.ts +27 -0
  176. package/dist/fancy-ui/flickering-grid/FlickeringGrid.test.d.ts +1 -0
  177. package/dist/fancy-ui/flickering-grid/FlickeringGrid.test.js +34 -0
  178. package/dist/fancy-ui/flickering-grid/README.md +24 -0
  179. package/dist/fancy-ui/flickering-grid/index.d.ts +2 -0
  180. package/dist/fancy-ui/flickering-grid/index.js +2 -0
  181. package/dist/fancy-ui/flip-card/FlipCard.svelte +48 -0
  182. package/dist/fancy-ui/flip-card/FlipCard.svelte.d.ts +10 -0
  183. package/dist/fancy-ui/flip-card/FlipCard.test.d.ts +1 -0
  184. package/dist/fancy-ui/flip-card/FlipCard.test.js +36 -0
  185. package/dist/fancy-ui/flip-card/README.md +26 -0
  186. package/dist/fancy-ui/flip-card/index.d.ts +1 -0
  187. package/dist/fancy-ui/flip-card/index.js +1 -0
  188. package/dist/fancy-ui/flip-words/FlipWords.svelte +135 -0
  189. package/dist/fancy-ui/flip-words/FlipWords.svelte.d.ts +18 -0
  190. package/dist/fancy-ui/flip-words/FlipWords.test.d.ts +1 -0
  191. package/dist/fancy-ui/flip-words/FlipWords.test.js +50 -0
  192. package/dist/fancy-ui/flip-words/README.md +17 -0
  193. package/dist/fancy-ui/flip-words/index.d.ts +2 -0
  194. package/dist/fancy-ui/flip-words/index.js +2 -0
  195. package/dist/fancy-ui/fluid-cursor/FluidCursor.svelte +1378 -0
  196. package/dist/fancy-ui/fluid-cursor/FluidCursor.svelte.d.ts +25 -0
  197. package/dist/fancy-ui/fluid-cursor/FluidCursor.test.d.ts +1 -0
  198. package/dist/fancy-ui/fluid-cursor/FluidCursor.test.js +41 -0
  199. package/dist/fancy-ui/fluid-cursor/README.md +34 -0
  200. package/dist/fancy-ui/fluid-cursor/index.d.ts +1 -0
  201. package/dist/fancy-ui/fluid-cursor/index.js +1 -0
  202. package/dist/fancy-ui/focus/Focus.svelte +177 -0
  203. package/dist/fancy-ui/focus/Focus.svelte.d.ts +12 -0
  204. package/dist/fancy-ui/focus/Focus.test.d.ts +1 -0
  205. package/dist/fancy-ui/focus/Focus.test.js +48 -0
  206. package/dist/fancy-ui/focus/README.md +21 -0
  207. package/dist/fancy-ui/focus/index.d.ts +1 -0
  208. package/dist/fancy-ui/focus/index.js +1 -0
  209. package/dist/fancy-ui/glare-card/GlareCard.svelte +133 -0
  210. package/dist/fancy-ui/glare-card/GlareCard.svelte.d.ts +8 -0
  211. package/dist/fancy-ui/glare-card/GlareCard.test.d.ts +1 -0
  212. package/dist/fancy-ui/glare-card/GlareCard.test.js +40 -0
  213. package/dist/fancy-ui/glare-card/README.md +24 -0
  214. package/dist/fancy-ui/glare-card/index.d.ts +1 -0
  215. package/dist/fancy-ui/glare-card/index.js +1 -0
  216. package/dist/fancy-ui/glow-border/GlowBorder.svelte +67 -0
  217. package/dist/fancy-ui/glow-border/GlowBorder.svelte.d.ts +10 -0
  218. package/dist/fancy-ui/glow-border/GlowBorder.test.d.ts +1 -0
  219. package/dist/fancy-ui/glow-border/GlowBorder.test.js +57 -0
  220. package/dist/fancy-ui/glow-border/README.md +54 -0
  221. package/dist/fancy-ui/glow-border/index.d.ts +1 -0
  222. package/dist/fancy-ui/glow-border/index.js +1 -0
  223. package/dist/fancy-ui/glowing-effect/GlowingEffect.svelte +182 -0
  224. package/dist/fancy-ui/glowing-effect/GlowingEffect.svelte.d.ts +15 -0
  225. package/dist/fancy-ui/glowing-effect/GlowingEffect.test.d.ts +1 -0
  226. package/dist/fancy-ui/glowing-effect/GlowingEffect.test.js +68 -0
  227. package/dist/fancy-ui/glowing-effect/README.md +29 -0
  228. package/dist/fancy-ui/glowing-effect/index.d.ts +1 -0
  229. package/dist/fancy-ui/glowing-effect/index.js +1 -0
  230. package/dist/fancy-ui/gradient-button/GradientButton.svelte +103 -0
  231. package/dist/fancy-ui/gradient-button/GradientButton.svelte.d.ts +24 -0
  232. package/dist/fancy-ui/gradient-button/GradientButton.test.d.ts +1 -0
  233. package/dist/fancy-ui/gradient-button/GradientButton.test.js +65 -0
  234. package/dist/fancy-ui/gradient-button/README.md +10 -0
  235. package/dist/fancy-ui/gradient-button/index.d.ts +2 -0
  236. package/dist/fancy-ui/gradient-button/index.js +2 -0
  237. package/dist/fancy-ui/hyper-text/HyperText.svelte +112 -0
  238. package/dist/fancy-ui/hyper-text/HyperText.svelte.d.ts +20 -0
  239. package/dist/fancy-ui/hyper-text/HyperText.test.d.ts +1 -0
  240. package/dist/fancy-ui/hyper-text/HyperText.test.js +39 -0
  241. package/dist/fancy-ui/hyper-text/README.md +19 -0
  242. package/dist/fancy-ui/hyper-text/index.d.ts +2 -0
  243. package/dist/fancy-ui/hyper-text/index.js +2 -0
  244. package/dist/fancy-ui/image-trail-cursor/ImageTrailCursor.svelte +89 -0
  245. package/dist/fancy-ui/image-trail-cursor/ImageTrailCursor.svelte.d.ts +9 -0
  246. package/dist/fancy-ui/image-trail-cursor/ImageTrailCursor.test.d.ts +1 -0
  247. package/dist/fancy-ui/image-trail-cursor/ImageTrailCursor.test.js +60 -0
  248. package/dist/fancy-ui/image-trail-cursor/README.md +36 -0
  249. package/dist/fancy-ui/image-trail-cursor/index.d.ts +3 -0
  250. package/dist/fancy-ui/image-trail-cursor/index.js +1 -0
  251. package/dist/fancy-ui/image-trail-cursor/trail-variants.d.ts +107 -0
  252. package/dist/fancy-ui/image-trail-cursor/trail-variants.js +703 -0
  253. package/dist/fancy-ui/index.d.ts +52 -0
  254. package/dist/fancy-ui/index.js +64 -0
  255. package/dist/fancy-ui/interactive-grid-pattern/InteractiveGridPattern.svelte +71 -0
  256. package/dist/fancy-ui/interactive-grid-pattern/InteractiveGridPattern.svelte.d.ts +15 -0
  257. package/dist/fancy-ui/interactive-grid-pattern/InteractiveGridPattern.test.d.ts +1 -0
  258. package/dist/fancy-ui/interactive-grid-pattern/InteractiveGridPattern.test.js +47 -0
  259. package/dist/fancy-ui/interactive-grid-pattern/README.md +30 -0
  260. package/dist/fancy-ui/interactive-grid-pattern/index.d.ts +2 -0
  261. package/dist/fancy-ui/interactive-grid-pattern/index.js +2 -0
  262. package/dist/fancy-ui/interactive-hover-button/InteractiveHoverButton.svelte +75 -0
  263. package/dist/fancy-ui/interactive-hover-button/InteractiveHoverButton.svelte.d.ts +14 -0
  264. package/dist/fancy-ui/interactive-hover-button/InteractiveHoverButton.test.d.ts +1 -0
  265. package/dist/fancy-ui/interactive-hover-button/InteractiveHoverButton.test.js +64 -0
  266. package/dist/fancy-ui/interactive-hover-button/README.md +28 -0
  267. package/dist/fancy-ui/interactive-hover-button/index.d.ts +2 -0
  268. package/dist/fancy-ui/interactive-hover-button/index.js +2 -0
  269. package/dist/fancy-ui/letter-pullup/LetterPullup.svelte +58 -0
  270. package/dist/fancy-ui/letter-pullup/LetterPullup.svelte.d.ts +17 -0
  271. package/dist/fancy-ui/letter-pullup/LetterPullup.test.d.ts +1 -0
  272. package/dist/fancy-ui/letter-pullup/LetterPullup.test.js +49 -0
  273. package/dist/fancy-ui/letter-pullup/README.md +18 -0
  274. package/dist/fancy-ui/letter-pullup/index.d.ts +2 -0
  275. package/dist/fancy-ui/letter-pullup/index.js +2 -0
  276. package/dist/fancy-ui/line-hover-link/LineHoverLink.svelte +450 -0
  277. package/dist/fancy-ui/line-hover-link/LineHoverLink.svelte.d.ts +35 -0
  278. package/dist/fancy-ui/line-hover-link/LineHoverLink.test.d.ts +1 -0
  279. package/dist/fancy-ui/line-hover-link/LineHoverLink.test.js +55 -0
  280. package/dist/fancy-ui/line-hover-link/index.d.ts +2 -0
  281. package/dist/fancy-ui/line-hover-link/index.js +1 -0
  282. package/dist/fancy-ui/line-shadow-text/LineShadowText.svelte +63 -0
  283. package/dist/fancy-ui/line-shadow-text/LineShadowText.svelte.d.ts +9 -0
  284. package/dist/fancy-ui/line-shadow-text/LineShadowText.test.d.ts +1 -0
  285. package/dist/fancy-ui/line-shadow-text/LineShadowText.test.js +59 -0
  286. package/dist/fancy-ui/line-shadow-text/README.md +12 -0
  287. package/dist/fancy-ui/line-shadow-text/index.d.ts +2 -0
  288. package/dist/fancy-ui/line-shadow-text/index.js +1 -0
  289. package/dist/fancy-ui/liquid-glass/LiquidGlass.svelte +204 -0
  290. package/dist/fancy-ui/liquid-glass/LiquidGlass.svelte.d.ts +23 -0
  291. package/dist/fancy-ui/liquid-glass/LiquidGlass.test.d.ts +1 -0
  292. package/dist/fancy-ui/liquid-glass/LiquidGlass.test.js +48 -0
  293. package/dist/fancy-ui/liquid-glass/README.md +34 -0
  294. package/dist/fancy-ui/liquid-glass/index.d.ts +1 -0
  295. package/dist/fancy-ui/liquid-glass/index.js +1 -0
  296. package/dist/fancy-ui/logo-cloud/AnimatedLogoCloud.svelte +61 -0
  297. package/dist/fancy-ui/logo-cloud/AnimatedLogoCloud.svelte.d.ts +15 -0
  298. package/dist/fancy-ui/logo-cloud/AnimatedLogoCloud.test.d.ts +1 -0
  299. package/dist/fancy-ui/logo-cloud/AnimatedLogoCloud.test.js +59 -0
  300. package/dist/fancy-ui/logo-cloud/IconLogoCloud.svelte +31 -0
  301. package/dist/fancy-ui/logo-cloud/IconLogoCloud.svelte.d.ts +11 -0
  302. package/dist/fancy-ui/logo-cloud/README.md +41 -0
  303. package/dist/fancy-ui/logo-cloud/StaticLogoCloud.svelte +31 -0
  304. package/dist/fancy-ui/logo-cloud/StaticLogoCloud.svelte.d.ts +11 -0
  305. package/dist/fancy-ui/logo-cloud/index.d.ts +4 -0
  306. package/dist/fancy-ui/logo-cloud/index.js +4 -0
  307. package/dist/fancy-ui/marquee/Marquee.svelte +70 -0
  308. package/dist/fancy-ui/marquee/Marquee.svelte.d.ts +11 -0
  309. package/dist/fancy-ui/marquee/Marquee.test.d.ts +1 -0
  310. package/dist/fancy-ui/marquee/Marquee.test.js +46 -0
  311. package/dist/fancy-ui/marquee/ReviewCard.svelte +25 -0
  312. package/dist/fancy-ui/marquee/ReviewCard.svelte.d.ts +9 -0
  313. package/dist/fancy-ui/marquee/index.d.ts +2 -0
  314. package/dist/fancy-ui/marquee/index.js +2 -0
  315. package/dist/fancy-ui/meteors/Meteors.svelte +59 -0
  316. package/dist/fancy-ui/meteors/Meteors.svelte.d.ts +15 -0
  317. package/dist/fancy-ui/meteors/Meteors.test.d.ts +1 -0
  318. package/dist/fancy-ui/meteors/Meteors.test.js +48 -0
  319. package/dist/fancy-ui/meteors/README.md +18 -0
  320. package/dist/fancy-ui/meteors/index.d.ts +2 -0
  321. package/dist/fancy-ui/meteors/index.js +2 -0
  322. package/dist/fancy-ui/neon-border/NeonBorder.svelte +135 -0
  323. package/dist/fancy-ui/neon-border/NeonBorder.svelte.d.ts +24 -0
  324. package/dist/fancy-ui/neon-border/NeonBorder.test.d.ts +1 -0
  325. package/dist/fancy-ui/neon-border/NeonBorder.test.js +80 -0
  326. package/dist/fancy-ui/neon-border/README.md +27 -0
  327. package/dist/fancy-ui/neon-border/index.d.ts +2 -0
  328. package/dist/fancy-ui/neon-border/index.js +2 -0
  329. package/dist/fancy-ui/number-ticker/NumberTicker.svelte +126 -0
  330. package/dist/fancy-ui/number-ticker/NumberTicker.svelte.d.ts +24 -0
  331. package/dist/fancy-ui/number-ticker/NumberTicker.test.d.ts +1 -0
  332. package/dist/fancy-ui/number-ticker/NumberTicker.test.js +64 -0
  333. package/dist/fancy-ui/number-ticker/README.md +22 -0
  334. package/dist/fancy-ui/number-ticker/index.d.ts +2 -0
  335. package/dist/fancy-ui/number-ticker/index.js +2 -0
  336. package/dist/fancy-ui/rainbow-button/RainbowButton.svelte +96 -0
  337. package/dist/fancy-ui/rainbow-button/RainbowButton.svelte.d.ts +18 -0
  338. package/dist/fancy-ui/rainbow-button/RainbowButton.test.d.ts +1 -0
  339. package/dist/fancy-ui/rainbow-button/RainbowButton.test.js +51 -0
  340. package/dist/fancy-ui/rainbow-button/index.d.ts +2 -0
  341. package/dist/fancy-ui/rainbow-button/index.js +2 -0
  342. package/dist/fancy-ui/registry.d.ts +72 -0
  343. package/dist/fancy-ui/registry.js +643 -0
  344. package/dist/fancy-ui/ripple/README.md +16 -0
  345. package/dist/fancy-ui/ripple/Ripple.svelte +64 -0
  346. package/dist/fancy-ui/ripple/Ripple.svelte.d.ts +13 -0
  347. package/dist/fancy-ui/ripple/Ripple.test.d.ts +1 -0
  348. package/dist/fancy-ui/ripple/Ripple.test.js +81 -0
  349. package/dist/fancy-ui/ripple/index.d.ts +1 -0
  350. package/dist/fancy-ui/ripple/index.js +1 -0
  351. package/dist/fancy-ui/ripple-button/RippleButton.svelte +111 -0
  352. package/dist/fancy-ui/ripple-button/RippleButton.svelte.d.ts +15 -0
  353. package/dist/fancy-ui/ripple-button/RippleButton.test.d.ts +1 -0
  354. package/dist/fancy-ui/ripple-button/RippleButton.test.js +44 -0
  355. package/dist/fancy-ui/ripple-button/index.d.ts +2 -0
  356. package/dist/fancy-ui/ripple-button/index.js +2 -0
  357. package/dist/fancy-ui/shimmer-button/README.md +10 -0
  358. package/dist/fancy-ui/shimmer-button/ShimmerButton.svelte +115 -0
  359. package/dist/fancy-ui/shimmer-button/ShimmerButton.svelte.d.ts +22 -0
  360. package/dist/fancy-ui/shimmer-button/ShimmerButton.test.d.ts +1 -0
  361. package/dist/fancy-ui/shimmer-button/ShimmerButton.test.js +69 -0
  362. package/dist/fancy-ui/shimmer-button/index.d.ts +2 -0
  363. package/dist/fancy-ui/shimmer-button/index.js +2 -0
  364. package/dist/fancy-ui/smooth-cursor/README.md +23 -0
  365. package/dist/fancy-ui/smooth-cursor/SmoothCursor.svelte +224 -0
  366. package/dist/fancy-ui/smooth-cursor/SmoothCursor.svelte.d.ts +20 -0
  367. package/dist/fancy-ui/smooth-cursor/index.d.ts +2 -0
  368. package/dist/fancy-ui/smooth-cursor/index.js +1 -0
  369. package/dist/fancy-ui/sparkles/README.md +15 -0
  370. package/dist/fancy-ui/sparkles/Sparkles.svelte +123 -0
  371. package/dist/fancy-ui/sparkles/Sparkles.svelte.d.ts +12 -0
  372. package/dist/fancy-ui/sparkles/Sparkles.test.d.ts +1 -0
  373. package/dist/fancy-ui/sparkles/Sparkles.test.js +66 -0
  374. package/dist/fancy-ui/sparkles/index.d.ts +1 -0
  375. package/dist/fancy-ui/sparkles/index.js +1 -0
  376. package/dist/fancy-ui/sparkles-text/README.md +19 -0
  377. package/dist/fancy-ui/sparkles-text/SparklesText.svelte +112 -0
  378. package/dist/fancy-ui/sparkles-text/SparklesText.svelte.d.ts +22 -0
  379. package/dist/fancy-ui/sparkles-text/SparklesText.test.d.ts +1 -0
  380. package/dist/fancy-ui/sparkles-text/SparklesText.test.js +54 -0
  381. package/dist/fancy-ui/sparkles-text/index.d.ts +2 -0
  382. package/dist/fancy-ui/sparkles-text/index.js +2 -0
  383. package/dist/fancy-ui/tailwind.css +3 -0
  384. package/dist/fancy-ui/text-generate-effect/README.md +14 -0
  385. package/dist/fancy-ui/text-generate-effect/TextGenerateEffect.svelte +66 -0
  386. package/dist/fancy-ui/text-generate-effect/TextGenerateEffect.svelte.d.ts +11 -0
  387. package/dist/fancy-ui/text-generate-effect/TextGenerateEffect.test.d.ts +1 -0
  388. package/dist/fancy-ui/text-generate-effect/TextGenerateEffect.test.js +73 -0
  389. package/dist/fancy-ui/text-generate-effect/index.d.ts +2 -0
  390. package/dist/fancy-ui/text-generate-effect/index.js +1 -0
  391. package/dist/fancy-ui/text-reveal-card/README.md +36 -0
  392. package/dist/fancy-ui/text-reveal-card/TextRevealCard.svelte +112 -0
  393. package/dist/fancy-ui/text-reveal-card/TextRevealCard.svelte.d.ts +12 -0
  394. package/dist/fancy-ui/text-reveal-card/TextRevealCard.test.d.ts +1 -0
  395. package/dist/fancy-ui/text-reveal-card/TextRevealCard.test.js +34 -0
  396. package/dist/fancy-ui/text-reveal-card/TextRevealStars.svelte +76 -0
  397. package/dist/fancy-ui/text-reveal-card/TextRevealStars.svelte.d.ts +7 -0
  398. package/dist/fancy-ui/text-reveal-card/index.d.ts +2 -0
  399. package/dist/fancy-ui/text-reveal-card/index.js +2 -0
  400. package/dist/fancy-ui/timeline/README.md +56 -0
  401. package/dist/fancy-ui/timeline/Timeline.svelte +141 -0
  402. package/dist/fancy-ui/timeline/Timeline.svelte.d.ts +20 -0
  403. package/dist/fancy-ui/timeline/Timeline.test.d.ts +1 -0
  404. package/dist/fancy-ui/timeline/Timeline.test.js +63 -0
  405. package/dist/fancy-ui/timeline/index.d.ts +2 -0
  406. package/dist/fancy-ui/timeline/index.js +2 -0
  407. package/dist/fancy-ui/tracing-beam/README.md +24 -0
  408. package/dist/fancy-ui/tracing-beam/TracingBeam.svelte +156 -0
  409. package/dist/fancy-ui/tracing-beam/TracingBeam.svelte.d.ts +8 -0
  410. package/dist/fancy-ui/tracing-beam/TracingBeam.test.d.ts +1 -0
  411. package/dist/fancy-ui/tracing-beam/TracingBeam.test.js +61 -0
  412. package/dist/fancy-ui/tracing-beam/index.d.ts +1 -0
  413. package/dist/fancy-ui/tracing-beam/index.js +1 -0
  414. package/dist/types.d.ts +87 -0
  415. package/dist/types.js +6 -0
  416. package/dist/utils.d.ts +12 -0
  417. package/dist/utils.js +5 -0
  418. package/package.json +105 -0
@@ -0,0 +1,1378 @@
1
+ <script lang="ts">
2
+ import { cn } from "../../utils.js";
3
+ import { onMount } from "svelte";
4
+
5
+ interface ColorRGB {
6
+ r: number;
7
+ g: number;
8
+ b: number;
9
+ }
10
+
11
+ interface Props {
12
+ simResolution?: number;
13
+ dyeResolution?: number;
14
+ captureResolution?: number;
15
+ densityDissipation?: number;
16
+ velocityDissipation?: number;
17
+ pressure?: number;
18
+ pressureIterations?: number;
19
+ curl?: number;
20
+ splatRadius?: number;
21
+ splatForce?: number;
22
+ shading?: boolean;
23
+ colorUpdateSpeed?: number;
24
+ backColor?: ColorRGB;
25
+ transparent?: boolean;
26
+ class?: string;
27
+ }
28
+
29
+ let {
30
+ simResolution = 128,
31
+ dyeResolution = 1440,
32
+ captureResolution = 512,
33
+ densityDissipation = 3.5,
34
+ velocityDissipation = 2,
35
+ pressure = 0.1,
36
+ pressureIterations = 20,
37
+ curl = 3,
38
+ splatRadius = 0.2,
39
+ splatForce = 6000,
40
+ shading = true,
41
+ colorUpdateSpeed = 10,
42
+ backColor = { r: 0.5, g: 0, b: 0 },
43
+ transparent = true,
44
+ class: className = "",
45
+ }: Props = $props();
46
+
47
+ let canvasRef: HTMLCanvasElement;
48
+
49
+ onMount(() => {
50
+ const canvas = canvasRef;
51
+ if (!canvas) return;
52
+
53
+ interface Pointer {
54
+ id: number;
55
+ texcoordX: number;
56
+ texcoordY: number;
57
+ prevTexcoordX: number;
58
+ prevTexcoordY: number;
59
+ deltaX: number;
60
+ deltaY: number;
61
+ down: boolean;
62
+ moved: boolean;
63
+ color: ColorRGB;
64
+ }
65
+
66
+ function pointerPrototype(): Pointer {
67
+ return {
68
+ id: -1,
69
+ texcoordX: 0,
70
+ texcoordY: 0,
71
+ prevTexcoordX: 0,
72
+ prevTexcoordY: 0,
73
+ deltaX: 0,
74
+ deltaY: 0,
75
+ down: false,
76
+ moved: false,
77
+ color: { r: 0, g: 0, b: 0 },
78
+ };
79
+ }
80
+
81
+ const pointers: Pointer[] = [pointerPrototype()];
82
+
83
+ const config = {
84
+ SIM_RESOLUTION: simResolution,
85
+ DYE_RESOLUTION: dyeResolution,
86
+ CAPTURE_RESOLUTION: captureResolution,
87
+ DENSITY_DISSIPATION: densityDissipation,
88
+ VELOCITY_DISSIPATION: velocityDissipation,
89
+ PRESSURE: pressure,
90
+ PRESSURE_ITERATIONS: pressureIterations,
91
+ CURL: curl,
92
+ SPLAT_RADIUS: splatRadius,
93
+ SPLAT_FORCE: splatForce,
94
+ SHADING: shading,
95
+ COLOR_UPDATE_SPEED: colorUpdateSpeed,
96
+ PAUSED: false,
97
+ BACK_COLOR: backColor,
98
+ TRANSPARENT: transparent,
99
+ };
100
+
101
+ // Get WebGL context
102
+ const context = getWebGLContext(canvas);
103
+ if (!context.gl || !context.ext) return;
104
+
105
+ // These are guaranteed non-null after the check above
106
+ const gl = context.gl;
107
+ const ext = context.ext;
108
+
109
+ // If no linear filtering, reduce resolution
110
+ if (!ext.supportLinearFiltering) {
111
+ config.DYE_RESOLUTION = 256;
112
+ config.SHADING = false;
113
+ }
114
+
115
+ function getWebGLContext(canvas: HTMLCanvasElement) {
116
+ const params = {
117
+ alpha: true,
118
+ depth: false,
119
+ stencil: false,
120
+ antialias: false,
121
+ preserveDrawingBuffer: false,
122
+ };
123
+
124
+ let gl = canvas.getContext("webgl2", params) as WebGL2RenderingContext | null;
125
+
126
+ if (!gl) {
127
+ gl = (canvas.getContext("webgl", params) ||
128
+ canvas.getContext("experimental-webgl", params)) as WebGL2RenderingContext | null;
129
+ }
130
+
131
+ if (!gl) {
132
+ console.error("Unable to initialize WebGL.");
133
+ return { gl: null, ext: null };
134
+ }
135
+
136
+ const isWebGL2 = "drawBuffers" in gl;
137
+
138
+ let supportLinearFiltering = false;
139
+ let halfFloat = null;
140
+
141
+ if (isWebGL2) {
142
+ (gl as WebGL2RenderingContext).getExtension("EXT_color_buffer_float");
143
+ supportLinearFiltering = !!(gl as WebGL2RenderingContext).getExtension(
144
+ "OES_texture_float_linear"
145
+ );
146
+ } else {
147
+ halfFloat = gl.getExtension("OES_texture_half_float");
148
+ supportLinearFiltering = !!gl.getExtension("OES_texture_half_float_linear");
149
+ }
150
+
151
+ gl.clearColor(0, 0, 0, 1);
152
+
153
+ const halfFloatTexType = isWebGL2
154
+ ? (gl as WebGL2RenderingContext).HALF_FLOAT
155
+ : (halfFloat && halfFloat.HALF_FLOAT_OES) || 0;
156
+
157
+ let formatRGBA: { internalFormat: number; format: number } | null;
158
+ let formatRG: { internalFormat: number; format: number } | null;
159
+ let formatR: { internalFormat: number; format: number } | null;
160
+
161
+ if (isWebGL2) {
162
+ formatRGBA = getSupportedFormat(
163
+ gl,
164
+ (gl as WebGL2RenderingContext).RGBA16F,
165
+ gl.RGBA,
166
+ halfFloatTexType
167
+ );
168
+ formatRG = getSupportedFormat(
169
+ gl,
170
+ (gl as WebGL2RenderingContext).RG16F,
171
+ (gl as WebGL2RenderingContext).RG,
172
+ halfFloatTexType
173
+ );
174
+ formatR = getSupportedFormat(
175
+ gl,
176
+ (gl as WebGL2RenderingContext).R16F,
177
+ (gl as WebGL2RenderingContext).RED,
178
+ halfFloatTexType
179
+ );
180
+ } else {
181
+ formatRGBA = getSupportedFormat(gl, gl.RGBA, gl.RGBA, halfFloatTexType);
182
+ formatRG = getSupportedFormat(gl, gl.RGBA, gl.RGBA, halfFloatTexType);
183
+ formatR = getSupportedFormat(gl, gl.RGBA, gl.RGBA, halfFloatTexType);
184
+ }
185
+
186
+ return {
187
+ gl,
188
+ ext: {
189
+ formatRGBA,
190
+ formatRG,
191
+ formatR,
192
+ halfFloatTexType,
193
+ supportLinearFiltering,
194
+ },
195
+ };
196
+ }
197
+
198
+ function getSupportedFormat(
199
+ gl: WebGLRenderingContext | WebGL2RenderingContext,
200
+ internalFormat: number,
201
+ format: number,
202
+ type: number
203
+ ): { internalFormat: number; format: number } | null {
204
+ if (!supportRenderTextureFormat(gl, internalFormat, format, type)) {
205
+ if ("drawBuffers" in gl) {
206
+ const gl2 = gl as WebGL2RenderingContext;
207
+ switch (internalFormat) {
208
+ case gl2.R16F:
209
+ return getSupportedFormat(gl2, gl2.RG16F, gl2.RG, type);
210
+ case gl2.RG16F:
211
+ return getSupportedFormat(gl2, gl2.RGBA16F, gl2.RGBA, type);
212
+ default:
213
+ return null;
214
+ }
215
+ }
216
+ return null;
217
+ }
218
+ return { internalFormat, format };
219
+ }
220
+
221
+ function supportRenderTextureFormat(
222
+ gl: WebGLRenderingContext | WebGL2RenderingContext,
223
+ internalFormat: number,
224
+ format: number,
225
+ type: number
226
+ ) {
227
+ const texture = gl.createTexture();
228
+ if (!texture) return false;
229
+
230
+ gl.bindTexture(gl.TEXTURE_2D, texture);
231
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
232
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
233
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
234
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
235
+ gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 4, 4, 0, format, type, null);
236
+
237
+ const fbo = gl.createFramebuffer();
238
+ if (!fbo) return false;
239
+
240
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
241
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
242
+ const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
243
+ return status === gl.FRAMEBUFFER_COMPLETE;
244
+ }
245
+
246
+ function hashCode(s: string) {
247
+ if (!s.length) return 0;
248
+ let hash = 0;
249
+ for (let i = 0; i < s.length; i++) {
250
+ hash = (hash << 5) - hash + s.charCodeAt(i);
251
+ hash |= 0;
252
+ }
253
+ return hash;
254
+ }
255
+
256
+ function addKeywords(source: string, keywords: string[] | null) {
257
+ if (!keywords) return source;
258
+ let keywordsString = "";
259
+ for (const keyword of keywords) {
260
+ keywordsString += `#define ${keyword}\n`;
261
+ }
262
+ return keywordsString + source;
263
+ }
264
+
265
+ function compileShader(
266
+ type: number,
267
+ source: string,
268
+ keywords: string[] | null = null
269
+ ): WebGLShader | null {
270
+ const shaderSource = addKeywords(source, keywords);
271
+ const shader = gl.createShader(type);
272
+ if (!shader) return null;
273
+ gl.shaderSource(shader, shaderSource);
274
+ gl.compileShader(shader);
275
+ return shader;
276
+ }
277
+
278
+ function createProgram(
279
+ vertexShader: WebGLShader | null,
280
+ fragmentShader: WebGLShader | null
281
+ ): WebGLProgram | null {
282
+ if (!vertexShader || !fragmentShader) return null;
283
+ const program = gl.createProgram();
284
+ if (!program) return null;
285
+ gl.attachShader(program, vertexShader);
286
+ gl.attachShader(program, fragmentShader);
287
+ gl.linkProgram(program);
288
+ return program;
289
+ }
290
+
291
+ function getUniforms(program: WebGLProgram) {
292
+ const uniforms: Record<string, WebGLUniformLocation | null> = {};
293
+ const uniformCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
294
+ for (let i = 0; i < uniformCount; i++) {
295
+ const uniformInfo = gl.getActiveUniform(program, i);
296
+ if (uniformInfo) {
297
+ uniforms[uniformInfo.name] = gl.getUniformLocation(program, uniformInfo.name);
298
+ }
299
+ }
300
+ return uniforms;
301
+ }
302
+
303
+ class Program {
304
+ program: WebGLProgram | null;
305
+ uniforms: Record<string, WebGLUniformLocation | null>;
306
+
307
+ constructor(vertexShader: WebGLShader | null, fragmentShader: WebGLShader | null) {
308
+ this.program = createProgram(vertexShader, fragmentShader);
309
+ this.uniforms = this.program ? getUniforms(this.program) : {};
310
+ }
311
+
312
+ bind() {
313
+ if (this.program) gl.useProgram(this.program);
314
+ }
315
+ }
316
+
317
+ class Material {
318
+ vertexShader: WebGLShader | null;
319
+ fragmentShaderSource: string;
320
+ programs: Record<number, WebGLProgram | null>;
321
+ activeProgram: WebGLProgram | null;
322
+ uniforms: Record<string, WebGLUniformLocation | null>;
323
+
324
+ constructor(vertexShader: WebGLShader | null, fragmentShaderSource: string) {
325
+ this.vertexShader = vertexShader;
326
+ this.fragmentShaderSource = fragmentShaderSource;
327
+ this.programs = {};
328
+ this.activeProgram = null;
329
+ this.uniforms = {};
330
+ }
331
+
332
+ setKeywords(keywords: string[]) {
333
+ let hash = 0;
334
+ for (const kw of keywords) {
335
+ hash += hashCode(kw);
336
+ }
337
+ let program = this.programs[hash];
338
+ if (program == null) {
339
+ const fragmentShader = compileShader(
340
+ gl.FRAGMENT_SHADER,
341
+ this.fragmentShaderSource,
342
+ keywords
343
+ );
344
+ program = createProgram(this.vertexShader, fragmentShader);
345
+ this.programs[hash] = program;
346
+ }
347
+ if (program === this.activeProgram) return;
348
+ if (program) {
349
+ this.uniforms = getUniforms(program);
350
+ }
351
+ this.activeProgram = program;
352
+ }
353
+
354
+ bind() {
355
+ if (this.activeProgram) {
356
+ gl.useProgram(this.activeProgram);
357
+ }
358
+ }
359
+ }
360
+
361
+ // Shaders
362
+ const baseVertexShader = compileShader(
363
+ gl.VERTEX_SHADER,
364
+ `
365
+ precision highp float;
366
+ attribute vec2 aPosition;
367
+ varying vec2 vUv;
368
+ varying vec2 vL;
369
+ varying vec2 vR;
370
+ varying vec2 vT;
371
+ varying vec2 vB;
372
+ uniform vec2 texelSize;
373
+
374
+ void main () {
375
+ vUv = aPosition * 0.5 + 0.5;
376
+ vL = vUv - vec2(texelSize.x, 0.0);
377
+ vR = vUv + vec2(texelSize.x, 0.0);
378
+ vT = vUv + vec2(0.0, texelSize.y);
379
+ vB = vUv - vec2(0.0, texelSize.y);
380
+ gl_Position = vec4(aPosition, 0.0, 1.0);
381
+ }
382
+ `
383
+ );
384
+
385
+ const copyShader = compileShader(
386
+ gl.FRAGMENT_SHADER,
387
+ `
388
+ precision mediump float;
389
+ precision mediump sampler2D;
390
+ varying highp vec2 vUv;
391
+ uniform sampler2D uTexture;
392
+
393
+ void main () {
394
+ gl_FragColor = texture2D(uTexture, vUv);
395
+ }
396
+ `
397
+ );
398
+
399
+ const clearShader = compileShader(
400
+ gl.FRAGMENT_SHADER,
401
+ `
402
+ precision mediump float;
403
+ precision mediump sampler2D;
404
+ varying highp vec2 vUv;
405
+ uniform sampler2D uTexture;
406
+ uniform float value;
407
+
408
+ void main () {
409
+ gl_FragColor = value * texture2D(uTexture, vUv);
410
+ }
411
+ `
412
+ );
413
+
414
+ const displayShaderSource = `
415
+ precision highp float;
416
+ precision highp sampler2D;
417
+ varying vec2 vUv;
418
+ varying vec2 vL;
419
+ varying vec2 vR;
420
+ varying vec2 vT;
421
+ varying vec2 vB;
422
+ uniform sampler2D uTexture;
423
+ uniform sampler2D uDithering;
424
+ uniform vec2 ditherScale;
425
+ uniform vec2 texelSize;
426
+
427
+ vec3 linearToGamma (vec3 color) {
428
+ color = max(color, vec3(0));
429
+ return max(1.055 * pow(color, vec3(0.416666667)) - 0.055, vec3(0));
430
+ }
431
+
432
+ void main () {
433
+ vec3 c = texture2D(uTexture, vUv).rgb;
434
+ #ifdef SHADING
435
+ vec3 lc = texture2D(uTexture, vL).rgb;
436
+ vec3 rc = texture2D(uTexture, vR).rgb;
437
+ vec3 tc = texture2D(uTexture, vT).rgb;
438
+ vec3 bc = texture2D(uTexture, vB).rgb;
439
+
440
+ float dx = length(rc) - length(lc);
441
+ float dy = length(tc) - length(bc);
442
+
443
+ vec3 n = normalize(vec3(dx, dy, length(texelSize)));
444
+ vec3 l = vec3(0.0, 0.0, 1.0);
445
+
446
+ float diffuse = clamp(dot(n, l) + 0.7, 0.7, 1.0);
447
+ c *= diffuse;
448
+ #endif
449
+
450
+ float a = max(c.r, max(c.g, c.b));
451
+ gl_FragColor = vec4(c, a);
452
+ }
453
+ `;
454
+
455
+ const splatShader = compileShader(
456
+ gl.FRAGMENT_SHADER,
457
+ `
458
+ precision highp float;
459
+ precision highp sampler2D;
460
+ varying vec2 vUv;
461
+ uniform sampler2D uTarget;
462
+ uniform float aspectRatio;
463
+ uniform vec3 color;
464
+ uniform vec2 point;
465
+ uniform float radius;
466
+
467
+ void main () {
468
+ vec2 p = vUv - point.xy;
469
+ p.x *= aspectRatio;
470
+ vec3 splat = exp(-dot(p, p) / radius) * color;
471
+ vec3 base = texture2D(uTarget, vUv).xyz;
472
+ gl_FragColor = vec4(base + splat, 1.0);
473
+ }
474
+ `
475
+ );
476
+
477
+ const advectionShader = compileShader(
478
+ gl.FRAGMENT_SHADER,
479
+ `
480
+ precision highp float;
481
+ precision highp sampler2D;
482
+ varying vec2 vUv;
483
+ uniform sampler2D uVelocity;
484
+ uniform sampler2D uSource;
485
+ uniform vec2 texelSize;
486
+ uniform vec2 dyeTexelSize;
487
+ uniform float dt;
488
+ uniform float dissipation;
489
+
490
+ vec4 bilerp (sampler2D sam, vec2 uv, vec2 tsize) {
491
+ vec2 st = uv / tsize - 0.5;
492
+ vec2 iuv = floor(st);
493
+ vec2 fuv = fract(st);
494
+
495
+ vec4 a = texture2D(sam, (iuv + vec2(0.5, 0.5)) * tsize);
496
+ vec4 b = texture2D(sam, (iuv + vec2(1.5, 0.5)) * tsize);
497
+ vec4 c = texture2D(sam, (iuv + vec2(0.5, 1.5)) * tsize);
498
+ vec4 d = texture2D(sam, (iuv + vec2(1.5, 1.5)) * tsize);
499
+
500
+ return mix(mix(a, b, fuv.x), mix(c, d, fuv.x), fuv.y);
501
+ }
502
+
503
+ void main () {
504
+ #ifdef MANUAL_FILTERING
505
+ vec2 coord = vUv - dt * bilerp(uVelocity, vUv, texelSize).xy * texelSize;
506
+ vec4 result = bilerp(uSource, coord, dyeTexelSize);
507
+ #else
508
+ vec2 coord = vUv - dt * texture2D(uVelocity, vUv).xy * texelSize;
509
+ vec4 result = texture2D(uSource, coord);
510
+ #endif
511
+ float decay = 1.0 + dissipation * dt;
512
+ gl_FragColor = result / decay;
513
+ }
514
+ `,
515
+ ext.supportLinearFiltering ? null : ["MANUAL_FILTERING"]
516
+ );
517
+
518
+ const divergenceShader = compileShader(
519
+ gl.FRAGMENT_SHADER,
520
+ `
521
+ precision mediump float;
522
+ precision mediump sampler2D;
523
+ varying highp vec2 vUv;
524
+ varying highp vec2 vL;
525
+ varying highp vec2 vR;
526
+ varying highp vec2 vT;
527
+ varying highp vec2 vB;
528
+ uniform sampler2D uVelocity;
529
+
530
+ void main () {
531
+ float L = texture2D(uVelocity, vL).x;
532
+ float R = texture2D(uVelocity, vR).x;
533
+ float T = texture2D(uVelocity, vT).y;
534
+ float B = texture2D(uVelocity, vB).y;
535
+
536
+ vec2 C = texture2D(uVelocity, vUv).xy;
537
+ if (vL.x < 0.0) { L = -C.x; }
538
+ if (vR.x > 1.0) { R = -C.x; }
539
+ if (vT.y > 1.0) { T = -C.y; }
540
+ if (vB.y < 0.0) { B = -C.y; }
541
+
542
+ float div = 0.5 * (R - L + T - B);
543
+ gl_FragColor = vec4(div, 0.0, 0.0, 1.0);
544
+ }
545
+ `
546
+ );
547
+
548
+ const curlShader = compileShader(
549
+ gl.FRAGMENT_SHADER,
550
+ `
551
+ precision mediump float;
552
+ precision mediump sampler2D;
553
+ varying highp vec2 vUv;
554
+ varying highp vec2 vL;
555
+ varying highp vec2 vR;
556
+ varying highp vec2 vT;
557
+ varying highp vec2 vB;
558
+ uniform sampler2D uVelocity;
559
+
560
+ void main () {
561
+ float L = texture2D(uVelocity, vL).y;
562
+ float R = texture2D(uVelocity, vR).y;
563
+ float T = texture2D(uVelocity, vT).x;
564
+ float B = texture2D(uVelocity, vB).x;
565
+ float vorticity = R - L - T + B;
566
+ gl_FragColor = vec4(0.5 * vorticity, 0.0, 0.0, 1.0);
567
+ }
568
+ `
569
+ );
570
+
571
+ const vorticityShader = compileShader(
572
+ gl.FRAGMENT_SHADER,
573
+ `
574
+ precision highp float;
575
+ precision highp sampler2D;
576
+ varying vec2 vUv;
577
+ varying vec2 vL;
578
+ varying vec2 vR;
579
+ varying vec2 vT;
580
+ varying vec2 vB;
581
+ uniform sampler2D uVelocity;
582
+ uniform sampler2D uCurl;
583
+ uniform float curl;
584
+ uniform float dt;
585
+
586
+ void main () {
587
+ float L = texture2D(uCurl, vL).x;
588
+ float R = texture2D(uCurl, vR).x;
589
+ float T = texture2D(uCurl, vT).x;
590
+ float B = texture2D(uCurl, vB).x;
591
+ float C = texture2D(uCurl, vUv).x;
592
+
593
+ vec2 force = 0.5 * vec2(abs(T) - abs(B), abs(R) - abs(L));
594
+ force /= length(force) + 0.0001;
595
+ force *= curl * C;
596
+ force.y *= -1.0;
597
+
598
+ vec2 velocity = texture2D(uVelocity, vUv).xy;
599
+ velocity += force * dt;
600
+ velocity = min(max(velocity, -1000.0), 1000.0);
601
+ gl_FragColor = vec4(velocity, 0.0, 1.0);
602
+ }
603
+ `
604
+ );
605
+
606
+ const pressureShader = compileShader(
607
+ gl.FRAGMENT_SHADER,
608
+ `
609
+ precision mediump float;
610
+ precision mediump sampler2D;
611
+ varying highp vec2 vUv;
612
+ varying highp vec2 vL;
613
+ varying highp vec2 vR;
614
+ varying highp vec2 vT;
615
+ varying highp vec2 vB;
616
+ uniform sampler2D uPressure;
617
+ uniform sampler2D uDivergence;
618
+
619
+ void main () {
620
+ float L = texture2D(uPressure, vL).x;
621
+ float R = texture2D(uPressure, vR).x;
622
+ float T = texture2D(uPressure, vT).x;
623
+ float B = texture2D(uPressure, vB).x;
624
+ float C = texture2D(uPressure, vUv).x;
625
+ float divergence = texture2D(uDivergence, vUv).x;
626
+ float pressure = (L + R + B + T - divergence) * 0.25;
627
+ gl_FragColor = vec4(pressure, 0.0, 0.0, 1.0);
628
+ }
629
+ `
630
+ );
631
+
632
+ const gradientSubtractShader = compileShader(
633
+ gl.FRAGMENT_SHADER,
634
+ `
635
+ precision mediump float;
636
+ precision mediump sampler2D;
637
+ varying highp vec2 vUv;
638
+ varying highp vec2 vL;
639
+ varying highp vec2 vR;
640
+ varying highp vec2 vT;
641
+ varying highp vec2 vB;
642
+ uniform sampler2D uPressure;
643
+ uniform sampler2D uVelocity;
644
+
645
+ void main () {
646
+ float L = texture2D(uPressure, vL).x;
647
+ float R = texture2D(uPressure, vR).x;
648
+ float T = texture2D(uPressure, vT).x;
649
+ float B = texture2D(uPressure, vB).x;
650
+ vec2 velocity = texture2D(uVelocity, vUv).xy;
651
+ velocity.xy -= vec2(R - L, T - B);
652
+ gl_FragColor = vec4(velocity, 0.0, 1.0);
653
+ }
654
+ `
655
+ );
656
+
657
+ // Fullscreen Triangles
658
+ interface FBO {
659
+ texture: WebGLTexture;
660
+ fbo: WebGLFramebuffer;
661
+ width: number;
662
+ height: number;
663
+ texelSizeX: number;
664
+ texelSizeY: number;
665
+ attach: (id: number) => number;
666
+ }
667
+
668
+ interface DoubleFBO {
669
+ width: number;
670
+ height: number;
671
+ texelSizeX: number;
672
+ texelSizeY: number;
673
+ read: FBO;
674
+ write: FBO;
675
+ swap: () => void;
676
+ }
677
+
678
+ const blit = (() => {
679
+ const buffer = gl.createBuffer()!;
680
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
681
+ gl.bufferData(
682
+ gl.ARRAY_BUFFER,
683
+ new Float32Array([-1, -1, -1, 1, 1, 1, 1, -1]),
684
+ gl.STATIC_DRAW
685
+ );
686
+ const elemBuffer = gl.createBuffer()!;
687
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elemBuffer);
688
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 0, 2, 3]), gl.STATIC_DRAW);
689
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
690
+ gl.enableVertexAttribArray(0);
691
+
692
+ return (target: FBO | null, doClear = false) => {
693
+ if (!gl) return;
694
+ if (!target) {
695
+ gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
696
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
697
+ } else {
698
+ gl.viewport(0, 0, target.width, target.height);
699
+ gl.bindFramebuffer(gl.FRAMEBUFFER, target.fbo);
700
+ }
701
+ if (doClear) {
702
+ gl.clearColor(0, 0, 0, 1);
703
+ gl.clear(gl.COLOR_BUFFER_BIT);
704
+ }
705
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
706
+ };
707
+ })();
708
+
709
+ // FBO variables
710
+ let dye: DoubleFBO;
711
+ let velocity: DoubleFBO;
712
+ let divergenceFBO: FBO;
713
+ let curlFBO: FBO;
714
+ let pressureFBO: DoubleFBO;
715
+
716
+ // WebGL Programs
717
+ const copyProgram = new Program(baseVertexShader, copyShader);
718
+ const clearProgram = new Program(baseVertexShader, clearShader);
719
+ const splatProgram = new Program(baseVertexShader, splatShader);
720
+ const advectionProgram = new Program(baseVertexShader, advectionShader);
721
+ const divergenceProgram = new Program(baseVertexShader, divergenceShader);
722
+ const curlProgram = new Program(baseVertexShader, curlShader);
723
+ const vorticityProgram = new Program(baseVertexShader, vorticityShader);
724
+ const pressureProgram = new Program(baseVertexShader, pressureShader);
725
+ const gradienSubtractProgram = new Program(baseVertexShader, gradientSubtractShader);
726
+ const displayMaterial = new Material(baseVertexShader, displayShaderSource);
727
+
728
+ // FBO creation
729
+ function createFBO(
730
+ w: number,
731
+ h: number,
732
+ internalFormat: number,
733
+ format: number,
734
+ type: number,
735
+ param: number
736
+ ): FBO {
737
+ gl.activeTexture(gl.TEXTURE0);
738
+ const texture = gl.createTexture()!;
739
+ gl.bindTexture(gl.TEXTURE_2D, texture);
740
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, param);
741
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, param);
742
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
743
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
744
+ gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, w, h, 0, format, type, null);
745
+ const fbo = gl.createFramebuffer()!;
746
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
747
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
748
+ gl.viewport(0, 0, w, h);
749
+ gl.clear(gl.COLOR_BUFFER_BIT);
750
+
751
+ const texelSizeX = 1 / w;
752
+ const texelSizeY = 1 / h;
753
+
754
+ return {
755
+ texture,
756
+ fbo,
757
+ width: w,
758
+ height: h,
759
+ texelSizeX,
760
+ texelSizeY,
761
+ attach(id: number) {
762
+ gl.activeTexture(gl.TEXTURE0 + id);
763
+ gl.bindTexture(gl.TEXTURE_2D, texture);
764
+ return id;
765
+ },
766
+ };
767
+ }
768
+
769
+ function createDoubleFBO(
770
+ w: number,
771
+ h: number,
772
+ internalFormat: number,
773
+ format: number,
774
+ type: number,
775
+ param: number
776
+ ): DoubleFBO {
777
+ const fbo1 = createFBO(w, h, internalFormat, format, type, param);
778
+ const fbo2 = createFBO(w, h, internalFormat, format, type, param);
779
+ return {
780
+ width: w,
781
+ height: h,
782
+ texelSizeX: fbo1.texelSizeX,
783
+ texelSizeY: fbo1.texelSizeY,
784
+ read: fbo1,
785
+ write: fbo2,
786
+ swap() {
787
+ const tmp = this.read;
788
+ this.read = this.write;
789
+ this.write = tmp;
790
+ },
791
+ };
792
+ }
793
+
794
+ function resizeFBO(
795
+ target: FBO,
796
+ w: number,
797
+ h: number,
798
+ internalFormat: number,
799
+ format: number,
800
+ type: number,
801
+ param: number
802
+ ) {
803
+ const newFBO = createFBO(w, h, internalFormat, format, type, param);
804
+ copyProgram.bind();
805
+ if (copyProgram.uniforms.uTexture)
806
+ gl.uniform1i(copyProgram.uniforms.uTexture, target.attach(0));
807
+ blit(newFBO, false);
808
+ return newFBO;
809
+ }
810
+
811
+ function resizeDoubleFBO(
812
+ target: DoubleFBO,
813
+ w: number,
814
+ h: number,
815
+ internalFormat: number,
816
+ format: number,
817
+ type: number,
818
+ param: number
819
+ ) {
820
+ if (target.width === w && target.height === h) return target;
821
+ target.read = resizeFBO(target.read, w, h, internalFormat, format, type, param);
822
+ target.write = createFBO(w, h, internalFormat, format, type, param);
823
+ target.width = w;
824
+ target.height = h;
825
+ target.texelSizeX = 1 / w;
826
+ target.texelSizeY = 1 / h;
827
+ return target;
828
+ }
829
+
830
+ function initFramebuffers() {
831
+ const simRes = getResolution(config.SIM_RESOLUTION!);
832
+ const dyeRes = getResolution(config.DYE_RESOLUTION!);
833
+
834
+ const texType = ext.halfFloatTexType;
835
+ const rgba = ext.formatRGBA!;
836
+ const rg = ext.formatRG!;
837
+ const r = ext.formatR!;
838
+ const filtering = ext.supportLinearFiltering ? gl.LINEAR : gl.NEAREST;
839
+ gl.disable(gl.BLEND);
840
+
841
+ if (!dye) {
842
+ dye = createDoubleFBO(
843
+ dyeRes.width,
844
+ dyeRes.height,
845
+ rgba.internalFormat,
846
+ rgba.format,
847
+ texType,
848
+ filtering
849
+ );
850
+ } else {
851
+ dye = resizeDoubleFBO(
852
+ dye,
853
+ dyeRes.width,
854
+ dyeRes.height,
855
+ rgba.internalFormat,
856
+ rgba.format,
857
+ texType,
858
+ filtering
859
+ );
860
+ }
861
+
862
+ if (!velocity) {
863
+ velocity = createDoubleFBO(
864
+ simRes.width,
865
+ simRes.height,
866
+ rg.internalFormat,
867
+ rg.format,
868
+ texType,
869
+ filtering
870
+ );
871
+ } else {
872
+ velocity = resizeDoubleFBO(
873
+ velocity,
874
+ simRes.width,
875
+ simRes.height,
876
+ rg.internalFormat,
877
+ rg.format,
878
+ texType,
879
+ filtering
880
+ );
881
+ }
882
+
883
+ divergenceFBO = createFBO(
884
+ simRes.width,
885
+ simRes.height,
886
+ r.internalFormat,
887
+ r.format,
888
+ texType,
889
+ gl.NEAREST
890
+ );
891
+ curlFBO = createFBO(
892
+ simRes.width,
893
+ simRes.height,
894
+ r.internalFormat,
895
+ r.format,
896
+ texType,
897
+ gl.NEAREST
898
+ );
899
+ pressureFBO = createDoubleFBO(
900
+ simRes.width,
901
+ simRes.height,
902
+ r.internalFormat,
903
+ r.format,
904
+ texType,
905
+ gl.NEAREST
906
+ );
907
+ }
908
+
909
+ function updateKeywords() {
910
+ const displayKeywords: string[] = [];
911
+ if (config.SHADING) displayKeywords.push("SHADING");
912
+ displayMaterial.setKeywords(displayKeywords);
913
+ }
914
+
915
+ function getResolution(resolution: number) {
916
+ const w = gl.drawingBufferWidth;
917
+ const h = gl.drawingBufferHeight;
918
+ const aspectRatio = w / h;
919
+ const aspect = aspectRatio < 1 ? 1 / aspectRatio : aspectRatio;
920
+ const min = Math.round(resolution);
921
+ const max = Math.round(resolution * aspect);
922
+ if (w > h) {
923
+ return { width: max, height: min };
924
+ }
925
+ return { width: min, height: max };
926
+ }
927
+
928
+ function scaleByPixelRatio(input: number) {
929
+ const pixelRatio = window.devicePixelRatio || 1;
930
+ return Math.floor(input * pixelRatio);
931
+ }
932
+
933
+ // Simulation Setup
934
+ updateKeywords();
935
+ initFramebuffers();
936
+
937
+ let lastUpdateTime = Date.now();
938
+ let colorUpdateTimer = 0.0;
939
+ let animationFrameId: number;
940
+
941
+ function updateFrame() {
942
+ const dt = calcDeltaTime();
943
+ if (resizeCanvas()) initFramebuffers();
944
+ updateColors(dt);
945
+ applyInputs();
946
+ step(dt);
947
+ render(null);
948
+ animationFrameId = requestAnimationFrame(updateFrame);
949
+ }
950
+
951
+ function calcDeltaTime() {
952
+ const now = Date.now();
953
+ let dt = (now - lastUpdateTime) / 1000;
954
+ dt = Math.min(dt, 0.016666);
955
+ lastUpdateTime = now;
956
+ return dt;
957
+ }
958
+
959
+ function resizeCanvas() {
960
+ const width = scaleByPixelRatio(canvas.clientWidth);
961
+ const height = scaleByPixelRatio(canvas.clientHeight);
962
+ if (canvas.width !== width || canvas.height !== height) {
963
+ canvas.width = width;
964
+ canvas.height = height;
965
+ return true;
966
+ }
967
+ return false;
968
+ }
969
+
970
+ function updateColors(dt: number) {
971
+ colorUpdateTimer += dt * config.COLOR_UPDATE_SPEED;
972
+ if (colorUpdateTimer >= 1) {
973
+ colorUpdateTimer = wrap(colorUpdateTimer, 0, 1);
974
+ pointers.forEach((p) => {
975
+ p.color = generateColor();
976
+ });
977
+ }
978
+ }
979
+
980
+ function applyInputs() {
981
+ for (const p of pointers) {
982
+ if (p.moved) {
983
+ p.moved = false;
984
+ splatPointer(p);
985
+ }
986
+ }
987
+ }
988
+
989
+ function step(dt: number) {
990
+ gl.disable(gl.BLEND);
991
+
992
+ // Curl
993
+ curlProgram.bind();
994
+ if (curlProgram.uniforms.texelSize) {
995
+ gl.uniform2f(curlProgram.uniforms.texelSize, velocity.texelSizeX, velocity.texelSizeY);
996
+ }
997
+ if (curlProgram.uniforms.uVelocity) {
998
+ gl.uniform1i(curlProgram.uniforms.uVelocity, velocity.read.attach(0));
999
+ }
1000
+ blit(curlFBO);
1001
+
1002
+ // Vorticity
1003
+ vorticityProgram.bind();
1004
+ if (vorticityProgram.uniforms.texelSize) {
1005
+ gl.uniform2f(vorticityProgram.uniforms.texelSize, velocity.texelSizeX, velocity.texelSizeY);
1006
+ }
1007
+ if (vorticityProgram.uniforms.uVelocity) {
1008
+ gl.uniform1i(vorticityProgram.uniforms.uVelocity, velocity.read.attach(0));
1009
+ }
1010
+ if (vorticityProgram.uniforms.uCurl) {
1011
+ gl.uniform1i(vorticityProgram.uniforms.uCurl, curlFBO.attach(1));
1012
+ }
1013
+ if (vorticityProgram.uniforms.curl) {
1014
+ gl.uniform1f(vorticityProgram.uniforms.curl, config.CURL);
1015
+ }
1016
+ if (vorticityProgram.uniforms.dt) {
1017
+ gl.uniform1f(vorticityProgram.uniforms.dt, dt);
1018
+ }
1019
+ blit(velocity.write);
1020
+ velocity.swap();
1021
+
1022
+ // Divergence
1023
+ divergenceProgram.bind();
1024
+ if (divergenceProgram.uniforms.texelSize) {
1025
+ gl.uniform2f(
1026
+ divergenceProgram.uniforms.texelSize,
1027
+ velocity.texelSizeX,
1028
+ velocity.texelSizeY
1029
+ );
1030
+ }
1031
+ if (divergenceProgram.uniforms.uVelocity) {
1032
+ gl.uniform1i(divergenceProgram.uniforms.uVelocity, velocity.read.attach(0));
1033
+ }
1034
+ blit(divergenceFBO);
1035
+
1036
+ // Clear pressure
1037
+ clearProgram.bind();
1038
+ if (clearProgram.uniforms.uTexture) {
1039
+ gl.uniform1i(clearProgram.uniforms.uTexture, pressureFBO.read.attach(0));
1040
+ }
1041
+ if (clearProgram.uniforms.value) {
1042
+ gl.uniform1f(clearProgram.uniforms.value, config.PRESSURE);
1043
+ }
1044
+ blit(pressureFBO.write);
1045
+ pressureFBO.swap();
1046
+
1047
+ // Pressure
1048
+ pressureProgram.bind();
1049
+ if (pressureProgram.uniforms.texelSize) {
1050
+ gl.uniform2f(pressureProgram.uniforms.texelSize, velocity.texelSizeX, velocity.texelSizeY);
1051
+ }
1052
+ if (pressureProgram.uniforms.uDivergence) {
1053
+ gl.uniform1i(pressureProgram.uniforms.uDivergence, divergenceFBO.attach(0));
1054
+ }
1055
+ for (let i = 0; i < config.PRESSURE_ITERATIONS; i++) {
1056
+ if (pressureProgram.uniforms.uPressure) {
1057
+ gl.uniform1i(pressureProgram.uniforms.uPressure, pressureFBO.read.attach(1));
1058
+ }
1059
+ blit(pressureFBO.write);
1060
+ pressureFBO.swap();
1061
+ }
1062
+
1063
+ // Gradient Subtract
1064
+ gradienSubtractProgram.bind();
1065
+ if (gradienSubtractProgram.uniforms.texelSize) {
1066
+ gl.uniform2f(
1067
+ gradienSubtractProgram.uniforms.texelSize,
1068
+ velocity.texelSizeX,
1069
+ velocity.texelSizeY
1070
+ );
1071
+ }
1072
+ if (gradienSubtractProgram.uniforms.uPressure) {
1073
+ gl.uniform1i(gradienSubtractProgram.uniforms.uPressure, pressureFBO.read.attach(0));
1074
+ }
1075
+ if (gradienSubtractProgram.uniforms.uVelocity) {
1076
+ gl.uniform1i(gradienSubtractProgram.uniforms.uVelocity, velocity.read.attach(1));
1077
+ }
1078
+ blit(velocity.write);
1079
+ velocity.swap();
1080
+
1081
+ // Advection - velocity
1082
+ advectionProgram.bind();
1083
+ if (advectionProgram.uniforms.texelSize) {
1084
+ gl.uniform2f(advectionProgram.uniforms.texelSize, velocity.texelSizeX, velocity.texelSizeY);
1085
+ }
1086
+ if (!ext.supportLinearFiltering && advectionProgram.uniforms.dyeTexelSize) {
1087
+ gl.uniform2f(
1088
+ advectionProgram.uniforms.dyeTexelSize,
1089
+ velocity.texelSizeX,
1090
+ velocity.texelSizeY
1091
+ );
1092
+ }
1093
+ const velocityId = velocity.read.attach(0);
1094
+ if (advectionProgram.uniforms.uVelocity) {
1095
+ gl.uniform1i(advectionProgram.uniforms.uVelocity, velocityId);
1096
+ }
1097
+ if (advectionProgram.uniforms.uSource) {
1098
+ gl.uniform1i(advectionProgram.uniforms.uSource, velocityId);
1099
+ }
1100
+ if (advectionProgram.uniforms.dt) {
1101
+ gl.uniform1f(advectionProgram.uniforms.dt, dt);
1102
+ }
1103
+ if (advectionProgram.uniforms.dissipation) {
1104
+ gl.uniform1f(advectionProgram.uniforms.dissipation, config.VELOCITY_DISSIPATION);
1105
+ }
1106
+ blit(velocity.write);
1107
+ velocity.swap();
1108
+
1109
+ // Advection - dye
1110
+ if (!ext.supportLinearFiltering && advectionProgram.uniforms.dyeTexelSize) {
1111
+ gl.uniform2f(advectionProgram.uniforms.dyeTexelSize, dye.texelSizeX, dye.texelSizeY);
1112
+ }
1113
+ if (advectionProgram.uniforms.uVelocity) {
1114
+ gl.uniform1i(advectionProgram.uniforms.uVelocity, velocity.read.attach(0));
1115
+ }
1116
+ if (advectionProgram.uniforms.uSource) {
1117
+ gl.uniform1i(advectionProgram.uniforms.uSource, dye.read.attach(1));
1118
+ }
1119
+ if (advectionProgram.uniforms.dissipation) {
1120
+ gl.uniform1f(advectionProgram.uniforms.dissipation, config.DENSITY_DISSIPATION);
1121
+ }
1122
+ blit(dye.write);
1123
+ dye.swap();
1124
+ }
1125
+
1126
+ function render(target: FBO | null) {
1127
+ gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
1128
+ gl.enable(gl.BLEND);
1129
+ drawDisplay(target);
1130
+ }
1131
+
1132
+ function drawDisplay(target: FBO | null) {
1133
+ const width = target ? target.width : gl.drawingBufferWidth;
1134
+ const height = target ? target.height : gl.drawingBufferHeight;
1135
+ displayMaterial.bind();
1136
+ if (config.SHADING && displayMaterial.uniforms.texelSize) {
1137
+ gl.uniform2f(displayMaterial.uniforms.texelSize, 1 / width, 1 / height);
1138
+ }
1139
+ if (displayMaterial.uniforms.uTexture) {
1140
+ gl.uniform1i(displayMaterial.uniforms.uTexture, dye.read.attach(0));
1141
+ }
1142
+ blit(target, false);
1143
+ }
1144
+
1145
+ // Interaction
1146
+ function splatPointer(pointer: Pointer) {
1147
+ const dx = pointer.deltaX * config.SPLAT_FORCE;
1148
+ const dy = pointer.deltaY * config.SPLAT_FORCE;
1149
+ splat(pointer.texcoordX, pointer.texcoordY, dx, dy, pointer.color);
1150
+ }
1151
+
1152
+ function clickSplat(pointer: Pointer) {
1153
+ const color = generateColor();
1154
+ color.r *= 10;
1155
+ color.g *= 10;
1156
+ color.b *= 10;
1157
+ const dx = 10 * (Math.random() - 0.5);
1158
+ const dy = 30 * (Math.random() - 0.5);
1159
+ splat(pointer.texcoordX, pointer.texcoordY, dx, dy, color);
1160
+ }
1161
+
1162
+ function splat(x: number, y: number, dx: number, dy: number, color: ColorRGB) {
1163
+ splatProgram.bind();
1164
+ if (splatProgram.uniforms.uTarget) {
1165
+ gl.uniform1i(splatProgram.uniforms.uTarget, velocity.read.attach(0));
1166
+ }
1167
+ if (splatProgram.uniforms.aspectRatio) {
1168
+ gl.uniform1f(splatProgram.uniforms.aspectRatio, canvas.width / canvas.height);
1169
+ }
1170
+ if (splatProgram.uniforms.point) {
1171
+ gl.uniform2f(splatProgram.uniforms.point, x, y);
1172
+ }
1173
+ if (splatProgram.uniforms.color) {
1174
+ gl.uniform3f(splatProgram.uniforms.color, dx, dy, 0);
1175
+ }
1176
+ if (splatProgram.uniforms.radius) {
1177
+ gl.uniform1f(splatProgram.uniforms.radius, correctRadius(config.SPLAT_RADIUS / 100)!);
1178
+ }
1179
+ blit(velocity.write);
1180
+ velocity.swap();
1181
+
1182
+ if (splatProgram.uniforms.uTarget) {
1183
+ gl.uniform1i(splatProgram.uniforms.uTarget, dye.read.attach(0));
1184
+ }
1185
+ if (splatProgram.uniforms.color) {
1186
+ gl.uniform3f(splatProgram.uniforms.color, color.r, color.g, color.b);
1187
+ }
1188
+ blit(dye.write);
1189
+ dye.swap();
1190
+ }
1191
+
1192
+ function correctRadius(radius: number) {
1193
+ const aspectRatio = canvas.width / canvas.height;
1194
+ if (aspectRatio > 1) radius *= aspectRatio;
1195
+ return radius;
1196
+ }
1197
+
1198
+ function updatePointerDownData(pointer: Pointer, id: number, posX: number, posY: number) {
1199
+ pointer.id = id;
1200
+ pointer.down = true;
1201
+ pointer.moved = false;
1202
+ pointer.texcoordX = posX / canvas.width;
1203
+ pointer.texcoordY = 1 - posY / canvas.height;
1204
+ pointer.prevTexcoordX = pointer.texcoordX;
1205
+ pointer.prevTexcoordY = pointer.texcoordY;
1206
+ pointer.deltaX = 0;
1207
+ pointer.deltaY = 0;
1208
+ pointer.color = generateColor();
1209
+ }
1210
+
1211
+ function updatePointerMoveData(pointer: Pointer, posX: number, posY: number, color: ColorRGB) {
1212
+ pointer.prevTexcoordX = pointer.texcoordX;
1213
+ pointer.prevTexcoordY = pointer.texcoordY;
1214
+ pointer.texcoordX = posX / canvas.width;
1215
+ pointer.texcoordY = 1 - posY / canvas.height;
1216
+ pointer.deltaX = correctDeltaX(pointer.texcoordX - pointer.prevTexcoordX)!;
1217
+ pointer.deltaY = correctDeltaY(pointer.texcoordY - pointer.prevTexcoordY)!;
1218
+ pointer.moved = Math.abs(pointer.deltaX) > 0 || Math.abs(pointer.deltaY) > 0;
1219
+ pointer.color = color;
1220
+ }
1221
+
1222
+ function correctDeltaX(delta: number) {
1223
+ const aspectRatio = canvas.width / canvas.height;
1224
+ if (aspectRatio < 1) delta *= aspectRatio;
1225
+ return delta;
1226
+ }
1227
+
1228
+ function correctDeltaY(delta: number) {
1229
+ const aspectRatio = canvas.width / canvas.height;
1230
+ if (aspectRatio > 1) delta /= aspectRatio;
1231
+ return delta;
1232
+ }
1233
+
1234
+ function generateColor(): ColorRGB {
1235
+ const c = HSVtoRGB(Math.random(), 1.0, 1.0);
1236
+ c.r *= 0.15;
1237
+ c.g *= 0.15;
1238
+ c.b *= 0.15;
1239
+ return c;
1240
+ }
1241
+
1242
+ function HSVtoRGB(h: number, s: number, v: number): ColorRGB {
1243
+ let r = 0;
1244
+ let g = 0;
1245
+ let b = 0;
1246
+ const i = Math.floor(h * 6);
1247
+ const f = h * 6 - i;
1248
+ const p = v * (1 - s);
1249
+ const q = v * (1 - f * s);
1250
+ const t = v * (1 - (1 - f) * s);
1251
+
1252
+ switch (i % 6) {
1253
+ case 0:
1254
+ r = v;
1255
+ g = t;
1256
+ b = p;
1257
+ break;
1258
+ case 1:
1259
+ r = q;
1260
+ g = v;
1261
+ b = p;
1262
+ break;
1263
+ case 2:
1264
+ r = p;
1265
+ g = v;
1266
+ b = t;
1267
+ break;
1268
+ case 3:
1269
+ r = p;
1270
+ g = q;
1271
+ b = v;
1272
+ break;
1273
+ case 4:
1274
+ r = t;
1275
+ g = p;
1276
+ b = v;
1277
+ break;
1278
+ case 5:
1279
+ r = v;
1280
+ g = p;
1281
+ b = q;
1282
+ break;
1283
+ }
1284
+ return { r, g, b };
1285
+ }
1286
+
1287
+ function wrap(value: number, min: number, max: number) {
1288
+ const range = max - min;
1289
+ if (range === 0) return min;
1290
+ return ((value - min) % range) + min;
1291
+ }
1292
+
1293
+ // Event Listeners
1294
+ function handleMouseDown(e: MouseEvent) {
1295
+ const pointer = pointers[0];
1296
+ const posX = scaleByPixelRatio(e.clientX);
1297
+ const posY = scaleByPixelRatio(e.clientY);
1298
+ updatePointerDownData(pointer, -1, posX, posY);
1299
+ clickSplat(pointer);
1300
+ }
1301
+
1302
+ function handleFirstMouseMove(e: MouseEvent) {
1303
+ const pointer = pointers[0];
1304
+ const posX = scaleByPixelRatio(e.clientX);
1305
+ const posY = scaleByPixelRatio(e.clientY);
1306
+ const color = generateColor();
1307
+ updateFrame();
1308
+ updatePointerMoveData(pointer, posX, posY, color);
1309
+ document.body.removeEventListener("mousemove", handleFirstMouseMove);
1310
+ }
1311
+
1312
+ function handleMouseMove(e: MouseEvent) {
1313
+ const pointer = pointers[0];
1314
+ const posX = scaleByPixelRatio(e.clientX);
1315
+ const posY = scaleByPixelRatio(e.clientY);
1316
+ const color = pointer.color;
1317
+ updatePointerMoveData(pointer, posX, posY, color);
1318
+ }
1319
+
1320
+ function handleFirstTouchStart(e: TouchEvent) {
1321
+ const touches = e.targetTouches;
1322
+ const pointer = pointers[0];
1323
+ for (let i = 0; i < touches.length; i++) {
1324
+ const posX = scaleByPixelRatio(touches[i].clientX);
1325
+ const posY = scaleByPixelRatio(touches[i].clientY);
1326
+ updateFrame();
1327
+ updatePointerDownData(pointer, touches[i].identifier, posX, posY);
1328
+ }
1329
+ document.body.removeEventListener("touchstart", handleFirstTouchStart);
1330
+ }
1331
+
1332
+ function handleTouchStart(e: TouchEvent) {
1333
+ const touches = e.targetTouches;
1334
+ const pointer = pointers[0];
1335
+ for (let i = 0; i < touches.length; i++) {
1336
+ const posX = scaleByPixelRatio(touches[i].clientX);
1337
+ const posY = scaleByPixelRatio(touches[i].clientY);
1338
+ updatePointerDownData(pointer, touches[i].identifier, posX, posY);
1339
+ }
1340
+ }
1341
+
1342
+ function handleTouchMove(e: TouchEvent) {
1343
+ const touches = e.targetTouches;
1344
+ const pointer = pointers[0];
1345
+ for (let i = 0; i < touches.length; i++) {
1346
+ const posX = scaleByPixelRatio(touches[i].clientX);
1347
+ const posY = scaleByPixelRatio(touches[i].clientY);
1348
+ updatePointerMoveData(pointer, posX, posY, pointer.color);
1349
+ }
1350
+ }
1351
+
1352
+ // Add event listeners
1353
+ window.addEventListener("mousedown", handleMouseDown);
1354
+ document.body.addEventListener("mousemove", handleFirstMouseMove);
1355
+ window.addEventListener("mousemove", handleMouseMove);
1356
+ document.body.addEventListener("touchstart", handleFirstTouchStart);
1357
+ window.addEventListener("touchstart", handleTouchStart, false);
1358
+ window.addEventListener("touchmove", handleTouchMove, false);
1359
+
1360
+ // Start animation
1361
+ updateFrame();
1362
+
1363
+ // Cleanup
1364
+ return () => {
1365
+ cancelAnimationFrame(animationFrameId);
1366
+ window.removeEventListener("mousedown", handleMouseDown);
1367
+ document.body.removeEventListener("mousemove", handleFirstMouseMove);
1368
+ window.removeEventListener("mousemove", handleMouseMove);
1369
+ document.body.removeEventListener("touchstart", handleFirstTouchStart);
1370
+ window.removeEventListener("touchstart", handleTouchStart);
1371
+ window.removeEventListener("touchmove", handleTouchMove);
1372
+ };
1373
+ });
1374
+ </script>
1375
+
1376
+ <div class={cn("pointer-events-none fixed top-0 left-0 z-50 size-full", className)}>
1377
+ <canvas bind:this={canvasRef} id="fluid" class="block h-screen w-screen"></canvas>
1378
+ </div>