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,38 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector3 } from 'three'
4
+ import { uniform, vec4, mix, cos, sin, float } from 'three/tsl'
5
+
6
+ const props = withDefaults(defineProps<{
7
+ colorA?: string
8
+ colorB?: string
9
+ /** Gradient angle in degrees (0 = left→right, 90 = bottom→top) */
10
+ angle?: number
11
+ order?: number
12
+ }>(), { colorA: '#000000', colorB: '#ffffff', angle: 45, order: 0 })
13
+
14
+ function toVec3Node(hex: string) {
15
+ const c = new Color(hex)
16
+ return uniform(new Vector3(c.r, c.g, c.b))
17
+ }
18
+
19
+ const colorANode = toVec3Node(props.colorA)
20
+ const colorBNode = toVec3Node(props.colorB)
21
+ const angleNode = uniform(props.angle * Math.PI / 180)
22
+ watch(() => props.colorA, v => { const c = new Color(v); colorANode.value.set(c.r, c.g, c.b) })
23
+ watch(() => props.colorB, v => { const c = new Color(v); colorBNode.value.set(c.r, c.g, c.b) })
24
+ watch(() => props.angle, v => { angleNode.value = v * Math.PI / 180 })
25
+
26
+ const pipeline = useShaderPipelineContext()
27
+
28
+ useShaderStage(
29
+ () => {
30
+ const uv = pipeline.uvNode.value
31
+ const t = uv.x.mul(cos(angleNode)).add(uv.y.mul(sin(angleNode))).clamp(float(0), float(1))
32
+ return vec4(mix(colorANode, colorBNode, t), float(1))
33
+ },
34
+ props.order,
35
+ )
36
+ </script>
37
+
38
+ <template><!-- --></template>
@@ -0,0 +1,40 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector3 } from 'three'
4
+ import { uniform, vec4, mix, float } from 'three/tsl'
5
+
6
+ /** Chebyshev-distance diamond gradient: max(|x|, |y|) from centre. */
7
+ const props = withDefaults(defineProps<{
8
+ colorA?: string
9
+ colorB?: string
10
+ /** Scale — higher = faster falloff */
11
+ scale?: number
12
+ order?: number
13
+ }>(), { colorA: '#000000', colorB: '#ffffff', scale: 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
+ watch(() => props.colorA, v => { const c = new Color(v); colorANode.value.set(c.r, c.g, c.b) })
24
+ watch(() => props.colorB, v => { const c = new Color(v); colorBNode.value.set(c.r, c.g, c.b) })
25
+ watch(() => props.scale, v => { scaleNode.value = v })
26
+
27
+ const pipeline = useShaderPipelineContext()
28
+
29
+ useShaderStage(
30
+ () => {
31
+ const uv = pipeline.uvNode.value
32
+ const centered = uv.sub(0.5).abs()
33
+ const t = centered.x.max(centered.y).mul(scaleNode).mul(2).min(float(1))
34
+ return vec4(mix(colorANode, colorBNode, t), float(1))
35
+ },
36
+ props.order,
37
+ )
38
+ </script>
39
+
40
+ <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 { blendDifference } 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, blendDifference(prev.xyz, colorNode), opacityNode), prev.w),
20
+ props.order,
21
+ )
22
+ </script>
23
+
24
+ <template><!-- --></template>
@@ -0,0 +1,26 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector3 } from 'three'
4
+ import { uniform, vec4, mix, clamp, float } from 'three/tsl'
5
+
6
+ const props = withDefaults(defineProps<{
7
+ color?: string
8
+ opacity?: number
9
+ order?: number
10
+ }>(), { color: '#808080', opacity: 1, order: 0 })
11
+
12
+ const colorNode = (() => { const c = new Color(props.color); return uniform(new Vector3(c.r, c.g, c.b)) })()
13
+ const opacityNode = uniform(props.opacity)
14
+ watch(() => props.color, v => { const c = new Color(v); colorNode.value.set(c.r, c.g, c.b) })
15
+ watch(() => props.opacity, v => { opacityNode.value = v })
16
+
17
+ useShaderStage(
18
+ (prev) => {
19
+ const divided = clamp(prev.xyz.div(colorNode.max(float(0.001))), float(0), float(1))
20
+ return vec4(mix(prev.xyz, divided, opacityNode), prev.w)
21
+ },
22
+ props.order,
23
+ )
24
+ </script>
25
+
26
+ <template><!-- --></template>
@@ -0,0 +1,48 @@
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 { domainWarp2D } from '../../shaders/common/noise'
6
+
7
+ const props = withDefaults(defineProps<{
8
+ colorA?: string
9
+ colorB?: string
10
+ scale?: number
11
+ warpStrength?: number
12
+ warpScale?: number
13
+ speed?: number
14
+ order?: number
15
+ }>(), { colorA: '#000000', colorB: '#ffffff', scale: 2, warpStrength: 0.5, warpScale: 2, speed: 0.1, 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
+ const warpStrNode = uniform(props.warpStrength)
26
+ const warpScaleNode = uniform(props.warpScale)
27
+ const speedNode = uniform(props.speed)
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.scale, v => { scaleNode.value = v })
31
+ watch(() => props.warpStrength, v => { warpStrNode.value = v })
32
+ watch(() => props.warpScale, v => { warpScaleNode.value = v })
33
+ watch(() => props.speed, v => { speedNode.value = v })
34
+
35
+ const pipeline = useShaderPipelineContext()
36
+
37
+ useShaderStage(
38
+ () => {
39
+ const uv = pipeline.uvNode.value
40
+ const animated = uv.add(time.mul(speedNode))
41
+ const n = domainWarp2D(animated.mul(scaleNode), warpStrNode, warpScaleNode).mul(0.5).add(0.5)
42
+ return vec4(mix(colorANode, colorBNode, n), float(1))
43
+ },
44
+ props.order,
45
+ )
46
+ </script>
47
+
48
+ <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 { dots } from '../../shaders/common/shapes'
6
+
7
+ const props = withDefaults(defineProps<{
8
+ colorA?: string
9
+ colorB?: string
10
+ cellSize?: number
11
+ dotRadius?: number
12
+ softness?: number
13
+ order?: number
14
+ }>(), { colorA: '#000000', colorB: '#ffffff', cellSize: 0.08, dotRadius: 0.025, softness: 0.005, 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 cellNode = uniform(props.cellSize)
24
+ const dotNode = uniform(props.dotRadius)
25
+ const softNode = 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.cellSize, v => { cellNode.value = v })
29
+ watch(() => props.dotRadius, v => { dotNode.value = v })
30
+ watch(() => props.softness, v => { softNode.value = v })
31
+
32
+ const pipeline = useShaderPipelineContext()
33
+
34
+ useShaderStage(
35
+ () => {
36
+ const uv = pipeline.uvNode.value
37
+ const mask = dots(uv, cellNode, dotNode, softNode)
38
+ return vec4(mix(colorANode, colorBNode, mask), float(1))
39
+ },
40
+ props.order,
41
+ )
42
+ </script>
43
+
44
+ <template><!-- --></template>
@@ -0,0 +1,34 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector3 } from 'three'
4
+ import { uniform, vec4, mix } from 'three/tsl'
5
+ import { luminance } from '../../shaders/common/blend'
6
+
7
+ const props = withDefaults(defineProps<{
8
+ /** Shadow colour (low luminance) */
9
+ shadowColor?: string
10
+ /** Highlight colour (high luminance) */
11
+ highlightColor?: string
12
+ order?: number
13
+ }>(), { shadowColor: '#1a0033', highlightColor: '#ffcc00', 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 shadowNode = toVec3Node(props.shadowColor)
21
+ const highlightNode = toVec3Node(props.highlightColor)
22
+ watch(() => props.shadowColor, v => { const c = new Color(v); shadowNode.value.set(c.r, c.g, c.b) })
23
+ watch(() => props.highlightColor, v => { const c = new Color(v); highlightNode.value.set(c.r, c.g, c.b) })
24
+
25
+ useShaderStage(
26
+ (prev) => {
27
+ const lum = luminance(prev.xyz)
28
+ return vec4(mix(shadowNode, highlightNode, lum), prev.w)
29
+ },
30
+ props.order,
31
+ )
32
+ </script>
33
+
34
+ <template><!-- --></template>
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector3 } from 'three'
4
+ import { uniform, vec4, mix } from 'three/tsl'
5
+ import { blendExclusion } from '../../shaders/common/blend'
6
+
7
+ const props = withDefaults(defineProps<{
8
+ color?: string
9
+ opacity?: number
10
+ order?: number
11
+ }>(), { color: '#ffffff', opacity: 1, order: 0 })
12
+
13
+ const colorNode = (() => { const c = new Color(props.color); return uniform(new Vector3(c.r, c.g, c.b)) })()
14
+ const opacityNode = uniform(props.opacity)
15
+ watch(() => props.color, v => { const c = new Color(v); colorNode.value.set(c.r, c.g, c.b) })
16
+ watch(() => props.opacity, v => { opacityNode.value = v })
17
+
18
+ useShaderStage(
19
+ (prev) => vec4(mix(prev.xyz, blendExclusion(prev.xyz, colorNode), opacityNode), prev.w),
20
+ props.order,
21
+ )
22
+ </script>
23
+
24
+ <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
+ /**
7
+ * Height-based exponential fog: exp2(-ray.y * density).
8
+ * Blends prev colour toward fogColor as the ray approaches the horizon.
9
+ * Pairs naturally with SkyAtmosphere — place before it so terrain gets fog too.
10
+ */
11
+ const props = withDefaults(defineProps<{
12
+ /** Fog colour */
13
+ fogColor?: string
14
+ /** Controls how quickly fog builds near the horizon — higher = thicker */
15
+ density?: number
16
+ /** Clamp the minimum ray Y used for fog (prevents underground fog) */
17
+ horizonBias?: number
18
+ order?: number
19
+ }>(), { fogColor: '#c8d8e8', density: 4, horizonBias: 0, 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 fogColorNode = toVec3Node(props.fogColor)
27
+ const densityNode = uniform(props.density)
28
+ const horizonBiasNode = uniform(props.horizonBias)
29
+ watch(() => props.fogColor, v => { const c = new Color(v); fogColorNode.value.set(c.r, c.g, c.b) })
30
+ watch(() => props.density, v => { densityNode.value = v })
31
+ watch(() => props.horizonBias, v => { horizonBiasNode.value = v })
32
+
33
+ const pipeline = useShaderPipelineContext()
34
+
35
+ useShaderStage(
36
+ (prev) => {
37
+ const ray = pipeline.rayNode.value
38
+ const h = ray ? ray.y.max(horizonBiasNode) : horizonBiasNode
39
+ const fogFactor = h.mul(densityNode).negate().exp2()
40
+ return vec4(mix(fogColorNode, prev.xyz, fogFactor), prev.w)
41
+ },
42
+ props.order,
43
+ )
44
+ </script>
45
+
46
+ <template><!-- --></template>
@@ -0,0 +1,23 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, vec4, pow, float } from 'three/tsl'
4
+
5
+ const props = withDefaults(defineProps<{
6
+ /** Exposure in stops: 0 = unchanged, +1 = 2× brighter, -1 = 2× darker */
7
+ stops?: number
8
+ order?: number
9
+ }>(), { stops: 0, order: 0 })
10
+
11
+ const stopsNode = uniform(props.stops)
12
+ watch(() => props.stops, v => { stopsNode.value = v })
13
+
14
+ useShaderStage(
15
+ (prev) => {
16
+ const scale = pow(float(2), stopsNode)
17
+ return vec4(prev.xyz.mul(scale), prev.w)
18
+ },
19
+ props.order,
20
+ )
21
+ </script>
22
+
23
+ <template><!-- --></template>
@@ -0,0 +1,50 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color } from 'three'
4
+ import { float, mix, time, uniform, vec2, vec4 } from 'three/tsl'
5
+ import { fbm2D } from '../../shaders/common/noise'
6
+
7
+ const props = withDefaults(defineProps<{
8
+ colorA?: string
9
+ colorB?: string
10
+ scale?: number
11
+ octaves?: number
12
+ animated?: boolean
13
+ speed?: number
14
+ order?: number
15
+ }>(), {
16
+ colorA: '#000000',
17
+ colorB: '#ffffff',
18
+ scale: 3,
19
+ octaves: 5,
20
+ animated: true,
21
+ speed: 0.15,
22
+ order: 0,
23
+ })
24
+
25
+ const colorAVal = new Color(props.colorA)
26
+ const colorBVal = new Color(props.colorB)
27
+ const colorANode = uniform(colorAVal)
28
+ const colorBNode = uniform(colorBVal)
29
+ const scaleNode = uniform(props.scale)
30
+ const speedNode = uniform(props.speed)
31
+
32
+ watch(() => props.colorA, v => { colorANode.value.set(v) })
33
+ watch(() => props.colorB, v => { colorBNode.value.set(v) })
34
+ watch(() => props.scale, v => { scaleNode.value = v })
35
+ watch(() => props.speed, v => { speedNode.value = v })
36
+
37
+ const { uvNode } = useShaderPipelineContext()
38
+
39
+ useShaderStage(
40
+ (_prev) => {
41
+ const offset = props.animated ? time.mul(speedNode) : float(0)
42
+ const input = uvNode.value.mul(scaleNode).add(vec2(offset, 0))
43
+ const n = fbm2D(input, { octaves: props.octaves }).mul(0.5).add(0.5)
44
+ return vec4(mix(colorANode, colorBNode, n), 1.0)
45
+ },
46
+ props.order,
47
+ )
48
+ </script>
49
+
50
+ <template><!-- --></template>
@@ -0,0 +1,49 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector2, Vector3 } from 'three'
4
+ import { uniform, vec4, vec2, mix, smoothstep, float } from 'three/tsl'
5
+
6
+ /**
7
+ * Orange/warm light leak emanating from a screen corner.
8
+ * Additive over-exposure effect — common in analogue film.
9
+ */
10
+ const props = withDefaults(defineProps<{
11
+ /** Light leak colour */
12
+ color?: string
13
+ /** Corner origin [0,1] — default top-left */
14
+ origin?: [number, number]
15
+ /** Reach of the leak */
16
+ radius?: number
17
+ /** Peak brightness */
18
+ intensity?: number
19
+ order?: number
20
+ }>(), { color: '#ff8822', origin: () => [0, 1], radius: 0.7, intensity: 0.5, order: 0 })
21
+
22
+ function toVec3Node(hex: string) {
23
+ const c = new Color(hex)
24
+ return uniform(new Vector3(c.r, c.g, c.b))
25
+ }
26
+
27
+ const colorNode = toVec3Node(props.color)
28
+ const originNode = uniform(new Vector2(...props.origin))
29
+ const radiusNode = uniform(props.radius)
30
+ const intensityNode = uniform(props.intensity)
31
+ watch(() => props.color, v => { const c = new Color(v); colorNode.value.set(c.r, c.g, c.b) })
32
+ watch(() => props.origin, ([x, y]) => { originNode.value.set(x, y) })
33
+ watch(() => props.radius, v => { radiusNode.value = v })
34
+ watch(() => props.intensity, v => { intensityNode.value = v })
35
+
36
+ const pipeline = useShaderPipelineContext()
37
+
38
+ useShaderStage(
39
+ (prev) => {
40
+ const uv = pipeline.uvNode.value
41
+ const dist = uv.sub(vec2(originNode.x, originNode.y)).length()
42
+ const leak = smoothstep(radiusNode, float(0), dist).mul(intensityNode)
43
+ return vec4(prev.xyz.add(colorNode.mul(leak)), prev.w)
44
+ },
45
+ props.order,
46
+ )
47
+ </script>
48
+
49
+ <template><!-- --></template>
@@ -0,0 +1,69 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { clamp, float, fract, mix, sin, 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
+
8
+ const props = withDefaults(defineProps<{
9
+ /** Grain intensity — amplitude of the noise effect */
10
+ intensity?: number
11
+ /** Blend opacity — how strongly grain mixes into the output */
12
+ opacity?: number
13
+ /** UV scale — higher = finer dots, lower = coarser */
14
+ size?: number
15
+ fps?: number
16
+ blendMode?: GrainBlendMode
17
+ order?: number
18
+ }>(), { intensity: 0.06, opacity: 1.0, size: 1.0, fps: 24, blendMode: 'sub', order: 0 })
19
+
20
+ const intensityNode = uniform(props.intensity)
21
+ const opacityNode = uniform(props.opacity)
22
+ const sizeNode = uniform(props.size)
23
+ const fpsNode = uniform(props.fps)
24
+ watch(() => props.intensity, v => { intensityNode.value = v })
25
+ watch(() => props.opacity, v => { opacityNode.value = v })
26
+ watch(() => props.size, v => { sizeNode.value = v })
27
+ watch(() => props.fps, v => { fpsNode.value = v })
28
+
29
+ const pipeline = useShaderPipelineContext()
30
+
31
+ useShaderStage(
32
+ (prev) => {
33
+ const uvScaled = pipeline.uvNode.value.mul(sizeNode)
34
+ const t = time.mul(fpsNode).floor().div(fpsNode)
35
+
36
+ // Two-pass hash for coarser, more organic texture
37
+ const k1 = vec2(127.1, 311.7)
38
+ const k2 = vec2(269.5, 183.3)
39
+ const p = uvScaled.add(t)
40
+ const h1 = p.dot(k1).sin().mul(43758.5453).fract()
41
+ const h2 = p.add(t.mul(0.3)).dot(k2).sin().mul(43758.5453).fract()
42
+ // Raw [0,1] noise from vector length, normalised by max possible (√2)
43
+ const raw = vec2(h1, h2).length().mul(float(0.7071))
44
+
45
+ const mixFactor = intensityNode.mul(opacityNode)
46
+ let blended
47
+ switch (props.blendMode) {
48
+ case 'add':
49
+ blended = prev.xyz.add(raw.sub(0.5).mul(intensityNode).mul(opacityNode))
50
+ break
51
+ case 'screen':
52
+ blended = mix(prev.xyz, blendScreen(prev.xyz, raw), mixFactor)
53
+ break
54
+ case 'overlay':
55
+ blended = mix(prev.xyz, blendOverlay(prev.xyz, raw), mixFactor)
56
+ break
57
+ case 'soft-light':
58
+ blended = mix(prev.xyz, blendSoftLight(prev.xyz, raw), mixFactor)
59
+ break
60
+ default: // 'sub' — original darkening behaviour
61
+ blended = prev.xyz.sub(raw.mul(intensityNode).mul(opacityNode))
62
+ }
63
+ return vec4(clamp(blended, 0, 1), prev.w)
64
+ },
65
+ props.order,
66
+ )
67
+ </script>
68
+
69
+ <template><!-- --></template>
@@ -0,0 +1,35 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, float, atan, vec3 } from 'three/tsl'
4
+
5
+ const props = withDefaults(defineProps<{
6
+ /**
7
+ * Field-of-view in radians for the fisheye projection.
8
+ * π = 180° hemisphere, π*2 = full sphere.
9
+ */
10
+ fov?: number
11
+ order?: number
12
+ }>(), { fov: Math.PI, order: 0 })
13
+
14
+ const fovNode = uniform(props.fov)
15
+ watch(() => props.fov, v => { fovNode.value = v })
16
+
17
+ useShaderStage(
18
+ (ray) => {
19
+ // Screen-space xy from the linear ray (z = 1 focal plane)
20
+ const screen = vec3(ray.x, ray.y, float(0))
21
+ const r = screen.length()
22
+
23
+ // Fisheye: map linear distance → angle on sphere
24
+ const theta = atan(r).mul(fovNode).div(Math.PI * 0.5)
25
+ const phi = screen.y.atan(screen.x)
26
+
27
+ const sinTheta = theta.sin()
28
+ return vec3(phi.cos().mul(sinTheta), phi.sin().mul(sinTheta), theta.cos()).normalize()
29
+ },
30
+ props.order,
31
+ 'ray',
32
+ )
33
+ </script>
34
+
35
+ <template><!-- --></template>
@@ -0,0 +1,51 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector3 } from 'three'
4
+ import { uniform, time, vec3, vec4, mix, clamp, float } from 'three/tsl'
5
+ import { fbm2D } from '../../shaders/common/noise'
6
+
7
+ const props = withDefaults(defineProps<{
8
+ /** Base flame colour (cool, inner) */
9
+ colorBase?: string
10
+ /** Tip flame colour (hot, outer) */
11
+ colorTip?: string
12
+ /** Flame height scale */
13
+ scale?: number
14
+ /** Rise speed */
15
+ speed?: number
16
+ order?: number
17
+ }>(), { colorBase: '#ffcc00', colorTip: '#ff2200', scale: 3, speed: 1.5, order: 0 })
18
+
19
+ function toVec3Node(hex: string) {
20
+ const c = new Color(hex)
21
+ return uniform(new Vector3(c.r, c.g, c.b))
22
+ }
23
+
24
+ const colorBaseNode = toVec3Node(props.colorBase)
25
+ const colorTipNode = toVec3Node(props.colorTip)
26
+ const scaleNode = uniform(props.scale)
27
+ const speedNode = uniform(props.speed)
28
+ watch(() => props.colorBase, v => { const c = new Color(v); colorBaseNode.value.set(c.r, c.g, c.b) })
29
+ watch(() => props.colorTip, v => { const c = new Color(v); colorTipNode.value.set(c.r, c.g, c.b) })
30
+ watch(() => props.scale, v => { scaleNode.value = v })
31
+ watch(() => props.speed, v => { speedNode.value = v })
32
+
33
+ const pipeline = useShaderPipelineContext()
34
+
35
+ useShaderStage(
36
+ () => {
37
+ const uv = pipeline.uvNode.value
38
+ // Animate upward by subtracting time from Y
39
+ const pos = uv.mul(scaleNode).sub(time.mul(speedNode))
40
+ const n = fbm2D(pos).mul(0.5).add(0.5)
41
+ // Heat = noise * (1 - uv.y): flames die out at the top
42
+ const heat = clamp(n.mul(float(1).sub(uv.y).mul(1.5)), float(0), float(1))
43
+ // Black background → tip colour → base colour
44
+ const fireColor = mix(vec3(0, 0, 0), mix(colorTipNode, colorBaseNode, heat), heat)
45
+ return vec4(fireColor, heat)
46
+ },
47
+ props.order,
48
+ )
49
+ </script>
50
+
51
+ <template><!-- --></template>
@@ -0,0 +1,43 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { Color, Vector2, Vector3 } from 'three'
4
+ import { uniform, vec2, vec4, mix, float } from 'three/tsl'
5
+
6
+ /** Radial gradient with an offset focal point — asymmetric radial. */
7
+ const props = withDefaults(defineProps<{
8
+ colorA?: string
9
+ colorB?: string
10
+ /** Focal point in UV space [0,1] */
11
+ focal?: [number, number]
12
+ /** Radius of full falloff */
13
+ radius?: number
14
+ order?: number
15
+ }>(), { colorA: '#ffffff', colorB: '#000000', focal: () => [0.3, 0.3], radius: 1.2, 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 focalNode = uniform(new Vector2(...props.focal))
25
+ const radiusNode = uniform(props.radius)
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.focal, ([x, y]) => { focalNode.value.set(x, y) })
29
+ watch(() => props.radius, v => { radiusNode.value = v })
30
+
31
+ const pipeline = useShaderPipelineContext()
32
+
33
+ useShaderStage(
34
+ () => {
35
+ const uv = pipeline.uvNode.value
36
+ const t = uv.sub(vec2(focalNode.x, focalNode.y)).length().div(radiusNode).min(float(1))
37
+ return vec4(mix(colorANode, colorBNode, t), float(1))
38
+ },
39
+ props.order,
40
+ )
41
+ </script>
42
+
43
+ <template><!-- --></template>
@@ -0,0 +1,23 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck
3
+ import { uniform, vec4, pow, float } from 'three/tsl'
4
+
5
+ const props = withDefaults(defineProps<{
6
+ /** Gamma value: 1 = unchanged, 2.2 = standard display gamma */
7
+ gamma?: number
8
+ order?: number
9
+ }>(), { gamma: 2.2, order: 0 })
10
+
11
+ const gammaNode = uniform(props.gamma)
12
+ watch(() => props.gamma, v => { gammaNode.value = v })
13
+
14
+ useShaderStage(
15
+ (prev) => {
16
+ const corrected = pow(prev.xyz.max(float(0)), float(1).div(gammaNode))
17
+ return vec4(corrected, prev.w)
18
+ },
19
+ props.order,
20
+ )
21
+ </script>
22
+
23
+ <template><!-- --></template>