forked from BRETT/BRETT
Initial Commit
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
<script setup lang="ts">
|
||||
import { hexToRgbTuple, shadeHex } from '@/lib/color'
|
||||
|
||||
// Portiert aus Vue Bits (DavidHDev/vue-bits), vereinfacht auf color-Prop
|
||||
const props = withDefaults(defineProps<{ color?: string }>(), {
|
||||
color: '#6366f1',
|
||||
})
|
||||
|
||||
const VERT = `#version 300 es
|
||||
in vec2 position;
|
||||
void main() {
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
}
|
||||
`
|
||||
|
||||
const FRAG = `#version 300 es
|
||||
precision highp float;
|
||||
uniform float iTime;
|
||||
uniform float uSpeed;
|
||||
uniform float uSweepSpeed;
|
||||
uniform float uSweepWidth;
|
||||
uniform float uSweepFalloff;
|
||||
uniform float uScale;
|
||||
uniform float uFrequency;
|
||||
uniform float uRipple;
|
||||
uniform float uBandDensity;
|
||||
uniform float uLineSharpness;
|
||||
uniform float uGlow;
|
||||
uniform float uColorSpread;
|
||||
uniform float uBrightness;
|
||||
uniform float uContrast;
|
||||
uniform float uSoftness;
|
||||
uniform float uVignette;
|
||||
uniform float uOpacity;
|
||||
uniform float uScanline;
|
||||
uniform float uGrain;
|
||||
uniform float uGrainIntensity;
|
||||
uniform vec2 uMouse;
|
||||
uniform float uMouseRadius;
|
||||
uniform float uMouseStrength;
|
||||
uniform float uMouseActive;
|
||||
uniform vec3 uColor1;
|
||||
uniform vec3 uColor2;
|
||||
uniform vec3 uColor3;
|
||||
uniform vec2 uCardRes;
|
||||
uniform float uRadius;
|
||||
out vec4 fragColor;
|
||||
|
||||
const float TAU = 6.2831853;
|
||||
|
||||
float signalField(vec2 p, float t) {
|
||||
float w = sin(p.x * 1.3 + t * 0.7);
|
||||
w += sin(p.y * 1.7 - t * 0.52) * 0.8;
|
||||
w += sin((p.x + p.y) * 0.9 + t * 0.91) * 0.6;
|
||||
w += sin((p.x - p.y) * 1.53 - t * 0.63) * 0.42;
|
||||
return w * 0.35;
|
||||
}
|
||||
|
||||
vec3 palette(float f) {
|
||||
f = clamp(f, 0.0, 1.0);
|
||||
f = pow(f, uContrast);
|
||||
vec3 c = mix(uColor1, uColor2, smoothstep(0.08, 0.6, f));
|
||||
return mix(c, uColor3, smoothstep(0.68, 1.0, f));
|
||||
}
|
||||
|
||||
float scanBand(float x, float aa, float sharp) {
|
||||
float v = mix(0.5, 0.5 + 0.5 * cos(x * TAU), aa);
|
||||
return pow(v, sharp);
|
||||
}
|
||||
|
||||
float cardMask(vec2 fc) {
|
||||
vec2 p = fc - uCardRes * 0.5;
|
||||
vec2 hb = uCardRes * 0.5 - vec2(uRadius);
|
||||
float rd = length(max(abs(p) - hb, 0.0)) - uRadius;
|
||||
return 1.0 - smoothstep(-0.75, 0.75, rd);
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Pixelkonsistent: auf Referenzhöhe 180px normieren,
|
||||
// damit Bänder/Wellen in flachen Containern nicht stauchen
|
||||
vec2 uv0 = (gl_FragCoord.xy * 2.0 - uCardRes.xy) / 180.0;
|
||||
vec2 p = uv0 / max(uScale, 0.001);
|
||||
|
||||
float t = iTime * uSpeed;
|
||||
|
||||
vec2 mUv = (uMouse * 2.0 - 1.0) * (uCardRes / 360.0);
|
||||
vec2 md = uv0 - mUv;
|
||||
float r = max(uMouseRadius, 0.001);
|
||||
float mouseBoost = exp(-dot(md, md) / (r * r)) * uMouseStrength * uMouseActive;
|
||||
|
||||
float axis = p.y;
|
||||
|
||||
float sig = signalField(p * uFrequency, t);
|
||||
float coord = axis + sig * uRipple;
|
||||
|
||||
float phase = coord / max(uSweepWidth, 0.05) - t * uSweepSpeed;
|
||||
float sweep = pow(0.5 + 0.5 * cos(phase * TAU), max(uSweepFalloff, 0.1));
|
||||
|
||||
float lc = coord * uBandDensity;
|
||||
float aa = 1.0 / (1.0 + uSoftness * fwidth(lc) * 3.0);
|
||||
aa = clamp(aa * (1.0 + mouseBoost * 0.6), 0.0, 1.0);
|
||||
|
||||
float bodyBase = clamp(0.5 + 0.5 * sig, 0.0, 1.0);
|
||||
float body = bodyBase * bodyBase * uGlow * sweep;
|
||||
|
||||
float sharp = max(uLineSharpness, 0.1);
|
||||
float split = uColorSpread * 0.16;
|
||||
float fr = clamp(scanBand(lc + split, aa, sharp) * sweep + body, 0.0, 1.0);
|
||||
float fg = clamp(scanBand(lc, aa, sharp) * sweep + body, 0.0, 1.0);
|
||||
float fb = clamp(scanBand(lc - split, aa, sharp) * sweep + body, 0.0, 1.0);
|
||||
|
||||
vec3 col = vec3(palette(fr).r, palette(fg).g, palette(fb).b);
|
||||
|
||||
float inten = (fr + fg + fb) * 0.3333333 * uBrightness;
|
||||
inten *= 1.0 + mouseBoost * 0.9;
|
||||
inten *= 1.0 - 0.18 * (0.5 + 0.5 * cos(gl_FragCoord.y * 1.7));
|
||||
|
||||
if (inten > 0.01) {
|
||||
float g = fract(sin(dot(gl_FragCoord.xy, vec2(12.9898, 78.233)) + iTime) * 43758.5453);
|
||||
inten += (g - 0.5) * uGrainIntensity;
|
||||
}
|
||||
|
||||
inten *= clamp(1.0 - uVignette * smoothstep(0.55, 1.65, length(uv0)), 0.0, 1.0);
|
||||
inten = clamp(inten, 0.0, 1.0);
|
||||
|
||||
float a = clamp(inten * uOpacity, 0.0, 1.0) * cardMask(gl_FragCoord.xy);
|
||||
fragColor = vec4(clamp(col, 0.0, 1.0) * a, a);
|
||||
}
|
||||
`
|
||||
|
||||
const ctnDom = ref<HTMLDivElement | null>(null)
|
||||
|
||||
useCardShader(ctnDom, {
|
||||
vertex: VERT,
|
||||
fragment: FRAG,
|
||||
mouse: true,
|
||||
uniforms: {
|
||||
iTime: { value: 0 },
|
||||
uSpeed: { value: 0.5 },
|
||||
uSweepSpeed: { value: 0.25 },
|
||||
uSweepWidth: { value: 1.6 },
|
||||
uSweepFalloff: { value: 6 },
|
||||
uScale: { value: 1.5 },
|
||||
uFrequency: { value: 2 },
|
||||
uRipple: { value: 0.22 },
|
||||
uBandDensity: { value: 11 },
|
||||
uLineSharpness: { value: 5.5 },
|
||||
uGlow: { value: 0.22 },
|
||||
uColorSpread: { value: 0.7 },
|
||||
uBrightness: { value: 1.0 },
|
||||
uContrast: { value: 1.15 },
|
||||
uSoftness: { value: 1.4 },
|
||||
uVignette: { value: 0.45 },
|
||||
uOpacity: { value: 1.0 },
|
||||
uScanline: { value: 1.0 },
|
||||
uGrain: { value: 1.0 },
|
||||
uGrainIntensity: { value: 0.05 },
|
||||
uMouse: { value: new Float32Array([0.5, 0.5]) },
|
||||
uMouseRadius: { value: 0.5 },
|
||||
uMouseStrength: { value: 0.5 },
|
||||
uMouseActive: { value: 0 },
|
||||
uColor1: { value: new Float32Array(hexToRgbTuple(shadeHex(props.color, -0.55))) },
|
||||
uColor2: { value: new Float32Array(hexToRgbTuple(props.color)) },
|
||||
uColor3: { value: new Float32Array([1, 1, 1]) },
|
||||
},
|
||||
color: () => props.color,
|
||||
colorUniforms: { uColor1: -0.55, uColor2: 0 },
|
||||
frame: ({ t, program, mouse }) => {
|
||||
const u = program.uniforms
|
||||
u.iTime.value = t * 0.001
|
||||
const m = u.uMouse.value as Float32Array
|
||||
m[0] = mouse.x
|
||||
m[1] = mouse.y
|
||||
u.uMouseActive.value = mouse.active
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="ctnDom" class="relative size-full overflow-hidden rounded-[inherit]" />
|
||||
</template>
|
||||
Reference in New Issue
Block a user