kmcom-nuxt-layers 2.2.11 → 2.2.13
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/docs/FALLOW-COMPLEXITY-DUPLICATION-AUDIT.md +65 -0
- package/docs/FEEDS.md +1 -2
- package/docs/IMPROVE-AUDIT-README.md +30 -0
- package/docs/IMPROVE-AUDIT-RESULTS.md +52 -0
- package/docs/IMPROVE-DEEP-AUDIT-RESULTS.md +81 -0
- package/docs/fallow-refactor/apps-debug.md +27 -0
- package/docs/fallow-refactor/apps-playground.md +46 -0
- package/docs/fallow-refactor/apps-visual-identity.md +41 -0
- package/docs/fallow-refactor/layers-animations.md +34 -0
- package/docs/fallow-refactor/layers-canvas.md +32 -0
- package/docs/fallow-refactor/layers-content.md +33 -0
- package/docs/fallow-refactor/layers-core.md +39 -0
- package/docs/fallow-refactor/layers-feeds.md +39 -0
- package/docs/fallow-refactor/layers-forms.md +30 -0
- package/docs/fallow-refactor/layers-layout.md +42 -0
- package/docs/fallow-refactor/layers-mailer.md +32 -0
- package/docs/fallow-refactor/layers-motion.md +27 -0
- package/docs/fallow-refactor/layers-navigation.md +31 -0
- package/docs/fallow-refactor/layers-page-transitions.md +30 -0
- package/docs/fallow-refactor/layers-routing.md +33 -0
- package/docs/fallow-refactor/layers-scripts.md +35 -0
- package/docs/fallow-refactor/layers-scroll.md +38 -0
- package/docs/fallow-refactor/layers-seo.md +32 -0
- package/docs/fallow-refactor/layers-shader.md +53 -0
- package/docs/fallow-refactor/layers-theme.md +33 -0
- package/docs/fallow-refactor/layers-transitions.md +27 -0
- package/docs/fallow-refactor/layers-typography.md +29 -0
- package/docs/fallow-refactor/layers-ui.md +27 -0
- package/docs/fallow-refactor/layers-visual.md +34 -0
- package/layers/animations/app/composables/useMagneticElement.ts +11 -9
- package/layers/animations/app/composables/useTiltEffect.ts +11 -9
- package/layers/animations/app/utils/pointerMotion.ts +31 -0
- package/layers/canvas/app/components/ShaderCanvas.vue +2 -2
- package/layers/content/app/composables/useCollectionItems.ts +28 -0
- package/layers/content/app/composables/useGalleryItems.ts +8 -14
- package/layers/content/app/composables/usePortfolioItems.ts +10 -18
- package/layers/core/app/composables/useBrowser.ts +9 -82
- package/layers/core/app/composables/useFeatures.ts +3 -27
- package/layers/core/app/plugins/init.ts +157 -135
- package/layers/core/app/utils/browserInfo.ts +115 -0
- package/layers/core/app/utils/featureClasses.ts +40 -0
- package/layers/core/app/utils/helpers.test.ts +51 -0
- package/layers/feeds/app/app.config.ts +4 -2
- package/layers/feeds/app/components/Feeds/Index.vue +229 -0
- package/layers/feeds/app/components/Feeds/RouteCard.vue +75 -0
- package/layers/feeds/app/plugins/feed-head.ts +27 -49
- package/layers/feeds/app/utils/feed-catalog.ts +184 -0
- package/layers/feeds/nuxt.config.ts +0 -1
- package/layers/feeds/package.json +1 -0
- package/layers/feeds/server/utils/content-adapter.test.ts +68 -0
- package/layers/feeds/server/utils/content-adapter.ts +2 -22
- package/layers/feeds/server/utils/feed-author.ts +32 -0
- package/layers/feeds/server/utils/feed-config.ts +88 -0
- package/layers/feeds/server/utils/feed-service.ts +11 -30
- package/layers/feeds/server/utils/feed-xml.ts +26 -0
- package/layers/feeds/server/utils/formats/rss.ts +10 -15
- package/layers/feeds/server/utils/formats.test.ts +71 -0
- package/layers/forms/app/components/Form/Field.vue +42 -30
- package/layers/forms/app/utils/fieldProps.ts +65 -0
- package/layers/layout/app/components/Layout/Grid/Item.vue +29 -146
- package/layers/layout/app/utils/gridPlacementStyle.ts +195 -0
- package/layers/mailer/app/types/mailer.ts +7 -25
- package/layers/mailer/server/utils/email.ts +28 -13
- package/layers/mailer/server/utils/hooks.ts +1 -20
- package/layers/navigation/app/composables/useSite.ts +2 -9
- package/layers/navigation/app/utils/site.ts +26 -0
- package/layers/routing/app/utils/resolveRoute.test.ts +47 -0
- package/layers/routing/app/utils/resolveRoute.ts +19 -10
- package/layers/scripts/app/composables/useAnalytics.ts +8 -41
- package/layers/scripts/app/composables/useGtm.ts +6 -13
- package/layers/scripts/app/utils/scriptClients.ts +70 -0
- package/layers/scroll/app/composables/useSmoothScroll.ts +9 -43
- package/layers/scroll/app/utils/scroll.ts +103 -0
- package/layers/seo/app/composables/useSeoConfig.ts +3 -9
- package/layers/seo/app/utils/seoConfig.ts +38 -0
- package/layers/shader/app/components/Material/AmbientAurora.client.vue +11 -33
- package/layers/shader/app/components/Material/AmbientFlow.client.vue +10 -37
- package/layers/shader/app/components/Material/AmbientGradientMesh.client.vue +10 -37
- package/layers/shader/app/components/Material/AmbientNebula.client.vue +12 -37
- package/layers/shader/app/components/Material/AmbientOcean.client.vue +9 -33
- package/layers/shader/app/components/Material/Gradient.client.vue +25 -46
- package/layers/shader/app/components/Material/Image.client.vue +10 -55
- package/layers/shader/app/components/Material/Node.client.vue +18 -5
- package/layers/shader/app/components/Material/Noise.client.vue +9 -43
- package/layers/shader/app/components/Preset/ThemeBubble.client.vue +2 -1
- package/layers/shader/app/components/Preset/ThemeFlow.client.vue +2 -1
- package/layers/shader/app/components/Preset/ThemeGradient.client.vue +2 -1
- package/layers/shader/app/components/Preset/ThemeLavaLamp.client.vue +2 -1
- package/layers/shader/app/components/Preset/ThemePlasma.client.vue +2 -1
- package/layers/shader/app/components/Preset/ThemeWave.client.vue +2 -1
- package/layers/shader/app/components/Shader/Background.client.vue +44 -24
- package/layers/shader/app/composables/useAmbientMaterials.ts +5 -1
- package/layers/shader/app/composables/useShader.ts +38 -23
- package/layers/shader/app/composables/useShaderGraph.ts +11 -6
- package/layers/shader/app/composables/useShaderMixBlend.ts +4 -4
- package/layers/shader/app/composables/useShaderRuntime.ts +0 -1
- package/layers/shader/app/composables/useShaderVec2.ts +2 -4
- package/layers/shader/app/composables/useThemePreset.ts +34 -8
- package/layers/shader/app/composables/useUniformWatchers.ts +15 -0
- package/layers/shader/app/composables/useUniforms.ts +0 -1
- package/layers/shader/app/shaders/common/blend.ts +4 -4
- package/layers/shader/app/shaders/common/effects.ts +38 -21
- package/layers/shader/app/shaders/common/grain.ts +46 -49
- package/layers/shader/app/shaders/common/lighting.ts +17 -15
- package/layers/shader/app/shaders/common/math.ts +2 -4
- package/layers/shader/app/shaders/common/nodes.ts +17 -0
- package/layers/shader/app/shaders/common/palette.ts +21 -11
- package/layers/shader/app/shaders/common/patterns.ts +25 -14
- package/layers/shader/app/shaders/common/shapes.ts +97 -88
- package/layers/shader/app/shaders/common/uv.ts +33 -34
- package/layers/shader/app/shaders/createMaterial.ts +92 -78
- package/layers/shader/app/shaders/layers/paperShading.ts +22 -10
- package/layers/shader/app/shaders/layers/shaderGradient.ts +46 -21
- package/layers/shader/app/utils/tsl/tween.ts +2 -4
- package/layers/shader/package.json +5 -1
- package/layers/theme/app/components/ThemePicker/Menu.vue +3 -25
- package/layers/theme/app/composables/useThemePreferenceModels.ts +39 -0
- package/layers/theme/server/plugins/theme-fouc.ts +1 -92
- package/layers/theme/server/utils/accent-css.ts +75 -0
- package/layers/typography/app/composables/typography.ts +3 -7
- package/layers/visual/app/composables/accent.ts +2 -9
- package/layers/visual/app/composables/gradient.ts +33 -46
- package/layers/visual/app/composables/picture.ts +2 -79
- package/layers/visual/app/utils/colorTokens.ts +23 -0
- package/layers/visual/app/utils/gradientStyle.ts +41 -0
- package/layers/visual/app/utils/responsiveSizes.ts +49 -0
- package/package.json +17 -5
- package/layers/feeds/server/routes/feed/discovery.get.ts +0 -29
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
import { simplexNoise2D } from '../../shaders/common/noise'
|
|
22
22
|
import type { TSLNode } from '../../shaders/types'
|
|
23
|
+
import { watchUniformProp } from '#layers/shader/app/composables/useUniformWatchers'
|
|
23
24
|
|
|
24
25
|
const {
|
|
25
26
|
speed = 1.0,
|
|
@@ -53,39 +54,14 @@
|
|
|
53
54
|
const color2Uniform: TSLNode = uniform(new Color(color2))
|
|
54
55
|
const color3Uniform: TSLNode = uniform(new Color(color3))
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
)
|
|
65
|
-
watch(
|
|
66
|
-
() => mouseX,
|
|
67
|
-
(val) => (mouseXUniform.value = val)
|
|
68
|
-
)
|
|
69
|
-
watch(
|
|
70
|
-
() => mouseY,
|
|
71
|
-
(val) => (mouseYUniform.value = val)
|
|
72
|
-
)
|
|
73
|
-
watch(
|
|
74
|
-
() => mouseStrength,
|
|
75
|
-
(val) => (mouseStrengthUniform.value = val)
|
|
76
|
-
)
|
|
77
|
-
watch(
|
|
78
|
-
() => color1,
|
|
79
|
-
(val) => (color1Uniform.value = new Color(val))
|
|
80
|
-
)
|
|
81
|
-
watch(
|
|
82
|
-
() => color2,
|
|
83
|
-
(val) => (color2Uniform.value = new Color(val))
|
|
84
|
-
)
|
|
85
|
-
watch(
|
|
86
|
-
() => color3,
|
|
87
|
-
(val) => (color3Uniform.value = new Color(val))
|
|
88
|
-
)
|
|
57
|
+
watchUniformProp(() => speed, speedUniform)
|
|
58
|
+
watchUniformProp(() => intensity, intensityUniform)
|
|
59
|
+
watchUniformProp(() => mouseX, mouseXUniform)
|
|
60
|
+
watchUniformProp(() => mouseY, mouseYUniform)
|
|
61
|
+
watchUniformProp(() => mouseStrength, mouseStrengthUniform)
|
|
62
|
+
watchUniformProp(() => color1, color1Uniform, (val) => new Color(val))
|
|
63
|
+
watchUniformProp(() => color2, color2Uniform, (val) => new Color(val))
|
|
64
|
+
watchUniformProp(() => color3, color3Uniform, (val) => new Color(val))
|
|
89
65
|
|
|
90
66
|
const material = computed(() => {
|
|
91
67
|
const mat = new MeshBasicNodeMaterial()
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { MeshBasicNodeMaterial } from 'three/webgpu'
|
|
5
5
|
|
|
6
6
|
import type { TSLNode } from '../../types'
|
|
7
|
+
import { watchUniformProp } from '#layers/shader/app/composables/useUniformWatchers'
|
|
7
8
|
|
|
8
9
|
const {
|
|
9
10
|
colors = ['#4f46e5', '#7c3aed', '#ec4899'],
|
|
@@ -49,37 +50,11 @@
|
|
|
49
50
|
uniform(new Color(colors[4] || '#ec4899')),
|
|
50
51
|
]
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
)
|
|
59
|
-
watch(
|
|
60
|
-
() => speed,
|
|
61
|
-
(val) => {
|
|
62
|
-
speedUniform.value = val
|
|
63
|
-
}
|
|
64
|
-
)
|
|
65
|
-
watch(
|
|
66
|
-
() => mouseX,
|
|
67
|
-
(val) => {
|
|
68
|
-
mouseXUniform.value = val
|
|
69
|
-
}
|
|
70
|
-
)
|
|
71
|
-
watch(
|
|
72
|
-
() => mouseY,
|
|
73
|
-
(val) => {
|
|
74
|
-
mouseYUniform.value = val
|
|
75
|
-
}
|
|
76
|
-
)
|
|
77
|
-
watch(
|
|
78
|
-
() => mouseStrength,
|
|
79
|
-
(val) => {
|
|
80
|
-
mouseStrengthUniform.value = val
|
|
81
|
-
}
|
|
82
|
-
)
|
|
53
|
+
watchUniformProp(() => angle, angleUniform)
|
|
54
|
+
watchUniformProp(() => speed, speedUniform)
|
|
55
|
+
watchUniformProp(() => mouseX, mouseXUniform)
|
|
56
|
+
watchUniformProp(() => mouseY, mouseYUniform)
|
|
57
|
+
watchUniformProp(() => mouseStrength, mouseStrengthUniform)
|
|
83
58
|
|
|
84
59
|
watch(
|
|
85
60
|
() => colors,
|
|
@@ -93,14 +68,10 @@
|
|
|
93
68
|
{ deep: true }
|
|
94
69
|
)
|
|
95
70
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const colorCount = colors.length
|
|
99
|
-
|
|
100
|
-
// Get UV coordinates
|
|
71
|
+
// fallow-ignore-next-line complexity
|
|
72
|
+
function resolveGradientT() {
|
|
101
73
|
let t: TSLNode = uv().y
|
|
102
74
|
|
|
103
|
-
// Apply angle rotation for linear gradient (using uniform for reactivity)
|
|
104
75
|
if (type === 'linear') {
|
|
105
76
|
const rad = angleUniform.mul(Math.PI / 180)
|
|
106
77
|
const cosVal = rad.cos()
|
|
@@ -108,10 +79,8 @@
|
|
|
108
79
|
t = uv().x.mul(sinVal).add(uv().y.mul(cosVal))
|
|
109
80
|
}
|
|
110
81
|
|
|
111
|
-
// Radial gradient uses distance from center
|
|
112
82
|
if (type === 'radial') {
|
|
113
83
|
let center = uv().sub(0.5)
|
|
114
|
-
// Add mouse interaction offset
|
|
115
84
|
if (mouseInteraction) {
|
|
116
85
|
const mouseOffset = vec3(
|
|
117
86
|
mouseXUniform.sub(0.5).mul(mouseStrengthUniform),
|
|
@@ -123,18 +92,20 @@
|
|
|
123
92
|
t = center.length().mul(2)
|
|
124
93
|
}
|
|
125
94
|
|
|
126
|
-
// Add mouse interaction for linear gradients
|
|
127
95
|
if (type === 'linear' && mouseInteraction) {
|
|
128
96
|
t = t.add(mouseXUniform.sub(0.5).mul(mouseStrengthUniform))
|
|
129
97
|
}
|
|
130
98
|
|
|
131
|
-
// Add animation
|
|
132
99
|
if (animated) {
|
|
133
100
|
t = t.add(sin(tslTime.mul(speedUniform)).mul(0.2))
|
|
134
101
|
}
|
|
135
102
|
|
|
136
|
-
|
|
137
|
-
|
|
103
|
+
return t
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// fallow-ignore-next-line complexity
|
|
107
|
+
function buildGradientColorNode(t: TSLNode) {
|
|
108
|
+
const colorCount = colors.length
|
|
138
109
|
const c0 = colorUniforms[0]
|
|
139
110
|
const c1 = colorUniforms[1]
|
|
140
111
|
const c2 = colorUniforms[2]
|
|
@@ -144,9 +115,10 @@
|
|
|
144
115
|
let colorNode: TSLNode = vec3(c0)
|
|
145
116
|
|
|
146
117
|
if (colorCount === 2) {
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
|
|
118
|
+
return mix(vec3(c0), vec3(c1), t)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (colorCount >= 3) {
|
|
150
122
|
const uniforms = [c0, c1, c2, c3, c4]
|
|
151
123
|
const segments = colorCount - 1
|
|
152
124
|
|
|
@@ -167,6 +139,13 @@
|
|
|
167
139
|
}
|
|
168
140
|
}
|
|
169
141
|
|
|
142
|
+
return colorNode
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const material = computed(() => {
|
|
146
|
+
const mat = new MeshBasicNodeMaterial()
|
|
147
|
+
|
|
148
|
+
const colorNode = buildGradientColorNode(resolveGradientT())
|
|
170
149
|
mat.colorNode = colorNode
|
|
171
150
|
mat.transparent = transparent
|
|
172
151
|
mat.side = DoubleSide
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
import type { TSLNode } from '../../types'
|
|
19
19
|
import { simplexNoise2D } from '../../utils/tsl/noise'
|
|
20
|
+
import { watchUniformProp } from '#layers/shader/app/composables/useUniformWatchers'
|
|
20
21
|
|
|
21
22
|
const {
|
|
22
23
|
src,
|
|
@@ -76,61 +77,15 @@
|
|
|
76
77
|
const rgbShiftUniform = uniform(rgbShift)
|
|
77
78
|
const vignetteIntensityUniform = uniform(vignetteIntensity)
|
|
78
79
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
(val) => {
|
|
89
|
-
mouseYUniform.value = val
|
|
90
|
-
}
|
|
91
|
-
)
|
|
92
|
-
watch(
|
|
93
|
-
() => distortion,
|
|
94
|
-
(val) => {
|
|
95
|
-
distortionUniform.value = val
|
|
96
|
-
}
|
|
97
|
-
)
|
|
98
|
-
watch(
|
|
99
|
-
() => distortionSpeed,
|
|
100
|
-
(val) => {
|
|
101
|
-
distortionSpeedUniform.value = val
|
|
102
|
-
}
|
|
103
|
-
)
|
|
104
|
-
watch(
|
|
105
|
-
() => rippleStrength,
|
|
106
|
-
(val) => {
|
|
107
|
-
rippleStrengthUniform.value = val
|
|
108
|
-
}
|
|
109
|
-
)
|
|
110
|
-
watch(
|
|
111
|
-
() => zoom,
|
|
112
|
-
(val) => {
|
|
113
|
-
zoomUniform.value = val
|
|
114
|
-
}
|
|
115
|
-
)
|
|
116
|
-
watch(
|
|
117
|
-
() => grayscale,
|
|
118
|
-
(val) => {
|
|
119
|
-
grayscaleUniform.value = val
|
|
120
|
-
}
|
|
121
|
-
)
|
|
122
|
-
watch(
|
|
123
|
-
() => rgbShift,
|
|
124
|
-
(val) => {
|
|
125
|
-
rgbShiftUniform.value = val
|
|
126
|
-
}
|
|
127
|
-
)
|
|
128
|
-
watch(
|
|
129
|
-
() => vignetteIntensity,
|
|
130
|
-
(val) => {
|
|
131
|
-
vignetteIntensityUniform.value = val
|
|
132
|
-
}
|
|
133
|
-
)
|
|
80
|
+
watchUniformProp(() => mouseX, mouseXUniform)
|
|
81
|
+
watchUniformProp(() => mouseY, mouseYUniform)
|
|
82
|
+
watchUniformProp(() => distortion, distortionUniform)
|
|
83
|
+
watchUniformProp(() => distortionSpeed, distortionSpeedUniform)
|
|
84
|
+
watchUniformProp(() => rippleStrength, rippleStrengthUniform)
|
|
85
|
+
watchUniformProp(() => zoom, zoomUniform)
|
|
86
|
+
watchUniformProp(() => grayscale, grayscaleUniform)
|
|
87
|
+
watchUniformProp(() => rgbShift, rgbShiftUniform)
|
|
88
|
+
watchUniformProp(() => vignetteIntensity, vignetteIntensityUniform)
|
|
134
89
|
|
|
135
90
|
// Load texture
|
|
136
91
|
watch(
|
|
@@ -42,10 +42,12 @@
|
|
|
42
42
|
double: DoubleSide,
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
function createMaterialInstance() {
|
|
46
|
+
return type === 'standard' ? new MeshStandardNodeMaterial() : new MeshBasicNodeMaterial()
|
|
47
|
+
}
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
// fallow-ignore-next-line complexity
|
|
50
|
+
function applyNodeProperties(mat: MeshBasicNodeMaterial | MeshStandardNodeMaterial) {
|
|
49
51
|
if (colorNode) mat.colorNode = colorNode
|
|
50
52
|
if (opacityNode) {
|
|
51
53
|
mat.opacityNode = opacityNode
|
|
@@ -53,22 +55,33 @@
|
|
|
53
55
|
}
|
|
54
56
|
if (normalNode) mat.normalNode = normalNode
|
|
55
57
|
if (positionNode) mat.positionNode = positionNode
|
|
58
|
+
}
|
|
56
59
|
|
|
57
|
-
|
|
60
|
+
// fallow-ignore-next-line complexity
|
|
61
|
+
function applyStandardProperties(mat: MeshBasicNodeMaterial | MeshStandardNodeMaterial) {
|
|
58
62
|
if (mat instanceof MeshStandardNodeMaterial) {
|
|
59
63
|
if (emissiveNode) mat.emissiveNode = emissiveNode
|
|
60
64
|
if (metalnessNode) mat.metalnessNode = metalnessNode
|
|
61
65
|
if (roughnessNode) mat.roughnessNode = roughnessNode
|
|
62
66
|
mat.flatShading = flatShading
|
|
63
67
|
}
|
|
68
|
+
}
|
|
64
69
|
|
|
65
|
-
|
|
70
|
+
function applySharedProperties(mat: MeshBasicNodeMaterial | MeshStandardNodeMaterial) {
|
|
66
71
|
mat.transparent = transparent || !!opacityNode
|
|
67
72
|
mat.side = sideMap[side]
|
|
68
73
|
mat.wireframe = wireframe
|
|
69
74
|
mat.depthTest = depthTest
|
|
70
75
|
mat.depthWrite = depthWrite
|
|
71
76
|
|
|
77
|
+
return mat
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const material = computed(() => {
|
|
81
|
+
const mat = createMaterialInstance()
|
|
82
|
+
applyNodeProperties(mat)
|
|
83
|
+
applyStandardProperties(mat)
|
|
84
|
+
applySharedProperties(mat)
|
|
72
85
|
return mat
|
|
73
86
|
})
|
|
74
87
|
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import type { TSLNode } from '../../shaders/types'
|
|
7
7
|
import { fbm, simplexNoise2D } from '../../utils/tsl/noise'
|
|
8
|
+
import { watchUniformProp } from '#layers/shader/app/composables/useUniformWatchers'
|
|
8
9
|
|
|
9
10
|
const {
|
|
10
11
|
scale = 3,
|
|
@@ -45,49 +46,14 @@
|
|
|
45
46
|
const baseColorUniform: TSLNode = uniform(new Color(baseColor))
|
|
46
47
|
const peakColorUniform: TSLNode = uniform(new Color(peakColor))
|
|
47
48
|
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
() => speed,
|
|
57
|
-
(val) => {
|
|
58
|
-
speedUniform.value = val
|
|
59
|
-
}
|
|
60
|
-
)
|
|
61
|
-
watch(
|
|
62
|
-
() => mouseX,
|
|
63
|
-
(val) => {
|
|
64
|
-
mouseXUniform.value = val
|
|
65
|
-
}
|
|
66
|
-
)
|
|
67
|
-
watch(
|
|
68
|
-
() => mouseY,
|
|
69
|
-
(val) => {
|
|
70
|
-
mouseYUniform.value = val
|
|
71
|
-
}
|
|
72
|
-
)
|
|
73
|
-
watch(
|
|
74
|
-
() => mouseStrength,
|
|
75
|
-
(val) => {
|
|
76
|
-
mouseStrengthUniform.value = val
|
|
77
|
-
}
|
|
78
|
-
)
|
|
79
|
-
watch(
|
|
80
|
-
() => baseColor,
|
|
81
|
-
(val) => {
|
|
82
|
-
baseColorUniform.value = new Color(val)
|
|
83
|
-
}
|
|
84
|
-
)
|
|
85
|
-
watch(
|
|
86
|
-
() => peakColor,
|
|
87
|
-
(val) => {
|
|
88
|
-
peakColorUniform.value = new Color(val)
|
|
89
|
-
}
|
|
90
|
-
)
|
|
49
|
+
// fallow-ignore-next-line code-duplication
|
|
50
|
+
watchUniformProp(() => scale, scaleUniform)
|
|
51
|
+
watchUniformProp(() => speed, speedUniform)
|
|
52
|
+
watchUniformProp(() => mouseX, mouseXUniform)
|
|
53
|
+
watchUniformProp(() => mouseY, mouseYUniform)
|
|
54
|
+
watchUniformProp(() => mouseStrength, mouseStrengthUniform)
|
|
55
|
+
watchUniformProp(() => baseColor, baseColorUniform, (val) => new Color(val))
|
|
56
|
+
watchUniformProp(() => peakColor, peakColorUniform, (val) => new Color(val))
|
|
91
57
|
|
|
92
58
|
const material = computed(() => {
|
|
93
59
|
const mat = new MeshBasicNodeMaterial()
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { createThemeBubbleColorNode } from '#layers/shader/app/composables/useAmbientMaterials'
|
|
3
|
-
import { type ThemePresetProps } from '#layers/shader/app/composables/useThemePreset'
|
|
4
3
|
import type { TSLNode } from '#layers/shader/app/types/tsl'
|
|
5
4
|
|
|
5
|
+
import type { ThemePresetProps } from '../../composables/useThemePreset'
|
|
6
|
+
|
|
6
7
|
const {
|
|
7
8
|
speed = 1.0,
|
|
8
9
|
intensity = 1.0,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { createThemeFlowColorNode } from '#layers/shader/app/composables/useAmbientMaterials'
|
|
3
|
-
import { type ThemePresetProps } from '#layers/shader/app/composables/useThemePreset'
|
|
4
3
|
import type { TSLNode } from '#layers/shader/app/types/tsl'
|
|
5
4
|
|
|
5
|
+
import type { ThemePresetProps } from '../../composables/useThemePreset'
|
|
6
|
+
|
|
6
7
|
const {
|
|
7
8
|
speed = 1.0,
|
|
8
9
|
intensity = 1.0,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { createThemeGradientColorNode } from '#layers/shader/app/composables/useAmbientMaterials'
|
|
3
|
-
import { type ThemePresetProps } from '#layers/shader/app/composables/useThemePreset'
|
|
4
3
|
import type { TSLNode } from '#layers/shader/app/types/tsl'
|
|
5
4
|
|
|
5
|
+
import type { ThemePresetProps } from '../../composables/useThemePreset'
|
|
6
|
+
|
|
6
7
|
const {
|
|
7
8
|
speed = 1.0,
|
|
8
9
|
intensity = 1.0,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { createThemeLavaLampColorNode } from '#layers/shader/app/composables/useAmbientMaterials'
|
|
3
|
-
import { type ThemePresetProps } from '#layers/shader/app/composables/useThemePreset'
|
|
4
3
|
import type { TSLNode } from '#layers/shader/app/types/tsl'
|
|
5
4
|
|
|
5
|
+
import type { ThemePresetProps } from '../../composables/useThemePreset'
|
|
6
|
+
|
|
6
7
|
const {
|
|
7
8
|
speed = 1.0,
|
|
8
9
|
intensity = 1.0,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { createThemePlasmaColorNode } from '#layers/shader/app/composables/useAmbientMaterials'
|
|
3
|
-
import { type ThemePresetProps } from '#layers/shader/app/composables/useThemePreset'
|
|
4
3
|
import type { TSLNode } from '#layers/shader/app/types/tsl'
|
|
5
4
|
|
|
5
|
+
import type { ThemePresetProps } from '../../composables/useThemePreset'
|
|
6
|
+
|
|
6
7
|
const {
|
|
7
8
|
speed = 1.0,
|
|
8
9
|
intensity = 1.0,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { createThemeWaveColorNode } from '#layers/shader/app/composables/useAmbientMaterials'
|
|
3
|
-
import { type ThemePresetProps } from '#layers/shader/app/composables/useThemePreset'
|
|
4
3
|
import type { TSLNode } from '#layers/shader/app/types/tsl'
|
|
5
4
|
|
|
5
|
+
import type { ThemePresetProps } from '../../composables/useThemePreset'
|
|
6
|
+
|
|
6
7
|
const {
|
|
7
8
|
speed = 1.0,
|
|
8
9
|
intensity = 1.0,
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
SRGBColorSpace,
|
|
15
15
|
type ToneMapping,
|
|
16
16
|
} from 'three'
|
|
17
|
-
import
|
|
17
|
+
import * as ThreeWebGPU from 'three/webgpu'
|
|
18
|
+
import { MeshBasicNodeMaterial } from 'three/webgpu'
|
|
18
19
|
|
|
19
20
|
const {
|
|
20
21
|
material = null,
|
|
@@ -42,13 +43,13 @@
|
|
|
42
43
|
}>()
|
|
43
44
|
|
|
44
45
|
const emit = defineEmits<{
|
|
45
|
-
ready: [renderer: WebGPURenderer]
|
|
46
|
+
ready: [renderer: ThreeWebGPU.WebGPURenderer]
|
|
46
47
|
}>()
|
|
47
48
|
|
|
48
49
|
const canvasRef = useTemplateRef<HTMLCanvasElement>('canvasRef')
|
|
49
50
|
const { width, height } = useWindowSize()
|
|
50
51
|
|
|
51
|
-
let renderer: WebGPURenderer | undefined
|
|
52
|
+
let renderer: ThreeWebGPU.WebGPURenderer | undefined
|
|
52
53
|
let scene: Scene
|
|
53
54
|
let camera: PerspectiveCamera
|
|
54
55
|
let planeMesh: Mesh
|
|
@@ -86,6 +87,38 @@
|
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
89
|
|
|
90
|
+
function createRenderer(canvas: HTMLCanvasElement) {
|
|
91
|
+
const nextRenderer = new ThreeWebGPU.WebGPURenderer({ canvas, antialias: antialias })
|
|
92
|
+
nextRenderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
|
|
93
|
+
nextRenderer.setSize(width.value, height.value)
|
|
94
|
+
nextRenderer.setClearColor(new Color(clearColor))
|
|
95
|
+
nextRenderer.toneMapping = toneMappingMap[toneMapping] ?? ACESFilmicToneMapping
|
|
96
|
+
nextRenderer.outputColorSpace = SRGBColorSpace
|
|
97
|
+
return nextRenderer
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function createSceneAndCamera() {
|
|
101
|
+
const nextScene = new Scene()
|
|
102
|
+
const nextCamera = new PerspectiveCamera(75, width.value / (height.value || 1), 0.1, 100)
|
|
103
|
+
nextCamera.position.set(0, 0, 1)
|
|
104
|
+
return { nextScene, nextCamera }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function createPlaneMesh() {
|
|
108
|
+
const { width: pw, height: ph } = getPlaneSize(width.value, height.value)
|
|
109
|
+
const geometry = new PlaneGeometry(pw, ph)
|
|
110
|
+
return new Mesh(geometry, material ?? new MeshBasicMaterial({ color: 0x000000 }))
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// fallow-ignore-next-line complexity
|
|
114
|
+
async function compileMaterialIfReady() {
|
|
115
|
+
if (!renderer || !scene || !camera || !material?.colorNode) return
|
|
116
|
+
await renderer.compileAsync(scene, camera)
|
|
117
|
+
if (disposed && renderer) {
|
|
118
|
+
renderer.dispose()
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
89
122
|
function animate() {
|
|
90
123
|
// Bail if the component unmounted — guards against a frame scheduled just
|
|
91
124
|
// before teardown rendering on a disposed renderer.
|
|
@@ -102,12 +135,7 @@
|
|
|
102
135
|
|
|
103
136
|
try {
|
|
104
137
|
// WebGPURenderer falls back to WebGL2 if WebGPU is unavailable
|
|
105
|
-
renderer =
|
|
106
|
-
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
|
|
107
|
-
renderer.setSize(width.value, height.value)
|
|
108
|
-
renderer.setClearColor(new Color(clearColor))
|
|
109
|
-
renderer.toneMapping = toneMappingMap[toneMapping] ?? ACESFilmicToneMapping
|
|
110
|
-
renderer.outputColorSpace = SRGBColorSpace
|
|
138
|
+
renderer = createRenderer(canvas)
|
|
111
139
|
|
|
112
140
|
// Required async init for WebGPU context setup
|
|
113
141
|
await renderer.init()
|
|
@@ -121,13 +149,10 @@
|
|
|
121
149
|
return
|
|
122
150
|
}
|
|
123
151
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
camera
|
|
127
|
-
|
|
128
|
-
const { width: pw, height: ph } = getPlaneSize(width.value, height.value)
|
|
129
|
-
const geometry = new PlaneGeometry(pw, ph)
|
|
130
|
-
planeMesh = new Mesh(geometry, material ?? new MeshBasicMaterial({ color: 0x000000 }))
|
|
152
|
+
const { nextScene, nextCamera } = createSceneAndCamera()
|
|
153
|
+
scene = nextScene
|
|
154
|
+
camera = nextCamera
|
|
155
|
+
planeMesh = createPlaneMesh()
|
|
131
156
|
scene.add(planeMesh)
|
|
132
157
|
|
|
133
158
|
// Pre-compile the shader pipeline only when the material's colorNode is already
|
|
@@ -136,18 +161,13 @@
|
|
|
136
161
|
// won't reliably trigger a GPU pipeline rebuild in all drivers.
|
|
137
162
|
// When colorNode is absent we skip pre-compilation and let the first render()
|
|
138
163
|
// call compile lazily — the browser may stutter once, but the output is correct.
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (disposed) {
|
|
142
|
-
renderer.dispose()
|
|
143
|
-
return
|
|
144
|
-
}
|
|
145
|
-
}
|
|
164
|
+
await compileMaterialIfReady()
|
|
165
|
+
if (disposed) return
|
|
146
166
|
|
|
147
167
|
initialized = true
|
|
148
168
|
emit('ready', renderer)
|
|
149
169
|
} catch (e) {
|
|
150
|
-
|
|
170
|
+
void e
|
|
151
171
|
}
|
|
152
172
|
|
|
153
173
|
// Always start the animation loop even if pre-compilation failed — Three.js
|
|
@@ -35,7 +35,11 @@ import type { ColorUniform, FloatUniform, TSLNode, Vec3Uniform } from '../shader
|
|
|
35
35
|
// ============================================
|
|
36
36
|
|
|
37
37
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38
|
-
function buildFlowWarpedUV(
|
|
38
|
+
function buildFlowWarpedUV(
|
|
39
|
+
uvCoord: any,
|
|
40
|
+
t: any,
|
|
41
|
+
mouseOffset: any
|
|
42
|
+
): {
|
|
39
43
|
warpedUV: TSLNode
|
|
40
44
|
n1: TSLNode
|
|
41
45
|
n2: TSLNode
|
|
@@ -11,6 +11,42 @@ export type UseShaderOptions = {
|
|
|
11
11
|
autoDispose?: boolean
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
function assignIfDefined<T extends object, K extends keyof T>(
|
|
15
|
+
target: T,
|
|
16
|
+
key: K,
|
|
17
|
+
value: T[K] | undefined
|
|
18
|
+
) {
|
|
19
|
+
if (value !== undefined) {
|
|
20
|
+
target[key] = value
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function applyStandardMaterialConfig(
|
|
25
|
+
material: MeshStandardNodeMaterial,
|
|
26
|
+
config: NodeMaterialConfig
|
|
27
|
+
) {
|
|
28
|
+
assignIfDefined(material, 'emissiveNode', config.emissiveNode)
|
|
29
|
+
assignIfDefined(material, 'metalnessNode', config.metalnessNode)
|
|
30
|
+
assignIfDefined(material, 'roughnessNode', config.roughnessNode)
|
|
31
|
+
assignIfDefined(material, 'flatShading', config.flatShading)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function applyCommonMaterialConfig(
|
|
35
|
+
material: MeshBasicNodeMaterial | MeshStandardNodeMaterial,
|
|
36
|
+
config: NodeMaterialConfig
|
|
37
|
+
) {
|
|
38
|
+
assignIfDefined(material, 'colorNode', config.colorNode)
|
|
39
|
+
assignIfDefined(material, 'opacityNode', config.opacityNode)
|
|
40
|
+
assignIfDefined(material, 'normalNode', config.normalNode)
|
|
41
|
+
assignIfDefined(material, 'positionNode', config.positionNode)
|
|
42
|
+
assignIfDefined(material, 'transparent', config.transparent)
|
|
43
|
+
assignIfDefined(material, 'side', config.side)
|
|
44
|
+
assignIfDefined(material, 'blending', config.blending)
|
|
45
|
+
assignIfDefined(material, 'depthTest', config.depthTest)
|
|
46
|
+
assignIfDefined(material, 'depthWrite', config.depthWrite)
|
|
47
|
+
assignIfDefined(material, 'wireframe', config.wireframe)
|
|
48
|
+
}
|
|
49
|
+
|
|
14
50
|
/**
|
|
15
51
|
* Main shader management composable
|
|
16
52
|
*/
|
|
@@ -39,30 +75,9 @@ export function useShader(options: UseShaderOptions = {}) {
|
|
|
39
75
|
if (!material.value) return
|
|
40
76
|
|
|
41
77
|
const mat = material.value
|
|
42
|
-
|
|
43
|
-
if (newConfig.colorNode !== undefined) mat.colorNode = newConfig.colorNode
|
|
44
|
-
if (newConfig.opacityNode !== undefined) mat.opacityNode = newConfig.opacityNode
|
|
45
|
-
if (newConfig.normalNode !== undefined) mat.normalNode = newConfig.normalNode
|
|
46
|
-
|
|
78
|
+
applyCommonMaterialConfig(mat, newConfig)
|
|
47
79
|
if (mat instanceof MeshStandardNodeMaterial) {
|
|
48
|
-
|
|
49
|
-
if (newConfig.metalnessNode !== undefined) mat.metalnessNode = newConfig.metalnessNode
|
|
50
|
-
if (newConfig.roughnessNode !== undefined) mat.roughnessNode = newConfig.roughnessNode
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (newConfig.positionNode !== undefined) mat.positionNode = newConfig.positionNode
|
|
54
|
-
|
|
55
|
-
// Standard material properties
|
|
56
|
-
if (newConfig.transparent !== undefined) mat.transparent = newConfig.transparent
|
|
57
|
-
if (newConfig.side !== undefined) mat.side = newConfig.side
|
|
58
|
-
if (newConfig.blending !== undefined) mat.blending = newConfig.blending
|
|
59
|
-
if (newConfig.depthTest !== undefined) mat.depthTest = newConfig.depthTest
|
|
60
|
-
if (newConfig.depthWrite !== undefined) mat.depthWrite = newConfig.depthWrite
|
|
61
|
-
if (newConfig.wireframe !== undefined) mat.wireframe = newConfig.wireframe
|
|
62
|
-
|
|
63
|
-
// flatShading only exists on MeshStandardNodeMaterial
|
|
64
|
-
if (mat instanceof MeshStandardNodeMaterial && newConfig.flatShading !== undefined) {
|
|
65
|
-
mat.flatShading = newConfig.flatShading
|
|
80
|
+
applyStandardMaterialConfig(mat, newConfig)
|
|
66
81
|
}
|
|
67
82
|
}
|
|
68
83
|
|