Skip to content

Instantly share code, notes, and snippets.

@douo
Last active July 31, 2025 01:05
Show Gist options
  • Select an option

  • Save douo/5778b2a13583ad7cbf3d6c005855dcb6 to your computer and use it in GitHub Desktop.

Select an option

Save douo/5778b2a13583ad7cbf3d6c005855dcb6 to your computer and use it in GitHub Desktop.
picom internal glow shader
#version 430
/*
* picom internal glow shader
*
* Effect: The glow is strongest at the bottom center of the window
* and fades out smoothly towards the sides and top.
*
* --- How to use in picom ---
*
* 1. Save this file to your config directory, e.g.:
* ~/.config/picom/shaders/bottom_glow.frag
*
* 2. In your picom.conf file, add the following rule:
*
* window-shader-fg-rule = [
* "/home/your_username/.config/picom/shaders/inner_glow.frag:focused"
* ];
*
* 3. Important: Make sure to replace "/home/your_username/" with the
* actual absolute path to your home directory.
*
* 4. Restart picom for the changes to take effect.
*
*/
// --- Required variable declarations ---
in vec2 texcoord;
uniform sampler2D tex;
// --- Define your preferred glow color and width here ---
#define GLOW_COLOR vec3(0.6, 0.4, 1.0) // A more modern, bright purple
#define GLOW_WIDTH 16.0 // The vertical width of the glow (in pixels)
// Declare picom's built-in post-processing function
vec4 default_post_processing(vec4 c);
// picom requires us to define this function
vec4 window_shader() {
// Use textureSize to get the exact pixel dimensions of the window
ivec2 window_size = textureSize(tex, 0);
// Get the original pixel color
vec4 original_color = texelFetch(tex, ivec2(texcoord), 0);
// **Crucial step**: Call picom's default post-processing first
vec4 c = default_post_processing(original_color);
// --- Bottom-center glow logic ---
// 1. Calculate vertical intensity (fades from bottom to top)
float dist_from_bottom = float(window_size.y) - texcoord.y;
float vertical_intensity = 1.0 - smoothstep(0.0, GLOW_WIDTH, dist_from_bottom);
// 2. Calculate horizontal intensity (fades from center to sides)
float center_x = float(window_size.x) / 2.0;
float dist_from_center_x = abs(texcoord.x - center_x);
float horizontal_intensity = 1.0 - smoothstep(0.0, center_x, dist_from_center_x);
// 3. The final intensity is the product of vertical and horizontal intensities
float final_intensity = vertical_intensity * horizontal_intensity;
// 4. Mix the glow color with the original color based on the final intensity
// Multiplying by 0.7 controls the maximum opacity of the glow to avoid complete coverage
c.rgb = mix(c.rgb, GLOW_COLOR, final_intensity * 0.7);
// Return the final color
return c;
}
#version 430
/*
* picom internal glow shader (v19 - Horizontal Breathing Effect)
*
* Core logic: The breathing effect is applied to the horizontal width of the glow,
* causing it to dynamically expand and contract from the center,
* creating a "breathing" gradient.
*
* --- How to use in picom ---
*
* 1. Save this file to your config directory, e.g.:
* ~/.config/picom/shaders/breathing_glow.frag
*
* 2. In your picom.conf file, add the following rule:
*
* window-shader-fg-rule = [
* "/home/your_username/.config/picom/shaders/breathing_glow.frag:focused"
* ];
*
* 3. IMPORTANT: For smooth animations based on the 'time' variable,
* you MUST disable 'use-damage' in your picom.conf:
*
* use-damage = false;
*
* Otherwise, picom will only redraw when there are window changes,
* and the animation will appear stuttery or not at all.
*
* 4. Restart picom for the changes to take effect.
*
*/
// --- Required variable declarations ---
in vec2 texcoord;
uniform sampler2D tex;
uniform float time; // time in milliseconds, provided by picom
// --- Define your preferred glow color and width here ---
#define GLOW_COLOR vec3(0.9, 0.2, 0.2) // A more modern, bright purple
#define GLOW_HEIGHT 16.0 // The vertical height of the glow (in pixels)
#define BREATHING_SPEED 0.002 // Breathing speed, larger value means faster
#define MIN_WIDTH_FACTOR 0.25 // The narrowest width of the glow during breathing,
// as a percentage of half the window width (25%)
// Declare picom's built-in post-processing function
vec4 default_post_processing(vec4 c);
// picom requires us to define this function
vec4 window_shader() {
// Use textureSize to get the exact pixel dimensions of the window
ivec2 window_size = textureSize(tex, 0);
// Get the original pixel color
vec4 original_color = texelFetch(tex, ivec2(texcoord), 0);
// **Crucial step**: Call picom's default post-processing first
vec4 c = default_post_processing(original_color);
// --- Bottom-center glow logic ---
// 1. Calculate vertical intensity (fades from bottom to top)
float dist_from_bottom = float(window_size.y) - texcoord.y;
float vertical_intensity = 1.0 - smoothstep(0.0, GLOW_HEIGHT, dist_from_bottom);
// --- Horizontal breathing logic ---
// a. Use a sine function to create a smooth wave between 0.0 and 1.0
float breathing_wave = (sin(time * BREATHING_SPEED) + 1.0) / 2.0;
// b. Calculate the dynamic glow width based on the wave
// The width varies between (half_window * MIN_WIDTH_FACTOR) and (half_window)
float center_x = float(window_size.x) / 2.0;
float dynamic_width = mix(center_x * MIN_WIDTH_FACTOR, center_x, breathing_wave);
// c. Calculate horizontal intensity based on the dynamic width (fades from center to sides)
float dist_from_center_x = abs(texcoord.x - center_x);
float horizontal_intensity = 1.0 - smoothstep(0.0, dynamic_width, dist_from_center_x);
// 3. The final intensity is the product of vertical and horizontal intensities
float final_intensity = vertical_intensity * horizontal_intensity;
// 4. Mix the glow color with the original color based on the final intensity
// Multiplying by 0.7 controls the maximum opacity of the glow to avoid complete coverage
c.rgb = mix(c.rgb, GLOW_COLOR, final_intensity * 0.7);
// Return the final color
return c;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment