kmcom-nuxt-layers 1.6.4 → 1.6.7

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 (167) 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/layers/ui/app/app.config.ts +2 -16
  166. package/layers/ui/app/types/app-config.d.ts +17 -0
  167. package/package.json +9 -7
@@ -0,0 +1,25 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, cos, sin, vec3 } from 'three/tsl'
4
+
5
+ const props = withDefaults(defineProps<{
6
+ /** Rotation angle in radians */
7
+ angle?: number
8
+ order?: number
9
+ }>(), { angle: 0, order: 0 })
10
+
11
+ const angleNode = uniform(props.angle)
12
+ watch(() => props.angle, v => { angleNode.value = v })
13
+
14
+ useShaderStage(
15
+ (ray) => {
16
+ const c = cos(angleNode)
17
+ const s = sin(angleNode)
18
+ return vec3(ray.x.mul(c).add(ray.z.mul(s)), ray.y, ray.z.mul(c).sub(ray.x.mul(s)))
19
+ },
20
+ props.order,
21
+ 'ray',
22
+ )
23
+ </script>
24
+
25
+ <template><!-- --></template>
@@ -0,0 +1,25 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, cos, sin, vec3 } from 'three/tsl'
4
+
5
+ const props = withDefaults(defineProps<{
6
+ /** Rotation angle in radians */
7
+ angle?: number
8
+ order?: number
9
+ }>(), { angle: 0, order: 0 })
10
+
11
+ const angleNode = uniform(props.angle)
12
+ watch(() => props.angle, v => { angleNode.value = v })
13
+
14
+ useShaderStage(
15
+ (ray) => {
16
+ const c = cos(angleNode)
17
+ const s = sin(angleNode)
18
+ return vec3(ray.x.mul(c).sub(ray.y.mul(s)), ray.x.mul(s).add(ray.y.mul(c)), ray.z)
19
+ },
20
+ props.order,
21
+ 'ray',
22
+ )
23
+ </script>
24
+
25
+ <template><!-- --></template>
@@ -0,0 +1,41 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, cos, sin, vec3 } from 'three/tsl'
4
+
5
+ const props = withDefaults(defineProps<{
6
+ /** Yaw offset in radians (horizontal look) */
7
+ yaw?: number
8
+ /** Pitch offset in radians (vertical tilt) */
9
+ pitch?: number
10
+ /** Roll offset in radians */
11
+ roll?: number
12
+ order?: number
13
+ }>(), { yaw: 0, pitch: 0, roll: 0, order: 0 })
14
+
15
+ const yawNode = uniform(props.yaw)
16
+ const pitchNode = uniform(props.pitch)
17
+ const rollNode = uniform(props.roll)
18
+ watch(() => props.yaw, v => { yawNode.value = v })
19
+ watch(() => props.pitch, v => { pitchNode.value = v })
20
+ watch(() => props.roll, v => { rollNode.value = v })
21
+
22
+ useShaderStage(
23
+ (ray) => {
24
+ // Yaw (Y)
25
+ const cy = cos(yawNode); const sy = sin(yawNode)
26
+ const r1 = vec3(ray.x.mul(cy).add(ray.z.mul(sy)), ray.y, ray.z.mul(cy).sub(ray.x.mul(sy)))
27
+
28
+ // Pitch (X)
29
+ const cp = cos(pitchNode); const sp = sin(pitchNode)
30
+ const r2 = vec3(r1.x, r1.y.mul(cp).sub(r1.z.mul(sp)), r1.y.mul(sp).add(r1.z.mul(cp)))
31
+
32
+ // Roll (Z)
33
+ const cr = cos(rollNode); const sr = sin(rollNode)
34
+ return vec3(r2.x.mul(cr).sub(r2.y.mul(sr)), r2.x.mul(sr).add(r2.y.mul(cr)), r2.z)
35
+ },
36
+ props.order,
37
+ 'ray',
38
+ )
39
+ </script>
40
+
41
+ <template><!-- --></template>
@@ -0,0 +1,101 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector3 } from 'three'
4
+ import { Fn, uniform, time, Loop, If, Break, vec3, vec4, float, clamp, mix, sin, cos, abs } from 'three/tsl'
5
+
6
+ const props = withDefaults(defineProps<{
7
+ /** Tunnel inner radius */
8
+ radius?: number
9
+ /** How fast the camera flies forward */
10
+ speed?: number
11
+ /** Wall colour A */
12
+ colorA?: string
13
+ /** Wall colour B */
14
+ colorB?: string
15
+ /** Number of march steps (fixed at shader compile) */
16
+ steps?: number
17
+ order?: number
18
+ }>(), {
19
+ radius: 0.8,
20
+ speed: 1,
21
+ colorA: '#1a0a3a',
22
+ colorB: '#ff4488',
23
+ steps: 64,
24
+ order: 0,
25
+ })
26
+
27
+ const radiusNode = uniform(props.radius)
28
+ const speedNode = uniform(props.speed)
29
+
30
+ function toVec3Node(hex: string) {
31
+ const c = new Color(hex)
32
+ return uniform(new Vector3(c.r, c.g, c.b))
33
+ }
34
+ const colorANode = toVec3Node(props.colorA)
35
+ const colorBNode = toVec3Node(props.colorB)
36
+
37
+ watch(() => props.radius, v => { radiusNode.value = v })
38
+ watch(() => props.speed, v => { speedNode.value = v })
39
+ watch(() => props.colorA, v => { const c = new Color(v); colorANode.value.set(c.r, c.g, c.b) })
40
+ watch(() => props.colorB, v => { const c = new Color(v); colorBNode.value.set(c.r, c.g, c.b) })
41
+
42
+ const pipeline = useShaderPipelineContext()
43
+
44
+ // Fn defined once at setup — Loop/If/Break/toVar/addAssign require a Fn() stack at compile time
45
+ const raymarchFn = Fn(([ray]) => {
46
+ // Three.js calls Fn bodies with null args during type-inference — bail out safely
47
+ if (!ray) return vec4(0, 0, 0, 0)
48
+
49
+ // Camera flies forward along Z
50
+ const camZ = time.mul(speedNode)
51
+ const ro = vec3(float(0), float(0), camZ)
52
+ const rd = ray.normalize()
53
+
54
+ const t = float(0).toVar()
55
+ const colour = vec3(0, 0, 0).toVar()
56
+ const hit = float(0).toVar()
57
+
58
+ Loop(props.steps, () => {
59
+ const p = ro.add(rd.mul(t))
60
+
61
+ // Tunnel SDF: cylinder with twisted walls
62
+ const twist = sin(p.z.mul(0.3).add(camZ.mul(0.1))).mul(0.15)
63
+ const d = p.xy.add(vec3(twist, twist, float(0)).xy).length().sub(radiusNode)
64
+
65
+ If(d.lessThan(float(0.001)), () => {
66
+ // Pattern on wall: mix colours by angle around tunnel
67
+ const angle = p.y.atan(p.x).mul(0.5).add(0.5)
68
+ const stripe = sin(p.z.mul(4.0).add(time)).mul(0.5).add(0.5)
69
+ const band = mix(colorANode, colorBNode, clamp(angle.add(stripe.mul(0.3)), 0, 1))
70
+ colour.assign(band)
71
+ hit.assign(float(1))
72
+ Break()
73
+ })
74
+
75
+ t.addAssign(abs(d).max(float(0.01)))
76
+
77
+ If(t.greaterThan(float(20.0)), () => { Break() })
78
+ })
79
+
80
+ // Fog out the far end of the tunnel
81
+ const fog = clamp(float(1).sub(t.div(20.0)), 0, 1)
82
+ const finalColour = colour.mul(fog).mul(hit)
83
+
84
+ return vec4(finalColour, hit)
85
+ })
86
+
87
+ useShaderStage(
88
+ () => {
89
+ // Fall back to a simple perspective ray from UV when no ray node is set
90
+ const provided = pipeline.rayNode.value
91
+ const uvc = pipeline.uvNode.value
92
+ // Use +1 for Z so the ray points forward into the tunnel (matching Pipeline.client.vue screenRayNode)
93
+ const ray = provided ?? (uvc ? vec3(uvc.sub(0.5).mul(2).x, uvc.sub(0.5).mul(2).y, float(1)) : null)
94
+ if (!ray) return vec4(0, 0, 0, 0)
95
+ return raymarchFn([ray])
96
+ },
97
+ props.order,
98
+ )
99
+ </script>
100
+
101
+ <template><!-- --></template>
@@ -0,0 +1,47 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector3 } from 'three'
4
+ import { uniform, vec4, mix, float } from 'three/tsl'
5
+ import { roundedRect } from '../../shaders/common/shapes'
6
+
7
+ const props = withDefaults(defineProps<{
8
+ colorA?: string
9
+ colorB?: string
10
+ width?: number
11
+ height?: number
12
+ cornerRadius?: number
13
+ softness?: number
14
+ order?: number
15
+ }>(), { colorA: '#000000', colorB: '#ffffff', width: 0.6, height: 0.4, cornerRadius: 0.05, softness: 0.01, 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 widthNode = uniform(props.width)
25
+ const heightNode = uniform(props.height)
26
+ const cornerNode = uniform(props.cornerRadius)
27
+ const softnessNode = uniform(props.softness)
28
+ watch(() => props.colorA, v => { const c = new Color(v); colorANode.value.set(c.r, c.g, c.b) })
29
+ watch(() => props.colorB, v => { const c = new Color(v); colorBNode.value.set(c.r, c.g, c.b) })
30
+ watch(() => props.width, v => { widthNode.value = v })
31
+ watch(() => props.height, v => { heightNode.value = v })
32
+ watch(() => props.cornerRadius, v => { cornerNode.value = v })
33
+ watch(() => props.softness, v => { softnessNode.value = v })
34
+
35
+ const pipeline = useShaderPipelineContext()
36
+
37
+ useShaderStage(
38
+ () => {
39
+ const uv = pipeline.uvNode.value
40
+ const mask = roundedRect(uv, [0.5, 0.5], widthNode, cornerNode, softnessNode)
41
+ return vec4(mix(colorANode, colorBNode, mask), float(1))
42
+ },
43
+ props.order,
44
+ )
45
+ </script>
46
+
47
+ <template><!-- --></template>
@@ -0,0 +1,18 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { vec4 } from 'three/tsl'
4
+ import { reinhardTonemap } from '../../shaders/common/tonemapping'
5
+
6
+ /**
7
+ * Simple Reinhard tone mapping: col / (col + 1).
8
+ * Compresses HDR values with no hard clip — highlights desaturate toward white.
9
+ */
10
+ const { order = 0 } = defineProps<{ order?: number }>()
11
+
12
+ useShaderStage(
13
+ (prev) => vec4(reinhardTonemap(prev.xyz), prev.w),
14
+ order,
15
+ )
16
+ </script>
17
+
18
+ <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 { ridgedFbm2d } 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: '#000000', colorB: '#ffffff', scale: 2, 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 n = ridgedFbm2d(uv.mul(scaleNode).add(time.mul(speedNode)))
35
+ return vec4(mix(colorANode, colorBNode, n), 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 { Color, Vector3 } from 'three'
4
+ import { uniform, vec4, mix, float } from 'three/tsl'
5
+ import { ring } from '../../shaders/common/shapes'
6
+
7
+ const props = withDefaults(defineProps<{
8
+ colorA?: string
9
+ colorB?: string
10
+ innerRadius?: number
11
+ outerRadius?: number
12
+ softness?: number
13
+ order?: number
14
+ }>(), { colorA: '#000000', colorB: '#ffffff', innerRadius: 0.25, outerRadius: 0.4, softness: 0.01, 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 innerNode = uniform(props.innerRadius)
24
+ const outerNode = uniform(props.outerRadius)
25
+ const softnessNode = uniform(props.softness)
26
+ watch(() => props.colorA, v => { const c = new Color(v); colorANode.value.set(c.r, c.g, c.b) })
27
+ watch(() => props.colorB, v => { const c = new Color(v); colorBNode.value.set(c.r, c.g, c.b) })
28
+ watch(() => props.innerRadius, v => { innerNode.value = v })
29
+ watch(() => props.outerRadius, v => { outerNode.value = v })
30
+ watch(() => props.softness, v => { softnessNode.value = v })
31
+
32
+ const pipeline = useShaderPipelineContext()
33
+
34
+ useShaderStage(
35
+ () => {
36
+ const uv = pipeline.uvNode.value
37
+ const mask = ring(uv, [0.5, 0.5], innerNode, outerNode, softnessNode)
38
+ return vec4(mix(colorANode, colorBNode, mask), float(1))
39
+ },
40
+ props.order,
41
+ )
42
+ </script>
43
+
44
+ <template><!-- --></template>
@@ -0,0 +1,69 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, vec4, float, abs } from 'three/tsl'
4
+
5
+ /**
6
+ * Accumulates ring-shaped SDF fields into a single float mask.
7
+ * Each ring: abs(length(uv + offset) - radius) * scale, then summed.
8
+ * Outputs a grayscale vec4 for consumption by CosinePalette (scalarSource: 'prev')
9
+ * or SDFColourMask.
10
+ *
11
+ * The flare8/flare9 pattern. Includes an optional radial vignette term.
12
+ *
13
+ * @example
14
+ * <RingField :order="0" :ring-radius="0.3" :ring-count="3" />
15
+ * <CosinePalette :order="1" scalar-source="prev" />
16
+ */
17
+ const props = withDefaults(defineProps<{
18
+ /** Radius of the primary ring */
19
+ ringRadius?: number
20
+ /** Number of rings (stacked with equidistant offsets) */
21
+ ringCount?: number
22
+ /** Spacing between stacked rings */
23
+ ringSpread?: number
24
+ /** Sharpness multiplier applied per ring */
25
+ ringScale?: number
26
+ /** Vignette: oneMinus(length(uv * vignetteScale)) — 0 = disabled */
27
+ vignetteScale?: number
28
+ order?: number
29
+ }>(), { ringRadius: 0.3, ringCount: 1, ringSpread: 0.15, ringScale: 4, vignetteScale: 0.8, order: 0 })
30
+
31
+ const ringRadiusNode = uniform(props.ringRadius)
32
+ const ringSpreadNode = uniform(props.ringSpread)
33
+ const ringScaleNode = uniform(props.ringScale)
34
+ const vignetteScaleNode = uniform(props.vignetteScale)
35
+ watch(() => props.ringRadius, v => { ringRadiusNode.value = v })
36
+ watch(() => props.ringSpread, v => { ringSpreadNode.value = v })
37
+ watch(() => props.ringScale, v => { ringScaleNode.value = v })
38
+ watch(() => props.vignetteScale, v => { vignetteScaleNode.value = v })
39
+
40
+ const pipeline = useShaderPipelineContext()
41
+
42
+ useShaderStage(
43
+ () => {
44
+ const uvCurrent = pipeline.uvNode.value
45
+ const centered = uvCurrent.sub(0.5)
46
+
47
+ // Accumulate rings at evenly-spaced radii
48
+ let acc = float(0)
49
+ for (let i = 0; i < props.ringCount; i++) {
50
+ const offset = ringSpreadNode.mul(float(i - (props.ringCount - 1) / 2))
51
+ const r = ringRadiusNode.add(offset)
52
+ const d = abs(centered.length().sub(r)).mul(ringScaleNode).oneMinus().max(float(0))
53
+ acc = acc.add(d)
54
+ }
55
+
56
+ // Optional vignette term
57
+ if (props.vignetteScale > 0) {
58
+ const vignette = float(1).sub(centered.mul(vignetteScaleNode).length()).max(float(0))
59
+ acc = acc.add(vignette)
60
+ }
61
+
62
+ const t = acc.div(float(props.ringCount)).min(float(1))
63
+ return vec4(t, t, t, float(1))
64
+ },
65
+ props.order,
66
+ )
67
+ </script>
68
+
69
+ <template><!-- --></template>
@@ -0,0 +1,74 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { clamp, floor, mix, time, uniform, vec3, vec4 } from 'three/tsl'
4
+ import { grain } from '../../shaders/common/grain'
5
+ import { blendOverlay, blendScreen, blendSoftLight } from '../../shaders/common/blend'
6
+
7
+ type GrainBlendMode = 'add' | 'sub' | 'screen' | 'overlay' | 'soft-light'
8
+
9
+ const props = withDefaults(defineProps<{
10
+ scale?: number
11
+ strength?: number
12
+ opacity?: number
13
+ misregistration?: number
14
+ fps?: number
15
+ blendMode?: GrainBlendMode
16
+ order?: number
17
+ }>(), { scale: 0.6, strength: 0.12, opacity: 1.0, misregistration: 0.003, fps: 8, blendMode: 'add', order: 0 })
18
+
19
+ const scaleNode = uniform(props.scale)
20
+ const strengthNode = uniform(props.strength)
21
+ const opacityNode = uniform(props.opacity)
22
+ const misregNode = uniform(props.misregistration)
23
+ const fpsNode = uniform(props.fps)
24
+ watch(() => props.scale, v => { scaleNode.value = v })
25
+ watch(() => props.strength, v => { strengthNode.value = v })
26
+ watch(() => props.opacity, v => { opacityNode.value = v })
27
+ watch(() => props.misregistration, v => { misregNode.value = v })
28
+ watch(() => props.fps, v => { fpsNode.value = v })
29
+
30
+ const pipeline = useShaderPipelineContext()
31
+
32
+ useShaderStage(
33
+ (prev) => {
34
+ const uv = pipeline.uvNode.value
35
+ const seed = floor(time.mul(fpsNode))
36
+
37
+ const uvR = uv.mul(scaleNode).add(misregNode)
38
+ const uvG = uv.mul(scaleNode)
39
+ const uvB = uv.mul(scaleNode).sub(misregNode)
40
+
41
+ // grain() returns (raw - 0.5) * strength → centred around 0
42
+ const rNoise = grain(uvR, strengthNode, seed)
43
+ const gNoise = grain(uvG, strengthNode, seed.add(17.0))
44
+ const bNoise = grain(uvB, strengthNode, seed.add(31.0))
45
+ const grainVec = vec3(rNoise, gNoise, bNoise)
46
+
47
+ // Lift centred delta back to [0,1] per-channel texture for blend modes
48
+ const rawVec = grainVec.div(strengthNode).add(0.5)
49
+
50
+ const mixFactor = strengthNode.mul(opacityNode)
51
+ let blended
52
+ switch (props.blendMode) {
53
+ case 'sub':
54
+ blended = prev.xyz.sub(grainVec.abs().mul(opacityNode))
55
+ break
56
+ case 'screen':
57
+ blended = mix(prev.xyz, blendScreen(prev.xyz, rawVec), mixFactor)
58
+ break
59
+ case 'overlay':
60
+ blended = mix(prev.xyz, blendOverlay(prev.xyz, rawVec), mixFactor)
61
+ break
62
+ case 'soft-light':
63
+ blended = mix(prev.xyz, blendSoftLight(prev.xyz, rawVec), mixFactor)
64
+ break
65
+ default: // 'add'
66
+ blended = prev.xyz.add(grainVec.mul(opacityNode))
67
+ }
68
+ return vec4(clamp(blended, 0, 1), prev.w)
69
+ },
70
+ props.order,
71
+ )
72
+ </script>
73
+
74
+ <template><!-- --></template>
@@ -0,0 +1,61 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color } from 'three'
4
+ import { mix, smoothstep, uniform, vec4 } from 'three/tsl'
5
+
6
+ /**
7
+ * Blends two colours along a rotated axis — the core Grainient colour pattern.
8
+ * Projects the current UV onto the rotated axis via (uv * Rot(angle)).x,
9
+ * then uses smoothstep to create the gradient.
10
+ *
11
+ * Stack multiple instances at consecutive orders to layer gradients.
12
+ */
13
+ const props = withDefaults(defineProps<{
14
+ colorA?: string
15
+ colorB?: string
16
+ /** Rotation angle in degrees */
17
+ angle?: number
18
+ /** Smoothstep lower edge (0 = sharp at centre-left) */
19
+ edge0?: number
20
+ /** Smoothstep upper edge (1 = sharp at centre-right) */
21
+ edge1?: number
22
+ order?: number
23
+ }>(), {
24
+ colorA: '#000000',
25
+ colorB: '#ffffff',
26
+ angle: -5,
27
+ edge0: 0.25,
28
+ edge1: 0.75,
29
+ order: 0,
30
+ })
31
+
32
+ const colorAVal = new Color(props.colorA)
33
+ const colorBVal = new Color(props.colorB)
34
+ const colorANode = uniform(colorAVal)
35
+ const colorBNode = uniform(colorBVal)
36
+ const angleNode = uniform(props.angle * (Math.PI / 180))
37
+ const edge0Node = uniform(props.edge0)
38
+ const edge1Node = uniform(props.edge1)
39
+
40
+ watch(() => props.colorA, v => { colorANode.value.set(v) })
41
+ watch(() => props.colorB, v => { colorBNode.value.set(v) })
42
+ watch(() => props.angle, v => { angleNode.value = v * (Math.PI / 180) })
43
+ watch(() => props.edge0, v => { edge0Node.value = v })
44
+ watch(() => props.edge1, v => { edge1Node.value = v })
45
+
46
+ const { uvNode } = useShaderPipelineContext()
47
+
48
+ useShaderStage(
49
+ (_prev) => {
50
+ const cosA = angleNode.cos()
51
+ const sinA = angleNode.sin()
52
+ // Project UV onto rotated axis, shift to 0-1 range
53
+ const rotatedX = uvNode.value.x.mul(cosA).sub(uvNode.value.y.mul(sinA)).add(0.5)
54
+ const t = smoothstep(edge0Node, edge1Node, rotatedX)
55
+ return vec4(mix(colorANode, colorBNode, t), 1.0)
56
+ },
57
+ props.order,
58
+ )
59
+ </script>
60
+
61
+ <template><!-- --></template>
@@ -0,0 +1,33 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, vec4, clamp, float } from 'three/tsl'
4
+
5
+ /**
6
+ * Multiplies RGB by prev.r (treating the previous stage as a grayscale scalar mask).
7
+ * Use after a scalar generator (RingField, ChebyshevNoiseField) and before CosinePalette
8
+ * to apply the `col.mul(t)` phobon pattern.
9
+ *
10
+ * Pipeline: RingField (order 0) → SDFColourMask (order 1) → CosinePalette (order 2, scalarSource: 'prev')
11
+ */
12
+ const props = withDefaults(defineProps<{
13
+ /** Raise the mask to a power before applying — values > 1 increase contrast */
14
+ power?: number
15
+ /** Clamp the mask to [0, 1] before multiplying */
16
+ clampMask?: boolean
17
+ order?: number
18
+ }>(), { power: 1, clampMask: true, order: 0 })
19
+
20
+ const powerNode = uniform(props.power)
21
+ watch(() => props.power, v => { powerNode.value = v })
22
+
23
+ useShaderStage(
24
+ (prev) => {
25
+ let mask = prev.x.pow(powerNode)
26
+ if (props.clampMask) mask = clamp(mask, float(0), float(1))
27
+ return vec4(prev.xyz.mul(mask), prev.w)
28
+ },
29
+ props.order,
30
+ )
31
+ </script>
32
+
33
+ <template><!-- --></template>
@@ -0,0 +1,31 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, vec4, float } from 'three/tsl'
4
+
5
+ const props = withDefaults(defineProps<{
6
+ /** Scale factor for the radial distance — larger = tighter mask */
7
+ scale?: number
8
+ /** Softness of the mask edge */
9
+ softness?: number
10
+ order?: number
11
+ }>(), { scale: 1.5, softness: 0.2, order: 0 })
12
+
13
+ const scaleNode = uniform(props.scale)
14
+ const softnessNode = uniform(props.softness)
15
+ watch(() => props.scale, v => { scaleNode.value = v })
16
+ watch(() => props.softness, v => { softnessNode.value = v })
17
+
18
+ const pipeline = useShaderPipelineContext()
19
+
20
+ useShaderStage(
21
+ (prev) => {
22
+ const uvCurrent = pipeline.uvNode.value
23
+ const dist = uvCurrent.sub(0.5).mul(scaleNode).length()
24
+ const mask = float(1).sub(dist).sub(softnessNode).max(0).div(float(1).sub(softnessNode))
25
+ return vec4(prev.xyz, prev.w.mul(mask))
26
+ },
27
+ props.order,
28
+ )
29
+ </script>
30
+
31
+ <template><!-- --></template>
@@ -0,0 +1,25 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, vec4, pow, float } from 'three/tsl'
4
+
5
+ /**
6
+ * Decodes sRGB to linear light — the inverse of LinearToSRGB.
7
+ * Apply before any physically-based blending or tonemapping.
8
+ * Approximate form: pow(col, 2.2).
9
+ */
10
+ const props = withDefaults(defineProps<{
11
+ /** Gamma exponent — 2.2 matches sRGB standard */
12
+ gamma?: number
13
+ order?: number
14
+ }>(), { gamma: 2.2, order: 0 })
15
+
16
+ const gammaNode = uniform(props.gamma)
17
+ watch(() => props.gamma, v => { gammaNode.value = v })
18
+
19
+ useShaderStage(
20
+ (prev) => vec4(pow(prev.xyz.max(float(0)), gammaNode), prev.w),
21
+ props.order,
22
+ )
23
+ </script>
24
+
25
+ <template><!-- --></template>
@@ -0,0 +1,21 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, vec4 } from 'three/tsl'
4
+ import { saturate } from '../../shaders/common/blend'
5
+
6
+ const props = withDefaults(defineProps<{
7
+ /** Saturation boost: 0 = unchanged, positive = more saturated */
8
+ amount?: number
9
+ order?: number
10
+ }>(), { amount: 0.5, order: 0 })
11
+
12
+ const amountNode = uniform(props.amount)
13
+ watch(() => props.amount, v => { amountNode.value = v })
14
+
15
+ useShaderStage(
16
+ (prev) => vec4(saturate(prev.xyz, amountNode), prev.w),
17
+ props.order,
18
+ )
19
+ </script>
20
+
21
+ <template><!-- --></template>