feat(overview-backdrop): softer wave, breathing pulse, random glitches

This commit is contained in:
Damocles 2026-04-17 10:34:34 +02:00
parent 862169aba0
commit 7cd6716eb8
2 changed files with 101 additions and 14 deletions

View file

@ -32,6 +32,9 @@ PanelWindow {
property real uSize: 50.0
property real uWavePhase: -200
property real uBreath: 0
property real uGlitch: 0
property real uGlitchSeed: 0.0
property vector4d uResolution: Qt.vector4d(width, height, 0, 0)
property color uC0: M.Theme.base0C
property color uC1: M.Theme.base0E
@ -40,8 +43,10 @@ PanelWindow {
Connections {
target: M.NiriIpc
function onOverviewOpenChanged() {
if (!M.NiriIpc.overviewOpen)
if (!M.NiriIpc.overviewOpen) {
fx.uWavePhase = -200;
fx.uBreath = 0;
}
}
}
@ -59,5 +64,66 @@ PanelWindow {
duration: 8000
}
}
// Breathing pulse while overview is open
SequentialAnimation on uBreath {
loops: Animation.Infinite
running: M.NiriIpc.overviewOpen && !M.Theme.reducedMotion
NumberAnimation {
from: 0
to: 1
duration: 2500
easing.type: Easing.InOutSine
}
NumberAnimation {
from: 1
to: 0
duration: 2500
easing.type: Easing.InOutSine
}
}
// Random subtle glitches fire every 1237s, total ~250ms each
Timer {
interval: 20000
repeat: true
running: !M.Theme.reducedMotion
onTriggered: {
interval = 12000 + Math.floor(Math.random() * 25000);
fx.uGlitchSeed = Math.random() * 1000.0;
_glitchAnim.start();
}
}
SequentialAnimation {
id: _glitchAnim
NumberAnimation {
target: fx
property: "uGlitch"
to: 0.7
duration: 50
easing.type: Easing.OutQuad
}
NumberAnimation {
target: fx
property: "uGlitch"
to: 0.15
duration: 50
}
NumberAnimation {
target: fx
property: "uGlitch"
to: 0.85
duration: 60
easing.type: Easing.OutQuad
}
NumberAnimation {
target: fx
property: "uGlitch"
to: 0
duration: 100
easing.type: Easing.InQuad
}
}
}
}

View file

@ -8,6 +8,9 @@ layout(std140, binding = 0) uniform buf {
float qt_Opacity;
float uSize;
float uWavePhase;
float uBreath;
float uGlitch;
float uGlitchSeed;
vec4 uResolution;
vec4 uC0;
vec4 uC1;
@ -29,9 +32,24 @@ vec3 themeGradient(float t) {
: mix(uC1.rgb, uC2.rgb, (t - 0.5) * 2.0);
}
// Cheap hash for glitch bands
float hash(float n) {
return fract(sin(n) * 43758.5453123);
}
void main() {
vec2 res = uResolution.xy;
// Glitch: shift some horizontal bands slightly
vec2 frag = qt_TexCoord0 * res;
if (uGlitch > 0.0) {
float band = floor(frag.y / 7.0);
float h = hash(band * 127.1 + uGlitchSeed * 311.7);
if (h > 0.72) {
float shift = (hash(band * 93.9 + uGlitchSeed) - 0.5) * 14.0 * uGlitch;
frag.x = clamp(frag.x + shift, 0.0, res.x);
}
}
float dx = uSize * 1.5;
float dy = uSize * 1.7320508;
@ -41,12 +59,12 @@ void main() {
float row = round((frag.y - yoff) / dy);
vec2 center = vec2(col * dx, row * dy + yoff);
// Wave factor
// Wave — wide gaussian so it reads more as a broad pulse than a sharp sweep
float dist = center.x - uWavePhase;
float wf = exp(-dist * dist / 9000.0);
float wf = exp(-dist * dist / 40000.0);
float baseR = uSize * 0.48;
float inradius = baseR * (1.0 + 0.35 * wf);
float inradius = baseR * (1.0 + 0.15 * wf);
vec2 p = frag - center;
float d = sdHexagon(p.yx, inradius); // swap for flat-top
@ -62,28 +80,31 @@ void main() {
? mix(uC0.rgb, uC1.rgb, fx * 2.0)
: mix(uC1.rgb, uC2.rgb, (fx - 0.5) * 2.0);
// Alpha from distance to center
// Alpha from distance to center (vignette)
float fy = clamp(center.y / res.y, 0.0, 1.0);
float dc = length(vec2(fx - 0.5, fy - 0.5));
float a = 0.03 + dc * 0.06;
// Wave brighten
rgb = min(rgb + vec3(0.3 * wf), vec3(1.0));
a += 0.12 * wf;
// Breathing pulse (when overview open)
a += 0.025 * uBreath;
rgb = min(rgb + vec3(0.04 * uBreath), vec3(1.0));
// Rainbow shimmer on hex edges when wave passes
// Wave brighten (softer than before)
rgb = min(rgb + vec3(0.15 * wf), vec3(1.0));
a += 0.07 * wf;
// Shimmer on hex edges as wave passes
float edgeWidth = 5.0;
float edgeFactor = smoothstep(-edgeWidth, 0.0, d); // 0 at interior, 1 at edge
float edgeFactor = smoothstep(-edgeWidth, 0.0, d);
if (wf > 0.01 && edgeFactor > 0.0) {
// Vary shimmer color across theme gradient using angle + position
float angle = atan(p.y, p.x);
float rawT = fract((angle + 3.14159) / 6.28318 + center.x * 0.003 + center.y * 0.005);
float t = abs(rawT * 2.0 - 1.0); // triangle wave → uC0→uC1→uC2→uC1→uC0, no hard jump
float t = abs(rawT * 2.0 - 1.0);
vec3 shimmerColor = themeGradient(t);
float shimmer = edgeFactor * wf;
rgb = mix(rgb, shimmerColor, shimmer * 0.8);
a = mix(a, 0.5, shimmer * 0.6);
rgb = mix(rgb, shimmerColor, shimmer * 0.5);
a = mix(a, 0.5, shimmer * 0.35);
}
// Anti-alias outer edge