git.lucas.co / cce-compositor
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 }