mirror of
https://github.com/yshui/picom.git
synced 2024-11-11 13:51:02 -05:00
3aed5599c3
We only considered residual in the positive direction, i.e. we would set dithering to zero if the color is (whole number + 0.0001). But we should also set dithering to zero if color is (whole number - 0.0001). Fixes #1064
220 lines
6 KiB
C
220 lines
6 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
|