Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
scenefx/render/fx_renderer/shaders/tex.frag (3.4K)
1 #define SOURCE %d
2 #define EFFECTS %d
3
4 #define SOURCE_TEXTURE_RGBA 1
5 #define SOURCE_TEXTURE_RGBX 2
6 #define SOURCE_TEXTURE_EXTERNAL 3
7
8 #if !defined(SOURCE) || !defined(EFFECTS)
9 #error "Missing shader preamble"
10 #endif
11
12 #if SOURCE == SOURCE_TEXTURE_EXTERNAL
13 #extension GL_OES_EGL_image_external : require
14 #endif
15
16 #ifdef GL_FRAGMENT_PRECISION_HIGH
17 precision highp float;
18 #else
19 precision mediump float;
20 #endif
21
22 varying vec2 v_texcoord;
23
24 #if SOURCE == SOURCE_TEXTURE_EXTERNAL
25 uniform samplerExternalOES tex;
26 #elif SOURCE == SOURCE_TEXTURE_RGBA || SOURCE == SOURCE_TEXTURE_RGBX
27 uniform sampler2D tex;
28 #endif
29
30 uniform float alpha;
31
32 #if EFFECTS
33 uniform vec2 size;
34 uniform vec2 position;
35 uniform float radius_top_left;
36 uniform float radius_top_right;
37 uniform float radius_bottom_left;
38 uniform float radius_bottom_right;
39
40 uniform vec2 clip_size;
41 uniform vec2 clip_position;
42 uniform float clip_radius_top_left;
43 uniform float clip_radius_top_right;
44 uniform float clip_radius_bottom_left;
45 uniform float clip_radius_bottom_right;
46 #endif
47
48 uniform bool discard_transparent;
49
50 // Backdrop compression (see compress_backdrop below). Ceiling and knee are
51 // linear luminances; a ceiling of 0 turns it off, which is every texture
52 // draw but a status segment's blurred backdrop.
53 uniform float compress_ceil;
54 uniform float compress_knee;
55 uniform bool compress_invert;
56
57 vec4 sample_texture() {
58 #if SOURCE == SOURCE_TEXTURE_RGBA || SOURCE == SOURCE_TEXTURE_EXTERNAL
59 return texture2D(tex, v_texcoord);
60 #elif SOURCE == SOURCE_TEXTURE_RGBX
61 return vec4(texture2D(tex, v_texcoord).rgb, 1.0);
62 #endif
63 }
64
65 // Pull the backdrop's luminance under a ceiling, so text of a known color
66 // keeps its contrast over every pixel of it. Below the knee nothing moves;
67 // above it the luminance approaches the ceiling asymptotically (slope 1 at
68 // the knee, so there is no visible seam), and the color is scaled rather
69 // than desaturated, so a bright backdrop keeps its hue and only loses
70 // brightness. Dark text compresses the INVERTED image, which lifts the
71 // shadows toward white instead. Keep in step with droplet.frag.
72 vec3 compress_backdrop(vec3 c) {
73 vec3 lin = pow(max(c, vec3(0.0)), vec3(2.2));
74 if (compress_invert) {
75 lin = vec3(1.0) - lin;
76 }
77 float y = dot(lin, vec3(0.2126, 0.7152, 0.0722));
78 if (y > compress_knee) {
79 float span = max(compress_ceil - compress_knee, 1e-4);
80 float y2 = compress_knee + span * (1.0 - exp(-(y - compress_knee) / span));
81 lin *= y2 / y;
82 }
83 if (compress_invert) {
84 lin = vec3(1.0) - lin;
85 }
86 return pow(clamp(lin, 0.0, 1.0), vec3(1.0 / 2.2));
87 }
88
89 vec4 sample_compressed() {
90 vec4 c = sample_texture();
91 if (compress_ceil > 0.0 && c.a > 0.0) {
92 c.rgb = compress_backdrop(c.rgb / c.a) * c.a;
93 }
94 return c;
95 }
96
97 #if EFFECTS
98 float corner_alpha(vec2 size, vec2 position, bool is_cutout,
99 float radius_tl, float radius_tr, float radius_bl, float radius_br);
100 #endif
101
102 void main() {
103 #if EFFECTS
104 float quad_corner_alpha = corner_alpha(
105 size - 0.5,
106 position + 0.25,
107 false,
108 radius_top_left,
109 radius_top_right,
110 radius_bottom_left,
111 radius_bottom_right
112 );
113
114 // Clipping
115 float clip_corner_alpha = corner_alpha(
116 clip_size - 1.0,
117 clip_position + 0.5,
118 true,
119 clip_radius_top_left,
120 clip_radius_top_right,
121 clip_radius_bottom_left,
122 clip_radius_bottom_right
123 );
124
125 gl_FragColor = sample_compressed() * alpha * quad_corner_alpha * clip_corner_alpha;
126 #else
127 gl_FragColor = sample_compressed() * alpha;
128 #endif
129
130 if (discard_transparent && gl_FragColor.a == 0.0) {
131 discard;
132 }
133 }