kmcom-nuxt-layers 1.6.4 → 1.6.6

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 (165) hide show
  1. package/layers/core/app/.DS_Store +0 -0
  2. package/layers/core/app/assets/.DS_Store +0 -0
  3. package/layers/core/app/assets/css/main.css +2 -0
  4. package/layers/core/app/components/ErrorBoundary.vue +1 -1
  5. package/layers/core/nuxt.config.ts +0 -8
  6. package/layers/motion/app/plugins/locomotive-scroll.client.ts +14 -11
  7. package/layers/motion/app.config.ts +6 -0
  8. package/layers/shader/app/components/Pipeline/ACESTonemap.client.vue +14 -0
  9. package/layers/shader/app/components/Pipeline/AddBlend.client.vue +24 -0
  10. package/layers/shader/app/components/Pipeline/AgedFilm.client.vue +62 -0
  11. package/layers/shader/app/components/Pipeline/Aurora.client.vue +81 -0
  12. package/layers/shader/app/components/Pipeline/BilinearGradient.client.vue +46 -0
  13. package/layers/shader/app/components/Pipeline/BillowNoise.client.vue +42 -0
  14. package/layers/shader/app/components/Pipeline/BrightnessContrast.client.vue +25 -0
  15. package/layers/shader/app/components/Pipeline/CellularNoise.client.vue +41 -0
  16. package/layers/shader/app/components/Pipeline/ChannelMixer.client.vue +44 -0
  17. package/layers/shader/app/components/Pipeline/ChebyshevNoiseField.client.vue +60 -0
  18. package/layers/shader/app/components/Pipeline/Checkerboard.client.vue +41 -0
  19. package/layers/shader/app/components/Pipeline/ChromaticAberration.client.vue +52 -0
  20. package/layers/shader/app/components/Pipeline/ChromaticScreenWaves.client.vue +49 -0
  21. package/layers/shader/app/components/Pipeline/Circle.client.vue +41 -0
  22. package/layers/shader/app/components/Pipeline/Clouds.client.vue +60 -0
  23. package/layers/shader/app/components/Pipeline/ColorBurnBlend.client.vue +24 -0
  24. package/layers/shader/app/components/Pipeline/ColorDodgeBlend.client.vue +24 -0
  25. package/layers/shader/app/components/Pipeline/ColourRamp.client.vue +57 -0
  26. package/layers/shader/app/components/Pipeline/ComplexPlaneField.client.vue +77 -0
  27. package/layers/shader/app/components/Pipeline/ConicGradient.client.vue +40 -0
  28. package/layers/shader/app/components/Pipeline/CosinePalette.client.vue +71 -0
  29. package/layers/shader/app/components/Pipeline/CoverageAlpha.client.vue +18 -0
  30. package/layers/shader/app/components/Pipeline/Cross.client.vue +51 -0
  31. package/layers/shader/app/components/Pipeline/CurlNoise.client.vue +48 -0
  32. package/layers/shader/app/components/Pipeline/DarkenBlend.client.vue +24 -0
  33. package/layers/shader/app/components/Pipeline/DayNightCycle.client.vue +48 -0
  34. package/layers/shader/app/components/Pipeline/Desaturate.client.vue +21 -0
  35. package/layers/shader/app/components/Pipeline/DiagonalGradient.client.vue +38 -0
  36. package/layers/shader/app/components/Pipeline/DiamondGradient.client.vue +40 -0
  37. package/layers/shader/app/components/Pipeline/DifferenceBlend.client.vue +24 -0
  38. package/layers/shader/app/components/Pipeline/DivideBlend.client.vue +26 -0
  39. package/layers/shader/app/components/Pipeline/DomainWarpedNoise.client.vue +48 -0
  40. package/layers/shader/app/components/Pipeline/Dots.client.vue +44 -0
  41. package/layers/shader/app/components/Pipeline/DuoTone.client.vue +34 -0
  42. package/layers/shader/app/components/Pipeline/ExclusionBlend.client.vue +24 -0
  43. package/layers/shader/app/components/Pipeline/ExponentialFog.client.vue +46 -0
  44. package/layers/shader/app/components/Pipeline/Exposure.client.vue +23 -0
  45. package/layers/shader/app/components/Pipeline/FBMNoise.client.vue +50 -0
  46. package/layers/shader/app/components/Pipeline/FilmBurn.client.vue +49 -0
  47. package/layers/shader/app/components/Pipeline/FilmGrain.client.vue +69 -0
  48. package/layers/shader/app/components/Pipeline/FisheyeRay.client.vue +35 -0
  49. package/layers/shader/app/components/Pipeline/Flame.client.vue +51 -0
  50. package/layers/shader/app/components/Pipeline/FocalGradient.client.vue +43 -0
  51. package/layers/shader/app/components/Pipeline/Gamma.client.vue +23 -0
  52. package/layers/shader/app/components/Pipeline/GodRays.client.vue +64 -0
  53. package/layers/shader/app/components/Pipeline/GradientNoise.client.vue +42 -0
  54. package/layers/shader/app/components/Pipeline/Grain.client.vue +81 -0
  55. package/layers/shader/app/components/Pipeline/Grid.client.vue +43 -0
  56. package/layers/shader/app/components/Pipeline/Halation.client.vue +43 -0
  57. package/layers/shader/app/components/Pipeline/Halftone.client.vue +33 -0
  58. package/layers/shader/app/components/Pipeline/HardLightBlend.client.vue +24 -0
  59. package/layers/shader/app/components/Pipeline/Haze.client.vue +50 -0
  60. package/layers/shader/app/components/Pipeline/Hexagon.client.vue +42 -0
  61. package/layers/shader/app/components/Pipeline/Hue.client.vue +21 -0
  62. package/layers/shader/app/components/Pipeline/Invert.client.vue +14 -0
  63. package/layers/shader/app/components/Pipeline/LensFlare.client.vue +67 -0
  64. package/layers/shader/app/components/Pipeline/LightenBlend.client.vue +24 -0
  65. package/layers/shader/app/components/Pipeline/LinearGradient.client.vue +36 -0
  66. package/layers/shader/app/components/Pipeline/LinearGradient4.client.vue +67 -0
  67. package/layers/shader/app/components/Pipeline/LinearToSRGB.client.vue +25 -0
  68. package/layers/shader/app/components/Pipeline/Marble.client.vue +69 -0
  69. package/layers/shader/app/components/Pipeline/MixBlend.client.vue +45 -0
  70. package/layers/shader/app/components/Pipeline/MonochromeTint.client.vue +31 -0
  71. package/layers/shader/app/components/Pipeline/MultiplyBlend.client.vue +24 -0
  72. package/layers/shader/app/components/Pipeline/NoisyGradient.client.vue +54 -0
  73. package/layers/shader/app/components/Pipeline/NoisyGradientBlend.client.vue +116 -0
  74. package/layers/shader/app/components/Pipeline/OverlayBlend.client.vue +24 -0
  75. package/layers/shader/app/components/Pipeline/PaperTexture.client.vue +41 -0
  76. package/layers/shader/app/components/Pipeline/Polygon.client.vue +47 -0
  77. package/layers/shader/app/components/Pipeline/Posterise.client.vue +23 -0
  78. package/layers/shader/app/components/Pipeline/RadialGradient.client.vue +39 -0
  79. package/layers/shader/app/components/Pipeline/RayAutoOrbit.client.vue +37 -0
  80. package/layers/shader/app/components/Pipeline/RayMouseOrbit.client.vue +49 -0
  81. package/layers/shader/app/components/Pipeline/RayRotateX.client.vue +25 -0
  82. package/layers/shader/app/components/Pipeline/RayRotateY.client.vue +25 -0
  83. package/layers/shader/app/components/Pipeline/RayRotateZ.client.vue +25 -0
  84. package/layers/shader/app/components/Pipeline/RayTiltBasis.client.vue +41 -0
  85. package/layers/shader/app/components/Pipeline/RaymarchTunnel.client.vue +101 -0
  86. package/layers/shader/app/components/Pipeline/Rectangle.client.vue +47 -0
  87. package/layers/shader/app/components/Pipeline/ReinhardTonemap.client.vue +18 -0
  88. package/layers/shader/app/components/Pipeline/RidgedNoise.client.vue +41 -0
  89. package/layers/shader/app/components/Pipeline/Ring.client.vue +44 -0
  90. package/layers/shader/app/components/Pipeline/RingField.client.vue +69 -0
  91. package/layers/shader/app/components/Pipeline/RisographGrain.client.vue +74 -0
  92. package/layers/shader/app/components/Pipeline/RotatedGradientBlend.client.vue +61 -0
  93. package/layers/shader/app/components/Pipeline/SDFColourMask.client.vue +33 -0
  94. package/layers/shader/app/components/Pipeline/SDFRadialMask.client.vue +31 -0
  95. package/layers/shader/app/components/Pipeline/SRGBToLinear.client.vue +25 -0
  96. package/layers/shader/app/components/Pipeline/Saturation.client.vue +21 -0
  97. package/layers/shader/app/components/Pipeline/Scanlines.client.vue +36 -0
  98. package/layers/shader/app/components/Pipeline/ScreenBlend.client.vue +24 -0
  99. package/layers/shader/app/components/Pipeline/ShaderDebugger.client.vue +74 -0
  100. package/layers/shader/app/components/Pipeline/SimplexNoise.client.vue +49 -0
  101. package/layers/shader/app/components/Pipeline/SkyAtmosphere.client.vue +75 -0
  102. package/layers/shader/app/components/Pipeline/SoftLightBlend.client.vue +24 -0
  103. package/layers/shader/app/components/Pipeline/SolidColour.client.vue +21 -0
  104. package/layers/shader/app/components/Pipeline/SplitTone.client.vue +47 -0
  105. package/layers/shader/app/components/Pipeline/Star.client.vue +47 -0
  106. package/layers/shader/app/components/Pipeline/Starfield.client.vue +65 -0
  107. package/layers/shader/app/components/Pipeline/Stripes.client.vue +46 -0
  108. package/layers/shader/app/components/Pipeline/SubtractBlend.client.vue +24 -0
  109. package/layers/shader/app/components/Pipeline/TanhTonemap.client.vue +24 -0
  110. package/layers/shader/app/components/Pipeline/Threshold.client.vue +25 -0
  111. package/layers/shader/app/components/Pipeline/Tint.client.vue +33 -0
  112. package/layers/shader/app/components/Pipeline/Triangle.client.vue +42 -0
  113. package/layers/shader/app/components/Pipeline/UVAspectCorrect.client.vue +14 -0
  114. package/layers/shader/app/components/Pipeline/UVBreath.client.vue +36 -0
  115. package/layers/shader/app/components/Pipeline/UVBulge.client.vue +26 -0
  116. package/layers/shader/app/components/Pipeline/UVClamp.client.vue +18 -0
  117. package/layers/shader/app/components/Pipeline/UVColumnOffset.client.vue +28 -0
  118. package/layers/shader/app/components/Pipeline/UVFlipX.client.vue +14 -0
  119. package/layers/shader/app/components/Pipeline/UVFlipXY.client.vue +14 -0
  120. package/layers/shader/app/components/Pipeline/UVFlipY.client.vue +14 -0
  121. package/layers/shader/app/components/Pipeline/UVFractBand.client.vue +31 -0
  122. package/layers/shader/app/components/Pipeline/UVMousePull.client.vue +39 -0
  123. package/layers/shader/app/components/Pipeline/UVNoiseRotate.client.vue +54 -0
  124. package/layers/shader/app/components/Pipeline/UVNoiseWarp.client.vue +35 -0
  125. package/layers/shader/app/components/Pipeline/UVOrbit.client.vue +34 -0
  126. package/layers/shader/app/components/Pipeline/UVParallax.client.vue +39 -0
  127. package/layers/shader/app/components/Pipeline/UVPixelate.client.vue +21 -0
  128. package/layers/shader/app/components/Pipeline/UVPulse.client.vue +33 -0
  129. package/layers/shader/app/components/Pipeline/UVRipple.client.vue +34 -0
  130. package/layers/shader/app/components/Pipeline/UVRotate.client.vue +37 -0
  131. package/layers/shader/app/components/Pipeline/UVScale.client.vue +30 -0
  132. package/layers/shader/app/components/Pipeline/UVScroll.client.vue +27 -0
  133. package/layers/shader/app/components/Pipeline/UVScrollX.client.vue +21 -0
  134. package/layers/shader/app/components/Pipeline/UVScrollY.client.vue +21 -0
  135. package/layers/shader/app/components/Pipeline/UVShear.client.vue +25 -0
  136. package/layers/shader/app/components/Pipeline/UVSineWarpXY.client.vue +46 -0
  137. package/layers/shader/app/components/Pipeline/UVSwapAxes.client.vue +14 -0
  138. package/layers/shader/app/components/Pipeline/UVTile.client.vue +27 -0
  139. package/layers/shader/app/components/Pipeline/UVTwirl.client.vue +26 -0
  140. package/layers/shader/app/components/Pipeline/UVWarp.client.vue +30 -0
  141. package/layers/shader/app/components/Pipeline/VHSBleed.client.vue +58 -0
  142. package/layers/shader/app/components/Pipeline/ValueNoise.client.vue +41 -0
  143. package/layers/shader/app/components/Pipeline/Vibrance.client.vue +24 -0
  144. package/layers/shader/app/components/Pipeline/Vignette.client.vue +32 -0
  145. package/layers/shader/app/components/Pipeline/VoronoiEdges.client.vue +50 -0
  146. package/layers/shader/app/components/Pipeline/Water.client.vue +53 -0
  147. package/layers/shader/app/components/Pipeline/WaveBendLayer.client.vue +61 -0
  148. package/layers/shader/app/components/Pipeline/WaveColourLayer.client.vue +56 -0
  149. package/layers/shader/app/components/Pipeline/WhiteBalance.client.vue +40 -0
  150. package/layers/shader/app/components/Pipeline/Wood.client.vue +63 -0
  151. package/layers/shader/app/components/Shader/Canvas.vue +24 -0
  152. package/layers/shader/app/components/Shader/Pipeline.client.vue +56 -0
  153. package/layers/shader/app/components/Shader/PipelineContext.vue +18 -0
  154. package/layers/shader/app/composables/useCSSColourUniform.ts +41 -0
  155. package/layers/shader/app/composables/useCSSFloatUniform.ts +34 -0
  156. package/layers/shader/app/composables/useShaderPerf.ts +73 -0
  157. package/layers/shader/app/composables/useShaderPipeline.ts +99 -0
  158. package/layers/shader/app/composables/useSunDirectionUniform.ts +54 -0
  159. package/layers/shader/app/composables/useTSLNodes.ts +0 -1
  160. package/layers/shader/app/shaders/common/complex.ts +29 -0
  161. package/layers/shader/app/shaders/common/shapes.ts +4 -4
  162. package/layers/shader/app/shaders/common/uv.ts +2 -2
  163. package/layers/shader/app/utils/tsl/patterns.ts +1 -1
  164. package/layers/shader/app/utils/tsl/uv.ts +3 -3
  165. package/package.json +9 -7
Binary file
Binary file
@@ -10,3 +10,5 @@
10
10
 
11
11
  @import '#layers/core/app/assets/css/layout.css';
12
12
  @import '#layers/core/app/assets/css/base.css';
13
+
14
+
@@ -61,7 +61,7 @@ const handleError = (error: unknown) => {
61
61
  <template #error="{ error, clearError }">
62
62
  <slot name="error" :error :clear-error>
63
63
  <!-- Default error UI -->
64
- <div class="rounded-lg border border-error bg-error/10 p-4">
64
+ <div class="rounded-lg border border-error bg-error/10 p-4 ">
65
65
  <div class="flex items-start gap-3">
66
66
  <!-- Error icon -->
67
67
  <span
@@ -21,14 +21,6 @@ export default defineNuxtConfig({
21
21
 
22
22
  css: ['#layers/core/app/assets/css/main.css'],
23
23
 
24
- plugins: [
25
- '#layers/core/app/plugins/init.ts',
26
- '#layers/core/app/plugins/error-handler.ts',
27
- '#layers/core/app/plugins/feature-detection.client.ts',
28
- '#layers/core/app/plugins/loading.client.ts',
29
- '#layers/core/app/plugins/scroll-guard.client.ts',
30
- ],
31
-
32
24
  devtools: {
33
25
  enabled: true,
34
26
 
@@ -45,19 +45,22 @@ export default defineNuxtPlugin(() => {
45
45
  }
46
46
 
47
47
  const router = useRouter()
48
+ const appConfig = useAppConfig() as any
49
+ const smoothScroll: boolean | string[] = appConfig.motion?.smoothScroll ?? true
48
50
 
49
- const SMOOTH_SCROLL_ROUTES = ['/locomotive-scroll', '/layout-stacking', '/layout-blind-reveal']
50
-
51
- addRouteMiddleware((to, from) => {
52
- if (SMOOTH_SCROLL_ROUTES.includes(to.path)) {
53
- nextTick(init)
54
- } else if (from?.path && SMOOTH_SCROLL_ROUTES.includes(from.path)) {
55
- destroy()
56
- }
57
- })
58
-
59
- if (SMOOTH_SCROLL_ROUTES.includes(router.currentRoute.value.path)) {
51
+ if (smoothScroll === true) {
60
52
  init()
53
+ } else if (Array.isArray(smoothScroll)) {
54
+ addRouteMiddleware((to, from) => {
55
+ if (smoothScroll.includes(to.path)) {
56
+ nextTick(init)
57
+ } else if (from?.path && smoothScroll.includes(from.path)) {
58
+ destroy()
59
+ }
60
+ })
61
+ if (smoothScroll.includes(router.currentRoute.value.path)) {
62
+ init()
63
+ }
61
64
  }
62
65
 
63
66
  return {
@@ -1,5 +1,11 @@
1
1
  export default defineAppConfig({
2
2
  motion: {
3
+ /**
4
+ * Enable smooth scroll globally (true), on specific routes (string[]), or disable (false).
5
+ * @default true
6
+ */
7
+ smoothScroll: true as boolean | string[],
8
+
3
9
  /**
4
10
  * Enable GSAP ScrollTrigger integration with Lenis
5
11
  * @default true
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { vec4 } from 'three/tsl'
4
+ import { acesTonemap } from '../../shaders/common/tonemapping'
5
+
6
+ const { order = 0 } = defineProps<{ order?: number }>()
7
+
8
+ useShaderStage(
9
+ (prev) => vec4(acesTonemap(prev.xyz), prev.w),
10
+ order,
11
+ )
12
+ </script>
13
+
14
+ <template><!-- --></template>
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color } from 'three'
4
+ import { clamp, uniform, vec4 } from 'three/tsl'
5
+ import { blendAdd } from '../../shaders/common/blend'
6
+
7
+ const props = withDefaults(defineProps<{
8
+ color?: string
9
+ opacity?: number
10
+ order?: number
11
+ }>(), { color: '#808080', opacity: 1, order: 0 })
12
+
13
+ const colorNode = uniform(new Color(props.color))
14
+ const opacityNode = uniform(props.opacity)
15
+ watch(() => props.color, v => { colorNode.value.set(v) })
16
+ watch(() => props.opacity, v => { opacityNode.value = v })
17
+
18
+ useShaderStage(
19
+ (prev) => clamp(vec4(blendAdd(prev.xyz, colorNode, opacityNode), prev.w), 0, 1),
20
+ props.order,
21
+ )
22
+ </script>
23
+
24
+ <template><!-- --></template>
@@ -0,0 +1,62 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, time, vec3, vec4, clamp, sin, floor, fract, float } from 'three/tsl'
4
+ import { grain } from '../../shaders/common/grain'
5
+ import { vignette } from '../../shaders/common/grain'
6
+ import { luminance } from '../../shaders/common/blend'
7
+
8
+ /**
9
+ * Preset: combines grain + warm tone shift + vignette + slight fade.
10
+ * A convenient one-stop aged film look.
11
+ */
12
+ const props = withDefaults(defineProps<{
13
+ /** Overall intensity: 0 = no effect, 1 = full aged look */
14
+ intensity?: number
15
+ /** Grain strength */
16
+ grainStrength?: number
17
+ /** Vignette darkness */
18
+ vignetteStrength?: number
19
+ /** Warm shadow tint amount */
20
+ warmth?: number
21
+ order?: number
22
+ }>(), { intensity: 1, grainStrength: 0.04, vignetteStrength: 0.5, warmth: 0.15, order: 0 })
23
+
24
+ const intensityNode = uniform(props.intensity)
25
+ const grainNode = uniform(props.grainStrength)
26
+ const vigNode = uniform(props.vignetteStrength)
27
+ const warmthNode = uniform(props.warmth)
28
+ watch(() => props.intensity, v => { intensityNode.value = v })
29
+ watch(() => props.grainStrength, v => { grainNode.value = v })
30
+ watch(() => props.vignetteStrength, v => { vigNode.value = v })
31
+ watch(() => props.warmth, v => { warmthNode.value = v })
32
+
33
+ const pipeline = useShaderPipelineContext()
34
+
35
+ useShaderStage(
36
+ (prev) => {
37
+ const uv = pipeline.uvNode.value
38
+ const t = time
39
+
40
+ // Film grain
41
+ const seed = floor(t.mul(24))
42
+ const g = grain(uv, grainNode, seed)
43
+
44
+ // Warm shadows: boost R and reduce B in dark areas
45
+ const lum = luminance(prev.xyz)
46
+ const shadowWarm = float(1).sub(lum).mul(warmthNode)
47
+ const warm = prev.xyz.add(vec3(shadowWarm, shadowWarm.mul(0.3), shadowWarm.negate()))
48
+
49
+ // Vignette
50
+ const vig = vignette(uv, vigNode, float(0.4))
51
+
52
+ // Slight overall fade (film desaturation/lift)
53
+ const faded = warm.mul(float(0.92)).add(float(0.04))
54
+
55
+ const result = clamp(faded.mul(vig).add(g), 0, 1)
56
+ return vec4(result.mix(prev.xyz, float(1).sub(intensityNode)), prev.w)
57
+ },
58
+ props.order,
59
+ )
60
+ </script>
61
+
62
+ <template><!-- --></template>
@@ -0,0 +1,81 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector3 } from 'three'
4
+ import { uniform, time, vec2, vec3, vec4, mix, sin, float, clamp } from 'three/tsl'
5
+ import { fbm2D } from '../../shaders/common/noise'
6
+
7
+ /**
8
+ * Aurora borealis — layered animated colour bands across the upper screen.
9
+ * Uses FBM noise to create organic ribbon-like curtains of light.
10
+ */
11
+ const props = withDefaults(defineProps<{
12
+ /** Primary aurora colour */
13
+ colorA?: string
14
+ /** Secondary aurora colour */
15
+ colorB?: string
16
+ /** Vertical position of aurora band centre */
17
+ bandY?: number
18
+ /** Vertical band height */
19
+ bandHeight?: number
20
+ /** Animation speed */
21
+ speed?: number
22
+ /** Effect intensity */
23
+ intensity?: number
24
+ order?: number
25
+ }>(), {
26
+ colorA: '#00ff88',
27
+ colorB: '#8844ff',
28
+ bandY: 0.7,
29
+ bandHeight: 0.3,
30
+ speed: 0.3,
31
+ intensity: 0.7,
32
+ order: 0,
33
+ })
34
+
35
+ function toVec3Node(hex: string) {
36
+ const c = new Color(hex)
37
+ return uniform(new Vector3(c.r, c.g, c.b))
38
+ }
39
+
40
+ const colorANode = toVec3Node(props.colorA)
41
+ const colorBNode = toVec3Node(props.colorB)
42
+ const bandYNode = uniform(props.bandY)
43
+ const bandHNode = uniform(props.bandHeight)
44
+ const speedNode = uniform(props.speed)
45
+ const intensityNode = uniform(props.intensity)
46
+ watch(() => props.colorA, v => { const c = new Color(v); colorANode.value.set(c.r, c.g, c.b) })
47
+ watch(() => props.colorB, v => { const c = new Color(v); colorBNode.value.set(c.r, c.g, c.b) })
48
+ watch(() => props.bandY, v => { bandYNode.value = v })
49
+ watch(() => props.bandHeight, v => { bandHNode.value = v })
50
+ watch(() => props.speed, v => { speedNode.value = v })
51
+ watch(() => props.intensity, v => { intensityNode.value = v })
52
+
53
+ const pipeline = useShaderPipelineContext()
54
+
55
+ useShaderStage(
56
+ (prev) => {
57
+ const uv = pipeline.uvNode.value
58
+ const t = time.mul(speedNode)
59
+
60
+ // FBM-warped vertical position to create curtain ripple
61
+ const warpedX = uv.x.add(fbm2D(uv.mul(2).add(t)).mul(0.15))
62
+ // warpedX is a float (scalar) — must wrap in vec2 before passing to fbm2D
63
+ const n = fbm2D(vec2(warpedX, uv.y).mul(3).add(t.mul(0.5)))
64
+
65
+ // Vertical band mask — soft gaussian around bandY
66
+ const dy = uv.y.sub(bandYNode.add(n.mul(0.1)))
67
+ const bandMask = clamp(float(1).sub(dy.abs().div(bandHNode)), 0, 1)
68
+ bandMask.pow(2)
69
+
70
+ // Colour: mix A/B via second noise layer
71
+ const colourMix = fbm2D(uv.mul(1.5).add(t.mul(0.3).add(1.5))).mul(0.5).add(0.5)
72
+ const aurora = mix(colorANode, colorBNode, colourMix)
73
+
74
+ const contribution = aurora.mul(bandMask.pow(2)).mul(intensityNode)
75
+ return vec4(prev.xyz.add(contribution), prev.w)
76
+ },
77
+ props.order,
78
+ )
79
+ </script>
80
+
81
+ <template><!-- --></template>
@@ -0,0 +1,46 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector3 } from 'three'
4
+ import { uniform, vec4, mix } from 'three/tsl'
5
+
6
+ const props = withDefaults(defineProps<{
7
+ /** Bottom-left corner colour */
8
+ bottomLeft?: string
9
+ /** Bottom-right corner colour */
10
+ bottomRight?: string
11
+ /** Top-left corner colour */
12
+ topLeft?: string
13
+ /** Top-right corner colour */
14
+ topRight?: string
15
+ order?: number
16
+ }>(), { bottomLeft: '#000000', bottomRight: '#ff0000', topLeft: '#0000ff', topRight: '#ffffff', order: 0 })
17
+
18
+ function toVec3Node(hex: string) {
19
+ const c = new Color(hex)
20
+ return uniform(new Vector3(c.r, c.g, c.b))
21
+ }
22
+
23
+ const blNode = toVec3Node(props.bottomLeft)
24
+ const brNode = toVec3Node(props.bottomRight)
25
+ const tlNode = toVec3Node(props.topLeft)
26
+ const trNode = toVec3Node(props.topRight)
27
+ watch(() => props.bottomLeft, v => { const c = new Color(v); blNode.value.set(c.r, c.g, c.b) })
28
+ watch(() => props.bottomRight, v => { const c = new Color(v); brNode.value.set(c.r, c.g, c.b) })
29
+ watch(() => props.topLeft, v => { const c = new Color(v); tlNode.value.set(c.r, c.g, c.b) })
30
+ watch(() => props.topRight, v => { const c = new Color(v); trNode.value.set(c.r, c.g, c.b) })
31
+
32
+ const pipeline = useShaderPipelineContext()
33
+
34
+ useShaderStage(
35
+ () => {
36
+ const uvCurrent = pipeline.uvNode.value
37
+ const bottom = mix(blNode, brNode, uvCurrent.x)
38
+ const top = mix(tlNode, trNode, uvCurrent.x)
39
+ const colour = mix(bottom, top, uvCurrent.y)
40
+ return vec4(colour, 1.0)
41
+ },
42
+ props.order,
43
+ )
44
+ </script>
45
+
46
+ <template><!-- --></template>
@@ -0,0 +1,42 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector3 } from 'three'
4
+ import { uniform, time, vec4, mix, float } from 'three/tsl'
5
+ import { turbulence2D } from '../../shaders/common/noise'
6
+
7
+ /** Billow/turbulence noise — folded abs() of FBM, producing cloud-like forms. */
8
+ const props = withDefaults(defineProps<{
9
+ colorA?: string
10
+ colorB?: string
11
+ scale?: number
12
+ speed?: number
13
+ order?: number
14
+ }>(), { colorA: '#1a3a8a', colorB: '#ffffff', scale: 2, speed: 0.1, order: 0 })
15
+
16
+ function toVec3Node(hex: string) {
17
+ const c = new Color(hex)
18
+ return uniform(new Vector3(c.r, c.g, c.b))
19
+ }
20
+
21
+ const colorANode = toVec3Node(props.colorA)
22
+ const colorBNode = toVec3Node(props.colorB)
23
+ const scaleNode = uniform(props.scale)
24
+ const speedNode = uniform(props.speed)
25
+ watch(() => props.colorA, v => { const c = new Color(v); colorANode.value.set(c.r, c.g, c.b) })
26
+ watch(() => props.colorB, v => { const c = new Color(v); colorBNode.value.set(c.r, c.g, c.b) })
27
+ watch(() => props.scale, v => { scaleNode.value = v })
28
+ watch(() => props.speed, v => { speedNode.value = v })
29
+
30
+ const pipeline = useShaderPipelineContext()
31
+
32
+ useShaderStage(
33
+ () => {
34
+ const uv = pipeline.uvNode.value
35
+ const n = turbulence2D(uv.mul(scaleNode).add(time.mul(speedNode)))
36
+ return vec4(mix(colorANode, colorBNode, n), float(1))
37
+ },
38
+ props.order,
39
+ )
40
+ </script>
41
+
42
+ <template><!-- --></template>
@@ -0,0 +1,25 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, vec4 } from 'three/tsl'
4
+ import { brightness, contrast } from '../../shaders/common/blend'
5
+
6
+ const props = withDefaults(defineProps<{
7
+ /** Additive brightness offset: 0 = unchanged, positive = brighter */
8
+ brightness?: number
9
+ /** Contrast multiplier: 1 = unchanged, >1 = more contrast */
10
+ contrast?: number
11
+ order?: number
12
+ }>(), { brightness: 0, contrast: 1, order: 0 })
13
+
14
+ const brightnessNode = uniform(props.brightness)
15
+ const contrastNode = uniform(props.contrast)
16
+ watch(() => props.brightness, v => { brightnessNode.value = v })
17
+ watch(() => props.contrast, v => { contrastNode.value = v })
18
+
19
+ useShaderStage(
20
+ (prev) => vec4(brightness(contrast(prev.xyz, contrastNode), brightnessNode), prev.w),
21
+ props.order,
22
+ )
23
+ </script>
24
+
25
+ <template><!-- --></template>
@@ -0,0 +1,41 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector3 } from 'three'
4
+ import { uniform, time, vec4, mix, float } from 'three/tsl'
5
+ import { voronoi2D } from '../../shaders/common/noise'
6
+
7
+ const props = withDefaults(defineProps<{
8
+ colorA?: string
9
+ colorB?: string
10
+ scale?: number
11
+ speed?: number
12
+ order?: number
13
+ }>(), { colorA: '#000033', colorB: '#ffffff', scale: 8, speed: 0.1, order: 0 })
14
+
15
+ function toVec3Node(hex: string) {
16
+ const c = new Color(hex)
17
+ return uniform(new Vector3(c.r, c.g, c.b))
18
+ }
19
+
20
+ const colorANode = toVec3Node(props.colorA)
21
+ const colorBNode = toVec3Node(props.colorB)
22
+ const scaleNode = uniform(props.scale)
23
+ const speedNode = uniform(props.speed)
24
+ watch(() => props.colorA, v => { const c = new Color(v); colorANode.value.set(c.r, c.g, c.b) })
25
+ watch(() => props.colorB, v => { const c = new Color(v); colorBNode.value.set(c.r, c.g, c.b) })
26
+ watch(() => props.scale, v => { scaleNode.value = v })
27
+ watch(() => props.speed, v => { speedNode.value = v })
28
+
29
+ const pipeline = useShaderPipelineContext()
30
+
31
+ useShaderStage(
32
+ () => {
33
+ const uv = pipeline.uvNode.value
34
+ const { distance } = voronoi2D(uv.add(time.mul(speedNode)), scaleNode)
35
+ return vec4(mix(colorANode, colorBNode, distance.min(float(1))), float(1))
36
+ },
37
+ props.order,
38
+ )
39
+ </script>
40
+
41
+ <template><!-- --></template>
@@ -0,0 +1,44 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, vec3, vec4, float } from 'three/tsl'
4
+
5
+ /**
6
+ * Arbitrary RGB channel mixing matrix.
7
+ * Each output channel is a weighted sum of all three input channels.
8
+ * Identity: rr=1 gg=1 bb=1, all cross-terms = 0.
9
+ */
10
+ const props = withDefaults(defineProps<{
11
+ /** R channel: [R contribution, G contribution, B contribution] */
12
+ rRow?: [number, number, number]
13
+ /** G channel: [R contribution, G contribution, B contribution] */
14
+ gRow?: [number, number, number]
15
+ /** B channel: [R contribution, G contribution, B contribution] */
16
+ bRow?: [number, number, number]
17
+ order?: number
18
+ }>(), {
19
+ rRow: () => [1, 0, 0],
20
+ gRow: () => [0, 1, 0],
21
+ bRow: () => [0, 0, 1],
22
+ order: 0,
23
+ })
24
+
25
+ const rrNode = uniform(props.rRow[0]); const rgNode = uniform(props.rRow[1]); const rbNode = uniform(props.rRow[2])
26
+ const grNode = uniform(props.gRow[0]); const ggNode = uniform(props.gRow[1]); const gbNode = uniform(props.gRow[2])
27
+ const brNode = uniform(props.bRow[0]); const bgNode = uniform(props.bRow[1]); const bbNode = uniform(props.bRow[2])
28
+
29
+ watch(() => props.rRow, ([r, g, b]) => { rrNode.value = r; rgNode.value = g; rbNode.value = b })
30
+ watch(() => props.gRow, ([r, g, b]) => { grNode.value = r; ggNode.value = g; gbNode.value = b })
31
+ watch(() => props.bRow, ([r, g, b]) => { brNode.value = r; bgNode.value = g; bbNode.value = b })
32
+
33
+ useShaderStage(
34
+ (prev) => {
35
+ const r = prev.r.mul(rrNode).add(prev.g.mul(rgNode)).add(prev.b.mul(rbNode))
36
+ const g = prev.r.mul(grNode).add(prev.g.mul(ggNode)).add(prev.b.mul(gbNode))
37
+ const b = prev.r.mul(brNode).add(prev.g.mul(bgNode)).add(prev.b.mul(bbNode))
38
+ return vec4(vec3(r, g, b), prev.w)
39
+ },
40
+ props.order,
41
+ )
42
+ </script>
43
+
44
+ <template><!-- --></template>
@@ -0,0 +1,60 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, time, vec4, float } from 'three/tsl'
4
+ import { simplexNoise2D } from '../../shaders/common/noise'
5
+
6
+ /**
7
+ * Noise-distorted Chebyshev box shape — the genuary22 pattern.
8
+ * Formula: 1 - max(abs(uv.x * scaleX * n), abs(uv.y * scaleY * n2))
9
+ * where n, n2 are two simplex noise octaves at different frequencies.
10
+ * Produces a noise-eroded cross/box silhouette. Outputs a float mask for CosinePalette.
11
+ */
12
+ const props = withDefaults(defineProps<{
13
+ /** Horizontal scale of the box */
14
+ scaleX?: number
15
+ /** Vertical scale of the box */
16
+ scaleY?: number
17
+ /** Noise frequency for the first octave (X distortion) */
18
+ noiseFreq1?: number
19
+ /** Noise frequency for the second octave (Y distortion) */
20
+ noiseFreq2?: number
21
+ /** Animation speed */
22
+ speed?: number
23
+ order?: number
24
+ }>(), { scaleX: 2, scaleY: 2, noiseFreq1: 1.5, noiseFreq2: 2.3, speed: 0.2, order: 0 })
25
+
26
+ const scaleXNode = uniform(props.scaleX)
27
+ const scaleYNode = uniform(props.scaleY)
28
+ const freq1Node = uniform(props.noiseFreq1)
29
+ const freq2Node = uniform(props.noiseFreq2)
30
+ const speedNode = uniform(props.speed)
31
+ watch(() => props.scaleX, v => { scaleXNode.value = v })
32
+ watch(() => props.scaleY, v => { scaleYNode.value = v })
33
+ watch(() => props.noiseFreq1, v => { freq1Node.value = v })
34
+ watch(() => props.noiseFreq2, v => { freq2Node.value = v })
35
+ watch(() => props.speed, v => { speedNode.value = v })
36
+
37
+ const pipeline = useShaderPipelineContext()
38
+
39
+ useShaderStage(
40
+ () => {
41
+ const uvCurrent = pipeline.uvNode.value
42
+ const centered = uvCurrent.sub(0.5)
43
+ const t = time.mul(speedNode)
44
+
45
+ const n = simplexNoise2D(centered.mul(freq1Node).add(t)).mul(0.5).add(0.5)
46
+ const n2 = simplexNoise2D(centered.mul(freq2Node).sub(t.mul(0.7))).mul(0.5).add(0.5)
47
+
48
+ const box = float(1).sub(
49
+ centered.x.mul(scaleXNode).mul(n).abs().max(
50
+ centered.y.mul(scaleYNode).mul(n2).abs()
51
+ )
52
+ ).max(float(0))
53
+
54
+ return vec4(box, box, box, float(1))
55
+ },
56
+ props.order,
57
+ )
58
+ </script>
59
+
60
+ <template><!-- --></template>
@@ -0,0 +1,41 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector3 } from 'three'
4
+ import { uniform, vec4, mix } from 'three/tsl'
5
+ import { checker } from '../../shaders/common/shapes'
6
+
7
+ const props = withDefaults(defineProps<{
8
+ /** First checker colour */
9
+ colorA?: string
10
+ /** Second checker colour */
11
+ colorB?: string
12
+ /** Number of checker tiles across each axis */
13
+ scale?: number
14
+ order?: number
15
+ }>(), { colorA: '#ffffff', colorB: '#000000', scale: 10, order: 0 })
16
+
17
+ function toVec3Node(hex: string) {
18
+ const c = new Color(hex)
19
+ return uniform(new Vector3(c.r, c.g, c.b))
20
+ }
21
+
22
+ const colorANode = toVec3Node(props.colorA)
23
+ const colorBNode = toVec3Node(props.colorB)
24
+ const scaleNode = uniform(props.scale)
25
+ watch(() => props.colorA, v => { const c = new Color(v); colorANode.value.set(c.r, c.g, c.b) })
26
+ watch(() => props.colorB, v => { const c = new Color(v); colorBNode.value.set(c.r, c.g, c.b) })
27
+ watch(() => props.scale, v => { scaleNode.value = v })
28
+
29
+ const pipeline = useShaderPipelineContext()
30
+
31
+ useShaderStage(
32
+ () => {
33
+ const uvCurrent = pipeline.uvNode.value
34
+ const t = checker(uvCurrent, scaleNode)
35
+ return vec4(mix(colorANode, colorBNode, t), 1.0)
36
+ },
37
+ props.order,
38
+ )
39
+ </script>
40
+
41
+ <template><!-- --></template>
@@ -0,0 +1,52 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, time, vec3, vec4, sin, float } from 'three/tsl'
4
+
5
+ /**
6
+ * Chromatic aberration — RGB channel offset approximated without texture sampling.
7
+ * Shifts colour contribution along each channel using screen-position phase offsets.
8
+ */
9
+ const props = withDefaults(defineProps<{
10
+ /** How far channels separate */
11
+ strength?: number
12
+ /** Boost aberration at screen edges */
13
+ edgeFalloff?: number
14
+ /** Animation speed for subtle drift */
15
+ speed?: number
16
+ order?: number
17
+ }>(), { strength: 0.008, edgeFalloff: 1.5, speed: 0.2, order: 0 })
18
+
19
+ const strengthNode = uniform(props.strength)
20
+ const edgeNode = uniform(props.edgeFalloff)
21
+ const speedNode = uniform(props.speed)
22
+ watch(() => props.strength, v => { strengthNode.value = v })
23
+ watch(() => props.edgeFalloff, v => { edgeNode.value = v })
24
+ watch(() => props.speed, v => { speedNode.value = v })
25
+
26
+ const pipeline = useShaderPipelineContext()
27
+
28
+ useShaderStage(
29
+ (prev) => {
30
+ const uv = pipeline.uvNode.value
31
+ const t = time.mul(speedNode)
32
+
33
+ // Edge mask: stronger near screen corners
34
+ const fromCenter = uv.sub(0.5).length().mul(edgeNode)
35
+
36
+ // Phase offsets per channel — small sinusoidal drift over time
37
+ const drift = sin(t).mul(0.002)
38
+ const rShift = strengthNode.add(drift)
39
+ const bShift = strengthNode.negate().sub(drift)
40
+
41
+ // Approximate channel shift: modulate the colour channels by phase-offset luminance
42
+ const rContrib = prev.x.mul(float(1).add(rShift.mul(fromCenter)))
43
+ const gContrib = prev.y
44
+ const bContrib = prev.z.mul(float(1).add(bShift.mul(fromCenter)))
45
+
46
+ return vec4(vec3(rContrib, gContrib, bContrib), prev.w)
47
+ },
48
+ props.order,
49
+ )
50
+ </script>
51
+
52
+ <template><!-- --></template>
@@ -0,0 +1,49 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, time, vec3, vec4, sin, float } from 'three/tsl'
4
+
5
+ /**
6
+ * Per-channel animated sine waves along the Y axis — the CRT chromatic oscillation effect.
7
+ * Each RGB channel gets its own phase offset, producing subtle chromatic breathing.
8
+ * Pattern: R: sin(freq/res * uv.y + (-time*speed - phaseOffset))
9
+ */
10
+ const props = withDefaults(defineProps<{
11
+ /** Wave amplitude (fraction of screen) */
12
+ amplitude?: number
13
+ /** Number of wave cycles across the screen height */
14
+ frequency?: number
15
+ /** Wave scroll speed */
16
+ speed?: number
17
+ /** Phase separation between RGB channels (radians) */
18
+ phaseOffset?: number
19
+ order?: number
20
+ }>(), { amplitude: 0.075, frequency: 20, speed: 2, phaseOffset: 0.4, order: 0 })
21
+
22
+ const ampNode = uniform(props.amplitude)
23
+ const freqNode = uniform(props.frequency)
24
+ const speedNode = uniform(props.speed)
25
+ const phaseNode = uniform(props.phaseOffset)
26
+ watch(() => props.amplitude, v => { ampNode.value = v })
27
+ watch(() => props.frequency, v => { freqNode.value = v })
28
+ watch(() => props.speed, v => { speedNode.value = v })
29
+ watch(() => props.phaseOffset, v => { phaseNode.value = v })
30
+
31
+ const pipeline = useShaderPipelineContext()
32
+
33
+ useShaderStage(
34
+ (prev) => {
35
+ const uvCurrent = pipeline.uvNode.value
36
+ const t = time.mul(speedNode).negate()
37
+
38
+ const base = freqNode.mul(uvCurrent.y)
39
+ const r = sin(base.add(t.sub(phaseNode))).mul(ampNode).add(float(1).sub(ampNode))
40
+ const g = sin(base.add(t)).mul(ampNode).add(float(1).sub(ampNode))
41
+ const b = sin(base.add(t.add(phaseNode))).mul(ampNode).add(float(1).sub(ampNode))
42
+
43
+ return vec4(prev.xyz.mul(vec3(r, g, b)), prev.w)
44
+ },
45
+ props.order,
46
+ )
47
+ </script>
48
+
49
+ <template><!-- --></template>