aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/modules/appearance/ripple.frag
blob: a61053789c7ef2898e6159cd6fdc31246a432060 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// Copyright (C) 2026 Danilo M. <danix@danix.xyz>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// A ring spreading from a random point, bending both pictures as it passes,
// the new one behind it. Opaque throughout. Compiled with:
// qsb --qt6 -o ripple.frag.qsb ripple.frag
#version 440
layout(location = 0) in vec2 qt_TexCoord0;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform buf {
    mat4 qt_Matrix;
    float qt_Opacity;
    float progress;
    float aspect;
    vec2 origin;
};
layout(binding = 1) uniform sampler2D source;
layout(binding = 2) uniform sampler2D target;

void main() {
    vec2 asp = vec2(aspect, 1.0);
    vec2 v = (qt_TexCoord0 - origin) * asp;
    float d = length(v) / length(max(origin, 1.0 - origin) * asp);

    // e runs -1 to 1 across the ring. It starts wholly outside the picture
    // and ends wholly past it, so neither end is bent.
    const float w = 0.12;
    float e = (d - mix(-w, 1.0 + w, progress)) / w;
    float ring = 1.0 - smoothstep(0.0, 1.0, abs(e));
    vec2 off = v / max(length(v), 1e-4) / asp * sin(e * 3.14159) * ring * 0.03;

    vec2 uv = qt_TexCoord0 + off;
    vec3 col = mix(texture(target, uv).rgb, texture(source, uv).rgb, smoothstep(-0.6, 0.6, e));
    fragColor = vec4(col, 1.0) * qt_Opacity;
}