Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
scenefx/render/fx_renderer/shaders/quad_round.frag (2.9K)
1 precision highp float;
2
3 varying vec4 v_color;
4 varying vec2 v_texcoord;
5
6 uniform vec2 size;
7 uniform vec2 position;
8 uniform float radius_top_left;
9 uniform float radius_top_right;
10 uniform float radius_bottom_left;
11 uniform float radius_bottom_right;
12 uniform float fade_inset;
13 uniform int fade_mode;
14
15 uniform vec2 clip_size;
16 uniform vec2 clip_position;
17 uniform float clip_radius_top_left;
18 uniform float clip_radius_top_right;
19 uniform float clip_radius_bottom_left;
20 uniform float clip_radius_bottom_right;
21
22 float corner_dist(vec2 size, vec2 position,
23 float radius_tl, float radius_tr, float radius_bl, float radius_br);
24 float corner_alpha(vec2 size, vec2 position, bool is_cutout,
25 float radius_tl, float radius_tr, float radius_bl, float radius_br);
26
27 void main() {
28 // The outline's signed distance, from the same function the clip below
29 // and the buffer corner cut use, so an edge pixel sits at dist 0.
30 //
31 // This was inlined here with two differences that made the node draw
32 // less than the scene thinks it covers. The y flip subtracted from
33 // size.y where the rest of the math works in size - 1, so the distance
34 // was one pixel off vertically: the box's top row got alpha 0 and the
35 // row under it 0.5. And the smoothstep ran -0.5..0.5, which left every
36 // straight edge pixel at half alpha. scene_node_opaque_region counts an
37 // alpha-1 rounded rect as opaque outside its corner squares, so what
38 // lay beneath those rows was culled and they blended over whatever the
39 // buffer last held — a tint that halved on every repaint, or never
40 // changed at all in the alpha-0 row.
41 float dist = corner_dist(size - 1.0, position + 0.5,
42 radius_top_left, radius_top_right,
43 radius_bottom_left, radius_bottom_right);
44
45 float result = smoothstep(0.0, 1.0, dist);
46 float quad_corner_alpha = 1.0 - result;
47
48 // Clipping
49 float clip_corner_alpha = corner_alpha(
50 clip_size - 1.0,
51 clip_position + 0.5,
52 true,
53 clip_radius_top_left,
54 clip_radius_top_right,
55 clip_radius_bottom_left,
56 clip_radius_bottom_right
57 );
58
59 vec4 final_color = v_color;
60 if (fade_inset > 0.0) {
61 // Fade by distance to the ROUNDED outline — the same SDF that cuts
62 // the corners — not the straight edges. The old per-axis product
63 // formed a square-cornered onset at each corner that visually
64 // swamped the corner arcs whenever fade and radius were combined.
65 float edge_dist = -dist;
66
67 // Clamp to [0, fade_inset] and normalize
68 float factor = clamp(edge_dist / fade_inset, 0.0, 1.0);
69
70 if (fade_mode == 1) {
71 factor = smoothstep(0.0, 1.0, factor);
72 } else if (fade_mode == 2) {
73 factor = factor * factor;
74 } else if (fade_mode == 3) {
75 factor = 0.5 - 0.5 * cos(factor * 3.14159265);
76 } else if (fade_mode == 4) {
77 float x = 1.0 - factor;
78 factor = clamp((exp(-3.0 * x * x) - 0.049) / 0.951, 0.0, 1.0);
79 }
80
81 final_color *= pow(factor, 2.2);
82 }
83
84 gl_FragColor = final_color * quad_corner_alpha * clip_corner_alpha;
85 }