picom/src/backend/gl/shaders.c

221 lines
6.0 KiB
C

#include "gl_common.h"
// clang-format off
const char dummy_frag[] = GLSL(330,
uniform sampler2D tex;
in vec2 texcoord;
void main() {
gl_FragColor = texelFetch(tex, ivec2(texcoord.xy), 0);
}
);
const char present_frag[] = GLSL(330,
uniform sampler2D tex;
in vec2 texcoord;
vec4 dither(vec4, vec2);
void main() {
gl_FragColor = dither(texelFetch(tex, ivec2(texcoord.xy), 0), texcoord);
}
);
const char copy_with_mask_frag[] = GLSL(330,
uniform sampler2D tex;
in vec2 texcoord;
float mask_factor();
void main() {
gl_FragColor = texelFetch(tex, ivec2(texcoord.xy), 0) * mask_factor();
}
);
const char fill_frag[] = GLSL(330,
uniform vec4 color;
void main() {
gl_FragColor = color;
}
);
const char fill_vert[] = GLSL(330,
layout(location = 0) in vec2 in_coord;
uniform mat4 projection;
void main() {
gl_Position = projection * vec4(in_coord, 0, 1);
}
);
const char interpolating_frag[] = GLSL(330,
uniform sampler2D tex;
in vec2 texcoord;
void main() {
gl_FragColor = vec4(texture2D(tex, vec2(texcoord.xy), 0).rgb, 1);
}
);
const char interpolating_vert[] = GLSL(330,
uniform mat4 projection;
uniform vec2 texsize;
layout(location = 0) in vec2 in_coord;
layout(location = 1) in vec2 in_texcoord;
out vec2 texcoord;
void main() {
gl_Position = projection * vec4(in_coord, 0, 1);
texcoord = in_texcoord / texsize;
}
);
const char masking_glsl[] = GLSL(330,
uniform sampler2D mask_tex;
uniform vec2 mask_offset;
uniform float mask_corner_radius;
uniform bool mask_inverted;
in vec2 texcoord;
float mask_rectangle_sdf(vec2 point, vec2 half_size) {
vec2 d = abs(point) - half_size;
return length(max(d, 0.0));
}
float mask_factor() {
vec2 mask_size = textureSize(mask_tex, 0);
vec2 maskcoord = texcoord - mask_offset;
vec4 mask = texture2D(mask_tex, maskcoord / mask_size);
if (mask_corner_radius != 0) {
vec2 inner_size = mask_size - vec2(mask_corner_radius) * 2.0f;
float dist = mask_rectangle_sdf(maskcoord - mask_size / 2.0f,
inner_size / 2.0f) - mask_corner_radius;
if (dist > 0.0f) {
mask.r *= (1.0f - clamp(dist, 0.0f, 1.0f));
}
}
if (mask_inverted) {
mask.rgb = 1.0 - mask.rgb;
}
return mask.r;
}
);
const char win_shader_glsl[] = GLSL(330,
uniform float opacity;
uniform float dim;
uniform float corner_radius;
uniform float border_width;
uniform bool invert_color;
in vec2 texcoord;
uniform sampler2D tex;
uniform sampler2D brightness;
uniform float max_brightness;
// Signed distance field for rectangle center at (0, 0), with size of
// half_size * 2
float rectangle_sdf(vec2 point, vec2 half_size) {
vec2 d = abs(point) - half_size;
return length(max(d, 0.0));
}
vec4 default_post_processing(vec4 c) {
vec4 border_color = texture(tex, vec2(0.0, 0.5));
if (invert_color) {
c = vec4(c.aaa - c.rgb, c.a);
border_color = vec4(border_color.aaa - border_color.rgb, border_color.a);
}
c = vec4(c.rgb * (1.0 - dim), c.a) * opacity;
border_color = vec4(border_color.rgb * (1.0 - dim), border_color.a) * opacity;
vec3 rgb_brightness = texelFetch(brightness, ivec2(0, 0), 0).rgb;
// Ref: https://en.wikipedia.org/wiki/Relative_luminance
float brightness = rgb_brightness.r * 0.21 +
rgb_brightness.g * 0.72 +
rgb_brightness.b * 0.07;
if (brightness > max_brightness) {
c.rgb = c.rgb * (max_brightness / brightness);
border_color.rgb = border_color.rgb * (max_brightness / brightness);
}
// Rim color is the color of the outer rim of the window, if there is no
// border, it's the color of the window itself, otherwise it's the border.
// Using mix() to avoid a branch here.
vec4 rim_color = mix(c, border_color, clamp(border_width, 0.0f, 1.0f));
vec2 outer_size = vec2(textureSize(tex, 0));
vec2 inner_size = outer_size - vec2(corner_radius) * 2.0f;
float rect_distance = rectangle_sdf(texcoord - outer_size / 2.0f,
inner_size / 2.0f) - corner_radius;
if (rect_distance > 0.0f) {
c = (1.0f - clamp(rect_distance, 0.0f, 1.0f)) * rim_color;
} else {
float factor = clamp(rect_distance + border_width, 0.0f, 1.0f);
c = (1.0f - factor) * c + factor * border_color;
}
return c;
}
vec4 window_shader();
float mask_factor();
void main() {
gl_FragColor = window_shader() * mask_factor();
}
);
const char win_shader_default[] = GLSL(330,
in vec2 texcoord;
uniform sampler2D tex;
vec4 default_post_processing(vec4 c);
vec4 window_shader() {
vec4 c = texelFetch(tex, ivec2(texcoord), 0);
return default_post_processing(c);
}
);
const char present_vertex_shader[] = GLSL(330,
uniform mat4 projection;
layout(location = 0) in vec2 coord;
out vec2 texcoord;
void main() {
gl_Position = projection * vec4(coord, 0, 1);
texcoord = coord;
}
);
const char vertex_shader[] = GLSL(330,
uniform mat4 projection;
uniform float scale = 1.0;
uniform vec2 texorig;
layout(location = 0) in vec2 coord;
layout(location = 1) in vec2 in_texcoord;
out vec2 texcoord;
void main() {
gl_Position = projection * vec4(coord, 0, scale);
texcoord = in_texcoord + texorig;
}
);
const char dither_glsl[] = GLSL(330,
// Stolen from: https://www.shadertoy.com/view/7sfXDn
float bayer2(vec2 a) {
a = floor(a);
return fract(a.x / 2. + a.y * a.y * .75);
}
// 16 * 16 is 2^8, so in total we have equivalent of 16-bit
// color depth, should be enough?
float bayer(vec2 a16) {
vec2 a8 = a16 * .5;
vec2 a4 = a8 * .5;
vec2 a2 = a4 * .5;
float bayer32 = ((bayer2(a2) * .25 + bayer2( a4))
* .25 + bayer2( a8))
* .25 + bayer2(a16);
return bayer32;
}
vec4 dither(vec4 c, vec2 coord) {
vec4 residual = mod(c, 1.0 / 255.0);
residual = min(residual, vec4(1.0 / 255.0) - residual);
vec4 dithered = vec4(greaterThan(residual, vec4(1.0 / 65535.0)));
return vec4(c + dithered * bayer(coord) / 255.0);
}
);
const char shadow_colorization_frag[] = GLSL(330,
uniform vec4 color;
uniform sampler2D tex;
in vec2 texcoord;
out vec4 out_color;
void main() {
vec4 c = texelFetch(tex, ivec2(texcoord), 0);
out_color = c.r * color;
}
);
// clang-format on