aboutsummaryrefslogtreecommitdiff
path: root/wiki/examples/close_custom_shader.frag
blob: fdd931ea45fe1a626c649e9ee1416a9fb02c588b (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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Your shader must contain one function (see the bottom of this file).
//
// It should not contain any uniform definitions or anything else, as niri
// provides them for you.
//
// All symbols defined by niri will have a niri_ prefix, so don't use it for
// your own variables and functions.

// The function that you must define looks like this:
vec4 close_color(vec3 coords_geo, vec3 size_geo) {
    vec4 color = /* ...compute the color... */;
    return color;
}

// It takes as input:
//
// * coords_geo: coordinates of the current pixel relative to the window
//   geometry.
//
// These are homogeneous (the Z component is equal to 1) and scaled in such a
// way that the 0 to 1 coordinates lie within the window geometry. Pixels
// outside the window geometry will have coordinates below 0 or above 1.
//
// The window geometry is its "visible bounds" from the user's perspective.
//
// The shader runs over the full screen area, so you must expect and handle
// coordinates outside the [0, 1] range. If the window is scrolled off-screen,
// all of the coordinates to the shader can fall outside the [0, 1] range.
//
// * size_geo: size of the window geometry in logical pixels.
//
// It is homogeneous (the Z component is equal to 1).
//
// The function must return the color of the pixel (with premultiplied alpha).
// The pixel color will be further processed by niri (for example, to apply the
// final opacity from window rules).

// Now let's go over the uniforms that niri defines.
//
// You should only rely on the uniforms documented here. Any other uniforms can
// change or be removed without notice.

// The window texture.
uniform sampler2D niri_tex;

// Matrix that converts geometry coordinates into the window texture
// coordinates.
//
// The window texture can and will go outside the geometry (for client-side
// decoration shadows for example), which is why this matrix is necessary.
uniform mat3 niri_geo_to_tex;


// Unclamped progress of the animation.
//
// Goes from 0 to 1 but may overshoot and oscillate.
uniform float niri_progress;

// Clamped progress of the animation.
//
// Goes from 0 to 1, but will stop at 1 as soon as it first reaches 1. Will not
// overshoot or oscillate.
uniform float niri_clamped_progress;

// Random float in [0; 1), consistent for the duration of the animation.
uniform float niri_random_seed;

// Now let's look at some examples. You can copy everything below this line
// into your custom-shader to experiment.

// Example: fill the current geometry with a solid vertical gradient and
// gradually make transparent.
vec4 solid_gradient(vec3 coords_geo, vec3 size_geo) {
    vec4 color = vec4(0.0);

    // Paint only the area inside the current geometry.
    if (0.0 <= coords_geo.x && coords_geo.x <= 1.0
            && 0.0 <= coords_geo.y && coords_geo.y <= 1.0)
    {
        vec4 from = vec4(1.0, 0.0, 0.0, 1.0);
        vec4 to = vec4(0.0, 1.0, 0.0, 1.0);
        color = mix(from, to, coords_geo.y);
    }

    // Make it transparent.
    color *= (1.0 - niri_clamped_progress);

    return color;
}

// Example: gradually scale down and make transparent, equivalent to the
// default closing animation.
vec4 default_close(vec3 coords_geo, vec3 size_geo) {
    // Scale down the window.
    float scale = max(0.0, ((1.0 - niri_clamped_progress) / 5.0 + 0.8));
    coords_geo = vec3((coords_geo.xy - vec2(0.5)) / scale + vec2(0.5), 1.0);

    // Get color from the window texture.
    vec3 coords_tex = niri_geo_to_tex * coords_geo;
    vec4 color = texture2D(niri_tex, coords_tex.st);

    // Make the window transparent.
    color *= (1.0 - niri_clamped_progress);

    return color;
}

// Example: make the window 'fall down' with slight rotation.
vec4 fall_and_rotate(vec3 coords_geo, vec3 size_geo) {
    // For this shader, set animation curve to linear for best results.

    // Simulate an accelerated fall: square the (linear) progress.
    float progress = niri_clamped_progress * niri_clamped_progress;

    // Get our rotation pivot point coordinates at the bottom center of the window.
    vec2 coords = (coords_geo.xy - vec2(0.5, 1.0)) * size_geo.xy;

    // Move the window down to simulate a fall.
    coords.y -= progress * 200.0;

    // Randomize rotation direction and maximum angle.
    float random = (niri_random_seed - 0.5) / 2.0;
    random = sign(random) - random;
    float max_angle = 0.05 * random;

    // Rotate the window around our pivot point.
    float angle = progress * max_angle;
    mat2 rotate = mat2(cos(angle), -sin(angle), sin(angle), cos(angle));
    coords = rotate * coords;

    // Transform the coordinates back.
    coords_geo = vec3(coords / size_geo.xy + vec2(0.5, 1.0), 1.0);

    // Sample the window texture.
    vec3 coords_tex = niri_geo_to_tex * coords_geo;
    vec4 color = texture2D(niri_tex, coords_tex.st);

    // Multiply by alpha to fade out.
    return color * (1.0 - niri_clamped_progress);
}

// This is the function that you must define.
vec4 close_color(vec3 coords_geo, vec3 size_geo) {
    // You can pick one of the example functions or write your own.
    return fall_and_rotate(coords_geo, size_geo);
}