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.
- package/layers/core/app/.DS_Store +0 -0
- package/layers/core/app/assets/.DS_Store +0 -0
- package/layers/core/app/assets/css/main.css +2 -0
- package/layers/core/app/components/ErrorBoundary.vue +1 -1
- package/layers/core/nuxt.config.ts +0 -8
- package/layers/motion/app/plugins/locomotive-scroll.client.ts +14 -11
- package/layers/motion/app.config.ts +6 -0
- package/layers/shader/app/components/Pipeline/ACESTonemap.client.vue +14 -0
- package/layers/shader/app/components/Pipeline/AddBlend.client.vue +24 -0
- package/layers/shader/app/components/Pipeline/AgedFilm.client.vue +62 -0
- package/layers/shader/app/components/Pipeline/Aurora.client.vue +81 -0
- package/layers/shader/app/components/Pipeline/BilinearGradient.client.vue +46 -0
- package/layers/shader/app/components/Pipeline/BillowNoise.client.vue +42 -0
- package/layers/shader/app/components/Pipeline/BrightnessContrast.client.vue +25 -0
- package/layers/shader/app/components/Pipeline/CellularNoise.client.vue +41 -0
- package/layers/shader/app/components/Pipeline/ChannelMixer.client.vue +44 -0
- package/layers/shader/app/components/Pipeline/ChebyshevNoiseField.client.vue +60 -0
- package/layers/shader/app/components/Pipeline/Checkerboard.client.vue +41 -0
- package/layers/shader/app/components/Pipeline/ChromaticAberration.client.vue +52 -0
- package/layers/shader/app/components/Pipeline/ChromaticScreenWaves.client.vue +49 -0
- package/layers/shader/app/components/Pipeline/Circle.client.vue +41 -0
- package/layers/shader/app/components/Pipeline/Clouds.client.vue +60 -0
- package/layers/shader/app/components/Pipeline/ColorBurnBlend.client.vue +24 -0
- package/layers/shader/app/components/Pipeline/ColorDodgeBlend.client.vue +24 -0
- package/layers/shader/app/components/Pipeline/ColourRamp.client.vue +57 -0
- package/layers/shader/app/components/Pipeline/ComplexPlaneField.client.vue +77 -0
- package/layers/shader/app/components/Pipeline/ConicGradient.client.vue +40 -0
- package/layers/shader/app/components/Pipeline/CosinePalette.client.vue +71 -0
- package/layers/shader/app/components/Pipeline/CoverageAlpha.client.vue +18 -0
- package/layers/shader/app/components/Pipeline/Cross.client.vue +51 -0
- package/layers/shader/app/components/Pipeline/CurlNoise.client.vue +48 -0
- package/layers/shader/app/components/Pipeline/DarkenBlend.client.vue +24 -0
- package/layers/shader/app/components/Pipeline/DayNightCycle.client.vue +48 -0
- package/layers/shader/app/components/Pipeline/Desaturate.client.vue +21 -0
- package/layers/shader/app/components/Pipeline/DiagonalGradient.client.vue +38 -0
- package/layers/shader/app/components/Pipeline/DiamondGradient.client.vue +40 -0
- package/layers/shader/app/components/Pipeline/DifferenceBlend.client.vue +24 -0
- package/layers/shader/app/components/Pipeline/DivideBlend.client.vue +26 -0
- package/layers/shader/app/components/Pipeline/DomainWarpedNoise.client.vue +48 -0
- package/layers/shader/app/components/Pipeline/Dots.client.vue +44 -0
- package/layers/shader/app/components/Pipeline/DuoTone.client.vue +34 -0
- package/layers/shader/app/components/Pipeline/ExclusionBlend.client.vue +24 -0
- package/layers/shader/app/components/Pipeline/ExponentialFog.client.vue +46 -0
- package/layers/shader/app/components/Pipeline/Exposure.client.vue +23 -0
- package/layers/shader/app/components/Pipeline/FBMNoise.client.vue +50 -0
- package/layers/shader/app/components/Pipeline/FilmBurn.client.vue +49 -0
- package/layers/shader/app/components/Pipeline/FilmGrain.client.vue +69 -0
- package/layers/shader/app/components/Pipeline/FisheyeRay.client.vue +35 -0
- package/layers/shader/app/components/Pipeline/Flame.client.vue +51 -0
- package/layers/shader/app/components/Pipeline/FocalGradient.client.vue +43 -0
- package/layers/shader/app/components/Pipeline/Gamma.client.vue +23 -0
- package/layers/shader/app/components/Pipeline/GodRays.client.vue +64 -0
- package/layers/shader/app/components/Pipeline/GradientNoise.client.vue +42 -0
- package/layers/shader/app/components/Pipeline/Grain.client.vue +81 -0
- package/layers/shader/app/components/Pipeline/Grid.client.vue +43 -0
- package/layers/shader/app/components/Pipeline/Halation.client.vue +43 -0
- package/layers/shader/app/components/Pipeline/Halftone.client.vue +33 -0
- package/layers/shader/app/components/Pipeline/HardLightBlend.client.vue +24 -0
- package/layers/shader/app/components/Pipeline/Haze.client.vue +50 -0
- package/layers/shader/app/components/Pipeline/Hexagon.client.vue +42 -0
- package/layers/shader/app/components/Pipeline/Hue.client.vue +21 -0
- package/layers/shader/app/components/Pipeline/Invert.client.vue +14 -0
- package/layers/shader/app/components/Pipeline/LensFlare.client.vue +67 -0
- package/layers/shader/app/components/Pipeline/LightenBlend.client.vue +24 -0
- package/layers/shader/app/components/Pipeline/LinearGradient.client.vue +36 -0
- package/layers/shader/app/components/Pipeline/LinearGradient4.client.vue +67 -0
- package/layers/shader/app/components/Pipeline/LinearToSRGB.client.vue +25 -0
- package/layers/shader/app/components/Pipeline/Marble.client.vue +69 -0
- package/layers/shader/app/components/Pipeline/MixBlend.client.vue +45 -0
- package/layers/shader/app/components/Pipeline/MonochromeTint.client.vue +31 -0
- package/layers/shader/app/components/Pipeline/MultiplyBlend.client.vue +24 -0
- package/layers/shader/app/components/Pipeline/NoisyGradient.client.vue +54 -0
- package/layers/shader/app/components/Pipeline/NoisyGradientBlend.client.vue +116 -0
- package/layers/shader/app/components/Pipeline/OverlayBlend.client.vue +24 -0
- package/layers/shader/app/components/Pipeline/PaperTexture.client.vue +41 -0
- package/layers/shader/app/components/Pipeline/Polygon.client.vue +47 -0
- package/layers/shader/app/components/Pipeline/Posterise.client.vue +23 -0
- package/layers/shader/app/components/Pipeline/RadialGradient.client.vue +39 -0
- package/layers/shader/app/components/Pipeline/RayAutoOrbit.client.vue +37 -0
- package/layers/shader/app/components/Pipeline/RayMouseOrbit.client.vue +49 -0
- package/layers/shader/app/components/Pipeline/RayRotateX.client.vue +25 -0
- package/layers/shader/app/components/Pipeline/RayRotateY.client.vue +25 -0
- package/layers/shader/app/components/Pipeline/RayRotateZ.client.vue +25 -0
- package/layers/shader/app/components/Pipeline/RayTiltBasis.client.vue +41 -0
- package/layers/shader/app/components/Pipeline/RaymarchTunnel.client.vue +101 -0
- package/layers/shader/app/components/Pipeline/Rectangle.client.vue +47 -0
- package/layers/shader/app/components/Pipeline/ReinhardTonemap.client.vue +18 -0
- package/layers/shader/app/components/Pipeline/RidgedNoise.client.vue +41 -0
- package/layers/shader/app/components/Pipeline/Ring.client.vue +44 -0
- package/layers/shader/app/components/Pipeline/RingField.client.vue +69 -0
- package/layers/shader/app/components/Pipeline/RisographGrain.client.vue +74 -0
- package/layers/shader/app/components/Pipeline/RotatedGradientBlend.client.vue +61 -0
- package/layers/shader/app/components/Pipeline/SDFColourMask.client.vue +33 -0
- package/layers/shader/app/components/Pipeline/SDFRadialMask.client.vue +31 -0
- package/layers/shader/app/components/Pipeline/SRGBToLinear.client.vue +25 -0
- package/layers/shader/app/components/Pipeline/Saturation.client.vue +21 -0
- package/layers/shader/app/components/Pipeline/Scanlines.client.vue +36 -0
- package/layers/shader/app/components/Pipeline/ScreenBlend.client.vue +24 -0
- package/layers/shader/app/components/Pipeline/ShaderDebugger.client.vue +74 -0
- package/layers/shader/app/components/Pipeline/SimplexNoise.client.vue +49 -0
- package/layers/shader/app/components/Pipeline/SkyAtmosphere.client.vue +75 -0
- package/layers/shader/app/components/Pipeline/SoftLightBlend.client.vue +24 -0
- package/layers/shader/app/components/Pipeline/SolidColour.client.vue +21 -0
- package/layers/shader/app/components/Pipeline/SplitTone.client.vue +47 -0
- package/layers/shader/app/components/Pipeline/Star.client.vue +47 -0
- package/layers/shader/app/components/Pipeline/Starfield.client.vue +65 -0
- package/layers/shader/app/components/Pipeline/Stripes.client.vue +46 -0
- package/layers/shader/app/components/Pipeline/SubtractBlend.client.vue +24 -0
- package/layers/shader/app/components/Pipeline/TanhTonemap.client.vue +24 -0
- package/layers/shader/app/components/Pipeline/Threshold.client.vue +25 -0
- package/layers/shader/app/components/Pipeline/Tint.client.vue +33 -0
- package/layers/shader/app/components/Pipeline/Triangle.client.vue +42 -0
- package/layers/shader/app/components/Pipeline/UVAspectCorrect.client.vue +14 -0
- package/layers/shader/app/components/Pipeline/UVBreath.client.vue +36 -0
- package/layers/shader/app/components/Pipeline/UVBulge.client.vue +26 -0
- package/layers/shader/app/components/Pipeline/UVClamp.client.vue +18 -0
- package/layers/shader/app/components/Pipeline/UVColumnOffset.client.vue +28 -0
- package/layers/shader/app/components/Pipeline/UVFlipX.client.vue +14 -0
- package/layers/shader/app/components/Pipeline/UVFlipXY.client.vue +14 -0
- package/layers/shader/app/components/Pipeline/UVFlipY.client.vue +14 -0
- package/layers/shader/app/components/Pipeline/UVFractBand.client.vue +31 -0
- package/layers/shader/app/components/Pipeline/UVMousePull.client.vue +39 -0
- package/layers/shader/app/components/Pipeline/UVNoiseRotate.client.vue +54 -0
- package/layers/shader/app/components/Pipeline/UVNoiseWarp.client.vue +35 -0
- package/layers/shader/app/components/Pipeline/UVOrbit.client.vue +34 -0
- package/layers/shader/app/components/Pipeline/UVParallax.client.vue +39 -0
- package/layers/shader/app/components/Pipeline/UVPixelate.client.vue +21 -0
- package/layers/shader/app/components/Pipeline/UVPulse.client.vue +33 -0
- package/layers/shader/app/components/Pipeline/UVRipple.client.vue +34 -0
- package/layers/shader/app/components/Pipeline/UVRotate.client.vue +37 -0
- package/layers/shader/app/components/Pipeline/UVScale.client.vue +30 -0
- package/layers/shader/app/components/Pipeline/UVScroll.client.vue +27 -0
- package/layers/shader/app/components/Pipeline/UVScrollX.client.vue +21 -0
- package/layers/shader/app/components/Pipeline/UVScrollY.client.vue +21 -0
- package/layers/shader/app/components/Pipeline/UVShear.client.vue +25 -0
- package/layers/shader/app/components/Pipeline/UVSineWarpXY.client.vue +46 -0
- package/layers/shader/app/components/Pipeline/UVSwapAxes.client.vue +14 -0
- package/layers/shader/app/components/Pipeline/UVTile.client.vue +27 -0
- package/layers/shader/app/components/Pipeline/UVTwirl.client.vue +26 -0
- package/layers/shader/app/components/Pipeline/UVWarp.client.vue +30 -0
- package/layers/shader/app/components/Pipeline/VHSBleed.client.vue +58 -0
- package/layers/shader/app/components/Pipeline/ValueNoise.client.vue +41 -0
- package/layers/shader/app/components/Pipeline/Vibrance.client.vue +24 -0
- package/layers/shader/app/components/Pipeline/Vignette.client.vue +32 -0
- package/layers/shader/app/components/Pipeline/VoronoiEdges.client.vue +50 -0
- package/layers/shader/app/components/Pipeline/Water.client.vue +53 -0
- package/layers/shader/app/components/Pipeline/WaveBendLayer.client.vue +61 -0
- package/layers/shader/app/components/Pipeline/WaveColourLayer.client.vue +56 -0
- package/layers/shader/app/components/Pipeline/WhiteBalance.client.vue +40 -0
- package/layers/shader/app/components/Pipeline/Wood.client.vue +63 -0
- package/layers/shader/app/components/Shader/Canvas.vue +24 -0
- package/layers/shader/app/components/Shader/Pipeline.client.vue +56 -0
- package/layers/shader/app/components/Shader/PipelineContext.vue +18 -0
- package/layers/shader/app/composables/useCSSColourUniform.ts +41 -0
- package/layers/shader/app/composables/useCSSFloatUniform.ts +34 -0
- package/layers/shader/app/composables/useShaderPerf.ts +73 -0
- package/layers/shader/app/composables/useShaderPipeline.ts +99 -0
- package/layers/shader/app/composables/useSunDirectionUniform.ts +54 -0
- package/layers/shader/app/composables/useTSLNodes.ts +0 -1
- package/layers/shader/app/shaders/common/complex.ts +29 -0
- package/layers/shader/app/shaders/common/shapes.ts +4 -4
- package/layers/shader/app/shaders/common/uv.ts +2 -2
- package/layers/shader/app/utils/tsl/patterns.ts +1 -1
- package/layers/shader/app/utils/tsl/uv.ts +3 -3
- package/layers/ui/app/app.config.ts +2 -16
- package/layers/ui/app/types/app-config.d.ts +17 -0
- package/package.json +9 -7
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { uniform, vec4, time } from 'three/tsl'
|
|
4
|
+
import { scanlines } from '../../shaders/common/grain'
|
|
5
|
+
|
|
6
|
+
const props = withDefaults(defineProps<{
|
|
7
|
+
/** Number of scanlines across the screen */
|
|
8
|
+
density?: number
|
|
9
|
+
/** Darkness of the lines: 0 = invisible, 1 = full black */
|
|
10
|
+
intensity?: number
|
|
11
|
+
/** Animate the lines — speed in lines/second */
|
|
12
|
+
scrollSpeed?: number
|
|
13
|
+
order?: number
|
|
14
|
+
}>(), { density: 400, intensity: 0.25, scrollSpeed: 0, order: 0 })
|
|
15
|
+
|
|
16
|
+
const densityNode = uniform(props.density)
|
|
17
|
+
const intensityNode = uniform(props.intensity)
|
|
18
|
+
const scrollSpeedNode = uniform(props.scrollSpeed)
|
|
19
|
+
watch(() => props.density, v => { densityNode.value = v })
|
|
20
|
+
watch(() => props.intensity, v => { intensityNode.value = v })
|
|
21
|
+
watch(() => props.scrollSpeed, v => { scrollSpeedNode.value = v })
|
|
22
|
+
|
|
23
|
+
const pipeline = useShaderPipelineContext()
|
|
24
|
+
|
|
25
|
+
useShaderStage(
|
|
26
|
+
(prev) => {
|
|
27
|
+
const uvCurrent = pipeline.uvNode.value
|
|
28
|
+
const offset = time.mul(scrollSpeedNode)
|
|
29
|
+
const factor = scanlines(uvCurrent, densityNode, intensityNode, offset)
|
|
30
|
+
return vec4(prev.xyz.mul(factor), prev.w)
|
|
31
|
+
},
|
|
32
|
+
props.order,
|
|
33
|
+
)
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<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 { blendScreen } 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, blendScreen(prev.xyz, colorNode), opacityNode), prev.w),
|
|
20
|
+
props.order,
|
|
21
|
+
)
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { uniform, vec3, vec4, float, floor, fract } from 'three/tsl'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* ShaderDebugger — dev-only visualization overlay for inspecting pipeline state.
|
|
7
|
+
*
|
|
8
|
+
* Modes:
|
|
9
|
+
* 'uv' — displays UV coordinates as red/green channels
|
|
10
|
+
* 'normal' — encodes normal-space UV as blue hue sweep
|
|
11
|
+
* 'grid' — overlays a reference grid on the current output
|
|
12
|
+
* 'pass' — passes through unchanged (no-op, useful for toggling off)
|
|
13
|
+
*
|
|
14
|
+
* Drop this at any `order` value to inspect that point in the pipeline.
|
|
15
|
+
* Only renders in development — remove from production compositions.
|
|
16
|
+
*/
|
|
17
|
+
const props = withDefaults(defineProps<{
|
|
18
|
+
/** Visualization mode */
|
|
19
|
+
mode?: 'uv' | 'normal' | 'grid' | 'pass'
|
|
20
|
+
/** Grid line count (grid mode) */
|
|
21
|
+
gridLines?: number
|
|
22
|
+
/** Grid line thickness */
|
|
23
|
+
gridThickness?: number
|
|
24
|
+
/** Blend with original output (0 = full debug, 1 = full original) */
|
|
25
|
+
blend?: number
|
|
26
|
+
order?: number
|
|
27
|
+
}>(), { mode: 'uv', gridLines: 10, gridThickness: 0.02, blend: 0, order: 0 })
|
|
28
|
+
|
|
29
|
+
const gridLinesNode = uniform(props.gridLines)
|
|
30
|
+
const gridThickNode = uniform(props.gridThickness)
|
|
31
|
+
const blendNode = uniform(props.blend)
|
|
32
|
+
watch(() => props.gridLines, v => { gridLinesNode.value = v })
|
|
33
|
+
watch(() => props.gridThickness, v => { gridThickNode.value = v })
|
|
34
|
+
watch(() => props.blend, v => { blendNode.value = v })
|
|
35
|
+
|
|
36
|
+
const pipeline = useShaderPipelineContext()
|
|
37
|
+
|
|
38
|
+
useShaderStage(
|
|
39
|
+
(prev) => {
|
|
40
|
+
const uv = pipeline.uvNode.value
|
|
41
|
+
|
|
42
|
+
let debugColour
|
|
43
|
+
|
|
44
|
+
if (props.mode === 'uv') {
|
|
45
|
+
// Red = U, Green = V, Blue = 0
|
|
46
|
+
debugColour = vec3(uv.x, uv.y, float(0))
|
|
47
|
+
}
|
|
48
|
+
else if (props.mode === 'normal') {
|
|
49
|
+
// Encodes centered UV — negative values become blue tones
|
|
50
|
+
const centered = uv.sub(0.5)
|
|
51
|
+
debugColour = vec3(centered.x.add(0.5), centered.y.add(0.5), float(0.5))
|
|
52
|
+
}
|
|
53
|
+
else if (props.mode === 'grid') {
|
|
54
|
+
// Grid lines via fract — line at every 1/gridLines interval
|
|
55
|
+
const scaled = uv.mul(gridLinesNode)
|
|
56
|
+
const fx = fract(scaled.x)
|
|
57
|
+
const fy = fract(scaled.y)
|
|
58
|
+
const lineX = float(1).sub(fx.smoothstep(gridThickNode, float(0)))
|
|
59
|
+
const lineY = float(1).sub(fy.smoothstep(gridThickNode, float(0)))
|
|
60
|
+
const line = lineX.max(lineY)
|
|
61
|
+
debugColour = prev.xyz.mul(float(1).sub(line)).add(vec3(line, line.mul(0.5), float(0)))
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
// pass — no-op
|
|
65
|
+
debugColour = prev.xyz
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return vec4(prev.xyz.mix(debugColour, float(1).sub(blendNode)), prev.w)
|
|
69
|
+
},
|
|
70
|
+
props.order,
|
|
71
|
+
)
|
|
72
|
+
</script>
|
|
73
|
+
|
|
74
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,49 @@
|
|
|
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 { simplexNoise2D } from '../../shaders/common/noise'
|
|
6
|
+
|
|
7
|
+
const props = withDefaults(defineProps<{
|
|
8
|
+
colorA?: string
|
|
9
|
+
colorB?: string
|
|
10
|
+
scale?: number
|
|
11
|
+
animated?: boolean
|
|
12
|
+
speed?: number
|
|
13
|
+
order?: number
|
|
14
|
+
}>(), {
|
|
15
|
+
colorA: '#000000',
|
|
16
|
+
colorB: '#ffffff',
|
|
17
|
+
scale: 3,
|
|
18
|
+
animated: true,
|
|
19
|
+
speed: 0.3,
|
|
20
|
+
order: 0,
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
const colorAVal = new Color(props.colorA)
|
|
24
|
+
const colorBVal = new Color(props.colorB)
|
|
25
|
+
const colorANode = uniform(colorAVal)
|
|
26
|
+
const colorBNode = uniform(colorBVal)
|
|
27
|
+
const scaleNode = uniform(props.scale)
|
|
28
|
+
const speedNode = uniform(props.speed)
|
|
29
|
+
|
|
30
|
+
watch(() => props.colorA, v => { colorANode.value.set(v) })
|
|
31
|
+
watch(() => props.colorB, v => { colorBNode.value.set(v) })
|
|
32
|
+
watch(() => props.scale, v => { scaleNode.value = v })
|
|
33
|
+
watch(() => props.speed, v => { speedNode.value = v })
|
|
34
|
+
|
|
35
|
+
const { uvNode } = useShaderPipelineContext()
|
|
36
|
+
|
|
37
|
+
useShaderStage(
|
|
38
|
+
(_prev) => {
|
|
39
|
+
// Scroll UV over time to animate noise (cheaper than 3D noise)
|
|
40
|
+
const offset = props.animated ? time.mul(speedNode) : float(0)
|
|
41
|
+
const input = uvNode.value.mul(scaleNode).add(vec2(offset, 0))
|
|
42
|
+
const n = simplexNoise2D(input).mul(0.5).add(0.5)
|
|
43
|
+
return vec4(mix(colorANode, colorBNode, n), 1.0)
|
|
44
|
+
},
|
|
45
|
+
props.order,
|
|
46
|
+
)
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { Color, Vector3 } from 'three'
|
|
4
|
+
import { uniform, clamp, mix, pow, dot, vec3, vec4, float } from 'three/tsl'
|
|
5
|
+
|
|
6
|
+
const props = withDefaults(defineProps<{
|
|
7
|
+
/** Sky colour at the zenith */
|
|
8
|
+
zenith?: string
|
|
9
|
+
/** Sky colour at the horizon */
|
|
10
|
+
horizon?: string
|
|
11
|
+
/** Ground colour below horizon */
|
|
12
|
+
ground?: string
|
|
13
|
+
/** Sun direction — [x, y, z] world space (will be normalised) */
|
|
14
|
+
sunDirection?: [number, number, number]
|
|
15
|
+
/** Sun colour */
|
|
16
|
+
sunColor?: string
|
|
17
|
+
/** Sun disk sharpness (higher = smaller disk) */
|
|
18
|
+
sunPower?: number
|
|
19
|
+
order?: number
|
|
20
|
+
}>(), {
|
|
21
|
+
zenith: '#1a3a8a',
|
|
22
|
+
horizon: '#7ab0d8',
|
|
23
|
+
ground: '#5a4a3a',
|
|
24
|
+
sunDirection: () => [0.3, 0.8, 0.5],
|
|
25
|
+
sunColor: '#fff8e0',
|
|
26
|
+
sunPower: 512,
|
|
27
|
+
order: 0,
|
|
28
|
+
})
|
|
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
|
+
|
|
35
|
+
const zenithNode = toVec3Node(props.zenith)
|
|
36
|
+
const horizonNode = toVec3Node(props.horizon)
|
|
37
|
+
const groundNode = toVec3Node(props.ground)
|
|
38
|
+
const sunColorNode = toVec3Node(props.sunColor)
|
|
39
|
+
const sunPowerNode = uniform(props.sunPower)
|
|
40
|
+
|
|
41
|
+
const sunDir = new Vector3(...props.sunDirection).normalize()
|
|
42
|
+
const sunDirNode = uniform(new Vector3(sunDir.x, sunDir.y, sunDir.z))
|
|
43
|
+
|
|
44
|
+
watch(() => props.zenith, v => { const c = new Color(v); zenithNode.value.set(c.r, c.g, c.b) })
|
|
45
|
+
watch(() => props.horizon, v => { const c = new Color(v); horizonNode.value.set(c.r, c.g, c.b) })
|
|
46
|
+
watch(() => props.ground, v => { const c = new Color(v); groundNode.value.set(c.r, c.g, c.b) })
|
|
47
|
+
watch(() => props.sunColor, v => { const c = new Color(v); sunColorNode.value.set(c.r, c.g, c.b) })
|
|
48
|
+
watch(() => props.sunPower, v => { sunPowerNode.value = v })
|
|
49
|
+
watch(() => props.sunDirection, ([x, y, z]) => {
|
|
50
|
+
const d = new Vector3(x, y, z).normalize()
|
|
51
|
+
sunDirNode.value.set(d.x, d.y, d.z)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
const pipeline = useShaderPipelineContext()
|
|
55
|
+
|
|
56
|
+
useShaderStage(
|
|
57
|
+
() => {
|
|
58
|
+
const ray = pipeline.rayNode.value
|
|
59
|
+
|
|
60
|
+
// Sky gradient: -1..+1 on Y → ground..zenith
|
|
61
|
+
const t = clamp(ray.y.mul(2.0).add(0.5), 0, 1)
|
|
62
|
+
const sky = mix(horizonNode, zenithNode, t)
|
|
63
|
+
const colour = mix(groundNode, sky, clamp(ray.y.add(0.1).mul(10.0), 0, 1))
|
|
64
|
+
|
|
65
|
+
// Sun disc
|
|
66
|
+
const sunDot = dot(ray, sunDirNode).max(float(0))
|
|
67
|
+
const sun = sunColorNode.mul(pow(sunDot, sunPowerNode))
|
|
68
|
+
|
|
69
|
+
return vec4(colour.add(sun), 1.0)
|
|
70
|
+
},
|
|
71
|
+
props.order,
|
|
72
|
+
)
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<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 { blendSoftLight } 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, blendSoftLight(prev.xyz, colorNode), opacityNode), prev.w),
|
|
20
|
+
props.order,
|
|
21
|
+
)
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { Color } from 'three'
|
|
4
|
+
import { uniform, vec4 } from 'three/tsl'
|
|
5
|
+
|
|
6
|
+
const props = withDefaults(defineProps<{
|
|
7
|
+
color?: string
|
|
8
|
+
order?: number
|
|
9
|
+
}>(), {
|
|
10
|
+
color: '#ffffff',
|
|
11
|
+
order: 0,
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
const colorVal = new Color(props.color)
|
|
15
|
+
const colorNode = uniform(colorVal)
|
|
16
|
+
watch(() => props.color, v => { colorNode.value.set(v) })
|
|
17
|
+
|
|
18
|
+
useShaderStage((_prev) => vec4(colorNode, 1.0), props.order)
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<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, smoothstep, float } from 'three/tsl'
|
|
5
|
+
import { luminance } from '../../shaders/common/blend'
|
|
6
|
+
|
|
7
|
+
const props = withDefaults(defineProps<{
|
|
8
|
+
/** Colour pushed into shadow tones */
|
|
9
|
+
shadowColor?: string
|
|
10
|
+
/** Colour pushed into highlight tones */
|
|
11
|
+
highlightColor?: string
|
|
12
|
+
/** Balance point: 0.5 = even split, lower = shadows dominate */
|
|
13
|
+
balance?: number
|
|
14
|
+
/** Overall blend strength */
|
|
15
|
+
opacity?: number
|
|
16
|
+
order?: number
|
|
17
|
+
}>(), { shadowColor: '#1a2a5a', highlightColor: '#ffeecc', balance: 0.5, opacity: 0.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 shadowNode = toVec3Node(props.shadowColor)
|
|
25
|
+
const highlightNode = toVec3Node(props.highlightColor)
|
|
26
|
+
const balanceNode = uniform(props.balance)
|
|
27
|
+
const opacityNode = uniform(props.opacity)
|
|
28
|
+
watch(() => props.shadowColor, v => { const c = new Color(v); shadowNode.value.set(c.r, c.g, c.b) })
|
|
29
|
+
watch(() => props.highlightColor, v => { const c = new Color(v); highlightNode.value.set(c.r, c.g, c.b) })
|
|
30
|
+
watch(() => props.balance, v => { balanceNode.value = v })
|
|
31
|
+
watch(() => props.opacity, v => { opacityNode.value = v })
|
|
32
|
+
|
|
33
|
+
useShaderStage(
|
|
34
|
+
(prev) => {
|
|
35
|
+
const lum = luminance(prev.xyz)
|
|
36
|
+
const shadowMask = smoothstep(balanceNode, float(0), lum)
|
|
37
|
+
const highlightMask = smoothstep(balanceNode, float(1), lum)
|
|
38
|
+
const toned = prev.xyz
|
|
39
|
+
.add(shadowNode.mul(shadowMask).mul(opacityNode))
|
|
40
|
+
.add(highlightNode.mul(highlightMask).mul(opacityNode))
|
|
41
|
+
return vec4(toned, prev.w)
|
|
42
|
+
},
|
|
43
|
+
props.order,
|
|
44
|
+
)
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<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 { star } from '../../shaders/common/shapes'
|
|
6
|
+
|
|
7
|
+
const props = withDefaults(defineProps<{
|
|
8
|
+
colorA?: string
|
|
9
|
+
colorB?: string
|
|
10
|
+
radius?: number
|
|
11
|
+
/** Number of points */
|
|
12
|
+
points?: number
|
|
13
|
+
/** Inner radius ratio (0–1) */
|
|
14
|
+
innerRatio?: number
|
|
15
|
+
softness?: number
|
|
16
|
+
order?: number
|
|
17
|
+
}>(), { colorA: '#000000', colorB: '#ffcc00', radius: 0.35, points: 5, innerRatio: 0.45, softness: 0.01, 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 colorANode = toVec3Node(props.colorA)
|
|
25
|
+
const colorBNode = toVec3Node(props.colorB)
|
|
26
|
+
const radiusNode = uniform(props.radius)
|
|
27
|
+
const innerNode = uniform(props.innerRatio)
|
|
28
|
+
const softnessNode = uniform(props.softness)
|
|
29
|
+
watch(() => props.colorA, v => { const c = new Color(v); colorANode.value.set(c.r, c.g, c.b) })
|
|
30
|
+
watch(() => props.colorB, v => { const c = new Color(v); colorBNode.value.set(c.r, c.g, c.b) })
|
|
31
|
+
watch(() => props.radius, v => { radiusNode.value = v })
|
|
32
|
+
watch(() => props.innerRatio, v => { innerNode.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 = star(uv, [0.5, 0.5], radiusNode, props.points, innerNode, softnessNode)
|
|
41
|
+
return vec4(mix(colorANode, colorBNode, mask), float(1))
|
|
42
|
+
},
|
|
43
|
+
props.order,
|
|
44
|
+
)
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { uniform, time, vec3, vec4, vec2, floor, fract, sin, dot, smoothstep, float } from 'three/tsl'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Hash-based procedural starfield.
|
|
7
|
+
* Each cell on a grid may contain a star whose brightness twinkles over time.
|
|
8
|
+
*/
|
|
9
|
+
const props = withDefaults(defineProps<{
|
|
10
|
+
/** Grid density — higher = more stars */
|
|
11
|
+
density?: number
|
|
12
|
+
/** Star brightness */
|
|
13
|
+
brightness?: number
|
|
14
|
+
/** Twinkle animation speed */
|
|
15
|
+
twinkleSpeed?: number
|
|
16
|
+
/** Star size (sharpness) */
|
|
17
|
+
size?: number
|
|
18
|
+
order?: number
|
|
19
|
+
}>(), { density: 80, brightness: 1.0, twinkleSpeed: 1.0, size: 0.4, order: 0 })
|
|
20
|
+
|
|
21
|
+
const densityNode = uniform(props.density)
|
|
22
|
+
const brightnessNode = uniform(props.brightness)
|
|
23
|
+
const twinkleNode = uniform(props.twinkleSpeed)
|
|
24
|
+
const sizeNode = uniform(props.size)
|
|
25
|
+
watch(() => props.density, v => { densityNode.value = v })
|
|
26
|
+
watch(() => props.brightness, v => { brightnessNode.value = v })
|
|
27
|
+
watch(() => props.twinkleSpeed, v => { twinkleNode.value = v })
|
|
28
|
+
watch(() => props.size, v => { sizeNode.value = v })
|
|
29
|
+
|
|
30
|
+
const pipeline = useShaderPipelineContext()
|
|
31
|
+
|
|
32
|
+
useShaderStage(
|
|
33
|
+
(prev) => {
|
|
34
|
+
const uv = pipeline.uvNode.value
|
|
35
|
+
const t = time.mul(twinkleNode)
|
|
36
|
+
|
|
37
|
+
// Scale UV into grid cells
|
|
38
|
+
const scaled = uv.mul(densityNode)
|
|
39
|
+
const cell = floor(scaled)
|
|
40
|
+
const local = fract(scaled).sub(0.5)
|
|
41
|
+
|
|
42
|
+
// Hash per cell → star position offset and brightness
|
|
43
|
+
const h1 = fract(sin(dot(cell, vec2(127.1, 311.7))).mul(43758.5453))
|
|
44
|
+
const h2 = fract(sin(dot(cell, vec2(269.5, 183.3))).mul(43758.5453))
|
|
45
|
+
const h3 = fract(sin(dot(cell, vec2(419.2, 371.9))).mul(43758.5453))
|
|
46
|
+
|
|
47
|
+
// Only ~30% of cells have stars
|
|
48
|
+
const hasStar = smoothstep(0.7, 0.75, h3)
|
|
49
|
+
|
|
50
|
+
// Star position within cell
|
|
51
|
+
const starPos = vec2(h1, h2).sub(0.5).mul(0.6)
|
|
52
|
+
const dist = local.sub(starPos).length()
|
|
53
|
+
|
|
54
|
+
// Twinkle via time-based sine modulation
|
|
55
|
+
const twinkle = sin(t.add(h1.mul(6.28))).mul(0.3).add(0.7)
|
|
56
|
+
const star = smoothstep(sizeNode, float(0), dist.mul(10)).mul(hasStar).mul(twinkle)
|
|
57
|
+
|
|
58
|
+
const colour = vec3(star.mul(brightnessNode))
|
|
59
|
+
return vec4(prev.xyz.add(colour), prev.w)
|
|
60
|
+
},
|
|
61
|
+
props.order,
|
|
62
|
+
)
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<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, float } from 'three/tsl'
|
|
5
|
+
import { stripes } from '../../shaders/common/shapes'
|
|
6
|
+
|
|
7
|
+
const props = withDefaults(defineProps<{
|
|
8
|
+
colorA?: string
|
|
9
|
+
colorB?: string
|
|
10
|
+
frequency?: number
|
|
11
|
+
/** Fraction of each stripe that is colorB (0–1) */
|
|
12
|
+
thickness?: number
|
|
13
|
+
/** Angle in degrees */
|
|
14
|
+
angle?: number
|
|
15
|
+
order?: number
|
|
16
|
+
}>(), { colorA: '#000000', colorB: '#ffffff', frequency: 10, thickness: 0.5, angle: 0, order: 0 })
|
|
17
|
+
|
|
18
|
+
function toVec3Node(hex: string) {
|
|
19
|
+
const c = new Color(hex)
|
|
20
|
+
return uniform(new Vector3(c.r, c.g, c.b))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const colorANode = toVec3Node(props.colorA)
|
|
24
|
+
const colorBNode = toVec3Node(props.colorB)
|
|
25
|
+
const freqNode = uniform(props.frequency)
|
|
26
|
+
const thickNode = uniform(props.thickness)
|
|
27
|
+
const angleNode = uniform(props.angle * Math.PI / 180)
|
|
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.frequency, v => { freqNode.value = v })
|
|
31
|
+
watch(() => props.thickness, v => { thickNode.value = v })
|
|
32
|
+
watch(() => props.angle, v => { angleNode.value = v * Math.PI / 180 })
|
|
33
|
+
|
|
34
|
+
const pipeline = useShaderPipelineContext()
|
|
35
|
+
|
|
36
|
+
useShaderStage(
|
|
37
|
+
() => {
|
|
38
|
+
const uv = pipeline.uvNode.value
|
|
39
|
+
const mask = stripes(uv, freqNode, thickNode, angleNode)
|
|
40
|
+
return vec4(mix(colorANode, colorBNode, mask), float(1))
|
|
41
|
+
},
|
|
42
|
+
props.order,
|
|
43
|
+
)
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { Color } from 'three'
|
|
4
|
+
import { clamp, uniform, vec4 } from 'three/tsl'
|
|
5
|
+
import { blendSubtract } from '../../shaders/common/blend'
|
|
6
|
+
|
|
7
|
+
const props = withDefaults(defineProps<{
|
|
8
|
+
color?: string
|
|
9
|
+
opacity?: number
|
|
10
|
+
order?: number
|
|
11
|
+
}>(), { color: '#808080', opacity: 1, order: 0 })
|
|
12
|
+
|
|
13
|
+
const colorNode = uniform(new Color(props.color))
|
|
14
|
+
const opacityNode = uniform(props.opacity)
|
|
15
|
+
watch(() => props.color, v => { colorNode.value.set(v) })
|
|
16
|
+
watch(() => props.opacity, v => { opacityNode.value = v })
|
|
17
|
+
|
|
18
|
+
useShaderStage(
|
|
19
|
+
(prev) => clamp(vec4(blendSubtract(prev.xyz, colorNode, opacityNode), prev.w), 0, 1),
|
|
20
|
+
props.order,
|
|
21
|
+
)
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { uniform, vec4 } from 'three/tsl'
|
|
4
|
+
import { tanhTonemap } from '../../shaders/common/tonemapping'
|
|
5
|
+
|
|
6
|
+
const props = withDefaults(defineProps<{
|
|
7
|
+
/** Controls how aggressively values above 1 are compressed. dawn5 uses 2.5. */
|
|
8
|
+
exposure?: number
|
|
9
|
+
order?: number
|
|
10
|
+
}>(), {
|
|
11
|
+
exposure: 1.0,
|
|
12
|
+
order: 0,
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const exposureNode = uniform(props.exposure)
|
|
16
|
+
watch(() => props.exposure, v => { exposureNode.value = v })
|
|
17
|
+
|
|
18
|
+
useShaderStage(
|
|
19
|
+
(prev) => vec4(tanhTonemap(prev.xyz.mul(exposureNode)), prev.w),
|
|
20
|
+
props.order,
|
|
21
|
+
)
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { uniform, vec4, step, float } from 'three/tsl'
|
|
4
|
+
import { luminance } from '../../shaders/common/blend'
|
|
5
|
+
|
|
6
|
+
const props = withDefaults(defineProps<{
|
|
7
|
+
/** Luminance threshold 0–1: below = black, above = white */
|
|
8
|
+
threshold?: number
|
|
9
|
+
order?: number
|
|
10
|
+
}>(), { threshold: 0.5, order: 0 })
|
|
11
|
+
|
|
12
|
+
const thresholdNode = uniform(props.threshold)
|
|
13
|
+
watch(() => props.threshold, v => { thresholdNode.value = v })
|
|
14
|
+
|
|
15
|
+
useShaderStage(
|
|
16
|
+
(prev) => {
|
|
17
|
+
const lum = luminance(prev.xyz)
|
|
18
|
+
const t = step(thresholdNode, lum)
|
|
19
|
+
return vec4(float(t), float(t), float(t), prev.w)
|
|
20
|
+
},
|
|
21
|
+
props.order,
|
|
22
|
+
)
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { Color, Vector3 } from 'three'
|
|
4
|
+
import { uniform, vec4 } from 'three/tsl'
|
|
5
|
+
|
|
6
|
+
const props = withDefaults(defineProps<{
|
|
7
|
+
/** Tint colour — multiplied against the existing colour */
|
|
8
|
+
color?: string
|
|
9
|
+
/** Blend between original (0) and fully tinted (1) */
|
|
10
|
+
opacity?: number
|
|
11
|
+
order?: number
|
|
12
|
+
}>(), { color: '#ff8844', opacity: 1, 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 colorNode = toVec3Node(props.color)
|
|
20
|
+
const opacityNode = uniform(props.opacity)
|
|
21
|
+
watch(() => props.color, v => { const c = new Color(v); colorNode.value.set(c.r, c.g, c.b) })
|
|
22
|
+
watch(() => props.opacity, v => { opacityNode.value = v })
|
|
23
|
+
|
|
24
|
+
useShaderStage(
|
|
25
|
+
(prev) => {
|
|
26
|
+
const tinted = prev.xyz.mul(colorNode)
|
|
27
|
+
return vec4(prev.xyz.mix(tinted, opacityNode), prev.w)
|
|
28
|
+
},
|
|
29
|
+
props.order,
|
|
30
|
+
)
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<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 { sdEquilateralTriangle } from '../../shaders/common/sdf'
|
|
6
|
+
|
|
7
|
+
const props = withDefaults(defineProps<{
|
|
8
|
+
colorA?: string
|
|
9
|
+
colorB?: string
|
|
10
|
+
size?: number
|
|
11
|
+
softness?: number
|
|
12
|
+
order?: number
|
|
13
|
+
}>(), { colorA: '#000000', colorB: '#ffffff', size: 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 sizeNode = uniform(props.size)
|
|
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.size, v => { sizeNode.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 = sdEquilateralTriangle(uv.sub(0.5), sizeNode)
|
|
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>
|