kmcom-nuxt-layers 1.0.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 (380) hide show
  1. package/.claude/rules/nuxt-layers.md +23 -0
  2. package/.claude/rules/typescript.md +16 -0
  3. package/.claude/rules/vue-components.md +34 -0
  4. package/.claude/settings.local.json +81 -0
  5. package/.editorconfig +27 -0
  6. package/.github/workflows/npm-publish.yml +33 -0
  7. package/.oxlintrc.json +10 -0
  8. package/.prettierignore +87 -0
  9. package/CLAUDE.md +71 -0
  10. package/apps/playground/README.md +75 -0
  11. package/apps/playground/app/app.config.ts +10 -0
  12. package/apps/playground/app/app.vue +12 -0
  13. package/apps/playground/app/components/AmbientBackground.client.vue +795 -0
  14. package/apps/playground/app/components/ShaderDemoCanvas.client.vue +636 -0
  15. package/apps/playground/app/components/ShaderImageDemo.client.vue +211 -0
  16. package/apps/playground/app/pages/ambient.vue +387 -0
  17. package/apps/playground/app/pages/content.vue +200 -0
  18. package/apps/playground/app/pages/core.vue +560 -0
  19. package/apps/playground/app/pages/forms.vue +645 -0
  20. package/apps/playground/app/pages/index.vue +257 -0
  21. package/apps/playground/app/pages/layout.vue +591 -0
  22. package/apps/playground/app/pages/locomotive-scroll.vue +738 -0
  23. package/apps/playground/app/pages/motion.vue +848 -0
  24. package/apps/playground/app/pages/shader.vue +1701 -0
  25. package/apps/playground/app/pages/theme.vue +115 -0
  26. package/apps/playground/app/pages/ui.vue +656 -0
  27. package/apps/playground/content/blog/hello-world.md +127 -0
  28. package/apps/playground/content/blog/second-post.md +99 -0
  29. package/apps/playground/content/blog/third-post.md +33 -0
  30. package/apps/playground/content/gallery/autumn-collection.md +57 -0
  31. package/apps/playground/content/gallery/summer-collection.md +52 -0
  32. package/apps/playground/content/pages/index.md +132 -0
  33. package/apps/playground/content/portfolio/project-one.md +90 -0
  34. package/apps/playground/content/portfolio/project-two.md +96 -0
  35. package/apps/playground/content.config.ts +93 -0
  36. package/apps/playground/nuxt.config.ts +99 -0
  37. package/apps/playground/package.json +17 -0
  38. package/apps/playground/public/favicon.ico +0 -0
  39. package/apps/playground/public/robots.txt +2 -0
  40. package/apps/playground/tsconfig.json +25 -0
  41. package/eslint.config.mjs +223 -0
  42. package/eslint.configCOPY.mjs +216 -0
  43. package/eslintconfigCURRENT.mjs +244 -0
  44. package/eslintconfigOLD.mjs +178 -0
  45. package/files for claude/Scroller.vue +31 -0
  46. package/files for claude/TextMarquee.vue +255 -0
  47. package/files for claude/gsap.client.ts +18 -0
  48. package/files for claude/gsap.ts +10 -0
  49. package/files for claude/scroll.ts +28 -0
  50. package/layers/content/app/assets/css/main.css +1 -0
  51. package/layers/content/app/components/Blog/Article.vue +29 -0
  52. package/layers/content/app/components/Blog/Card.vue +40 -0
  53. package/layers/content/app/components/Blog/List.vue +35 -0
  54. package/layers/content/app/components/Gallery/AmbientImage.vue +52 -0
  55. package/layers/content/app/components/Gallery/Card.vue +39 -0
  56. package/layers/content/app/components/Gallery/Detail.vue +76 -0
  57. package/layers/content/app/components/Gallery/Grid.vue +48 -0
  58. package/layers/content/app/components/Gallery/ImageDetail.vue +92 -0
  59. package/layers/content/app/components/Gallery/Lightbox.vue +102 -0
  60. package/layers/content/app/components/NuxtContent/Detail.vue +53 -0
  61. package/layers/content/app/components/NuxtContent/List.vue +21 -0
  62. package/layers/content/app/components/NuxtContent/Renderer.vue +14 -0
  63. package/layers/content/app/components/NuxtContent/Surround.vue +15 -0
  64. package/layers/content/app/components/NuxtContent/Toc.vue +18 -0
  65. package/layers/content/app/components/Portfolio/Card.vue +39 -0
  66. package/layers/content/app/components/Portfolio/ColorPalette.vue +39 -0
  67. package/layers/content/app/components/Portfolio/Detail.vue +49 -0
  68. package/layers/content/app/components/Portfolio/List.vue +44 -0
  69. package/layers/content/app/components/Portfolio/Typography.vue +37 -0
  70. package/layers/content/app/components/content/Figure.vue +31 -0
  71. package/layers/content/app/composables/useBlogPost.ts +3 -0
  72. package/layers/content/app/composables/useBlogPosts.ts +23 -0
  73. package/layers/content/app/composables/useCollectionItem.ts +5 -0
  74. package/layers/content/app/composables/useCollectionSurround.ts +9 -0
  75. package/layers/content/app/composables/useContentPage.ts +3 -0
  76. package/layers/content/app/composables/useGalleryItem.ts +3 -0
  77. package/layers/content/app/composables/useGalleryItems.ts +19 -0
  78. package/layers/content/app/composables/usePortfolioItem.ts +3 -0
  79. package/layers/content/app/composables/usePortfolioItems.ts +23 -0
  80. package/layers/content/app/pages/blog/[slug].vue +10 -0
  81. package/layers/content/app/pages/blog/index.vue +15 -0
  82. package/layers/content/app/pages/gallery/[slug]/[imageId].vue +11 -0
  83. package/layers/content/app/pages/gallery/[slug]/index.vue +10 -0
  84. package/layers/content/app/pages/gallery/index.vue +15 -0
  85. package/layers/content/app/pages/portfolio/[slug].vue +10 -0
  86. package/layers/content/app/pages/portfolio/index.vue +15 -0
  87. package/layers/content/app/types/content.ts +84 -0
  88. package/layers/content/app.config.ts +12 -0
  89. package/layers/content/content.config.ts +93 -0
  90. package/layers/content/nuxt.config.ts +31 -0
  91. package/layers/content/package.json +31 -0
  92. package/layers/content/tsconfig.json +6 -0
  93. package/layers/core/app/assets/css/base.css +88 -0
  94. package/layers/core/app/assets/css/layout.css +36 -0
  95. package/layers/core/app/assets/css/main.css +7 -0
  96. package/layers/core/app/assets/css-backup.zip +0 -0
  97. package/layers/core/app/components/ErrorBoundary.vue +102 -0
  98. package/layers/core/app/components/LoadingScreen.vue +137 -0
  99. package/layers/core/app/composables/useBrowser.ts +161 -0
  100. package/layers/core/app/composables/useCache.ts +138 -0
  101. package/layers/core/app/composables/useDevice.ts +36 -0
  102. package/layers/core/app/composables/useEnv.ts +23 -0
  103. package/layers/core/app/composables/useErrorLog.ts +158 -0
  104. package/layers/core/app/composables/useFeatures.ts +269 -0
  105. package/layers/core/app/composables/useLoading.ts +109 -0
  106. package/layers/core/app/composables/useNetworkInfo.ts +83 -0
  107. package/layers/core/app/composables/usePWAInfo.ts +104 -0
  108. package/layers/core/app/composables/useRendering.ts +97 -0
  109. package/layers/core/app/composables/useScreen.ts +95 -0
  110. package/layers/core/app/composables/useScrollGuard.ts +266 -0
  111. package/layers/core/app/error.vue +103 -0
  112. package/layers/core/app/layouts/default.vue +4 -0
  113. package/layers/core/app/pages/[...slug].vue +168 -0
  114. package/layers/core/app/pages/diagnostics.vue +228 -0
  115. package/layers/core/app/plugins/error-handler.ts +47 -0
  116. package/layers/core/app/plugins/feature-detection.client.ts +32 -0
  117. package/layers/core/app/plugins/init.ts +188 -0
  118. package/layers/core/app/plugins/loading.client.ts +54 -0
  119. package/layers/core/app/plugins/scroll-guard.client.ts +53 -0
  120. package/layers/core/app/types/detection.ts +117 -0
  121. package/layers/core/app/types/index.ts +10 -0
  122. package/layers/core/app/types/loading.ts +47 -0
  123. package/layers/core/app/types/runtime-config.ts +31 -0
  124. package/layers/core/app/types/scroll-guard.ts +25 -0
  125. package/layers/core/app/utils/helpers.ts +246 -0
  126. package/layers/core/app/utils/index.ts +8 -0
  127. package/layers/core/app/utils/regex.ts +6 -0
  128. package/layers/core/app.config.ts +193 -0
  129. package/layers/core/nuxt.config.ts +84 -0
  130. package/layers/core/package.json +25 -0
  131. package/layers/core/tailwind.config.js +28 -0
  132. package/layers/core/tsconfig.json +6 -0
  133. package/layers/forms/app/components/Form/Contact.vue +78 -0
  134. package/layers/forms/app/components/Form/Field.vue +85 -0
  135. package/layers/forms/app/composables/useFormSchema.ts +35 -0
  136. package/layers/forms/app/config/fields.ts +104 -0
  137. package/layers/forms/app/types/fields.ts +60 -0
  138. package/layers/forms/app.config.ts +12 -0
  139. package/layers/forms/nuxt.config.ts +17 -0
  140. package/layers/forms/package.json +17 -0
  141. package/layers/forms/tsconfig.json +6 -0
  142. package/layers/layout/.nuxtrc +1 -0
  143. package/layers/layout/CLAUDE.MD +186 -0
  144. package/layers/layout/GRID_SYSTEM.md +993 -0
  145. package/layers/layout/README.md +73 -0
  146. package/layers/layout/app/assets/css/layout/grids.css +180 -0
  147. package/layers/layout/app/assets/css/main.css +1 -0
  148. package/layers/layout/app/components/Layout/Grid/Debug.vue +79 -0
  149. package/layers/layout/app/components/Layout/Grid/Item.vue +180 -0
  150. package/layers/layout/app/components/Layout/Page/Container.vue +100 -0
  151. package/layers/layout/app/components/Layout/Page/Header.vue +33 -0
  152. package/layers/layout/app/components/Layout/Section/Gallery.vue +68 -0
  153. package/layers/layout/app/components/Layout/Section/Hero.vue +71 -0
  154. package/layers/layout/app/components/Layout/Section/Split.vue +56 -0
  155. package/layers/layout/app/components/Layout/Section/index.vue +39 -0
  156. package/layers/layout/app/composables/GridPlacement.ts +31 -0
  157. package/layers/layout/app/composables/useGridConfig.ts +27 -0
  158. package/layers/layout/app/types/layouts.ts +37 -0
  159. package/layers/layout/app.config.ts +97 -0
  160. package/layers/layout/nuxt.config.ts +14 -0
  161. package/layers/layout/package.json +14 -0
  162. package/layers/layout/tailwind.config.js +28 -0
  163. package/layers/layout/tsconfig.json +6 -0
  164. package/layers/motion/README.md +107 -0
  165. package/layers/motion/TASKS.MD +16 -0
  166. package/layers/motion/app/assets/css/main.css +111 -0
  167. package/layers/motion/app/components/Motion/Marquee.vue +171 -0
  168. package/layers/motion/app/components/Motion/Parallax.vue +75 -0
  169. package/layers/motion/app/components/Motion/ScrollLink.vue +49 -0
  170. package/layers/motion/app/components/Motion/ScrollProgress.vue +127 -0
  171. package/layers/motion/app/components/Motion/ScrollStats.vue +102 -0
  172. package/layers/motion/app/components/Motion/Staggered.vue +73 -0
  173. package/layers/motion/app/components/Motion/TextReveal.vue +101 -0
  174. package/layers/motion/app/components/Motion/Transition.vue +89 -0
  175. package/layers/motion/app/components/Motion/VelocityEffect.vue +139 -0
  176. package/layers/motion/app/components/Motion/index.vue +16 -0
  177. package/layers/motion/app/composables/useGsap.ts +21 -0
  178. package/layers/motion/app/composables/useMotion.ts +137 -0
  179. package/layers/motion/app/composables/useSmoothScroll.ts +154 -0
  180. package/layers/motion/app/plugins/gsap.client.ts +15 -0
  181. package/layers/motion/app/plugins/locomotive-scroll.client.ts +49 -0
  182. package/layers/motion/app/utils/gsapAnimations.ts +122 -0
  183. package/layers/motion/app.config.ts +30 -0
  184. package/layers/motion/nuxt.config.ts +19 -0
  185. package/layers/motion/package.json +17 -0
  186. package/layers/motion/tsconfig.json +6 -0
  187. package/layers/shader/AGENTS.MD +195 -0
  188. package/layers/shader/additional-modular-tsl-shaders-for-claude/.prettierignore +6 -0
  189. package/layers/shader/additional-modular-tsl-shaders-for-claude/.prettierrc +18 -0
  190. package/layers/shader/additional-modular-tsl-shaders-for-claude/LICENSE +21 -0
  191. package/layers/shader/additional-modular-tsl-shaders-for-claude/README.md +100 -0
  192. package/layers/shader/additional-modular-tsl-shaders-for-claude/index.html +13 -0
  193. package/layers/shader/additional-modular-tsl-shaders-for-claude/jsconfig.json +30 -0
  194. package/layers/shader/additional-modular-tsl-shaders-for-claude/package.json +18 -0
  195. package/layers/shader/additional-modular-tsl-shaders-for-claude/pnpm-lock.yaml +633 -0
  196. package/layers/shader/additional-modular-tsl-shaders-for-claude/public/vite.svg +1 -0
  197. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/components/sketch/webgpu_sketch.js +128 -0
  198. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/components/sketches_dropdown/index.css +87 -0
  199. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/components/sketches_dropdown/sketches_dropdown.js +169 -0
  200. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/index.css +25 -0
  201. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/main.js +93 -0
  202. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/router.js +43 -0
  203. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/sketches/flare-1.js +68 -0
  204. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/sketches/noise/dawn-1.js +56 -0
  205. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/distortion/bulge_distortion.js +35 -0
  206. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/distortion/swirl_distortion.js +35 -0
  207. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/distortion/wave_distortion.js +43 -0
  208. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/noise/common.js +145 -0
  209. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/noise/curl_noise_3d.js +53 -0
  210. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/noise/curl_noise_4d.js +55 -0
  211. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/noise/fbm.js +163 -0
  212. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/noise/perlin_noise_3d.js +70 -0
  213. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/noise/simplex_noise_3d.js +59 -0
  214. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/noise/simplex_noise_4d.js +72 -0
  215. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/noise/turbulence.js +41 -0
  216. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/patterns/canvas_weave_pattern.js +26 -0
  217. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/patterns/grain_texture_pattern.js +10 -0
  218. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/patterns/led_pattern.js +45 -0
  219. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/patterns/pixellation_pattern.js +15 -0
  220. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/patterns/speckled_noise_pattern.js +34 -0
  221. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/patterns/vignette_pattern.js +21 -0
  222. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/bulge_distortion_effect.js +27 -0
  223. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/chromatic_aberration_effect.js +45 -0
  224. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/crt_scanline_effect.js +45 -0
  225. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/dither_effect.js +126 -0
  226. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/grain_texture_effect.js +21 -0
  227. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/halftone_effect.js +44 -0
  228. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/led_effect.js +31 -0
  229. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/pixellation_effect.js +29 -0
  230. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/swirl_distortion_effect.js +25 -0
  231. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/vignette_effect.js +22 -0
  232. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/wave_distortion_effect.js +27 -0
  233. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/color/cosine_palette.js +15 -0
  234. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/color/tonemapping.js +151 -0
  235. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/function/bloom.js +13 -0
  236. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/function/bloom_edge_pattern.js +20 -0
  237. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/function/domain_index.js +11 -0
  238. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/function/median3.js +22 -0
  239. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/function/repeating_pattern.js +13 -0
  240. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/function/screen_aspect_uv.js +14 -0
  241. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/lighting.js +60 -0
  242. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/math/complex.js +86 -0
  243. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/math/coordinates.js +119 -0
  244. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/sdf/operations.js +24 -0
  245. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/sdf/shapes.js +182 -0
  246. package/layers/shader/additional-modular-tsl-shaders-for-claude/src/utils/math.js +33 -0
  247. package/layers/shader/additional-modular-tsl-shaders-for-claude/vite.config.js +23 -0
  248. package/layers/shader/app/assets/css/main.css +41 -0
  249. package/layers/shader/app/components/Effect/Bloom.vue +8 -0
  250. package/layers/shader/app/components/Effect/ChromaticAberration.vue +8 -0
  251. package/layers/shader/app/components/Effect/PostProcessing.vue +20 -0
  252. package/layers/shader/app/components/Material/AmbientAurora.vue +172 -0
  253. package/layers/shader/app/components/Material/AmbientFlow.vue +175 -0
  254. package/layers/shader/app/components/Material/AmbientGradientMesh.vue +173 -0
  255. package/layers/shader/app/components/Material/AmbientNebula.vue +181 -0
  256. package/layers/shader/app/components/Material/AmbientOcean.vue +161 -0
  257. package/layers/shader/app/components/Material/Fresnel.vue +89 -0
  258. package/layers/shader/app/components/Material/Gradient.vue +185 -0
  259. package/layers/shader/app/components/Material/Image.vue +232 -0
  260. package/layers/shader/app/components/Material/Node.vue +79 -0
  261. package/layers/shader/app/components/Material/Noise.vue +141 -0
  262. package/layers/shader/app/components/Mesh/Plane.vue +27 -0
  263. package/layers/shader/app/components/Shader/Background.vue +159 -0
  264. package/layers/shader/app/components/Shader/Canvas.vue +97 -0
  265. package/layers/shader/app/components/Shader/Debug.vue +66 -0
  266. package/layers/shader/app/components/WebGPUCanvas.client.vue +245 -0
  267. package/layers/shader/app/composables/useAmbientMaterials.ts +452 -0
  268. package/layers/shader/app/composables/useMousePosition.ts +94 -0
  269. package/layers/shader/app/composables/useRendererCapabilities.ts +111 -0
  270. package/layers/shader/app/composables/useShader.ts +148 -0
  271. package/layers/shader/app/composables/useShaderTime.ts +146 -0
  272. package/layers/shader/app/composables/useTSLNodes.ts +112 -0
  273. package/layers/shader/app/composables/useUniforms.ts +188 -0
  274. package/layers/shader/app/plugins/shader.client.ts +30 -0
  275. package/layers/shader/app/shaders/common/blend.ts +255 -0
  276. package/layers/shader/app/shaders/common/effects.ts +299 -0
  277. package/layers/shader/app/shaders/common/grain.ts +453 -0
  278. package/layers/shader/app/shaders/common/index.ts +22 -0
  279. package/layers/shader/app/shaders/common/lighting.ts +146 -0
  280. package/layers/shader/app/shaders/common/math.ts +250 -0
  281. package/layers/shader/app/shaders/common/noise.ts +823 -0
  282. package/layers/shader/app/shaders/common/noiseHelpers.ts +114 -0
  283. package/layers/shader/app/shaders/common/palette.ts +319 -0
  284. package/layers/shader/app/shaders/common/patterns.ts +216 -0
  285. package/layers/shader/app/shaders/common/sdf.ts +224 -0
  286. package/layers/shader/app/shaders/common/shapes.ts +366 -0
  287. package/layers/shader/app/shaders/common/tonemapping.ts +172 -0
  288. package/layers/shader/app/shaders/common/uv.ts +396 -0
  289. package/layers/shader/app/shaders/createMaterial.ts +314 -0
  290. package/layers/shader/app/shaders/index.ts +282 -0
  291. package/layers/shader/app/shaders/layers/aurora.ts +146 -0
  292. package/layers/shader/app/shaders/layers/index.ts +19 -0
  293. package/layers/shader/app/shaders/layers/meshGradient.ts +152 -0
  294. package/layers/shader/app/shaders/layers/paperShading.ts +148 -0
  295. package/layers/shader/app/shaders/layers/shaderGradient.ts +152 -0
  296. package/layers/shader/app/shaders/layers/stripe.ts +137 -0
  297. package/layers/shader/app/shaders/types.ts +12 -0
  298. package/layers/shader/app/types/index.ts +4 -0
  299. package/layers/shader/app/types/materials.ts +45 -0
  300. package/layers/shader/app/types/renderer.ts +50 -0
  301. package/layers/shader/app/types/tsl.ts +39 -0
  302. package/layers/shader/app/types/uniforms.ts +21 -0
  303. package/layers/shader/app/utils/tsl/animation.ts +251 -0
  304. package/layers/shader/app/utils/tsl/color.ts +189 -0
  305. package/layers/shader/app/utils/tsl/index.ts +84 -0
  306. package/layers/shader/app/utils/tsl/math.ts +111 -0
  307. package/layers/shader/app/utils/tsl/noise.ts +195 -0
  308. package/layers/shader/app/utils/tsl/patterns.ts +183 -0
  309. package/layers/shader/app/utils/tsl/uv.ts +145 -0
  310. package/layers/shader/app.config.ts +18 -0
  311. package/layers/shader/modular-tsl-shaders-for-claude/common/blend.tsl +1 -0
  312. package/layers/shader/modular-tsl-shaders-for-claude/common/noise.tsl +1 -0
  313. package/layers/shader/modular-tsl-shaders-for-claude/common/shapes.tsl +1 -0
  314. package/layers/shader/modular-tsl-shaders-for-claude/common/vertexFresnel.tsl +9 -0
  315. package/layers/shader/modular-tsl-shaders-for-claude/common/vertexPlane.tsl +6 -0
  316. package/layers/shader/modular-tsl-shaders-for-claude/effects/background.tsl +1 -0
  317. package/layers/shader/modular-tsl-shaders-for-claude/effects/gradient.tsl +1 -0
  318. package/layers/shader/modular-tsl-shaders-for-claude/effects/gradientLegend.tsl +1 -0
  319. package/layers/shader/modular-tsl-shaders-for-claude/effects/simpleGradient.tsl +1 -0
  320. package/layers/shader/modular-tsl-shaders-for-claude/layers/aurora.ts +1 -0
  321. package/layers/shader/modular-tsl-shaders-for-claude/layers/fragmentsTech.ts +1 -0
  322. package/layers/shader/modular-tsl-shaders-for-claude/layers/fresnel.ts +1 -0
  323. package/layers/shader/modular-tsl-shaders-for-claude/layers/linearGradient.ts +1 -0
  324. package/layers/shader/modular-tsl-shaders-for-claude/layers/meshGradient.ts +1 -0
  325. package/layers/shader/modular-tsl-shaders-for-claude/layers/noise.ts +1 -0
  326. package/layers/shader/modular-tsl-shaders-for-claude/layers/paperShading.ts +1 -0
  327. package/layers/shader/modular-tsl-shaders-for-claude/layers/radial.ts +1 -0
  328. package/layers/shader/modular-tsl-shaders-for-claude/layers/shaderGradient.ts +1 -0
  329. package/layers/shader/modular-tsl-shaders-for-claude/layers/stripe.ts +1 -0
  330. package/layers/shader/modular-tsl-shaders-for-claude/materials/createMaterial.ts +1 -0
  331. package/layers/shader/modular-tsl-shaders-for-claude/utils/glslUtils.ts +1 -0
  332. package/layers/shader/modular-tsl-shaders-for-claude/utils/palette.ts +1 -0
  333. package/layers/shader/nuxt.config.ts +48 -0
  334. package/layers/shader/package.json +17 -0
  335. package/layers/shader/tsconfig.json +6 -0
  336. package/layers/theme/app/assets/css/theme.css +47 -0
  337. package/layers/theme/app/components/ThemePicker/AccentButton.vue +51 -0
  338. package/layers/theme/app/components/ThemePicker/Colors.vue +22 -0
  339. package/layers/theme/app/components/ThemePicker/Menu.vue +108 -0
  340. package/layers/theme/app/components/ThemePicker/MenuButton.vue +9 -0
  341. package/layers/theme/app/composables/useThemePreferences.ts +158 -0
  342. package/layers/theme/app/plugins/theme.client.ts +5 -0
  343. package/layers/theme/app/types/theme.ts +34 -0
  344. package/layers/theme/app.config.ts +14 -0
  345. package/layers/theme/nuxt.config.ts +46 -0
  346. package/layers/theme/package.json +14 -0
  347. package/layers/theme/server/plugins/theme-fouc.ts +51 -0
  348. package/layers/theme/tsconfig.json +7 -0
  349. package/layers/ui/CLAUDE.MD +325 -0
  350. package/layers/ui/app/assets/css/main.css +4 -0
  351. package/layers/ui/app/components/Links/Group.vue +38 -0
  352. package/layers/ui/app/components/Links/Named.vue +32 -0
  353. package/layers/ui/app/components/Media/Picture.vue +41 -0
  354. package/layers/ui/app/components/Site/Title.vue +15 -0
  355. package/layers/ui/app/components/Typography/CodeBlock.vue +37 -0
  356. package/layers/ui/app/components/Typography/Headline.vue +73 -0
  357. package/layers/ui/app/components/Typography/QuoteBlock.vue +13 -0
  358. package/layers/ui/app/components/Typography/TextStroke.vue +109 -0
  359. package/layers/ui/app/components/Typography/index.vue +49 -0
  360. package/layers/ui/app/composables/color.ts +36 -0
  361. package/layers/ui/app/composables/picture.ts +145 -0
  362. package/layers/ui/app/composables/typography.ts +77 -0
  363. package/layers/ui/app/layouts/default.vue +4 -0
  364. package/layers/ui/app/pages/index.vue +236 -0
  365. package/layers/ui/app/types/breakpoints.ts +179 -0
  366. package/layers/ui/app/types/colors.ts +29 -0
  367. package/layers/ui/app/types/media.ts +185 -0
  368. package/layers/ui/app/types/typography.ts +108 -0
  369. package/layers/ui/app/utils/regex.ts +6 -0
  370. package/layers/ui/app.config.ts +12 -0
  371. package/layers/ui/nuxt.config.ts +38 -0
  372. package/layers/ui/package.json +14 -0
  373. package/layers/ui/tsconfig.json +6 -0
  374. package/package.json +128 -0
  375. package/playgroundOLD/app.config.ts +5 -0
  376. package/playgroundOLD/nuxt.config.ts +12 -0
  377. package/pnpm-workspace.yaml +6 -0
  378. package/prettier.config.cjs +19 -0
  379. package/stylelint.config.mjs +111 -0
  380. package/turbo.json +16 -0
@@ -0,0 +1,453 @@
1
+ // @ts-nocheck - TSL types are complex and not fully exported from three/tsl
2
+ /**
3
+ * Modular TSL Grain & Film Effects
4
+ * Provides composable grain and texture overlay functions
5
+ */
6
+ import { clamp, dot, float, floor, fract, mix, sin, smoothstep, vec2, vec3 } from 'three/tsl'
7
+ import type { TSLNode } from '../types'
8
+
9
+ // ============================================
10
+ // Basic Grain
11
+ // ============================================
12
+
13
+ /**
14
+ * Simple film grain
15
+ */
16
+ export function grain(
17
+ uv: TSLNode,
18
+ intensity: TSLNode | number = 0.1,
19
+ seed: TSLNode | number = 0
20
+ ): TSLNode {
21
+ const int = typeof intensity === 'number' ? float(intensity) : intensity
22
+ const s = typeof seed === 'number' ? float(seed) : seed
23
+
24
+ const noise = fract(sin(dot(uv.add(s), vec2(12.9898, 78.233))).mul(43758.5453))
25
+ return noise.sub(0.5).mul(int)
26
+ }
27
+
28
+ /**
29
+ * Animated film grain
30
+ */
31
+ export function animatedGrain(
32
+ uv: TSLNode,
33
+ time: TSLNode,
34
+ intensity: TSLNode | number = 0.1,
35
+ speed: TSLNode | number = 1
36
+ ): TSLNode {
37
+ const int = typeof intensity === 'number' ? float(intensity) : intensity
38
+ const spd = typeof speed === 'number' ? float(speed) : speed
39
+
40
+ // Use time as seed for animation
41
+ const seed = floor(time.mul(spd).mul(24)) // 24 fps grain
42
+ return grain(uv, int, seed)
43
+ }
44
+
45
+ /**
46
+ * Colored film grain (RGB noise)
47
+ */
48
+ export function coloredGrain(
49
+ uv: TSLNode,
50
+ intensity: TSLNode | number = 0.1,
51
+ seed: TSLNode | number = 0
52
+ ): TSLNode {
53
+ const int = typeof intensity === 'number' ? float(intensity) : intensity
54
+ const s = typeof seed === 'number' ? float(seed) : seed
55
+
56
+ const r = grain(uv, int, s)
57
+ const g = grain(uv.add(vec2(1.0, 0.0)), int, s)
58
+ const b = grain(uv.add(vec2(0.0, 1.0)), int, s)
59
+
60
+ return vec3(r, g, b)
61
+ }
62
+
63
+ // ============================================
64
+ // Dithering
65
+ // ============================================
66
+
67
+ /**
68
+ * Bayer 2x2 dithering matrix
69
+ */
70
+ export function bayer2x2(uv: TSLNode, scale: TSLNode | number = 1): TSLNode {
71
+ const s = typeof scale === 'number' ? float(scale) : scale
72
+ const pos = floor(uv.mul(s)).mod(2)
73
+ const matrix = vec2(0.25, 0.75)
74
+ return mix(mix(matrix.x, matrix.y, pos.x), mix(matrix.y, matrix.x, pos.x), pos.y)
75
+ }
76
+
77
+ /**
78
+ * Bayer 4x4 dithering (simplified)
79
+ */
80
+ export function bayer4x4(uv: TSLNode, scale: TSLNode | number = 1): TSLNode {
81
+ const s = typeof scale === 'number' ? float(scale) : scale
82
+ const pos = floor(uv.mul(s)).mod(4)
83
+
84
+ // Simplified 4x4 Bayer matrix approximation
85
+ const bayer2 = bayer2x2(uv, s)
86
+ const offset = bayer2x2(uv.mul(0.5), s).mul(0.25)
87
+
88
+ return bayer2.add(offset).sub(0.5)
89
+ }
90
+
91
+ /**
92
+ * Apply dithering to color
93
+ */
94
+ export function ditherColor(
95
+ color: TSLNode,
96
+ uv: TSLNode,
97
+ levels: TSLNode | number = 16,
98
+ strength: TSLNode | number = 1
99
+ ): TSLNode {
100
+ const lvl = typeof levels === 'number' ? float(levels) : levels
101
+ const str = typeof strength === 'number' ? float(strength) : strength
102
+
103
+ const threshold = bayer4x4(uv, 4).mul(str).div(lvl)
104
+ const dithered = floor(color.mul(lvl).add(threshold)).div(lvl)
105
+
106
+ return clamp(dithered, 0, 1)
107
+ }
108
+
109
+ // ============================================
110
+ // Scanlines
111
+ // ============================================
112
+
113
+ /**
114
+ * CRT scanlines
115
+ */
116
+ export function scanlines(
117
+ uv: TSLNode,
118
+ density: TSLNode | number = 400,
119
+ intensity: TSLNode | number = 0.25,
120
+ offset: TSLNode | number = 0
121
+ ): TSLNode {
122
+ const d = typeof density === 'number' ? float(density) : density
123
+ const int = typeof intensity === 'number' ? float(intensity) : intensity
124
+ const off = typeof offset === 'number' ? float(offset) : offset
125
+
126
+ const line = sin(uv.y.add(off).mul(d).mul(Math.PI)).mul(0.5).add(0.5)
127
+ return float(1).sub(line.mul(int))
128
+ }
129
+
130
+ /**
131
+ * Interlaced scanlines (every other line)
132
+ */
133
+ export function interlace(
134
+ uv: TSLNode,
135
+ density: TSLNode | number = 400,
136
+ intensity: TSLNode | number = 0.5,
137
+ frame: TSLNode | number = 0
138
+ ): TSLNode {
139
+ const d = typeof density === 'number' ? float(density) : density
140
+ const int = typeof intensity === 'number' ? float(intensity) : intensity
141
+ const f = typeof frame === 'number' ? float(frame) : frame
142
+
143
+ const line = floor(uv.y.mul(d)).add(f).mod(2)
144
+ return float(1).sub(line.mul(int))
145
+ }
146
+
147
+ // ============================================
148
+ // Vignette
149
+ // ============================================
150
+
151
+ /**
152
+ * Circular vignette
153
+ */
154
+ export function vignette(
155
+ uv: TSLNode,
156
+ intensity: TSLNode | number = 0.5,
157
+ smoothness: TSLNode | number = 0.5,
158
+ roundness: TSLNode | number = 1
159
+ ): TSLNode {
160
+ const int = typeof intensity === 'number' ? float(intensity) : intensity
161
+ const smooth = typeof smoothness === 'number' ? float(smoothness) : smoothness
162
+ const round = typeof roundness === 'number' ? float(roundness) : roundness
163
+
164
+ const center = uv.sub(0.5)
165
+ const dist = center.length().mul(round)
166
+
167
+ return float(1).sub(smoothstep(float(1).sub(smooth), float(1), dist.mul(int.mul(2))))
168
+ }
169
+
170
+ /**
171
+ * Rectangular vignette
172
+ */
173
+ export function rectVignette(
174
+ uv: TSLNode,
175
+ intensity: TSLNode | number = 0.5,
176
+ smoothness: TSLNode | number = 0.3
177
+ ): TSLNode {
178
+ const int = typeof intensity === 'number' ? float(intensity) : intensity
179
+ const smooth = typeof smoothness === 'number' ? float(smoothness) : smoothness
180
+
181
+ const distX = smoothstep(0, smooth, uv.x).mul(smoothstep(0, smooth, float(1).sub(uv.x)))
182
+ const distY = smoothstep(0, smooth, uv.y).mul(smoothstep(0, smooth, float(1).sub(uv.y)))
183
+
184
+ return mix(float(1), distX.mul(distY), int)
185
+ }
186
+
187
+ // ============================================
188
+ // Paper / Texture Effects
189
+ // ============================================
190
+
191
+ /**
192
+ * Paper texture noise
193
+ */
194
+ export function paperTexture(
195
+ uv: TSLNode,
196
+ scale: TSLNode | number = 10,
197
+ intensity: TSLNode | number = 0.1,
198
+ seed: TSLNode | number = 0
199
+ ): TSLNode {
200
+ const s = typeof scale === 'number' ? float(scale) : scale
201
+ const int = typeof intensity === 'number' ? float(intensity) : intensity
202
+ const sd = typeof seed === 'number' ? float(seed) : seed
203
+
204
+ // Multi-octave noise for paper texture
205
+ const noise1 = grain(uv.mul(s), 1, sd)
206
+ const noise2 = grain(uv.mul(s.mul(2)), 0.5, sd.add(1))
207
+ const noise3 = grain(uv.mul(s.mul(4)), 0.25, sd.add(2))
208
+
209
+ return noise1.add(noise2).add(noise3).mul(int)
210
+ }
211
+
212
+ /**
213
+ * Halftone dot pattern
214
+ */
215
+ export function halftone(
216
+ uv: TSLNode,
217
+ value: TSLNode,
218
+ scale: TSLNode | number = 50,
219
+ angle: TSLNode | number = 0
220
+ ): TSLNode {
221
+ const s = typeof scale === 'number' ? float(scale) : scale
222
+ const a = typeof angle === 'number' ? float(angle) : angle
223
+
224
+ // Rotate UV
225
+ const cosA = a.cos()
226
+ const sinA = a.sin()
227
+ const rotatedUV = vec2(uv.x.mul(cosA).sub(uv.y.mul(sinA)), uv.x.mul(sinA).add(uv.y.mul(cosA)))
228
+
229
+ const scaledUV = rotatedUV.mul(s)
230
+ const center = fract(scaledUV).sub(0.5)
231
+ const dist = center.length()
232
+
233
+ // Dot size based on value
234
+ const dotSize = value.mul(0.5)
235
+
236
+ return smoothstep(dotSize.add(0.01), dotSize.sub(0.01), dist)
237
+ }
238
+
239
+ // ============================================
240
+ // Apply Effects to Color
241
+ // ============================================
242
+
243
+ /**
244
+ * Apply grain to color
245
+ */
246
+ export function applyGrain(
247
+ color: TSLNode,
248
+ uv: TSLNode,
249
+ intensity: TSLNode | number = 0.05,
250
+ seed: TSLNode | number = 0
251
+ ): TSLNode {
252
+ const grainValue = grain(uv, intensity, seed)
253
+ return clamp(color.add(grainValue), 0, 1)
254
+ }
255
+
256
+ /**
257
+ * Apply colored grain to color
258
+ */
259
+ export function applyColoredGrain(
260
+ color: TSLNode,
261
+ uv: TSLNode,
262
+ intensity: TSLNode | number = 0.05,
263
+ seed: TSLNode | number = 0
264
+ ): TSLNode {
265
+ const grainValue = coloredGrain(uv, intensity, seed)
266
+ return clamp(color.add(grainValue), 0, 1)
267
+ }
268
+
269
+ /**
270
+ * Apply vignette to color
271
+ */
272
+ export function applyVignette(
273
+ color: TSLNode,
274
+ uv: TSLNode,
275
+ intensity: TSLNode | number = 0.5
276
+ ): TSLNode {
277
+ const vignetteValue = vignette(uv, intensity)
278
+ return color.mul(vignetteValue)
279
+ }
280
+
281
+ /**
282
+ * Apply scanlines to color
283
+ */
284
+ export function applyScanlines(
285
+ color: TSLNode,
286
+ uv: TSLNode,
287
+ density: TSLNode | number = 400,
288
+ intensity: TSLNode | number = 0.25
289
+ ): TSLNode {
290
+ const scanlineValue = scanlines(uv, density, intensity)
291
+ return color.mul(scanlineValue)
292
+ }
293
+
294
+ /**
295
+ * Full CRT effect (scanlines + vignette + grain)
296
+ */
297
+ export function crtEffect(
298
+ color: TSLNode,
299
+ uv: TSLNode,
300
+ options: {
301
+ scanlinesDensity?: number
302
+ scanlinesIntensity?: number
303
+ vignetteIntensity?: number
304
+ grainIntensity?: number
305
+ grainSeed?: TSLNode | number
306
+ } = {}
307
+ ): TSLNode {
308
+ const {
309
+ scanlinesDensity = 300,
310
+ scanlinesIntensity = 0.15,
311
+ vignetteIntensity = 0.4,
312
+ grainIntensity = 0.03,
313
+ grainSeed = 0,
314
+ } = options
315
+
316
+ let result = color
317
+
318
+ // Apply scanlines
319
+ result = applyScanlines(result, uv, scanlinesDensity, scanlinesIntensity)
320
+
321
+ // Apply vignette
322
+ result = applyVignette(result, uv, vignetteIntensity)
323
+
324
+ // Apply grain
325
+ result = applyGrain(result, uv, grainIntensity, grainSeed)
326
+
327
+ return result
328
+ }
329
+
330
+ // ============================================
331
+ // 8x8 Bayer Dithering
332
+ // ============================================
333
+
334
+ // 8x8 Bayer matrix values (normalized to 0-1 range)
335
+ const BAYER_8X8_MATRIX = [
336
+ 0.0 / 64.0,
337
+ 48.0 / 64.0,
338
+ 12.0 / 64.0,
339
+ 60.0 / 64.0,
340
+ 3.0 / 64.0,
341
+ 51.0 / 64.0,
342
+ 15.0 / 64.0,
343
+ 63.0 / 64.0,
344
+ 32.0 / 64.0,
345
+ 16.0 / 64.0,
346
+ 44.0 / 64.0,
347
+ 28.0 / 64.0,
348
+ 35.0 / 64.0,
349
+ 19.0 / 64.0,
350
+ 47.0 / 64.0,
351
+ 31.0 / 64.0,
352
+ 8.0 / 64.0,
353
+ 56.0 / 64.0,
354
+ 4.0 / 64.0,
355
+ 52.0 / 64.0,
356
+ 11.0 / 64.0,
357
+ 59.0 / 64.0,
358
+ 7.0 / 64.0,
359
+ 55.0 / 64.0,
360
+ 40.0 / 64.0,
361
+ 24.0 / 64.0,
362
+ 36.0 / 64.0,
363
+ 20.0 / 64.0,
364
+ 43.0 / 64.0,
365
+ 27.0 / 64.0,
366
+ 39.0 / 64.0,
367
+ 23.0 / 64.0,
368
+ 2.0 / 64.0,
369
+ 50.0 / 64.0,
370
+ 14.0 / 64.0,
371
+ 62.0 / 64.0,
372
+ 1.0 / 64.0,
373
+ 49.0 / 64.0,
374
+ 13.0 / 64.0,
375
+ 61.0 / 64.0,
376
+ 34.0 / 64.0,
377
+ 18.0 / 64.0,
378
+ 46.0 / 64.0,
379
+ 30.0 / 64.0,
380
+ 33.0 / 64.0,
381
+ 17.0 / 64.0,
382
+ 45.0 / 64.0,
383
+ 29.0 / 64.0,
384
+ 10.0 / 64.0,
385
+ 58.0 / 64.0,
386
+ 6.0 / 64.0,
387
+ 54.0 / 64.0,
388
+ 9.0 / 64.0,
389
+ 57.0 / 64.0,
390
+ 5.0 / 64.0,
391
+ 53.0 / 64.0,
392
+ 42.0 / 64.0,
393
+ 26.0 / 64.0,
394
+ 38.0 / 64.0,
395
+ 22.0 / 64.0,
396
+ 41.0 / 64.0,
397
+ 25.0 / 64.0,
398
+ 37.0 / 64.0,
399
+ 21.0 / 64.0,
400
+ ]
401
+
402
+ /**
403
+ * Get value from 8x8 Bayer matrix at given coordinates
404
+ * Used for ordered dithering
405
+ */
406
+ function getBayer8x8Value(x: TSLNode, y: TSLNode): TSLNode {
407
+ const index = y.mul(8).add(x).toVar()
408
+ const value = float(0.0).toVar()
409
+
410
+ // Unroll array lookup using conditionals
411
+ for (let i = 0; i < 64; i++) {
412
+ value.assign(mix(value, float(BAYER_8X8_MATRIX[i]), index.equal(i)))
413
+ }
414
+
415
+ return value
416
+ }
417
+
418
+ /**
419
+ * 8x8 Bayer dithering matrix
420
+ * Higher quality than 4x4, better gradient reproduction
421
+ * @param uv - UV coordinates
422
+ * @param scale - Scale of the dithering pattern
423
+ */
424
+ export function bayer8x8(uv: TSLNode, scale: TSLNode | number = 1): TSLNode {
425
+ const s = typeof scale === 'number' ? float(scale) : scale
426
+ const pos = floor(uv.mul(s)).mod(8)
427
+ return getBayer8x8Value(pos.x, pos.y)
428
+ }
429
+
430
+ /**
431
+ * Apply 8x8 dithering to color
432
+ * @param color - Input color
433
+ * @param uv - UV coordinates
434
+ * @param levels - Number of color levels per channel
435
+ * @param strength - Dithering strength
436
+ * @param bias - Bias offset for threshold
437
+ */
438
+ export function dither8x8Color(
439
+ color: TSLNode,
440
+ uv: TSLNode,
441
+ levels: TSLNode | number = 16,
442
+ strength: TSLNode | number = 1,
443
+ bias: TSLNode | number = 0.5
444
+ ): TSLNode {
445
+ const lvl = typeof levels === 'number' ? float(levels) : levels
446
+ const str = typeof strength === 'number' ? float(strength) : strength
447
+ const b = typeof bias === 'number' ? float(bias) : bias
448
+
449
+ const threshold = bayer8x8(uv, 8).sub(b).mul(str).div(lvl)
450
+ const dithered = floor(color.mul(lvl).add(threshold)).div(lvl)
451
+
452
+ return clamp(dithered, 0, 1)
453
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Common TSL Shader Utilities
3
+ * Re-exports all common utilities for easy importing
4
+ */
5
+
6
+ // Noise utilities
7
+ export * from './noise'
8
+
9
+ // Shape utilities
10
+ export * from './shapes'
11
+
12
+ // Color blending
13
+ export * from './blend'
14
+
15
+ // Color palettes
16
+ export * from './palette'
17
+
18
+ // Grain and film effects
19
+ export * from './grain'
20
+
21
+ // UV manipulation
22
+ export * from './uv'
@@ -0,0 +1,146 @@
1
+ // @ts-nocheck - TSL types are complex and not fully exported from three/tsl
2
+ /**
3
+ * Modular TSL Lighting Utilities
4
+ * Provides common lighting models for shader effects
5
+ */
6
+ import { dot, float, max, mix, normalize, pow, reflect, vec3 } from 'three/tsl'
7
+ import type { TSLNode } from '../types'
8
+
9
+ // ============================================
10
+ // Fresnel Effect
11
+ // ============================================
12
+
13
+ /**
14
+ * Fresnel effect (rim lighting)
15
+ * Returns higher values at grazing angles
16
+ * @param viewDir - View direction vector (normalized)
17
+ * @param normal - Surface normal vector (normalized)
18
+ * @param exponent - Fresnel exponent (higher = sharper falloff)
19
+ */
20
+ export function fresnel(
21
+ viewDir: TSLNode,
22
+ normal: TSLNode,
23
+ exponent: TSLNode | number = 2
24
+ ): TSLNode {
25
+ const p = typeof exponent === 'number' ? float(exponent) : exponent
26
+ return float(1)
27
+ .sub(max(0, dot(viewDir, normal)))
28
+ .pow(p)
29
+ }
30
+
31
+ // ============================================
32
+ // Hemispheric Lighting
33
+ // ============================================
34
+
35
+ /**
36
+ * Hemispheric ambient lighting
37
+ * Blends between ground and sky colors based on surface normal
38
+ * @param normal - Surface normal vector
39
+ * @param groundColor - Color from below (ground)
40
+ * @param skyColor - Color from above (sky)
41
+ */
42
+ export function hemi(normal: TSLNode, groundColor: TSLNode, skyColor: TSLNode): TSLNode {
43
+ const hemiMix = normal.y.mul(0.5).add(0.5)
44
+ return mix(groundColor, skyColor, hemiMix)
45
+ }
46
+
47
+ // ============================================
48
+ // Diffuse Lighting
49
+ // ============================================
50
+
51
+ /**
52
+ * Lambertian diffuse lighting
53
+ * @param lightDir - Light direction vector (normalized, pointing toward light)
54
+ * @param normal - Surface normal vector (normalized)
55
+ * @param lightColor - Light color
56
+ */
57
+ export function diffuse(lightDir: TSLNode, normal: TSLNode, lightColor: TSLNode): TSLNode {
58
+ const dp = max(0, dot(lightDir, normal))
59
+ return dp.mul(lightColor)
60
+ }
61
+
62
+ // ============================================
63
+ // Phong Specular
64
+ // ============================================
65
+
66
+ /**
67
+ * Phong specular highlights
68
+ * @param viewDir - View direction vector (normalized)
69
+ * @param normal - Surface normal vector (normalized)
70
+ * @param lightDir - Light direction vector (normalized, pointing toward light)
71
+ * @param shininess - Phong exponent (higher = smaller, sharper highlights)
72
+ */
73
+ export function phongSpecular(
74
+ viewDir: TSLNode,
75
+ normal: TSLNode,
76
+ lightDir: TSLNode,
77
+ shininess: TSLNode | number = 32
78
+ ): TSLNode {
79
+ const p = typeof shininess === 'number' ? float(shininess) : shininess
80
+ const reflectDir = normalize(reflect(lightDir.negate(), normal))
81
+ const phongValue = max(0, dot(viewDir, reflectDir)).pow(p)
82
+ return vec3(phongValue)
83
+ }
84
+
85
+ // ============================================
86
+ // Blinn-Phong Specular
87
+ // ============================================
88
+
89
+ /**
90
+ * Blinn-Phong specular highlights
91
+ * More physically accurate than standard Phong
92
+ * @param viewDir - View direction vector (normalized)
93
+ * @param normal - Surface normal vector (normalized)
94
+ * @param lightDir - Light direction vector (normalized, pointing toward light)
95
+ * @param shininess - Shininess exponent
96
+ */
97
+ export function blinnPhongSpecular(
98
+ viewDir: TSLNode,
99
+ normal: TSLNode,
100
+ lightDir: TSLNode,
101
+ shininess: TSLNode | number = 32
102
+ ): TSLNode {
103
+ const p = typeof shininess === 'number' ? float(shininess) : shininess
104
+ const halfDir = normalize(lightDir.add(viewDir))
105
+ const specAngle = max(0, dot(halfDir, normal))
106
+ return vec3(pow(specAngle, p))
107
+ }
108
+
109
+ // ============================================
110
+ // Combined Lighting
111
+ // ============================================
112
+
113
+ export interface LightingOptions {
114
+ ambient?: TSLNode | number
115
+ diffuseStrength?: TSLNode | number
116
+ specularStrength?: TSLNode | number
117
+ shininess?: TSLNode | number
118
+ }
119
+
120
+ /**
121
+ * Combined Phong lighting model
122
+ * @param viewDir - View direction vector
123
+ * @param normal - Surface normal vector
124
+ * @param lightDir - Light direction vector
125
+ * @param lightColor - Light color
126
+ * @param options - Lighting parameters
127
+ */
128
+ export function phongLighting(
129
+ viewDir: TSLNode,
130
+ normal: TSLNode,
131
+ lightDir: TSLNode,
132
+ lightColor: TSLNode,
133
+ options: LightingOptions = {}
134
+ ): TSLNode {
135
+ const { ambient = 0.1, diffuseStrength = 1.0, specularStrength = 0.5, shininess = 32 } = options
136
+
137
+ const ambientVal = typeof ambient === 'number' ? float(ambient) : ambient
138
+ const diffStr = typeof diffuseStrength === 'number' ? float(diffuseStrength) : diffuseStrength
139
+ const specStr = typeof specularStrength === 'number' ? float(specularStrength) : specularStrength
140
+
141
+ const ambientLight = lightColor.mul(ambientVal)
142
+ const diffuseLight = diffuse(lightDir, normal, lightColor).mul(diffStr)
143
+ const specularLight = phongSpecular(viewDir, normal, lightDir, shininess).mul(specStr)
144
+
145
+ return ambientLight.add(diffuseLight).add(specularLight)
146
+ }