-
-
Notifications
You must be signed in to change notification settings - Fork 589
Shader Shop
This page lists window shaders created by users of picom. You can put your own shaders here.
For information on how to use these shaders, please consult the --glx-fshader-win
option in the man page. Note currently this feature is not implemented in the experimental backends yet.
Author: @yshui
Description: This shader turns all of your windows black-and-white.
Screenshot:
#version 330
in vec2 texcoord;
uniform sampler2D tex;
uniform float opacity;
vec4 default_post_processing(vec4 c);
vec4 window_shader() {
vec2 texsize = textureSize(tex, 0);
vec4 color = texture2D(tex, texcoord / texsize, 0);
color = vec4(vec3(0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b) * opacity, color.a * opacity);
return default_post_processing(color);
}
Author: @KiranWells
Description: This shader restricts all windows to a certain colorscheme, by default Gruvbox.
Screenshot:
// The Gruvbox colorscheme is used by default,
// but you can make your own by changing `colors`
#version 330
uniform float opacity;
uniform float time;
uniform bool invert_color;
uniform sampler2D tex;
in vec2 texcoord;
vec4 default_post_processing(vec4 c);
float sin_rand() {
return sin(gl_FragCoord.x + cos(gl_FragCoord.y));
}
float random(float seedChange) {
vec2 seed = gl_FragCoord.xy + sin(seedChange);
return fract(dot(vec2(sin(mod(seed.x / cos(seed.y), 5.0) * 10000.0)), vec2(1.1, 12.2)));
}
vec4 window_shader() {
vec2 texsize = textureSize(tex, 0);
vec4 c = texture2D(tex, texcoord / texsize, 0);
vec4 d = c;
vec3 colors[16];
colors[0] = vec3(0.1568627450980392, 0.1568627450980392, 0.1568627450980392);
colors[1] = vec3(0.8, 0.1411764705882353, 0.11372549019607843);
colors[2] = vec3(0.596078431372549, 0.592156862745098, 0.10196078431372549);
colors[3] = vec3(0.8431372549019608, 0.6, 0.12941176470588237);
colors[4] = vec3(0.27058823529411763, 0.5215686274509804, 0.5333333333333333);
colors[5] = vec3(0.6941176470588235, 0.3843137254901961, 0.5254901960784314);
colors[6] = vec3(0.40784313725490196, 0.615686274509804, 0.41568627450980394);
colors[7] = vec3(0.8352941176470589, 0.7686274509803922, 0.6313725490196078);
colors[8] = vec3(0.5725490196078431, 0.5137254901960784, 0.4549019607843137);
colors[9] = vec3(0.8, 0.1411764705882353, 0.11372549019607843);
colors[10] = vec3(0.596078431372549, 0.592156862745098, 0.10196078431372549);
colors[11] = vec3(0.8431372549019608, 0.6, 0.12941176470588237);
colors[12] = vec3(0.27058823529411763, 0.5215686274509804, 0.5333333333333333);
colors[13] = vec3(0.6941176470588235, 0.3843137254901961, 0.5254901960784314);
colors[14] = vec3(0.4588235294117647, 0.7098039215686275, 0.6666666666666666);
colors[15] = vec3(0.9215686274509803, 0.8588235294117647, 0.6980392156862745);
float mindist = 100.0;
int minind = 0;
float mindist2 = 100.0;
int minind2 = 0;
for (int i = 0; i < 16; i++) {
float dist = length(c.xyz - colors[i]);
if (dist < mindist) {
mindist2 = mindist;
mindist = dist;
minind2 = minind;
minind = i;
}
}
float ratio = mindist / (mindist + mindist2);
float r = random(1.0) * 0.4 + 0.25;
if (r > ratio)
c.xyz = colors[minind];
else
c.xyz = colors[minind2];
c.xyz = mix(mix(colors[minind], colors[minind2], ratio), c.xyz, 0.5);
if (invert_color)
c = vec4(vec3(c.a, c.a, c.a) - vec3(c), c.a);
c *= opacity;
return default_post_processing(c);
}
Author: @FranchuFranchu
Description: This shader slowly "swizzles" the colors of your windows. Swizzling means, for example, changing all the green colors to red, all the red colors to blue, and all the blue colors to green. The result is the colors of your screen changing like a rainbow.
Screenshot:
#version 330
#extension GL_ARB_shading_language_420pack: enable
#define CYCLE 5000 // The amount of miliseconds it takes to do a full "loop" around all the colors.
uniform float opacity;
uniform bool invert_color;
uniform sampler2D tex;
uniform float time;
in vec2 texcoord;
float get_decimal_part(float f) {
return f - int(f);
}
float snap0(float f) {
return (f < 0) ? 0 : f;
}
vec4 default_post_processing(vec4 c);
vec4 window_shader() {
vec2 texsize = textureSize(tex, 0);
vec4 c = texture2D(tex, texcoord / texsize, 0);
float f = get_decimal_part(time / CYCLE);
float p[3] = {
snap0(0.33 - abs(f - 0.33)) * 4,
snap0(0.33 - abs(f - 0.66)) * 4,
snap0(0.33 - abs(f - 1.00)) * 4 + snap0(0.33 - abs(f - 0.0)) * 4
};
c = vec4(
p[0] * c.r + p[1] * c.g + p[2] * c.b,
p[2] * c.r + p[0] * c.g + p[1] * c.b,
p[1] * c.r + p[2] * c.g + p[0] * c.b,
c.a * opacity
);
return default_post_processing(c);
}
Author: @KiranWells
Description: This shader preserves the colors of an image when inverting the value. It allows the invert flag to be used without causing an unsightly neon mess. This helps preserve the look of pictures and things while keeping the high contrast look. Note: this shader has no effect unless the invert_color
flag is set to true. To permanently enable it, replace the if statement to always be true.
Screenshot:
#version 330
// Changes the behavior of inverting color to preserve the hue
// In other words, the invert flag will now only invert the
// lightness value. This helps preserve the look of pictures and
// things while keeping the high contrast look.
uniform float opacity;
uniform bool invert_color;
uniform sampler2D tex;
in vec2 texcoord;
#define pi 3.14159265358979323846264
vec4 default_post_processing(vec4 c);
// adapted from https://stackoverflow.com/questions/9234724/how-to-change-hue-of-a-texture-with-glsl
vec3 hue_rotate(in vec3 c, in float hueAdjust) {
const vec4 kRGBToYPrime = vec4 (0.299, 0.587, 0.114, 0.0);
const vec4 kRGBToI = vec4 (0.596, -0.275, -0.321, 0.0);
const vec4 kRGBToQ = vec4 (0.212, -0.523, 0.311, 0.0);
const vec4 kYIQToR = vec4 (1.0, 0.956, 0.621, 0.0);
const vec4 kYIQToG = vec4 (1.0, -0.272, -0.647, 0.0);
const vec4 kYIQToB = vec4 (1.0, -1.107, 1.704, 0.0);
vec4 color = vec4(c, 1.0);
// Convert to YIQ
float YPrime = dot (color, kRGBToYPrime);
float I = dot (color, kRGBToI);
float Q = dot (color, kRGBToQ);
// Calculate the hue and chroma
float hue = atan (Q, I);
float chroma = sqrt (I * I + Q * Q);
// Make the adjustments
hue += hueAdjust * 2. * pi;
// Convert back to YIQ
Q = chroma * sin (hue);
I = chroma * cos (hue);
// Convert back to RGB
vec4 yIQ = vec4 (YPrime, I, Q, 0.0);
color.r = dot (yIQ, kYIQToR);
color.g = dot (yIQ, kYIQToG);
color.b = dot (yIQ, kYIQToB);
return color.rgb;
}
vec4 window_shader() {
vec2 texsize = textureSize(tex, 0);
vec4 c = texture2D(tex, texcoord / texsize, 0);
if (invert_color) {
c.xyz = 1.0 - c.xyz;
c.xyz = hue_rotate(c.xyz, 0.5);
}
c *= opacity;
return default_post_processing(c);
}
Author: @nick87720z
Description: This shader allowes to get fullscreen subpixel or greyscale antialiasing in X11 window system with XRandr assistance. Written in honor of expiration of patents, covering subpixel graphics layout. This can make LCD display look like CRT / analogue display.
Principle:
- XRandr sets virtual display resolutions 3x higher than physical (for popular rgb layouts, supported by freetype).
- Picom applies shader, which filters content so, that Xrandr can just pick pixels using nearest-neighbor scaling mode.
Be advised: it's very power hungry, which can overheat system, turn PC into toster, scramble cocroaches... (you were warned).
Screenshot:
(needs update, doesn't reflect gamma correction effect)
Note: This screenshot is made for horizontal RGB subpixel layout, supported by fontconfig. For bgr or vertical variants try to rotate to 90, 180 or 270 deg.
Code: downscale-filter.glsl
#version 330
/**
* Goal: Fullscreen subpixel antialiasing filter.
*
* Motivation:
* - Natural, less pixelated look.
* See https://entropymine.com/imageworsener/subpixel (note: there's image, useful to calibrate subpixel shift parameter).
* - It's written while celebrating the expiration of patents, covering subpixel graphics layout.
*
* Principle:
* - XRandr sets 3x scaled virtual display resolutions 3x higher than physical (for popular rgb layouts, supported by freetype).
* - Picom shader performs all the downscale filtering (interpolation, channels shift, sharpening) against content with multiplied resolution.
* - Sharpening amount is kept just enough to get same crispness as for freetype-rendered text.
* - After it's done, necessary pixels are simply picked by Xrandr with nearest neighbor downscale method.
*
* Downsides:
* Very power hungry, so good graphics card is required for relatively smooth experience (good if not gaming grade).
* Besides 9x more Mpix, there's also some ~2x overhead (could be more), yet there's possible frequency throtling on overheat.
*
* Setup:
* - Other subpixel rendering methods (e.g. font subpixel rendering) don't combine with this.
* - Mouse pointer bypasses picom, so you may need prefiltered mouse theme.
* - WARNING: This shader is meaned to be applied to screen instead of windows.
* When used per-window, this may need more job than one screen; using 'wx_3fold' makes empty content for windows, not aligned to 3x3 pixel block center.
*
* Example ~/.xprofile:
* ############################
* export GDK_SCALE=3
* export GDK_DPI_SCALE=0.33333
* export ELM_SCALE=3
* export QT_AUTO_SCREEN_SCALE_FACTOR=0
* export QT_SCREEN_SCALE_FACTORS=3
*
* # Size needs to be configured early, before desktop loading, or it could behave incorrectly.
* xrandr --output LVDS1 --scale 1x1 --filter nearest
* xrandr --output LVDS1 --scale 3x3 --filter nearest
* ############################
*/
/*********** Configuration choices ************/
#define wx_3fold 0 /** Flag to skip positions to be ignored by following nearest filter, greatly reducing power waste.
** Only for 3-fold window position (best use is for screen post-processing). */
#define FUNC 1 /** Filter function choice.
** 0 - 3x3 averaging: no stages (default, intended for first run test),
** 1 - 3x3 averaging + subpixel: 0 to 2 stages. */
#define STAGE 0 /** Stage number to run (0 - single stage version). */
#define GAMMA 2.0 /** Use custom gamma correction instead of builtin square.
** NOTE: Use proper gamma calibration tool to find right value, don't judge by color fringes intensity. */
#if FUNC == 1
#define LCD_RGB /** Subpixel order choice: LCD_RGB, LCD_BGR. */
#define LCD_HORZ /** Subpixel layout orientation: LCD_HORZ, LCD_VERT. */
#define shift (100) /** Subpixel shift in percents from full (0..1/3 pixel width for linear RGB stripes). */
#define RGB_CONTRAST 1.0
/** Antiblur level. Negates extra blur after box is applied to existing 3px or wider areas.
** Recomended default is 1.0. Higher values might have clear support shadows overweight. */
#endif
/*********** Implementations ***********************/
/** Development note:
** When 'wx_3fold' is enabled, filtering in multiple per-axis stages doesn't enhance performance for small kernels,
** because 1st stage can skip only 1/3 points instead of 1/9.
**
** Expecting full-screen post-processing support in picom. */
vec4 default_post_processing( vec4 c);
uniform vec2 texcoord;
uniform sampler2D tex;
#if wx_3fold
const vec4 skip_color = vec4( 0.0, 0.0, 0.0, 1.0);
#endif
#if defined GAMMA
const vec4 pow_to_lin = vec4( 2.2);
const vec4 pow_from_lin = vec4( 1.0 / 2.2);
#define to_lin( c) c=pow( c, pow_to_lin )
#define from_lin( c) c=pow( c, pow_from_lin )
#else
#define to_lin( c) c*=( c)
#define from_lin( c) c=sqrt( c)
#endif
#if FUNC == 0
/***************************** Greyscale 3x3 box (test) *****************************/
vec4 window_shader()
{
#if wx_3fold
if (int( texcoord.x) % 3 != 1)
return skip_color;
if (int( texcoord.y) % 3 != 1)
return skip_color;
#endif
vec4 accum = vec4( 0), tmp;
ivec2 p = ivec2( texcoord);
p.y--;
int x = int( texcoord.x) - 1;
for (int i=0; i<3; i++, p.y++)
{
p.x = x;
for (int j=0; j<3; j++, p.x++)
{
tmp = texelFetch( tex, p, 0);
to_lin( tmp);
accum += tmp;
}
}
accum /= 9;
from_lin( accum);
return accum;
}
#endif
/********** Subpixel: linear RGB stripe format ********************************/
#if FUNC == 1
#if defined LCD_HORZ
#define sub_x x
#define sub_y y
#elif defined LCD_VERT
#define sub_x y
#define sub_y x
#endif
#if defined LCD_RGB
#define ch_1st r
#define ch_last b
#elif defined LCD_BGR
#define ch_1st b
#define ch_last r
#endif
#if defined shift
#if (shift == 100)
#undef shift
#else
float _shift = float( shift) / 100;
#endif
#endif
#define RGB_SOFT int( RGB_CONTRAST == 0.0 ? 9000.0 : (27.0 / RGB_CONTRAST))
#if defined shift
#define chan_shift( a, l) \
for (int j=1; j <= l/2; j++) { \
a[ l-1-j].ch_1st = (1.0 - _shift) * a[ l-1-j].ch_1st + _shift * a[ l-2-j].ch_1st; \
a[ j].ch_last = (1.0 - _shift) * a[ j].ch_last + _shift * a[ 1+j].ch_last; \
} \
to_lin( a[ l/2 ]); \
for (int j=l/2+1; j < l-1; j++) { \
a[ l-1-j].ch_1st = (1.0 - _shift) * a[ l-1-j].ch_1st + _shift * a[ l-2-j].ch_1st; \
a[ j].ch_last = (1.0 - _shift) * a[ j].ch_last + _shift * a[ 1+j].ch_last; \
to_lin( a[ j]), to_lin( a[ l-1-j]); \
}
#else
#define chan_shift( a, l) \
for (int j=1; j <= l/2; j++) { \
a[ l-1-j].ch_1st = a[ l-2-j].ch_1st; \
a[ j].ch_last = a[ 1+j].ch_last; \
} \
to_lin( a[ l/2 ]); \
for (int j=l/2+1; j < l-1; j++) { \
a[ l-1-j].ch_1st = a[ l-2-j].ch_1st; \
a[ j].ch_last = a[ 1+j].ch_last; \
to_lin( a[ j]), to_lin( a[ l-1-j]); \
}
#endif
#define prepare_subpix_line( a, l, c) \
c.sub_x = int( texcoord.sub_x) - int( l / 2); \
for (int j=0; j < l; j++, c.sub_x++) \
{ \
a[ j] = texelFetch( tex, c, 0); /* Reading between stripes */ \
} \
chan_shift( a, l)
#define return_foreach_sub_line( l, accum_expr, accum_div) \
{ \
ivec2 p; \
p.sub_y = int( texcoord.sub_y) - 1; \
for (int i=0; i < 3; i++, p.sub_y++) \
{ \
vec4 c[ l]; \
prepare_subpix_line( c, l, p); \
accum_expr; \
} \
accum_div; \
}
#if STAGE == 0
/**************** One-stage implementation (worse performance) *******************/
vec4 window_shader()
{
#if wx_3fold
if (int( texcoord.x) % 3 != 1)
return skip_color;
if (int( texcoord.y) % 3 != 1)
return skip_color;
#endif
vec4 accum[ 3] = vec4[ 3]( vec4(0), vec4(0), vec4(0) );
return_foreach_sub_line(
11,
( accum[ 0] += c[1] + c[2] + c[3],
accum[ 1] += c[4] + c[5] + c[6],
accum[ 2] += c[7] + c[8] + c[9] ),
( accum[ 0] /= 9, from_lin( accum[ 0]),
accum[ 1] /= 9, from_lin( accum[ 1]),
accum[ 2] /= 9, from_lin( accum[ 2]) )
);
return (RGB_SOFT * accum[ 1] - accum[ 0] - accum[ 2]) / (RGB_SOFT - 2);
}
#elif STAGE == 1
/**************** Stage 1 *******************/
vec4 window_shader()
{
#if wx_3fold
if (int( texcoord.x) % 3 != 1)
return skip_color;
if (int( texcoord.y) % 3 != 1)
return skip_color;
#endif
vec4 accum = vec4(0);
return_foreach_sub_line(
5,
accum += c[1] + c[2] + c[3],
accum /= 9
);
from_lin( accum);
return accum;
}
#elif STAGE == 2
/**************** Stage 2 *******************/
// NOTE: No gamma correction (contrast must be in perception scale)
vec4 window_shader()
{
#if wx_3fold
if (int( texcoord.x) % 3 != 1)
return skip_color;
if (int( texcoord.y) % 3 != 1)
return skip_color;
#endif
vec4 c[3];
ivec2 p;
p.sub_y = int( texcoord.sub_y);
p.sub_x = int( texcoord.sub_x) - 3;
c[0] = texelFetch( tex, p, 0); p.sub_x += 3
c[1] = texelFetch( tex, p, 0); p.sub_x += 3
c[2] = texelFetch( tex, p, 0);
return (RGB_SOFT * c[1] - c[0] - c[2]) / (RGB_SOFT - 2);
}
#endif
#endif
Everything in this wiki is published under the CC BY-SA 4.0 license. You can find the license text here