kmcom-nuxt-layers 1.6.3 → 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 +17 -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
@@ -0,0 +1,64 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector2, Vector3 } from 'three'
4
+ import { uniform, vec2, vec3, vec4, smoothstep, sin, cos, float } from 'three/tsl'
5
+
6
+ /**
7
+ * Radial god rays — procedural volumetric light shafts emanating from a source point.
8
+ * Uses angular spokes in UV space to approximate crepuscular rays.
9
+ */
10
+ const props = withDefaults(defineProps<{
11
+ /** Light source UV position */
12
+ position?: [number, number]
13
+ /** Ray colour */
14
+ color?: string
15
+ /** Ray brightness */
16
+ intensity?: number
17
+ /** Number of ray spokes */
18
+ rayCount?: number
19
+ /** Radial decay rate */
20
+ decay?: number
21
+ order?: number
22
+ }>(), { position: () => [0.5, 0.9], color: '#fff9e0', intensity: 0.35, rayCount: 12, decay: 2.0, order: 0 })
23
+
24
+ function toVec3Node(hex: string) {
25
+ const c = new Color(hex)
26
+ return uniform(new Vector3(c.r, c.g, c.b))
27
+ }
28
+
29
+ const posNode = uniform(new Vector2(...props.position))
30
+ const colorNode = toVec3Node(props.color)
31
+ const intensityNode = uniform(props.intensity)
32
+ const rayCountNode = uniform(props.rayCount)
33
+ const decayNode = uniform(props.decay)
34
+ watch(() => props.position, ([x, y]) => { posNode.value.set(x, y) })
35
+ watch(() => props.color, v => { const c = new Color(v); colorNode.value.set(c.r, c.g, c.b) })
36
+ watch(() => props.intensity, v => { intensityNode.value = v })
37
+ watch(() => props.rayCount, v => { rayCountNode.value = v })
38
+ watch(() => props.decay, v => { decayNode.value = v })
39
+
40
+ const pipeline = useShaderPipelineContext()
41
+
42
+ useShaderStage(
43
+ (prev) => {
44
+ const uv = pipeline.uvNode.value
45
+ const src = vec2(posNode.x, posNode.y)
46
+ const dir = uv.sub(src)
47
+ const dist = dir.length()
48
+
49
+ // Angular spokes: cos(angle * rayCount) drives streak pattern
50
+ const angle = dir.y.atan(dir.x)
51
+ const spoke = cos(angle.mul(rayCountNode)).mul(0.5).add(0.5)
52
+ spoke.pow(3)
53
+
54
+ // Radial falloff from source
55
+ const radialFade = smoothstep(decayNode, float(0), dist)
56
+
57
+ const rays = spoke.pow(3).mul(radialFade).mul(intensityNode)
58
+ return vec4(prev.xyz.add(colorNode.mul(rays)), prev.w)
59
+ },
60
+ props.order,
61
+ )
62
+ </script>
63
+
64
+ <template><!-- --></template>
@@ -0,0 +1,42 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector3 } from 'three'
4
+ import { uniform, time, vec3, vec4, mix, float } from 'three/tsl'
5
+ import { gradientNoise3D } 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: 3, speed: 0.2, 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 t = time.mul(speedNode)
35
+ const n = gradientNoise3D(vec3(uv.mul(scaleNode), t)).mul(0.5).add(0.5)
36
+ return vec4(mix(colorANode, colorBNode, n), float(1))
37
+ },
38
+ props.order,
39
+ )
40
+ </script>
41
+
42
+ <template><!-- --></template>
@@ -0,0 +1,81 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { clamp, dot, float, floor, fract, mix, pow, sin, step, time, uniform, vec2, vec4 } from 'three/tsl'
4
+ import { blendOverlay, blendScreen, blendSoftLight } from '../../shaders/common/blend'
5
+
6
+ type GrainBlendMode = 'add' | 'sub' | 'screen' | 'overlay' | 'soft-light'
7
+ type GrainStyle = 'smooth' | 'dotted' | 'coarse'
8
+
9
+ const props = withDefaults(defineProps<{
10
+ intensity?: number
11
+ opacity?: number
12
+ /** UV scale — higher = finer grain, lower = bigger dots */
13
+ size?: number
14
+ /** smooth = continuous noise, dotted = binary on/off specks, coarse = concentrated bright grit */
15
+ style?: GrainStyle
16
+ animated?: boolean
17
+ fps?: number
18
+ blendMode?: GrainBlendMode
19
+ order?: number
20
+ }>(), {
21
+ intensity: 0.08,
22
+ opacity: 1.0,
23
+ size: 1.0,
24
+ style: 'smooth',
25
+ animated: true,
26
+ fps: 24,
27
+ blendMode: 'add',
28
+ order: 0,
29
+ })
30
+
31
+ const intensityNode = uniform(props.intensity)
32
+ const opacityNode = uniform(props.opacity)
33
+ const sizeNode = uniform(props.size)
34
+ const fpsNode = uniform(props.fps)
35
+ watch(() => props.intensity, v => { intensityNode.value = v })
36
+ watch(() => props.opacity, v => { opacityNode.value = v })
37
+ watch(() => props.size, v => { sizeNode.value = v })
38
+ watch(() => props.fps, v => { fpsNode.value = v })
39
+
40
+ const { uvNode } = useShaderPipelineContext()
41
+
42
+ useShaderStage(
43
+ (prev) => {
44
+ const uvScaled = uvNode.value.mul(sizeNode)
45
+ const seed = props.animated ? floor(time.mul(fpsNode)) : float(0)
46
+
47
+ // Raw [0,1] hash noise
48
+ const raw = fract(sin(dot(uvScaled.add(seed), vec2(12.9898, 78.233))).mul(43758.5453))
49
+
50
+ // Shape the noise based on style
51
+ const shaped = props.style === 'dotted'
52
+ ? step(float(0.65), raw) // binary: sparse bright specks
53
+ : props.style === 'coarse'
54
+ ? pow(raw, float(4.0)).mul(2.5) // concentrated bright grit, rest dark
55
+ : raw // smooth: continuous noise
56
+
57
+ const mixFactor = intensityNode.mul(opacityNode)
58
+ let blended
59
+ switch (props.blendMode) {
60
+ case 'sub':
61
+ blended = prev.xyz.sub(shaped.mul(intensityNode).mul(opacityNode))
62
+ break
63
+ case 'screen':
64
+ blended = mix(prev.xyz, blendScreen(prev.xyz, shaped), mixFactor)
65
+ break
66
+ case 'overlay':
67
+ blended = mix(prev.xyz, blendOverlay(prev.xyz, shaped), mixFactor)
68
+ break
69
+ case 'soft-light':
70
+ blended = mix(prev.xyz, blendSoftLight(prev.xyz, shaped), mixFactor)
71
+ break
72
+ default: // 'add'
73
+ blended = prev.xyz.add(shaped.sub(0.5).mul(intensityNode).mul(opacityNode))
74
+ }
75
+ return clamp(vec4(blended, prev.w), 0, 1)
76
+ },
77
+ props.order,
78
+ )
79
+ </script>
80
+
81
+ <template><!-- --></template>
@@ -0,0 +1,43 @@
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 { grid } from '../../shaders/common/shapes'
6
+
7
+ const props = withDefaults(defineProps<{
8
+ /** Background colour */
9
+ colorA?: string
10
+ /** Grid line colour */
11
+ colorB?: string
12
+ cellSize?: number
13
+ lineWidth?: number
14
+ order?: number
15
+ }>(), { colorA: '#000000', colorB: '#ffffff', cellSize: 0.1, lineWidth: 0.005, 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 cellNode = uniform(props.cellSize)
25
+ const lineNode = uniform(props.lineWidth)
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.cellSize, v => { cellNode.value = v })
29
+ watch(() => props.lineWidth, v => { lineNode.value = v })
30
+
31
+ const pipeline = useShaderPipelineContext()
32
+
33
+ useShaderStage(
34
+ () => {
35
+ const uv = pipeline.uvNode.value
36
+ const mask = grid(uv, cellNode, lineNode)
37
+ return vec4(mix(colorANode, colorBNode, mask), float(1))
38
+ },
39
+ props.order,
40
+ )
41
+ </script>
42
+
43
+ <template><!-- --></template>
@@ -0,0 +1,43 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector3 } from 'three'
4
+ import { uniform, vec4, mix, smoothstep, float } from 'three/tsl'
5
+ import { luminance } from '../../shaders/common/blend'
6
+
7
+ /**
8
+ * Red/warm glow bleed around highlight areas — the analogue film halation effect.
9
+ * Bright areas bleed a coloured halo into their surroundings.
10
+ */
11
+ const props = withDefaults(defineProps<{
12
+ /** Glow colour */
13
+ color?: string
14
+ /** Luminance threshold above which glow starts */
15
+ threshold?: number
16
+ /** Glow intensity */
17
+ intensity?: number
18
+ order?: number
19
+ }>(), { color: '#ff2200', threshold: 0.7, intensity: 0.4, order: 0 })
20
+
21
+ function toVec3Node(hex: string) {
22
+ const c = new Color(hex)
23
+ return uniform(new Vector3(c.r, c.g, c.b))
24
+ }
25
+
26
+ const colorNode = toVec3Node(props.color)
27
+ const thresholdNode = uniform(props.threshold)
28
+ const intensityNode = uniform(props.intensity)
29
+ watch(() => props.color, v => { const c = new Color(v); colorNode.value.set(c.r, c.g, c.b) })
30
+ watch(() => props.threshold, v => { thresholdNode.value = v })
31
+ watch(() => props.intensity, v => { intensityNode.value = v })
32
+
33
+ useShaderStage(
34
+ (prev) => {
35
+ const lum = luminance(prev.xyz)
36
+ const glow = smoothstep(thresholdNode, float(1), lum).mul(intensityNode)
37
+ return vec4(prev.xyz.add(colorNode.mul(glow)), prev.w)
38
+ },
39
+ props.order,
40
+ )
41
+ </script>
42
+
43
+ <template><!-- --></template>
@@ -0,0 +1,33 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, vec4 } from 'three/tsl'
4
+ import { halftone } from '../../shaders/common/grain'
5
+ import { luminance } from '../../shaders/common/blend'
6
+
7
+ const props = withDefaults(defineProps<{
8
+ /** Dot density — higher = finer dots */
9
+ scale?: number
10
+ /** Screen angle in radians */
11
+ angle?: number
12
+ order?: number
13
+ }>(), { scale: 50, angle: 0, order: 0 })
14
+
15
+ const scaleNode = uniform(props.scale)
16
+ const angleNode = uniform(props.angle)
17
+ watch(() => props.scale, v => { scaleNode.value = v })
18
+ watch(() => props.angle, v => { angleNode.value = v })
19
+
20
+ const pipeline = useShaderPipelineContext()
21
+
22
+ useShaderStage(
23
+ (prev) => {
24
+ const uvCurrent = pipeline.uvNode.value
25
+ const lum = luminance(prev.xyz)
26
+ const dot = halftone(uvCurrent, lum, scaleNode, angleNode)
27
+ return vec4(prev.xyz.mul(dot), prev.w)
28
+ },
29
+ props.order,
30
+ )
31
+ </script>
32
+
33
+ <template><!-- --></template>
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color } from 'three'
4
+ import { mix, uniform, vec4 } from 'three/tsl'
5
+ import { blendHardLight } 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) => vec4(mix(prev.xyz, blendHardLight(prev.xyz, colorNode), opacityNode), prev.w),
20
+ props.order,
21
+ )
22
+ </script>
23
+
24
+ <template><!-- --></template>
@@ -0,0 +1,50 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector3 } from 'three'
4
+ import { uniform, vec3, vec4, smoothstep, float } from 'three/tsl'
5
+
6
+ /**
7
+ * Edge haze — additive fog/bloom at screen boundaries.
8
+ * Useful for dreamlike or atmospheric borders.
9
+ */
10
+ const props = withDefaults(defineProps<{
11
+ /** Haze tint colour */
12
+ color?: string
13
+ /** How far inward the haze reaches (0 = edge only, 1 = full screen) */
14
+ reach?: number
15
+ /** Haze brightness */
16
+ intensity?: number
17
+ order?: number
18
+ }>(), { color: '#ffffff', reach: 0.4, intensity: 0.3, order: 0 })
19
+
20
+ function toVec3Node(hex: string) {
21
+ const c = new Color(hex)
22
+ return uniform(new Vector3(c.r, c.g, c.b))
23
+ }
24
+
25
+ const colorNode = toVec3Node(props.color)
26
+ const reachNode = uniform(props.reach)
27
+ const intensityNode = uniform(props.intensity)
28
+ watch(() => props.color, v => { const c = new Color(v); colorNode.value.set(c.r, c.g, c.b) })
29
+ watch(() => props.reach, v => { reachNode.value = v })
30
+ watch(() => props.intensity, v => { intensityNode.value = v })
31
+
32
+ const pipeline = useShaderPipelineContext()
33
+
34
+ useShaderStage(
35
+ (prev) => {
36
+ const uv = pipeline.uvNode.value
37
+
38
+ // Horizontal edge proximity
39
+ const edgeX = smoothstep(reachNode, float(0), uv.x).add(smoothstep(float(1).sub(reachNode), float(1), uv.x))
40
+ // Vertical edge proximity
41
+ const edgeY = smoothstep(reachNode, float(0), uv.y).add(smoothstep(float(1).sub(reachNode), float(1), uv.y))
42
+
43
+ const edgeMask = edgeX.add(edgeY).clamp(0, 1).mul(intensityNode)
44
+ return vec4(prev.xyz.add(colorNode.mul(edgeMask)), prev.w)
45
+ },
46
+ props.order,
47
+ )
48
+ </script>
49
+
50
+ <template><!-- --></template>
@@ -0,0 +1,42 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector3 } from 'three'
4
+ import { uniform, vec4, mix, smoothstep, float } from 'three/tsl'
5
+ import { sdHexagon } from '../../shaders/common/sdf'
6
+
7
+ const props = withDefaults(defineProps<{
8
+ colorA?: string
9
+ colorB?: string
10
+ radius?: number
11
+ softness?: number
12
+ order?: number
13
+ }>(), { colorA: '#000000', colorB: '#ffffff', radius: 0.35, softness: 0.01, 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 radiusNode = uniform(props.radius)
23
+ const softnessNode = uniform(props.softness)
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.radius, v => { radiusNode.value = v })
27
+ watch(() => props.softness, v => { softnessNode.value = v })
28
+
29
+ const pipeline = useShaderPipelineContext()
30
+
31
+ useShaderStage(
32
+ () => {
33
+ const uv = pipeline.uvNode.value
34
+ const d = sdHexagon(uv.sub(0.5), radiusNode)
35
+ const mask = smoothstep(softnessNode, softnessNode.negate(), d)
36
+ return vec4(mix(colorANode, colorBNode, mask), float(1))
37
+ },
38
+ props.order,
39
+ )
40
+ </script>
41
+
42
+ <template><!-- --></template>
@@ -0,0 +1,21 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, vec4 } from 'three/tsl'
4
+ import { hueShift } from '../../shaders/common/palette'
5
+
6
+ const props = withDefaults(defineProps<{
7
+ /** Hue shift amount in [0, 1] (1 = full rotation) */
8
+ shift?: number
9
+ order?: number
10
+ }>(), { shift: 0, order: 0 })
11
+
12
+ const shiftNode = uniform(props.shift)
13
+ watch(() => props.shift, v => { shiftNode.value = v })
14
+
15
+ useShaderStage(
16
+ (prev) => vec4(hueShift(prev.xyz, shiftNode), prev.w),
17
+ props.order,
18
+ )
19
+ </script>
20
+
21
+ <template><!-- --></template>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { vec4 } from 'three/tsl'
4
+ import { invert } from '../../shaders/common/blend'
5
+
6
+ const { order = 0 } = defineProps<{ order?: number }>()
7
+
8
+ useShaderStage(
9
+ (prev) => vec4(invert(prev.xyz), prev.w),
10
+ order,
11
+ )
12
+ </script>
13
+
14
+ <template><!-- --></template>
@@ -0,0 +1,67 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector2, Vector3 } from 'three'
4
+ import { uniform, vec2, vec3, vec4, smoothstep, float } from 'three/tsl'
5
+
6
+ /**
7
+ * Procedural lens flare — starburst + ghost circle artefacts along the flare axis.
8
+ */
9
+ const props = withDefaults(defineProps<{
10
+ /** Light source position in UV space */
11
+ position?: [number, number]
12
+ /** Flare colour */
13
+ color?: string
14
+ /** Overall brightness */
15
+ intensity?: number
16
+ /** How many ghost circles along the axis */
17
+ ghostCount?: number
18
+ order?: number
19
+ }>(), { position: () => [0.7, 0.8], color: '#fffde0', intensity: 0.6, ghostCount: 4, order: 0 })
20
+
21
+ function toVec3Node(hex: string) {
22
+ const c = new Color(hex)
23
+ return uniform(new Vector3(c.r, c.g, c.b))
24
+ }
25
+
26
+ const posNode = uniform(new Vector2(...props.position))
27
+ const colorNode = toVec3Node(props.color)
28
+ const intensityNode = uniform(props.intensity)
29
+ const ghostCountNode = uniform(props.ghostCount)
30
+ watch(() => props.position, ([x, y]) => { posNode.value.set(x, y) })
31
+ watch(() => props.color, v => { const c = new Color(v); colorNode.value.set(c.r, c.g, c.b) })
32
+ watch(() => props.intensity, v => { intensityNode.value = v })
33
+ watch(() => props.ghostCount, v => { ghostCountNode.value = v })
34
+
35
+ const pipeline = useShaderPipelineContext()
36
+
37
+ useShaderStage(
38
+ (prev) => {
39
+ const uv = pipeline.uvNode.value
40
+ const src = vec2(posNode.x, posNode.y)
41
+
42
+ // Starburst: bright disc at source
43
+ const distToSrc = uv.sub(src).length()
44
+ const burst = smoothstep(float(0.08), float(0), distToSrc).mul(intensityNode)
45
+
46
+ // Ghost circles: evenly spaced along the axis toward screen centre
47
+ const axis = vec2(0.5, 0.5).sub(src)
48
+ const ghost1 = uv.sub(src.add(axis.mul(0.4))).length()
49
+ const ghost2 = uv.sub(src.add(axis.mul(0.7))).length()
50
+ const ghost3 = uv.sub(src.add(axis.mul(1.1))).length()
51
+ const ghost4 = uv.sub(src.add(axis.mul(1.5))).length()
52
+
53
+ const g1 = smoothstep(float(0.05), float(0), ghost1).mul(0.4)
54
+ const g2 = smoothstep(float(0.03), float(0), ghost2).mul(0.3)
55
+ const g3 = smoothstep(float(0.04), float(0), ghost3).mul(0.2)
56
+ const g4 = smoothstep(float(0.06), float(0), ghost4).mul(0.15)
57
+
58
+ const ghosts = g1.add(g2).add(g3).add(g4).mul(intensityNode)
59
+ const flare = colorNode.mul(burst.add(ghosts))
60
+
61
+ return vec4(prev.xyz.add(flare), prev.w)
62
+ },
63
+ props.order,
64
+ )
65
+ </script>
66
+
67
+ <template><!-- --></template>
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color } from 'three'
4
+ import { mix, uniform, vec4 } from 'three/tsl'
5
+ import { blendLighten } 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) => vec4(mix(prev.xyz, blendLighten(prev.xyz, colorNode), opacityNode), prev.w),
20
+ props.order,
21
+ )
22
+ </script>
23
+
24
+ <template><!-- --></template>
@@ -0,0 +1,36 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color } from 'three'
4
+ import { mix, uniform, vec4 } from 'three/tsl'
5
+
6
+ const props = withDefaults(defineProps<{
7
+ colorA?: string
8
+ colorB?: string
9
+ axis?: 'x' | 'y'
10
+ order?: number
11
+ }>(), {
12
+ colorA: '#000000',
13
+ colorB: '#ffffff',
14
+ axis: 'y',
15
+ order: 0,
16
+ })
17
+
18
+ const colorAVal = new Color(props.colorA)
19
+ const colorBVal = new Color(props.colorB)
20
+ const colorANode = uniform(colorAVal)
21
+ const colorBNode = uniform(colorBVal)
22
+ watch(() => props.colorA, v => { colorANode.value.set(v) })
23
+ watch(() => props.colorB, v => { colorBNode.value.set(v) })
24
+
25
+ const { uvNode } = useShaderPipelineContext()
26
+
27
+ useShaderStage(
28
+ (_prev) => {
29
+ const t = props.axis === 'x' ? uvNode.value.x : uvNode.value.y
30
+ return vec4(mix(colorANode, colorBNode, t), 1.0)
31
+ },
32
+ props.order,
33
+ )
34
+ </script>
35
+
36
+ <template><!-- --></template>
@@ -0,0 +1,67 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector3 } from 'three'
4
+ import { float, mix, step, uniform, vec4 } from 'three/tsl'
5
+
6
+ const props = withDefaults(defineProps<{
7
+ colorA?: string
8
+ colorB?: string
9
+ /** Optional third stop (defaults to colorB when omitted → 2-stop gradient) */
10
+ colorC?: string
11
+ /** Optional fourth stop (defaults to colorC when omitted → 3-stop gradient) */
12
+ colorD?: string
13
+ axis?: 'x' | 'y'
14
+ order?: number
15
+ }>(), {
16
+ colorA: '#000000',
17
+ colorB: '#ffffff',
18
+ colorC: undefined,
19
+ colorD: undefined,
20
+ axis: 'y',
21
+ order: 0,
22
+ })
23
+
24
+ function toVec3U(hex: string) {
25
+ const c = new Color(hex)
26
+ return uniform(new Vector3(c.r, c.g, c.b))
27
+ }
28
+
29
+ const cA = toVec3U(props.colorA)
30
+ const cB = toVec3U(props.colorB)
31
+ const cC = toVec3U(props.colorC ?? props.colorB)
32
+ const cD = toVec3U(props.colorD ?? props.colorC ?? props.colorB)
33
+
34
+ watch(() => props.colorA, v => { const c = new Color(v); cA.value.set(c.r, c.g, c.b) })
35
+ watch(() => props.colorB, v => { const c = new Color(v); cB.value.set(c.r, c.g, c.b) })
36
+ watch(() => props.colorC, v => { const c = new Color(v ?? props.colorB); cC.value.set(c.r, c.g, c.b) })
37
+ watch(() => props.colorD, v => { const c = new Color(v ?? props.colorC ?? props.colorB); cD.value.set(c.r, c.g, c.b) })
38
+
39
+ const pipeline = useShaderPipelineContext()
40
+
41
+ useShaderStage(
42
+ () => {
43
+ const t = props.axis === 'x' ? pipeline.uvNode.value.x : pipeline.uvNode.value.y
44
+
45
+ // Map t [0,1] to 3 equal segments, clamping so t=1 maps to lt=1 not lt=0
46
+ const tN = t.mul(float(3)).min(float(2.9999))
47
+ const seg = tN.floor()
48
+ const lt = tN.sub(seg) // local t within segment [0,1)
49
+
50
+ // All three segment interpolations share the same local t
51
+ const c01 = mix(cA, cB, lt)
52
+ const c12 = mix(cB, cC, lt)
53
+ const c23 = mix(cC, cD, lt)
54
+
55
+ // step(edge, x): 0 if x < edge, 1 if x >= edge
56
+ const inSeg1 = step(float(1), tN) // 1 when in segments 1 or 2
57
+ const inSeg2 = step(float(2), tN) // 1 when in segment 2
58
+
59
+ // Cascade: start with c01, replace with c12 at seg>=1, replace with c23 at seg>=2
60
+ const col = mix(mix(c01, c12, inSeg1), c23, inSeg2)
61
+ return vec4(col, float(1))
62
+ },
63
+ props.order,
64
+ )
65
+ </script>
66
+
67
+ <template><!-- --></template>