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,25 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { uniform, vec4, pow, float } from 'three/tsl'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Gamma-encodes linear light to sRGB for display.
|
|
7
|
+
* Use as the last step in HDR pipelines before output.
|
|
8
|
+
* Approximate form: pow(col, 1/2.2).
|
|
9
|
+
*/
|
|
10
|
+
const props = withDefaults(defineProps<{
|
|
11
|
+
/** Gamma exponent — 2.2 matches sRGB standard */
|
|
12
|
+
gamma?: number
|
|
13
|
+
order?: number
|
|
14
|
+
}>(), { gamma: 2.2, order: 0 })
|
|
15
|
+
|
|
16
|
+
const gammaNode = uniform(props.gamma)
|
|
17
|
+
watch(() => props.gamma, v => { gammaNode.value = v })
|
|
18
|
+
|
|
19
|
+
useShaderStage(
|
|
20
|
+
(prev) => vec4(pow(prev.xyz.max(float(0)), float(1).div(gammaNode)), prev.w),
|
|
21
|
+
props.order,
|
|
22
|
+
)
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { Color, Vector3 } from 'three'
|
|
4
|
+
import { uniform, time, vec4, mix, sin, float } from 'three/tsl'
|
|
5
|
+
import { fbm2D } from '../../shaders/common/noise'
|
|
6
|
+
|
|
7
|
+
const props = withDefaults(defineProps<{
|
|
8
|
+
/** Base (vein background) colour */
|
|
9
|
+
colorA?: string
|
|
10
|
+
/** Vein colour */
|
|
11
|
+
colorB?: string
|
|
12
|
+
/** Marble vein frequency */
|
|
13
|
+
frequency?: number
|
|
14
|
+
/** FBM noise scale for vein turbulence */
|
|
15
|
+
noiseScale?: number
|
|
16
|
+
/** Noise strength applied to sine input */
|
|
17
|
+
noiseStrength?: number
|
|
18
|
+
/** Vein sharpness — higher = thinner veins */
|
|
19
|
+
sharpness?: number
|
|
20
|
+
/** Animation speed */
|
|
21
|
+
speed?: number
|
|
22
|
+
order?: number
|
|
23
|
+
}>(), {
|
|
24
|
+
colorA: '#f5f0e8',
|
|
25
|
+
colorB: '#6a5a4a',
|
|
26
|
+
frequency: 5,
|
|
27
|
+
noiseScale: 3,
|
|
28
|
+
noiseStrength: 8,
|
|
29
|
+
sharpness: 4,
|
|
30
|
+
speed: 0,
|
|
31
|
+
order: 0,
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
function toVec3Node(hex: string) {
|
|
35
|
+
const c = new Color(hex)
|
|
36
|
+
return uniform(new Vector3(c.r, c.g, c.b))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const colorANode = toVec3Node(props.colorA)
|
|
40
|
+
const colorBNode = toVec3Node(props.colorB)
|
|
41
|
+
const freqNode = uniform(props.frequency)
|
|
42
|
+
const noiseScaleNode = uniform(props.noiseScale)
|
|
43
|
+
const noiseStrNode = uniform(props.noiseStrength)
|
|
44
|
+
const sharpNode = uniform(props.sharpness)
|
|
45
|
+
const speedNode = uniform(props.speed)
|
|
46
|
+
watch(() => props.colorA, v => { const c = new Color(v); colorANode.value.set(c.r, c.g, c.b) })
|
|
47
|
+
watch(() => props.colorB, v => { const c = new Color(v); colorBNode.value.set(c.r, c.g, c.b) })
|
|
48
|
+
watch(() => props.frequency, v => { freqNode.value = v })
|
|
49
|
+
watch(() => props.noiseScale, v => { noiseScaleNode.value = v })
|
|
50
|
+
watch(() => props.noiseStrength, v => { noiseStrNode.value = v })
|
|
51
|
+
watch(() => props.sharpness, v => { sharpNode.value = v })
|
|
52
|
+
watch(() => props.speed, v => { speedNode.value = v })
|
|
53
|
+
|
|
54
|
+
const pipeline = useShaderPipelineContext()
|
|
55
|
+
|
|
56
|
+
useShaderStage(
|
|
57
|
+
() => {
|
|
58
|
+
const uv = pipeline.uvNode.value
|
|
59
|
+
const t = time.mul(speedNode)
|
|
60
|
+
const n = fbm2D(uv.mul(noiseScaleNode).add(t))
|
|
61
|
+
// Sine + noise offset creates the vein pattern
|
|
62
|
+
const vein = sin(uv.x.mul(freqNode).add(n.mul(noiseStrNode))).abs().pow(sharpNode)
|
|
63
|
+
return vec4(mix(colorANode, colorBNode, vein), float(1))
|
|
64
|
+
},
|
|
65
|
+
props.order,
|
|
66
|
+
)
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { smoothstep, uniform, vec4 } from 'three/tsl'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Fades the accumulated pipeline colour toward transparent/black based on
|
|
7
|
+
* a UV axis threshold. Useful as a final Y/X-axis gradient mask.
|
|
8
|
+
*
|
|
9
|
+
* Example (Grainient final step):
|
|
10
|
+
* <MixBlend axis="y" :edge0="0.45" :edge1="0.55" />
|
|
11
|
+
*/
|
|
12
|
+
const props = withDefaults(defineProps<{
|
|
13
|
+
axis?: 'x' | 'y'
|
|
14
|
+
edge0?: number
|
|
15
|
+
edge1?: number
|
|
16
|
+
/** 0 = fade to transparent, 1 = fade to opaque (keep prev) */
|
|
17
|
+
invert?: boolean
|
|
18
|
+
order?: number
|
|
19
|
+
}>(), {
|
|
20
|
+
axis: 'y',
|
|
21
|
+
edge0: 0.45,
|
|
22
|
+
edge1: 0.55,
|
|
23
|
+
invert: false,
|
|
24
|
+
order: 0,
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const edge0Node = uniform(props.edge0)
|
|
28
|
+
const edge1Node = uniform(props.edge1)
|
|
29
|
+
watch(() => props.edge0, v => { edge0Node.value = v })
|
|
30
|
+
watch(() => props.edge1, v => { edge1Node.value = v })
|
|
31
|
+
|
|
32
|
+
const { uvNode } = useShaderPipelineContext()
|
|
33
|
+
|
|
34
|
+
useShaderStage(
|
|
35
|
+
(prev) => {
|
|
36
|
+
const coord = props.axis === 'x' ? uvNode.value.x : uvNode.value.y
|
|
37
|
+
const mask = smoothstep(edge0Node, edge1Node, coord)
|
|
38
|
+
const alpha = props.invert ? mask.oneMinus() : mask
|
|
39
|
+
return vec4(prev.xyz, prev.w.mul(alpha))
|
|
40
|
+
},
|
|
41
|
+
props.order,
|
|
42
|
+
)
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { Color, Vector3 } from 'three'
|
|
4
|
+
import { uniform, vec4 } from 'three/tsl'
|
|
5
|
+
import { desaturate } from '../../shaders/common/blend'
|
|
6
|
+
|
|
7
|
+
const props = withDefaults(defineProps<{
|
|
8
|
+
/** Tint colour applied after desaturation */
|
|
9
|
+
color?: string
|
|
10
|
+
/** How much to desaturate before tinting: 1 = full greyscale */
|
|
11
|
+
desaturation?: number
|
|
12
|
+
order?: number
|
|
13
|
+
}>(), { color: '#4466aa', desaturation: 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 colorNode = toVec3Node(props.color)
|
|
21
|
+
const desatNode = uniform(props.desaturation)
|
|
22
|
+
watch(() => props.color, v => { const c = new Color(v); colorNode.value.set(c.r, c.g, c.b) })
|
|
23
|
+
watch(() => props.desaturation, v => { desatNode.value = v })
|
|
24
|
+
|
|
25
|
+
useShaderStage(
|
|
26
|
+
(prev) => vec4(desaturate(prev.xyz, desatNode).mul(colorNode), prev.w),
|
|
27
|
+
props.order,
|
|
28
|
+
)
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<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 { blendMultiply } 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, blendMultiply(prev.xyz, colorNode), opacityNode), prev.w),
|
|
20
|
+
props.order,
|
|
21
|
+
)
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,54 @@
|
|
|
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 { fbm2D } from '../../shaders/common/noise'
|
|
6
|
+
|
|
7
|
+
/** Linear gradient with per-pixel FBM noise offset — living, organic gradient. */
|
|
8
|
+
const props = withDefaults(defineProps<{
|
|
9
|
+
colorA?: string
|
|
10
|
+
colorB?: string
|
|
11
|
+
/** Gradient axis angle in degrees */
|
|
12
|
+
angle?: number
|
|
13
|
+
/** Noise displacement strength */
|
|
14
|
+
noiseStrength?: number
|
|
15
|
+
/** Noise input scale */
|
|
16
|
+
noiseScale?: number
|
|
17
|
+
/** Animation speed */
|
|
18
|
+
speed?: number
|
|
19
|
+
order?: number
|
|
20
|
+
}>(), { colorA: '#1a0a5a', colorB: '#ff8866', angle: 0, noiseStrength: 0.3, noiseScale: 2, speed: 0.15, 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 colorANode = toVec3Node(props.colorA)
|
|
28
|
+
const colorBNode = toVec3Node(props.colorB)
|
|
29
|
+
const angleNode = uniform(props.angle * Math.PI / 180)
|
|
30
|
+
const noiseStrNode = uniform(props.noiseStrength)
|
|
31
|
+
const noiseScaleNode = uniform(props.noiseScale)
|
|
32
|
+
const speedNode = uniform(props.speed)
|
|
33
|
+
watch(() => props.colorA, v => { const c = new Color(v); colorANode.value.set(c.r, c.g, c.b) })
|
|
34
|
+
watch(() => props.colorB, v => { const c = new Color(v); colorBNode.value.set(c.r, c.g, c.b) })
|
|
35
|
+
watch(() => props.angle, v => { angleNode.value = v * Math.PI / 180 })
|
|
36
|
+
watch(() => props.noiseStrength, v => { noiseStrNode.value = v })
|
|
37
|
+
watch(() => props.noiseScale, v => { noiseScaleNode.value = v })
|
|
38
|
+
watch(() => props.speed, v => { speedNode.value = v })
|
|
39
|
+
|
|
40
|
+
const pipeline = useShaderPipelineContext()
|
|
41
|
+
|
|
42
|
+
useShaderStage(
|
|
43
|
+
() => {
|
|
44
|
+
const uv = pipeline.uvNode.value
|
|
45
|
+
const n = fbm2D(uv.mul(noiseScaleNode).add(time.mul(speedNode)))
|
|
46
|
+
const base = uv.x.mul(angleNode.cos()).add(uv.y.mul(angleNode.sin()))
|
|
47
|
+
const t = base.add(n.mul(noiseStrNode)).clamp(float(0), float(1))
|
|
48
|
+
return vec4(mix(colorANode, colorBNode, t), float(1))
|
|
49
|
+
},
|
|
50
|
+
props.order,
|
|
51
|
+
)
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { Color, Vector3 } from 'three'
|
|
4
|
+
import { uniform, time, vec2, vec4, mix, smoothstep, cos, sin, float } from 'three/tsl'
|
|
5
|
+
import { simplexNoise2D } from '../../shaders/common/noise'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Self-contained Grainient/Shadertoy gradient pattern.
|
|
9
|
+
* Combines: GradientNoise → noise-driven UV rotation → asymmetric sine warp
|
|
10
|
+
* → rotated two-colour blend.
|
|
11
|
+
* Equivalent to: UVNoiseRotate + UVSineWarpXY + RotatedGradientBlend in one component.
|
|
12
|
+
* Exposes all params individually so the pipeline can still intercept at any stage,
|
|
13
|
+
* but provides a convenient self-contained starting point.
|
|
14
|
+
*/
|
|
15
|
+
const props = withDefaults(defineProps<{
|
|
16
|
+
colorA?: string
|
|
17
|
+
colorB?: string
|
|
18
|
+
/** Noise input scale */
|
|
19
|
+
noiseScale?: number
|
|
20
|
+
/** Max rotation amount driven by noise (degrees) */
|
|
21
|
+
rotationAmount?: number
|
|
22
|
+
/** Sine warp frequency */
|
|
23
|
+
warpFrequency?: number
|
|
24
|
+
/** Sine warp amplitude (higher = subtler) */
|
|
25
|
+
warpAmplitude?: number
|
|
26
|
+
/** Gradient blend angle (degrees) */
|
|
27
|
+
blendAngle?: number
|
|
28
|
+
/** Smoothstep lower edge */
|
|
29
|
+
edge0?: number
|
|
30
|
+
/** Smoothstep upper edge */
|
|
31
|
+
edge1?: number
|
|
32
|
+
/** Animation speed */
|
|
33
|
+
speed?: number
|
|
34
|
+
order?: number
|
|
35
|
+
}>(), {
|
|
36
|
+
colorA: '#1a0a5a',
|
|
37
|
+
colorB: '#ff6688',
|
|
38
|
+
noiseScale: 1,
|
|
39
|
+
rotationAmount: 720,
|
|
40
|
+
warpFrequency: 3,
|
|
41
|
+
warpAmplitude: 3,
|
|
42
|
+
blendAngle: 45,
|
|
43
|
+
edge0: 0.2,
|
|
44
|
+
edge1: 0.8,
|
|
45
|
+
speed: 0.3,
|
|
46
|
+
order: 0,
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
const DEG2RAD = Math.PI / 180
|
|
50
|
+
|
|
51
|
+
function toVec3Node(hex: string) {
|
|
52
|
+
const c = new Color(hex)
|
|
53
|
+
return uniform(new Vector3(c.r, c.g, c.b))
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const colorANode = toVec3Node(props.colorA)
|
|
57
|
+
const colorBNode = toVec3Node(props.colorB)
|
|
58
|
+
const noiseScaleNode = uniform(props.noiseScale)
|
|
59
|
+
const rotAmountNode = uniform(props.rotationAmount * DEG2RAD)
|
|
60
|
+
const warpFreqNode = uniform(props.warpFrequency)
|
|
61
|
+
const warpAmpNode = uniform(props.warpAmplitude)
|
|
62
|
+
const blendAngleNode = uniform(props.blendAngle * DEG2RAD)
|
|
63
|
+
const edge0Node = uniform(props.edge0)
|
|
64
|
+
const edge1Node = uniform(props.edge1)
|
|
65
|
+
const speedNode = uniform(props.speed)
|
|
66
|
+
|
|
67
|
+
watch(() => props.colorA, v => { const c = new Color(v); colorANode.value.set(c.r, c.g, c.b) })
|
|
68
|
+
watch(() => props.colorB, v => { const c = new Color(v); colorBNode.value.set(c.r, c.g, c.b) })
|
|
69
|
+
watch(() => props.noiseScale, v => { noiseScaleNode.value = v })
|
|
70
|
+
watch(() => props.rotationAmount, v => { rotAmountNode.value = v * DEG2RAD })
|
|
71
|
+
watch(() => props.warpFrequency, v => { warpFreqNode.value = v })
|
|
72
|
+
watch(() => props.warpAmplitude, v => { warpAmpNode.value = v })
|
|
73
|
+
watch(() => props.blendAngle, v => { blendAngleNode.value = v * DEG2RAD })
|
|
74
|
+
watch(() => props.edge0, v => { edge0Node.value = v })
|
|
75
|
+
watch(() => props.edge1, v => { edge1Node.value = v })
|
|
76
|
+
watch(() => props.speed, v => { speedNode.value = v })
|
|
77
|
+
|
|
78
|
+
const pipeline = useShaderPipelineContext()
|
|
79
|
+
|
|
80
|
+
useShaderStage(
|
|
81
|
+
() => {
|
|
82
|
+
const uvCurrent = pipeline.uvNode.value
|
|
83
|
+
if (!uvCurrent) return vec4(0, 0, 0, 1)
|
|
84
|
+
|
|
85
|
+
const t = time.mul(speedNode)
|
|
86
|
+
|
|
87
|
+
// 1. Noise-driven UV rotation
|
|
88
|
+
const n = simplexNoise2D(uvCurrent.mul(noiseScaleNode).add(t))
|
|
89
|
+
const angle = n.mul(0.5).add(0.5).mul(rotAmountNode).add(float(Math.PI)).sub(rotAmountNode.mul(0.5))
|
|
90
|
+
const c1 = cos(angle)
|
|
91
|
+
const s1 = sin(angle)
|
|
92
|
+
const centered = uvCurrent.sub(0.5)
|
|
93
|
+
const rotated = vec2(
|
|
94
|
+
centered.x.mul(c1).sub(centered.y.mul(s1)),
|
|
95
|
+
centered.x.mul(s1).add(centered.y.mul(c1)),
|
|
96
|
+
).add(0.5)
|
|
97
|
+
|
|
98
|
+
// 2. Asymmetric sine warp — pure functional (no toVar/addAssign needed)
|
|
99
|
+
// warpedY uses warpedX to replicate the sequential addAssign behaviour
|
|
100
|
+
const warpedX = rotated.x.add(sin(rotated.y.mul(warpFreqNode).add(t)).div(warpAmpNode))
|
|
101
|
+
const warpedY = rotated.y.add(sin(warpedX.mul(warpFreqNode.mul(1.5)).add(t)).div(warpAmpNode.mul(0.5)))
|
|
102
|
+
const tuv = vec2(warpedX, warpedY)
|
|
103
|
+
|
|
104
|
+
// 3. Rotated gradient blend
|
|
105
|
+
const cb = cos(blendAngleNode)
|
|
106
|
+
const sb = sin(blendAngleNode)
|
|
107
|
+
const rotX = tuv.sub(0.5).x.mul(cb).sub(tuv.sub(0.5).y.mul(sb)).add(0.5)
|
|
108
|
+
const blend = smoothstep(edge0Node, edge1Node, rotX)
|
|
109
|
+
|
|
110
|
+
return vec4(mix(colorANode, colorBNode, blend), float(1))
|
|
111
|
+
},
|
|
112
|
+
props.order,
|
|
113
|
+
)
|
|
114
|
+
</script>
|
|
115
|
+
|
|
116
|
+
<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 { blendOverlay } 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, blendOverlay(prev.xyz, colorNode), opacityNode), prev.w),
|
|
20
|
+
props.order,
|
|
21
|
+
)
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { uniform, time, vec4, floor, float } from 'three/tsl'
|
|
4
|
+
import { paperTexture } from '../../shaders/common/grain'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Paper texture overlay — multi-octave grain that reads like coarse paper or canvas.
|
|
8
|
+
* Adds tactile analogue feel to any underlying image.
|
|
9
|
+
*/
|
|
10
|
+
const props = withDefaults(defineProps<{
|
|
11
|
+
/** Texture scale — higher = finer grain pattern */
|
|
12
|
+
scale?: number
|
|
13
|
+
/** Overlay intensity */
|
|
14
|
+
intensity?: number
|
|
15
|
+
/** Animate slowly for a living-paper effect (0 = static) */
|
|
16
|
+
speed?: number
|
|
17
|
+
order?: number
|
|
18
|
+
}>(), { scale: 12, intensity: 0.08, speed: 0, order: 0 })
|
|
19
|
+
|
|
20
|
+
const scaleNode = uniform(props.scale)
|
|
21
|
+
const intensityNode = uniform(props.intensity)
|
|
22
|
+
const speedNode = uniform(props.speed)
|
|
23
|
+
watch(() => props.scale, v => { scaleNode.value = v })
|
|
24
|
+
watch(() => props.intensity, v => { intensityNode.value = v })
|
|
25
|
+
watch(() => props.speed, v => { speedNode.value = v })
|
|
26
|
+
|
|
27
|
+
const pipeline = useShaderPipelineContext()
|
|
28
|
+
|
|
29
|
+
useShaderStage(
|
|
30
|
+
(prev) => {
|
|
31
|
+
const uv = pipeline.uvNode.value
|
|
32
|
+
const seed = floor(time.mul(speedNode).mul(6))
|
|
33
|
+
|
|
34
|
+
const tex = paperTexture(uv, scaleNode, intensityNode, seed)
|
|
35
|
+
return vec4(prev.xyz.add(tex), prev.w)
|
|
36
|
+
},
|
|
37
|
+
props.order,
|
|
38
|
+
)
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<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 { polygon } from '../../shaders/common/shapes'
|
|
6
|
+
|
|
7
|
+
const props = withDefaults(defineProps<{
|
|
8
|
+
colorA?: string
|
|
9
|
+
colorB?: string
|
|
10
|
+
/** Number of sides */
|
|
11
|
+
sides?: number
|
|
12
|
+
radius?: number
|
|
13
|
+
softness?: number
|
|
14
|
+
/** Rotation offset in degrees */
|
|
15
|
+
rotation?: number
|
|
16
|
+
order?: number
|
|
17
|
+
}>(), { colorA: '#000000', colorB: '#ffffff', sides: 6, radius: 0.35, softness: 0.01, rotation: 0, 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 softnessNode = uniform(props.softness)
|
|
28
|
+
const rotationNode = uniform(props.rotation * Math.PI / 180)
|
|
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.softness, v => { softnessNode.value = v })
|
|
33
|
+
watch(() => props.rotation, v => { rotationNode.value = v * Math.PI / 180 })
|
|
34
|
+
|
|
35
|
+
const pipeline = useShaderPipelineContext()
|
|
36
|
+
|
|
37
|
+
useShaderStage(
|
|
38
|
+
() => {
|
|
39
|
+
const uv = pipeline.uvNode.value
|
|
40
|
+
const mask = polygon(uv, [0.5, 0.5], radiusNode, props.sides, softnessNode)
|
|
41
|
+
return vec4(mix(colorANode, colorBNode, mask), float(1))
|
|
42
|
+
},
|
|
43
|
+
props.order,
|
|
44
|
+
)
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { uniform, vec4, floor, float } from 'three/tsl'
|
|
4
|
+
|
|
5
|
+
const props = withDefaults(defineProps<{
|
|
6
|
+
/** Number of colour steps per channel */
|
|
7
|
+
steps?: number
|
|
8
|
+
order?: number
|
|
9
|
+
}>(), { steps: 6, order: 0 })
|
|
10
|
+
|
|
11
|
+
const stepsNode = uniform(props.steps)
|
|
12
|
+
watch(() => props.steps, v => { stepsNode.value = v })
|
|
13
|
+
|
|
14
|
+
useShaderStage(
|
|
15
|
+
(prev) => {
|
|
16
|
+
const posterised = floor(prev.xyz.mul(stepsNode)).div(stepsNode.sub(float(1)))
|
|
17
|
+
return vec4(posterised, prev.w)
|
|
18
|
+
},
|
|
19
|
+
props.order,
|
|
20
|
+
)
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { Color } from 'three'
|
|
4
|
+
import { clamp, mix, uniform, vec4 } from 'three/tsl'
|
|
5
|
+
|
|
6
|
+
const props = withDefaults(defineProps<{
|
|
7
|
+
colorCenter?: string
|
|
8
|
+
colorEdge?: string
|
|
9
|
+
radius?: number
|
|
10
|
+
order?: number
|
|
11
|
+
}>(), {
|
|
12
|
+
colorCenter: '#ffffff',
|
|
13
|
+
colorEdge: '#000000',
|
|
14
|
+
radius: 0.7,
|
|
15
|
+
order: 0,
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
const colorCenterVal = new Color(props.colorCenter)
|
|
19
|
+
const colorEdgeVal = new Color(props.colorEdge)
|
|
20
|
+
const colorCenterNode = uniform(colorCenterVal)
|
|
21
|
+
const colorEdgeNode = uniform(colorEdgeVal)
|
|
22
|
+
const radiusNode = uniform(props.radius)
|
|
23
|
+
|
|
24
|
+
watch(() => props.colorCenter, v => { colorCenterNode.value.set(v) })
|
|
25
|
+
watch(() => props.colorEdge, v => { colorEdgeNode.value.set(v) })
|
|
26
|
+
watch(() => props.radius, v => { radiusNode.value = v })
|
|
27
|
+
|
|
28
|
+
const { uvNode } = useShaderPipelineContext()
|
|
29
|
+
|
|
30
|
+
useShaderStage(
|
|
31
|
+
(_prev) => {
|
|
32
|
+
const t = clamp(uvNode.value.sub(0.5).length().div(radiusNode), 0, 1)
|
|
33
|
+
return vec4(mix(colorCenterNode, colorEdgeNode, t), 1.0)
|
|
34
|
+
},
|
|
35
|
+
props.order,
|
|
36
|
+
)
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { uniform, time, cos, sin, vec3 } from 'three/tsl'
|
|
4
|
+
|
|
5
|
+
const props = withDefaults(defineProps<{
|
|
6
|
+
/** Orbit speed in radians per second (Y axis) */
|
|
7
|
+
speed?: number
|
|
8
|
+
/** Additional fixed pitch in radians (X axis) */
|
|
9
|
+
pitch?: number
|
|
10
|
+
order?: number
|
|
11
|
+
}>(), { speed: 0.5, pitch: 0, order: 0 })
|
|
12
|
+
|
|
13
|
+
const speedNode = uniform(props.speed)
|
|
14
|
+
const pitchNode = uniform(props.pitch)
|
|
15
|
+
watch(() => props.speed, v => { speedNode.value = v })
|
|
16
|
+
watch(() => props.pitch, v => { pitchNode.value = v })
|
|
17
|
+
|
|
18
|
+
useShaderStage(
|
|
19
|
+
(ray) => {
|
|
20
|
+
const yaw = time.mul(speedNode)
|
|
21
|
+
|
|
22
|
+
// Y-axis rotation (orbit)
|
|
23
|
+
const cy = cos(yaw)
|
|
24
|
+
const sy = sin(yaw)
|
|
25
|
+
const rayY = vec3(ray.x.mul(cy).add(ray.z.mul(sy)), ray.y, ray.z.mul(cy).sub(ray.x.mul(sy)))
|
|
26
|
+
|
|
27
|
+
// X-axis pitch
|
|
28
|
+
const cp = cos(pitchNode)
|
|
29
|
+
const sp = sin(pitchNode)
|
|
30
|
+
return vec3(rayY.x, rayY.y.mul(cp).sub(rayY.z.mul(sp)), rayY.y.mul(sp).add(rayY.z.mul(cp)))
|
|
31
|
+
},
|
|
32
|
+
props.order,
|
|
33
|
+
'ray',
|
|
34
|
+
)
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { Vector2 } from 'three'
|
|
4
|
+
import { uniform, cos, sin, vec3 } from 'three/tsl'
|
|
5
|
+
|
|
6
|
+
const props = withDefaults(defineProps<{
|
|
7
|
+
/** Multiplier for horizontal mouse sweep → yaw range (radians) */
|
|
8
|
+
yawRange?: number
|
|
9
|
+
/** Multiplier for vertical mouse sweep → pitch range (radians) */
|
|
10
|
+
pitchRange?: number
|
|
11
|
+
order?: number
|
|
12
|
+
}>(), { yawRange: Math.PI, pitchRange: Math.PI / 3, order: 0 })
|
|
13
|
+
|
|
14
|
+
const mouse = uniform(new Vector2(0.5, 0.5))
|
|
15
|
+
|
|
16
|
+
onMounted(() => {
|
|
17
|
+
const onMove = (e: MouseEvent) => {
|
|
18
|
+
mouse.value.set(e.clientX / window.innerWidth, 1 - e.clientY / window.innerHeight)
|
|
19
|
+
}
|
|
20
|
+
window.addEventListener('mousemove', onMove)
|
|
21
|
+
onUnmounted(() => window.removeEventListener('mousemove', onMove))
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const yawRangeNode = uniform(props.yawRange)
|
|
25
|
+
const pitchRangeNode = uniform(props.pitchRange)
|
|
26
|
+
watch(() => props.yawRange, v => { yawRangeNode.value = v })
|
|
27
|
+
watch(() => props.pitchRange, v => { pitchRangeNode.value = v })
|
|
28
|
+
|
|
29
|
+
useShaderStage(
|
|
30
|
+
(ray) => {
|
|
31
|
+
const yaw = mouse.x.sub(0.5).mul(yawRangeNode)
|
|
32
|
+
const pitch = mouse.y.sub(0.5).mul(pitchRangeNode)
|
|
33
|
+
|
|
34
|
+
// Yaw (Y-axis)
|
|
35
|
+
const cy = cos(yaw)
|
|
36
|
+
const sy = sin(yaw)
|
|
37
|
+
const rayY = vec3(ray.x.mul(cy).add(ray.z.mul(sy)), ray.y, ray.z.mul(cy).sub(ray.x.mul(sy)))
|
|
38
|
+
|
|
39
|
+
// Pitch (X-axis)
|
|
40
|
+
const cp = cos(pitch)
|
|
41
|
+
const sp = sin(pitch)
|
|
42
|
+
return vec3(rayY.x, rayY.y.mul(cp).sub(rayY.z.mul(sp)), rayY.y.mul(sp).add(rayY.z.mul(cp)))
|
|
43
|
+
},
|
|
44
|
+
props.order,
|
|
45
|
+
'ray',
|
|
46
|
+
)
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<template><!-- --></template>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { uniform, cos, sin, vec3 } from 'three/tsl'
|
|
4
|
+
|
|
5
|
+
const props = withDefaults(defineProps<{
|
|
6
|
+
/** Rotation angle in radians */
|
|
7
|
+
angle?: number
|
|
8
|
+
order?: number
|
|
9
|
+
}>(), { angle: 0, order: 0 })
|
|
10
|
+
|
|
11
|
+
const angleNode = uniform(props.angle)
|
|
12
|
+
watch(() => props.angle, v => { angleNode.value = v })
|
|
13
|
+
|
|
14
|
+
useShaderStage(
|
|
15
|
+
(ray) => {
|
|
16
|
+
const c = cos(angleNode)
|
|
17
|
+
const s = sin(angleNode)
|
|
18
|
+
return vec3(ray.x, ray.y.mul(c).sub(ray.z.mul(s)), ray.y.mul(s).add(ray.z.mul(c)))
|
|
19
|
+
},
|
|
20
|
+
props.order,
|
|
21
|
+
'ray',
|
|
22
|
+
)
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template><!-- --></template>
|