forked from BRETT/BRETT
Initial Commit
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
<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 = `
|
||||
attribute vec2 uv;
|
||||
attribute vec2 position;
|
||||
varying vec2 vUv;
|
||||
void main() {
|
||||
vUv = uv;
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
}
|
||||
`
|
||||
|
||||
const FRAG = `
|
||||
precision highp float;
|
||||
|
||||
uniform float uTime;
|
||||
uniform float uSpeed;
|
||||
uniform float uInnerLines;
|
||||
uniform float uOuterLines;
|
||||
uniform float uWarpIntensity;
|
||||
uniform float uRotation;
|
||||
uniform float uEdgeFadeWidth;
|
||||
uniform float uColorCycleSpeed;
|
||||
uniform float uBrightness;
|
||||
uniform vec3 uColor1;
|
||||
uniform vec3 uColor2;
|
||||
uniform vec3 uColor3;
|
||||
uniform vec2 uMouse;
|
||||
uniform float uMouseActive;
|
||||
uniform float uMouseInfluence;
|
||||
uniform vec2 uCardRes;
|
||||
uniform float uRadius;
|
||||
|
||||
#define HALF_PI 1.5707963
|
||||
|
||||
float hashF(float n) {
|
||||
return fract(sin(n * 127.1) * 43758.5453123);
|
||||
}
|
||||
|
||||
float smoothNoise(float x) {
|
||||
float i = floor(x);
|
||||
float f = fract(x);
|
||||
float u = f * f * (3.0 - 2.0 * f);
|
||||
return mix(hashF(i), hashF(i + 1.0), u);
|
||||
}
|
||||
|
||||
float displaceA(float coord, float t) {
|
||||
float result = sin(coord * 2.123) * 0.2;
|
||||
result += sin(coord * 3.234 + t * 4.345) * 0.1;
|
||||
result += sin(coord * 0.589 + t * 0.934) * 0.5;
|
||||
return result;
|
||||
}
|
||||
|
||||
float displaceB(float coord, float t) {
|
||||
float result = sin(coord * 1.345) * 0.3;
|
||||
result += sin(coord * 2.734 + t * 3.345) * 0.2;
|
||||
result += sin(coord * 0.189 + t * 0.934) * 0.3;
|
||||
return result;
|
||||
}
|
||||
|
||||
vec2 rotate2D(vec2 p, float angle) {
|
||||
float c = cos(angle);
|
||||
float s = sin(angle);
|
||||
return vec2(p.x * c - p.y * s, p.x * s + p.y * c);
|
||||
}
|
||||
|
||||
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: Koordinaten auf eine Referenzhöhe von 180px normieren,
|
||||
// damit die Liniendichte in flachen Containern nicht zusammengestaucht wird
|
||||
vec2 coords = (gl_FragCoord.xy * 2.0 - uCardRes.xy) / 180.0;
|
||||
coords = rotate2D(coords, uRotation);
|
||||
|
||||
float halfT = uTime * uSpeed * 0.5;
|
||||
float fullT = uTime * uSpeed;
|
||||
|
||||
vec2 mPos = rotate2D((uMouse * 2.0 - 1.0) * (uCardRes / 360.0), uRotation);
|
||||
float mDist = length(coords - mPos);
|
||||
float mouseWarp = uMouseInfluence * exp(-mDist * mDist * 4.0) * uMouseActive;
|
||||
|
||||
float warpAx = coords.x + displaceA(coords.y, halfT) * uWarpIntensity + mouseWarp;
|
||||
float warpAy = coords.y - displaceA(coords.x * cos(fullT) * 1.235, halfT) * uWarpIntensity;
|
||||
float warpBx = coords.x + displaceB(coords.y, halfT) * uWarpIntensity + mouseWarp;
|
||||
float warpBy = coords.y - displaceB(coords.x * sin(fullT) * 1.235, halfT) * uWarpIntensity;
|
||||
|
||||
vec2 fieldA = vec2(warpAx, warpAy);
|
||||
vec2 fieldB = vec2(warpBx, warpBy);
|
||||
vec2 blended = mix(fieldA, fieldB, mix(fieldA, fieldB, 0.5));
|
||||
|
||||
float fadeTop = smoothstep(uEdgeFadeWidth, uEdgeFadeWidth + 0.4, blended.y);
|
||||
float fadeBottom = smoothstep(-uEdgeFadeWidth, -(uEdgeFadeWidth + 0.4), blended.y);
|
||||
float vMask = 1.0 - max(fadeTop, fadeBottom);
|
||||
|
||||
float tileCount = mix(uOuterLines, uInnerLines, vMask);
|
||||
float scaledY = blended.y * tileCount;
|
||||
float nY = smoothNoise(abs(scaledY));
|
||||
|
||||
float ridge = pow(
|
||||
step(abs(nY - blended.x) * 2.0, HALF_PI) * cos(2.0 * (nY - blended.x)),
|
||||
5.0
|
||||
);
|
||||
|
||||
float waveProfile = max(0.0, (max(fract(scaledY), fract(-scaledY)) - 0.55) / 0.45);
|
||||
float lines = pow(waveProfile, 2.0) + pow(waveProfile, 4.0);
|
||||
|
||||
float pattern = vMask * lines;
|
||||
|
||||
float cycleT = fullT * uColorCycleSpeed;
|
||||
float rChannel = (pattern + lines * ridge) * (cos(blended.y + cycleT * 0.234) * 0.5 + 1.0);
|
||||
float gChannel = (pattern + vMask * ridge) * (sin(blended.x + cycleT * 1.745) * 0.5 + 1.0);
|
||||
float bChannel = (pattern + lines * ridge) * (cos(blended.x + cycleT * 0.534) * 0.5 + 1.0);
|
||||
|
||||
vec3 col = (rChannel * uColor1 + gChannel * uColor2 + bChannel * uColor3) * uBrightness;
|
||||
float alpha = clamp(length(col), 0.0, 1.0) * cardMask(gl_FragCoord.xy);
|
||||
|
||||
gl_FragColor = vec4(col * alpha, alpha);
|
||||
}
|
||||
`
|
||||
|
||||
const ctnDom = ref<HTMLDivElement | null>(null)
|
||||
|
||||
useCardShader(ctnDom, {
|
||||
vertex: VERT,
|
||||
fragment: FRAG,
|
||||
mouse: true,
|
||||
uniforms: {
|
||||
uTime: { value: 0 },
|
||||
uSpeed: { value: 0.3 },
|
||||
uInnerLines: { value: 32 },
|
||||
uOuterLines: { value: 36 },
|
||||
uWarpIntensity: { value: 1 },
|
||||
uRotation: { value: -45 * Math.PI / 180 },
|
||||
uEdgeFadeWidth: { value: 0 },
|
||||
uColorCycleSpeed: { value: 1 },
|
||||
uBrightness: { value: 0.35 },
|
||||
uColor1: { value: new Float32Array(hexToRgbTuple(props.color)) },
|
||||
uColor2: { value: new Float32Array(hexToRgbTuple(shadeHex(props.color, 0.35))) },
|
||||
uColor3: { value: new Float32Array(hexToRgbTuple(shadeHex(props.color, -0.25))) },
|
||||
uMouse: { value: new Float32Array([0.5, 0.5]) },
|
||||
uMouseActive: { value: 0 },
|
||||
uMouseInfluence: { value: 2.0 },
|
||||
},
|
||||
color: () => props.color,
|
||||
colorUniforms: { uColor1: 0, uColor2: 0.35, uColor3: -0.25 },
|
||||
frame: ({ t, program, mouse }) => {
|
||||
const u = program.uniforms
|
||||
u.uTime.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