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.
- package/.claude/rules/nuxt-layers.md +23 -0
- package/.claude/rules/typescript.md +16 -0
- package/.claude/rules/vue-components.md +34 -0
- package/.claude/settings.local.json +81 -0
- package/.editorconfig +27 -0
- package/.github/workflows/npm-publish.yml +33 -0
- package/.oxlintrc.json +10 -0
- package/.prettierignore +87 -0
- package/CLAUDE.md +71 -0
- package/apps/playground/README.md +75 -0
- package/apps/playground/app/app.config.ts +10 -0
- package/apps/playground/app/app.vue +12 -0
- package/apps/playground/app/components/AmbientBackground.client.vue +795 -0
- package/apps/playground/app/components/ShaderDemoCanvas.client.vue +636 -0
- package/apps/playground/app/components/ShaderImageDemo.client.vue +211 -0
- package/apps/playground/app/pages/ambient.vue +387 -0
- package/apps/playground/app/pages/content.vue +200 -0
- package/apps/playground/app/pages/core.vue +560 -0
- package/apps/playground/app/pages/forms.vue +645 -0
- package/apps/playground/app/pages/index.vue +257 -0
- package/apps/playground/app/pages/layout.vue +591 -0
- package/apps/playground/app/pages/locomotive-scroll.vue +738 -0
- package/apps/playground/app/pages/motion.vue +848 -0
- package/apps/playground/app/pages/shader.vue +1701 -0
- package/apps/playground/app/pages/theme.vue +115 -0
- package/apps/playground/app/pages/ui.vue +656 -0
- package/apps/playground/content/blog/hello-world.md +127 -0
- package/apps/playground/content/blog/second-post.md +99 -0
- package/apps/playground/content/blog/third-post.md +33 -0
- package/apps/playground/content/gallery/autumn-collection.md +57 -0
- package/apps/playground/content/gallery/summer-collection.md +52 -0
- package/apps/playground/content/pages/index.md +132 -0
- package/apps/playground/content/portfolio/project-one.md +90 -0
- package/apps/playground/content/portfolio/project-two.md +96 -0
- package/apps/playground/content.config.ts +93 -0
- package/apps/playground/nuxt.config.ts +99 -0
- package/apps/playground/package.json +17 -0
- package/apps/playground/public/favicon.ico +0 -0
- package/apps/playground/public/robots.txt +2 -0
- package/apps/playground/tsconfig.json +25 -0
- package/eslint.config.mjs +223 -0
- package/eslint.configCOPY.mjs +216 -0
- package/eslintconfigCURRENT.mjs +244 -0
- package/eslintconfigOLD.mjs +178 -0
- package/files for claude/Scroller.vue +31 -0
- package/files for claude/TextMarquee.vue +255 -0
- package/files for claude/gsap.client.ts +18 -0
- package/files for claude/gsap.ts +10 -0
- package/files for claude/scroll.ts +28 -0
- package/layers/content/app/assets/css/main.css +1 -0
- package/layers/content/app/components/Blog/Article.vue +29 -0
- package/layers/content/app/components/Blog/Card.vue +40 -0
- package/layers/content/app/components/Blog/List.vue +35 -0
- package/layers/content/app/components/Gallery/AmbientImage.vue +52 -0
- package/layers/content/app/components/Gallery/Card.vue +39 -0
- package/layers/content/app/components/Gallery/Detail.vue +76 -0
- package/layers/content/app/components/Gallery/Grid.vue +48 -0
- package/layers/content/app/components/Gallery/ImageDetail.vue +92 -0
- package/layers/content/app/components/Gallery/Lightbox.vue +102 -0
- package/layers/content/app/components/NuxtContent/Detail.vue +53 -0
- package/layers/content/app/components/NuxtContent/List.vue +21 -0
- package/layers/content/app/components/NuxtContent/Renderer.vue +14 -0
- package/layers/content/app/components/NuxtContent/Surround.vue +15 -0
- package/layers/content/app/components/NuxtContent/Toc.vue +18 -0
- package/layers/content/app/components/Portfolio/Card.vue +39 -0
- package/layers/content/app/components/Portfolio/ColorPalette.vue +39 -0
- package/layers/content/app/components/Portfolio/Detail.vue +49 -0
- package/layers/content/app/components/Portfolio/List.vue +44 -0
- package/layers/content/app/components/Portfolio/Typography.vue +37 -0
- package/layers/content/app/components/content/Figure.vue +31 -0
- package/layers/content/app/composables/useBlogPost.ts +3 -0
- package/layers/content/app/composables/useBlogPosts.ts +23 -0
- package/layers/content/app/composables/useCollectionItem.ts +5 -0
- package/layers/content/app/composables/useCollectionSurround.ts +9 -0
- package/layers/content/app/composables/useContentPage.ts +3 -0
- package/layers/content/app/composables/useGalleryItem.ts +3 -0
- package/layers/content/app/composables/useGalleryItems.ts +19 -0
- package/layers/content/app/composables/usePortfolioItem.ts +3 -0
- package/layers/content/app/composables/usePortfolioItems.ts +23 -0
- package/layers/content/app/pages/blog/[slug].vue +10 -0
- package/layers/content/app/pages/blog/index.vue +15 -0
- package/layers/content/app/pages/gallery/[slug]/[imageId].vue +11 -0
- package/layers/content/app/pages/gallery/[slug]/index.vue +10 -0
- package/layers/content/app/pages/gallery/index.vue +15 -0
- package/layers/content/app/pages/portfolio/[slug].vue +10 -0
- package/layers/content/app/pages/portfolio/index.vue +15 -0
- package/layers/content/app/types/content.ts +84 -0
- package/layers/content/app.config.ts +12 -0
- package/layers/content/content.config.ts +93 -0
- package/layers/content/nuxt.config.ts +31 -0
- package/layers/content/package.json +31 -0
- package/layers/content/tsconfig.json +6 -0
- package/layers/core/app/assets/css/base.css +88 -0
- package/layers/core/app/assets/css/layout.css +36 -0
- package/layers/core/app/assets/css/main.css +7 -0
- package/layers/core/app/assets/css-backup.zip +0 -0
- package/layers/core/app/components/ErrorBoundary.vue +102 -0
- package/layers/core/app/components/LoadingScreen.vue +137 -0
- package/layers/core/app/composables/useBrowser.ts +161 -0
- package/layers/core/app/composables/useCache.ts +138 -0
- package/layers/core/app/composables/useDevice.ts +36 -0
- package/layers/core/app/composables/useEnv.ts +23 -0
- package/layers/core/app/composables/useErrorLog.ts +158 -0
- package/layers/core/app/composables/useFeatures.ts +269 -0
- package/layers/core/app/composables/useLoading.ts +109 -0
- package/layers/core/app/composables/useNetworkInfo.ts +83 -0
- package/layers/core/app/composables/usePWAInfo.ts +104 -0
- package/layers/core/app/composables/useRendering.ts +97 -0
- package/layers/core/app/composables/useScreen.ts +95 -0
- package/layers/core/app/composables/useScrollGuard.ts +266 -0
- package/layers/core/app/error.vue +103 -0
- package/layers/core/app/layouts/default.vue +4 -0
- package/layers/core/app/pages/[...slug].vue +168 -0
- package/layers/core/app/pages/diagnostics.vue +228 -0
- package/layers/core/app/plugins/error-handler.ts +47 -0
- package/layers/core/app/plugins/feature-detection.client.ts +32 -0
- package/layers/core/app/plugins/init.ts +188 -0
- package/layers/core/app/plugins/loading.client.ts +54 -0
- package/layers/core/app/plugins/scroll-guard.client.ts +53 -0
- package/layers/core/app/types/detection.ts +117 -0
- package/layers/core/app/types/index.ts +10 -0
- package/layers/core/app/types/loading.ts +47 -0
- package/layers/core/app/types/runtime-config.ts +31 -0
- package/layers/core/app/types/scroll-guard.ts +25 -0
- package/layers/core/app/utils/helpers.ts +246 -0
- package/layers/core/app/utils/index.ts +8 -0
- package/layers/core/app/utils/regex.ts +6 -0
- package/layers/core/app.config.ts +193 -0
- package/layers/core/nuxt.config.ts +84 -0
- package/layers/core/package.json +25 -0
- package/layers/core/tailwind.config.js +28 -0
- package/layers/core/tsconfig.json +6 -0
- package/layers/forms/app/components/Form/Contact.vue +78 -0
- package/layers/forms/app/components/Form/Field.vue +85 -0
- package/layers/forms/app/composables/useFormSchema.ts +35 -0
- package/layers/forms/app/config/fields.ts +104 -0
- package/layers/forms/app/types/fields.ts +60 -0
- package/layers/forms/app.config.ts +12 -0
- package/layers/forms/nuxt.config.ts +17 -0
- package/layers/forms/package.json +17 -0
- package/layers/forms/tsconfig.json +6 -0
- package/layers/layout/.nuxtrc +1 -0
- package/layers/layout/CLAUDE.MD +186 -0
- package/layers/layout/GRID_SYSTEM.md +993 -0
- package/layers/layout/README.md +73 -0
- package/layers/layout/app/assets/css/layout/grids.css +180 -0
- package/layers/layout/app/assets/css/main.css +1 -0
- package/layers/layout/app/components/Layout/Grid/Debug.vue +79 -0
- package/layers/layout/app/components/Layout/Grid/Item.vue +180 -0
- package/layers/layout/app/components/Layout/Page/Container.vue +100 -0
- package/layers/layout/app/components/Layout/Page/Header.vue +33 -0
- package/layers/layout/app/components/Layout/Section/Gallery.vue +68 -0
- package/layers/layout/app/components/Layout/Section/Hero.vue +71 -0
- package/layers/layout/app/components/Layout/Section/Split.vue +56 -0
- package/layers/layout/app/components/Layout/Section/index.vue +39 -0
- package/layers/layout/app/composables/GridPlacement.ts +31 -0
- package/layers/layout/app/composables/useGridConfig.ts +27 -0
- package/layers/layout/app/types/layouts.ts +37 -0
- package/layers/layout/app.config.ts +97 -0
- package/layers/layout/nuxt.config.ts +14 -0
- package/layers/layout/package.json +14 -0
- package/layers/layout/tailwind.config.js +28 -0
- package/layers/layout/tsconfig.json +6 -0
- package/layers/motion/README.md +107 -0
- package/layers/motion/TASKS.MD +16 -0
- package/layers/motion/app/assets/css/main.css +111 -0
- package/layers/motion/app/components/Motion/Marquee.vue +171 -0
- package/layers/motion/app/components/Motion/Parallax.vue +75 -0
- package/layers/motion/app/components/Motion/ScrollLink.vue +49 -0
- package/layers/motion/app/components/Motion/ScrollProgress.vue +127 -0
- package/layers/motion/app/components/Motion/ScrollStats.vue +102 -0
- package/layers/motion/app/components/Motion/Staggered.vue +73 -0
- package/layers/motion/app/components/Motion/TextReveal.vue +101 -0
- package/layers/motion/app/components/Motion/Transition.vue +89 -0
- package/layers/motion/app/components/Motion/VelocityEffect.vue +139 -0
- package/layers/motion/app/components/Motion/index.vue +16 -0
- package/layers/motion/app/composables/useGsap.ts +21 -0
- package/layers/motion/app/composables/useMotion.ts +137 -0
- package/layers/motion/app/composables/useSmoothScroll.ts +154 -0
- package/layers/motion/app/plugins/gsap.client.ts +15 -0
- package/layers/motion/app/plugins/locomotive-scroll.client.ts +49 -0
- package/layers/motion/app/utils/gsapAnimations.ts +122 -0
- package/layers/motion/app.config.ts +30 -0
- package/layers/motion/nuxt.config.ts +19 -0
- package/layers/motion/package.json +17 -0
- package/layers/motion/tsconfig.json +6 -0
- package/layers/shader/AGENTS.MD +195 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/.prettierignore +6 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/.prettierrc +18 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/LICENSE +21 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/README.md +100 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/index.html +13 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/jsconfig.json +30 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/package.json +18 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/pnpm-lock.yaml +633 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/public/vite.svg +1 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/components/sketch/webgpu_sketch.js +128 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/components/sketches_dropdown/index.css +87 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/components/sketches_dropdown/sketches_dropdown.js +169 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/index.css +25 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/main.js +93 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/router.js +43 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/sketches/flare-1.js +68 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/sketches/noise/dawn-1.js +56 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/distortion/bulge_distortion.js +35 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/distortion/swirl_distortion.js +35 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/distortion/wave_distortion.js +43 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/noise/common.js +145 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/noise/curl_noise_3d.js +53 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/noise/curl_noise_4d.js +55 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/noise/fbm.js +163 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/noise/perlin_noise_3d.js +70 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/noise/simplex_noise_3d.js +59 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/noise/simplex_noise_4d.js +72 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/noise/turbulence.js +41 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/patterns/canvas_weave_pattern.js +26 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/patterns/grain_texture_pattern.js +10 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/patterns/led_pattern.js +45 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/patterns/pixellation_pattern.js +15 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/patterns/speckled_noise_pattern.js +34 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/patterns/vignette_pattern.js +21 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/bulge_distortion_effect.js +27 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/chromatic_aberration_effect.js +45 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/crt_scanline_effect.js +45 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/dither_effect.js +126 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/grain_texture_effect.js +21 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/halftone_effect.js +44 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/led_effect.js +31 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/pixellation_effect.js +29 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/swirl_distortion_effect.js +25 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/vignette_effect.js +22 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/post_processing/wave_distortion_effect.js +27 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/color/cosine_palette.js +15 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/color/tonemapping.js +151 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/function/bloom.js +13 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/function/bloom_edge_pattern.js +20 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/function/domain_index.js +11 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/function/median3.js +22 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/function/repeating_pattern.js +13 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/function/screen_aspect_uv.js +14 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/lighting.js +60 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/math/complex.js +86 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/math/coordinates.js +119 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/sdf/operations.js +24 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/tsl/utils/sdf/shapes.js +182 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/src/utils/math.js +33 -0
- package/layers/shader/additional-modular-tsl-shaders-for-claude/vite.config.js +23 -0
- package/layers/shader/app/assets/css/main.css +41 -0
- package/layers/shader/app/components/Effect/Bloom.vue +8 -0
- package/layers/shader/app/components/Effect/ChromaticAberration.vue +8 -0
- package/layers/shader/app/components/Effect/PostProcessing.vue +20 -0
- package/layers/shader/app/components/Material/AmbientAurora.vue +172 -0
- package/layers/shader/app/components/Material/AmbientFlow.vue +175 -0
- package/layers/shader/app/components/Material/AmbientGradientMesh.vue +173 -0
- package/layers/shader/app/components/Material/AmbientNebula.vue +181 -0
- package/layers/shader/app/components/Material/AmbientOcean.vue +161 -0
- package/layers/shader/app/components/Material/Fresnel.vue +89 -0
- package/layers/shader/app/components/Material/Gradient.vue +185 -0
- package/layers/shader/app/components/Material/Image.vue +232 -0
- package/layers/shader/app/components/Material/Node.vue +79 -0
- package/layers/shader/app/components/Material/Noise.vue +141 -0
- package/layers/shader/app/components/Mesh/Plane.vue +27 -0
- package/layers/shader/app/components/Shader/Background.vue +159 -0
- package/layers/shader/app/components/Shader/Canvas.vue +97 -0
- package/layers/shader/app/components/Shader/Debug.vue +66 -0
- package/layers/shader/app/components/WebGPUCanvas.client.vue +245 -0
- package/layers/shader/app/composables/useAmbientMaterials.ts +452 -0
- package/layers/shader/app/composables/useMousePosition.ts +94 -0
- package/layers/shader/app/composables/useRendererCapabilities.ts +111 -0
- package/layers/shader/app/composables/useShader.ts +148 -0
- package/layers/shader/app/composables/useShaderTime.ts +146 -0
- package/layers/shader/app/composables/useTSLNodes.ts +112 -0
- package/layers/shader/app/composables/useUniforms.ts +188 -0
- package/layers/shader/app/plugins/shader.client.ts +30 -0
- package/layers/shader/app/shaders/common/blend.ts +255 -0
- package/layers/shader/app/shaders/common/effects.ts +299 -0
- package/layers/shader/app/shaders/common/grain.ts +453 -0
- package/layers/shader/app/shaders/common/index.ts +22 -0
- package/layers/shader/app/shaders/common/lighting.ts +146 -0
- package/layers/shader/app/shaders/common/math.ts +250 -0
- package/layers/shader/app/shaders/common/noise.ts +823 -0
- package/layers/shader/app/shaders/common/noiseHelpers.ts +114 -0
- package/layers/shader/app/shaders/common/palette.ts +319 -0
- package/layers/shader/app/shaders/common/patterns.ts +216 -0
- package/layers/shader/app/shaders/common/sdf.ts +224 -0
- package/layers/shader/app/shaders/common/shapes.ts +366 -0
- package/layers/shader/app/shaders/common/tonemapping.ts +172 -0
- package/layers/shader/app/shaders/common/uv.ts +396 -0
- package/layers/shader/app/shaders/createMaterial.ts +314 -0
- package/layers/shader/app/shaders/index.ts +282 -0
- package/layers/shader/app/shaders/layers/aurora.ts +146 -0
- package/layers/shader/app/shaders/layers/index.ts +19 -0
- package/layers/shader/app/shaders/layers/meshGradient.ts +152 -0
- package/layers/shader/app/shaders/layers/paperShading.ts +148 -0
- package/layers/shader/app/shaders/layers/shaderGradient.ts +152 -0
- package/layers/shader/app/shaders/layers/stripe.ts +137 -0
- package/layers/shader/app/shaders/types.ts +12 -0
- package/layers/shader/app/types/index.ts +4 -0
- package/layers/shader/app/types/materials.ts +45 -0
- package/layers/shader/app/types/renderer.ts +50 -0
- package/layers/shader/app/types/tsl.ts +39 -0
- package/layers/shader/app/types/uniforms.ts +21 -0
- package/layers/shader/app/utils/tsl/animation.ts +251 -0
- package/layers/shader/app/utils/tsl/color.ts +189 -0
- package/layers/shader/app/utils/tsl/index.ts +84 -0
- package/layers/shader/app/utils/tsl/math.ts +111 -0
- package/layers/shader/app/utils/tsl/noise.ts +195 -0
- package/layers/shader/app/utils/tsl/patterns.ts +183 -0
- package/layers/shader/app/utils/tsl/uv.ts +145 -0
- package/layers/shader/app.config.ts +18 -0
- package/layers/shader/modular-tsl-shaders-for-claude/common/blend.tsl +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/common/noise.tsl +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/common/shapes.tsl +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/common/vertexFresnel.tsl +9 -0
- package/layers/shader/modular-tsl-shaders-for-claude/common/vertexPlane.tsl +6 -0
- package/layers/shader/modular-tsl-shaders-for-claude/effects/background.tsl +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/effects/gradient.tsl +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/effects/gradientLegend.tsl +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/effects/simpleGradient.tsl +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/layers/aurora.ts +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/layers/fragmentsTech.ts +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/layers/fresnel.ts +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/layers/linearGradient.ts +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/layers/meshGradient.ts +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/layers/noise.ts +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/layers/paperShading.ts +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/layers/radial.ts +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/layers/shaderGradient.ts +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/layers/stripe.ts +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/materials/createMaterial.ts +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/utils/glslUtils.ts +1 -0
- package/layers/shader/modular-tsl-shaders-for-claude/utils/palette.ts +1 -0
- package/layers/shader/nuxt.config.ts +48 -0
- package/layers/shader/package.json +17 -0
- package/layers/shader/tsconfig.json +6 -0
- package/layers/theme/app/assets/css/theme.css +47 -0
- package/layers/theme/app/components/ThemePicker/AccentButton.vue +51 -0
- package/layers/theme/app/components/ThemePicker/Colors.vue +22 -0
- package/layers/theme/app/components/ThemePicker/Menu.vue +108 -0
- package/layers/theme/app/components/ThemePicker/MenuButton.vue +9 -0
- package/layers/theme/app/composables/useThemePreferences.ts +158 -0
- package/layers/theme/app/plugins/theme.client.ts +5 -0
- package/layers/theme/app/types/theme.ts +34 -0
- package/layers/theme/app.config.ts +14 -0
- package/layers/theme/nuxt.config.ts +46 -0
- package/layers/theme/package.json +14 -0
- package/layers/theme/server/plugins/theme-fouc.ts +51 -0
- package/layers/theme/tsconfig.json +7 -0
- package/layers/ui/CLAUDE.MD +325 -0
- package/layers/ui/app/assets/css/main.css +4 -0
- package/layers/ui/app/components/Links/Group.vue +38 -0
- package/layers/ui/app/components/Links/Named.vue +32 -0
- package/layers/ui/app/components/Media/Picture.vue +41 -0
- package/layers/ui/app/components/Site/Title.vue +15 -0
- package/layers/ui/app/components/Typography/CodeBlock.vue +37 -0
- package/layers/ui/app/components/Typography/Headline.vue +73 -0
- package/layers/ui/app/components/Typography/QuoteBlock.vue +13 -0
- package/layers/ui/app/components/Typography/TextStroke.vue +109 -0
- package/layers/ui/app/components/Typography/index.vue +49 -0
- package/layers/ui/app/composables/color.ts +36 -0
- package/layers/ui/app/composables/picture.ts +145 -0
- package/layers/ui/app/composables/typography.ts +77 -0
- package/layers/ui/app/layouts/default.vue +4 -0
- package/layers/ui/app/pages/index.vue +236 -0
- package/layers/ui/app/types/breakpoints.ts +179 -0
- package/layers/ui/app/types/colors.ts +29 -0
- package/layers/ui/app/types/media.ts +185 -0
- package/layers/ui/app/types/typography.ts +108 -0
- package/layers/ui/app/utils/regex.ts +6 -0
- package/layers/ui/app.config.ts +12 -0
- package/layers/ui/nuxt.config.ts +38 -0
- package/layers/ui/package.json +14 -0
- package/layers/ui/tsconfig.json +6 -0
- package/package.json +128 -0
- package/playgroundOLD/app.config.ts +5 -0
- package/playgroundOLD/nuxt.config.ts +12 -0
- package/pnpm-workspace.yaml +6 -0
- package/prettier.config.cjs +19 -0
- package/stylelint.config.mjs +111 -0
- 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
|
+
}
|