auroraea8f173
add shader script and keybinds
+800 −6
20 files changed
- A .config/hypr/shaders/01_red_tint.glsl +16 −0
- A .config/hypr/shaders/02_green_tint.glsl +16 −0
- A .config/hypr/shaders/03_blue_tint.glsl +15 −0
- A .config/hypr/shaders/04_optics_compensate.glsl +72 −0
- A .config/hypr/shaders/05_sketch.glsl +89 −0
- A .config/hypr/shaders/06_wobble.glsl +72 −0
- A .config/hypr/shaders/07_chromatic_aberration.glsl +43 −0
- A .config/hypr/shaders/08_newspaper.glsl +114 −0
- A .config/hypr/shaders/09_pixelated.glsl +28 −0
- A .config/hypr/shaders/10_grayscale.glsl +40 −0
- A .config/hypr/shaders/11_invert.glsl +30 −0
- A .config/hypr/shaders/12_posterization.glsl +39 −0
- A .config/hypr/shaders/13_sepia.glsl +33 −0
- A .config/hypr/shaders/14_vibrance.glsl +37 −0
- A .config/hypr/shaders/15_anaglyph_3d.glsl +35 −0
- A .config/hypr/shaders/16_vignette.glsl +37 −0
- A .config/hypr/shaders/vibrance.glsl +40 −0
- M .config/hypr/source/keybinds.conf +12 −6
- M .config/waybar/config.jsonc +1 −0
- A .local/bin/hypr/hypr_shader_menu.sh +31 −0
| @@ -0,0 +1,16 @@ | |||
| 1 | + | #version 300 es | |
| 2 | + | // Pure Red Channel Shader - OPTIMIZED | |
| 3 | + | precision highp float; | |
| 4 | + | ||
| 5 | + | in vec2 v_texcoord; | |
| 6 | + | uniform sampler2D tex; | |
| 7 | + | out vec4 fragColor; | |
| 8 | + | ||
| 9 | + | // Using Rec. 709 for consistency | |
| 10 | + | const vec3 LUMA = vec3(0.2126, 0.7152, 0.0722); | |
| 11 | + | ||
| 12 | + | void main() { | |
| 13 | + | vec4 pixColor = texture(tex, v_texcoord); | |
| 14 | + | float gray = dot(pixColor.rgb, LUMA); | |
| 15 | + | fragColor = vec4(gray, 0.0, 0.0, pixColor.a); | |
| 16 | + | } | |
| @@ -0,0 +1,16 @@ | |||
| 1 | + | #version 300 es | |
| 2 | + | // Pure Green Channel Shader - FIXED | |
| 3 | + | precision highp float; | |
| 4 | + | ||
| 5 | + | in vec2 v_texcoord; | |
| 6 | + | uniform sampler2D tex; | |
| 7 | + | out vec4 fragColor; | |
| 8 | + | ||
| 9 | + | const vec3 LUMA = vec3(0.2126, 0.7152, 0.0722); | |
| 10 | + | ||
| 11 | + | void main() { | |
| 12 | + | vec4 pixColor = texture(tex, v_texcoord); | |
| 13 | + | float gray = dot(pixColor.rgb, LUMA); | |
| 14 | + | // FIXED: Now correctly outputs to GREEN channel | |
| 15 | + | fragColor = vec4(0.0, gray, 0.0, pixColor.a); | |
| 16 | + | } | |
| @@ -0,0 +1,15 @@ | |||
| 1 | + | #version 300 es | |
| 2 | + | // Pure Blue Channel Shader - OPTIMIZED | |
| 3 | + | precision highp float; | |
| 4 | + | ||
| 5 | + | in vec2 v_texcoord; | |
| 6 | + | uniform sampler2D tex; | |
| 7 | + | out vec4 fragColor; | |
| 8 | + | ||
| 9 | + | const vec3 LUMA = vec3(0.2126, 0.7152, 0.0722); | |
| 10 | + | ||
| 11 | + | void main() { | |
| 12 | + | vec4 pixColor = texture(tex, v_texcoord); | |
| 13 | + | float gray = dot(pixColor.rgb, LUMA); | |
| 14 | + | fragColor = vec4(0.0, 0.0, gray, pixColor.a); | |
| 15 | + | } | |
| @@ -0,0 +1,72 @@ | |||
| 1 | + | #version 300 es | |
| 2 | + | // Retro CRT Shader - FULLY OPTIMIZED | |
| 3 | + | // Fixes: Resolution-aware scanlines, proper vignette, edge clamping, | |
| 4 | + | // correct aberration direction, anti-aliased scanlines | |
| 5 | + | ||
| 6 | + | precision highp float; | |
| 7 | + | ||
| 8 | + | in vec2 v_texcoord; | |
| 9 | + | uniform sampler2D tex; | |
| 10 | + | out vec4 fragColor; | |
| 11 | + | ||
| 12 | + | // --- CONFIGURATION --- | |
| 13 | + | const float CURVATURE = 3.5; | |
| 14 | + | const float SCANLINE_STRENGTH = 0.25; | |
| 15 | + | // Approximate screen height in pixels (adjust to your resolution) | |
| 16 | + | const float SCREEN_HEIGHT = 1080.0; | |
| 17 | + | // Scanlines per screen height (lower = thicker lines) | |
| 18 | + | const float SCANLINE_COUNT = 540.0; | |
| 19 | + | const float ABERRATION = 0.002; | |
| 20 | + | const float VIGNETTE_RADIUS = 1.00; | |
| 21 | + | const float VIGNETTE_SOFTNESS = 0.45; | |
| 22 | + | // Phosphor glow simulation | |
| 23 | + | const float GLOW = 0.03; | |
| 24 | + | ||
| 25 | + | vec2 curveUV(vec2 uv) { | |
| 26 | + | uv = uv * 2.0 - 1.0; | |
| 27 | + | vec2 offset = abs(uv.yx) / vec2(CURVATURE); | |
| 28 | + | uv = uv + uv * offset * offset; | |
| 29 | + | uv = uv * 0.5 + 0.5; | |
| 30 | + | return uv; | |
| 31 | + | } | |
| 32 | + | ||
| 33 | + | void main() { | |
| 34 | + | vec2 uv = curveUV(v_texcoord); | |
| 35 | + | ||
| 36 | + | // Black bezel for out-of-bounds | |
| 37 | + | if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) { | |
| 38 | + | fragColor = vec4(0.0, 0.0, 0.0, 1.0); | |
| 39 | + | return; | |
| 40 | + | } | |
| 41 | + | ||
| 42 | + | // FIXED: Clamp aberration samples to prevent edge artifacts | |
| 43 | + | vec2 centerDist = uv - 0.5; | |
| 44 | + | vec2 aberrOffset = centerDist * ABERRATION; | |
| 45 | + | ||
| 46 | + | // FIXED: Correct direction - red focuses short, blue focuses long | |
| 47 | + | float r = texture(tex, clamp(uv + aberrOffset, 0.0, 1.0)).r; | |
| 48 | + | float g = texture(tex, uv).g; | |
| 49 | + | float b = texture(tex, clamp(uv - aberrOffset, 0.0, 1.0)).b; | |
| 50 | + | vec3 color = vec3(r, g, b); | |
| 51 | + | ||
| 52 | + | // FIXED: Anti-aliased scanlines that don't shimmer during scroll | |
| 53 | + | // Using smooth triangle wave instead of harsh sine | |
| 54 | + | float scanlinePhase = uv.y * SCANLINE_COUNT * 2.0; | |
| 55 | + | float scanline = abs(fract(scanlinePhase) - 0.5) * 2.0; // Triangle wave 0-1 | |
| 56 | + | scanline = smoothstep(0.0, 1.0, scanline); // Smooth it | |
| 57 | + | float scanlineFactor = 1.0 - (SCANLINE_STRENGTH * (1.0 - scanline)); | |
| 58 | + | color *= scanlineFactor; | |
| 59 | + | ||
| 60 | + | // Subtle phosphor glow (brightens slightly between scanlines) | |
| 61 | + | color += GLOW * (1.0 - scanline); | |
| 62 | + | ||
| 63 | + | // FIXED: Proper circular vignette with correct smoothstep bounds | |
| 64 | + | float dist = length(centerDist) * 2.0; // 0 at center, ~1.414 at corners | |
| 65 | + | float vignette = 1.0 - smoothstep(VIGNETTE_RADIUS, VIGNETTE_RADIUS + VIGNETTE_SOFTNESS, dist); | |
| 66 | + | color *= vignette; | |
| 67 | + | ||
| 68 | + | // Subtle brightness boost to compensate for darkening effects | |
| 69 | + | color *= 1.1; | |
| 70 | + | ||
| 71 | + | fragColor = vec4(clamp(color, 0.0, 1.0), 1.0); | |
| 72 | + | } | |
| @@ -0,0 +1,89 @@ | |||
| 1 | + | #version 300 es | |
| 2 | + | precision highp float; | |
| 3 | + | ||
| 4 | + | in vec2 v_texcoord; | |
| 5 | + | uniform sampler2D tex; | |
| 6 | + | out vec4 fragColor; | |
| 7 | + | ||
| 8 | + | // --- CONFIGURATION --- | |
| 9 | + | const float edge_threshold = 0.15; // Sensitivity (0.05-0.5) - lower = more edges | |
| 10 | + | const float edge_softness = 0.08; // Anti-aliasing amount | |
| 11 | + | const float line_thickness = 1.0; // 1.0 = normal, 2.0 = thicker | |
| 12 | + | const float line_darkness = 0.05; // 0.0 = pure black, higher = lighter | |
| 13 | + | const float paper_brightness = 0.98; // Paper color | |
| 14 | + | const float paper_grain = 0.03; // Paper texture intensity | |
| 15 | + | const float noise_reduction = 0.5; // Reduces speckles in smooth areas | |
| 16 | + | // --------------------- | |
| 17 | + | ||
| 18 | + | float luminance(vec3 color) { | |
| 19 | + | return dot(color, vec3(0.2126, 0.7152, 0.0722)); | |
| 20 | + | } | |
| 21 | + | ||
| 22 | + | float hash12(vec2 p) { | |
| 23 | + | vec3 p3 = fract(vec3(p.xyx) * 0.1031); | |
| 24 | + | p3 += dot(p3, p3.yzx + 33.33); | |
| 25 | + | return fract((p3.x + p3.y) * p3.z); | |
| 26 | + | } | |
| 27 | + | ||
| 28 | + | // Sample luminance with bounds checking | |
| 29 | + | float sampleLum(vec2 uv) { | |
| 30 | + | vec2 safe_uv = clamp(uv, 0.0, 1.0); | |
| 31 | + | return luminance(texture(tex, safe_uv).rgb); | |
| 32 | + | } | |
| 33 | + | ||
| 34 | + | void main() { | |
| 35 | + | vec2 screen_res = vec2(textureSize(tex, 0)); | |
| 36 | + | vec2 pixel_size = line_thickness / screen_res; | |
| 37 | + | vec2 pixel_coords = v_texcoord * screen_res; | |
| 38 | + | ||
| 39 | + | // Sobel kernel sampling with proper edge clamping | |
| 40 | + | float tl = sampleLum(v_texcoord + vec2(-pixel_size.x, -pixel_size.y)); | |
| 41 | + | float t = sampleLum(v_texcoord + vec2( 0.0, -pixel_size.y)); | |
| 42 | + | float tr = sampleLum(v_texcoord + vec2( pixel_size.x, -pixel_size.y)); | |
| 43 | + | float l = sampleLum(v_texcoord + vec2(-pixel_size.x, 0.0)); | |
| 44 | + | float c = sampleLum(v_texcoord); // Center pixel | |
| 45 | + | float r = sampleLum(v_texcoord + vec2( pixel_size.x, 0.0)); | |
| 46 | + | float bl = sampleLum(v_texcoord + vec2(-pixel_size.x, pixel_size.y)); | |
| 47 | + | float b = sampleLum(v_texcoord + vec2( 0.0, pixel_size.y)); | |
| 48 | + | float br = sampleLum(v_texcoord + vec2( pixel_size.x, pixel_size.y)); | |
| 49 | + | ||
| 50 | + | // Sobel operators | |
| 51 | + | float Gx = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl); | |
| 52 | + | float Gy = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr); | |
| 53 | + | float gradient = sqrt(Gx * Gx + Gy * Gy); | |
| 54 | + | ||
| 55 | + | // Calculate local variance for noise reduction | |
| 56 | + | // (reduces speckles in smooth areas while preserving real edges) | |
| 57 | + | float mean = (tl + t + tr + l + c + r + bl + b + br) / 9.0; | |
| 58 | + | float variance = 0.0; | |
| 59 | + | variance += (tl - mean) * (tl - mean); | |
| 60 | + | variance += (t - mean) * (t - mean); | |
| 61 | + | variance += (tr - mean) * (tr - mean); | |
| 62 | + | variance += (l - mean) * (l - mean); | |
| 63 | + | variance += (c - mean) * (c - mean); | |
| 64 | + | variance += (r - mean) * (r - mean); | |
| 65 | + | variance += (bl - mean) * (bl - mean); | |
| 66 | + | variance += (b - mean) * (b - mean); | |
| 67 | + | variance += (br - mean) * (br - mean); | |
| 68 | + | variance = sqrt(variance / 9.0); | |
| 69 | + | ||
| 70 | + | // Adaptive threshold: require stronger edges in noisy areas | |
| 71 | + | float adaptive_threshold = edge_threshold + variance * noise_reduction; | |
| 72 | + | ||
| 73 | + | // Smooth edge detection (anti-aliased) | |
| 74 | + | float edge = smoothstep( | |
| 75 | + | adaptive_threshold - edge_softness, | |
| 76 | + | adaptive_threshold + edge_softness, | |
| 77 | + | gradient | |
| 78 | + | ); | |
| 79 | + | ||
| 80 | + | // Paper texture | |
| 81 | + | float paper = paper_brightness; | |
| 82 | + | paper -= hash12(pixel_coords * 0.4) * paper_grain; | |
| 83 | + | paper -= hash12(pixel_coords * 2.1) * paper_grain * 0.4; | |
| 84 | + | ||
| 85 | + | // Final blend | |
| 86 | + | float final_value = mix(paper, line_darkness, edge); | |
| 87 | + | ||
| 88 | + | fragColor = vec4(vec3(final_value), 1.0); | |
| 89 | + | } | |
| @@ -0,0 +1,72 @@ | |||
| 1 | + | #version 300 es | |
| 2 | + | precision highp float; | |
| 3 | + | ||
| 4 | + | in vec2 v_texcoord; | |
| 5 | + | uniform sampler2D tex; | |
| 6 | + | uniform float TIME; | |
| 7 | + | out vec4 fragColor; | |
| 8 | + | ||
| 9 | + | // --- CONFIGURATION --- | |
| 10 | + | const float wobble_speed = 3.0; // Animation speed | |
| 11 | + | const float wobble_frequency = 15.0; // Wave density | |
| 12 | + | const float wobble_amplitude = 0.025; // Displacement amount | |
| 13 | + | const float edge_fade = 0.1; // Fade near edges (0.0 to disable) | |
| 14 | + | const bool organic_motion = true; // Multi-frequency for natural look | |
| 15 | + | const bool prevent_edge_artifacts = true; | |
| 16 | + | // --------------------- | |
| 17 | + | ||
| 18 | + | void main() { | |
| 19 | + | // Use local time to prevent floating point precision issues with large TIME values | |
| 20 | + | float t = mod(TIME, 628.318); // Wrap at 2*PI*100 | |
| 21 | + | ||
| 22 | + | vec2 new_uv = v_texcoord; | |
| 23 | + | ||
| 24 | + | // Calculate edge fade mask (reduces artifacts at screen borders) | |
| 25 | + | float edge_mask = 1.0; | |
| 26 | + | if (edge_fade > 0.0) { | |
| 27 | + | vec2 dist_to_edge = min(v_texcoord, 1.0 - v_texcoord); | |
| 28 | + | float min_dist = min(dist_to_edge.x, dist_to_edge.y); | |
| 29 | + | edge_mask = smoothstep(0.0, edge_fade, min_dist); | |
| 30 | + | } | |
| 31 | + | ||
| 32 | + | float amplitude = wobble_amplitude * edge_mask; | |
| 33 | + | ||
| 34 | + | float h_offset, v_offset; | |
| 35 | + | ||
| 36 | + | if (organic_motion) { | |
| 37 | + | // Layer multiple frequencies for organic, natural motion | |
| 38 | + | // Different speeds prevent repetitive patterns | |
| 39 | + | ||
| 40 | + | // Horizontal wobble (based on Y position) | |
| 41 | + | h_offset = 0.0; | |
| 42 | + | h_offset += sin(v_texcoord.y * wobble_frequency * 1.0 + t * wobble_speed * 1.00) * 0.50; | |
| 43 | + | h_offset += sin(v_texcoord.y * wobble_frequency * 2.1 + t * wobble_speed * 1.37) * 0.30; | |
| 44 | + | h_offset += sin(v_texcoord.y * wobble_frequency * 0.5 + t * wobble_speed * 0.71) * 0.20; | |
| 45 | + | ||
| 46 | + | // Vertical wobble (based on X position) | |
| 47 | + | v_offset = 0.0; | |
| 48 | + | v_offset += cos(v_texcoord.x * wobble_frequency * 0.9 + t * wobble_speed * 1.13) * 0.50; | |
| 49 | + | v_offset += cos(v_texcoord.x * wobble_frequency * 1.7 + t * wobble_speed * 0.83) * 0.30; | |
| 50 | + | v_offset += cos(v_texcoord.x * wobble_frequency * 0.4 + t * wobble_speed * 1.41) * 0.20; | |
| 51 | + | ||
| 52 | + | // Add subtle interaction between axes | |
| 53 | + | h_offset += sin(v_texcoord.x * wobble_frequency * 0.3 + t * wobble_speed * 0.5) * 0.1; | |
| 54 | + | v_offset += cos(v_texcoord.y * wobble_frequency * 0.3 + t * wobble_speed * 0.6) * 0.1; | |
| 55 | + | ||
| 56 | + | } else { | |
| 57 | + | // Simple single-frequency wobble | |
| 58 | + | h_offset = sin(v_texcoord.y * wobble_frequency + t * wobble_speed); | |
| 59 | + | v_offset = cos(v_texcoord.x * wobble_frequency + t * wobble_speed); | |
| 60 | + | } | |
| 61 | + | ||
| 62 | + | new_uv.x += h_offset * amplitude; | |
| 63 | + | new_uv.y += v_offset * amplitude; | |
| 64 | + | ||
| 65 | + | // Prevent sampling outside texture bounds | |
| 66 | + | if (prevent_edge_artifacts) { | |
| 67 | + | // Clamp with small margin to prevent edge bleeding | |
| 68 | + | new_uv = clamp(new_uv, 0.002, 0.998); | |
| 69 | + | } | |
| 70 | + | ||
| 71 | + | fragColor = texture(tex, new_uv); | |
| 72 | + | } | |
| @@ -0,0 +1,43 @@ | |||
| 1 | + | #version 300 es | |
| 2 | + | // Chromatic Aberration Shader for Hyprland - OPTIMIZED | |
| 3 | + | // Fixes: Edge clamping, aspect ratio correction, quadratic falloff | |
| 4 | + | ||
| 5 | + | precision highp float; | |
| 6 | + | ||
| 7 | + | in vec2 v_texcoord; | |
| 8 | + | uniform sampler2D tex; | |
| 9 | + | out vec4 fragColor; | |
| 10 | + | ||
| 11 | + | // --- CONFIGURATION --- | |
| 12 | + | const float STRENGTH = 0.010; | |
| 13 | + | // Set to your monitor's aspect ratio (16/9, 21/9, etc.) or use 1.0 for uncorrected | |
| 14 | + | const float ASPECT_RATIO = 16.0 / 9.0; | |
| 15 | + | // Use quadratic falloff for more realistic lens distortion | |
| 16 | + | const bool QUADRATIC_FALLOFF = true; | |
| 17 | + | ||
| 18 | + | void main() { | |
| 19 | + | // Aspect-corrected center distance | |
| 20 | + | vec2 distFromCenter = v_texcoord - 0.5; | |
| 21 | + | distFromCenter.x *= ASPECT_RATIO; | |
| 22 | + | ||
| 23 | + | // Calculate offset magnitude | |
| 24 | + | float dist = length(distFromCenter); | |
| 25 | + | float falloff = QUADRATIC_FALLOFF ? dist * dist : dist; | |
| 26 | + | ||
| 27 | + | // Normalize direction and apply strength | |
| 28 | + | vec2 dir = normalize(distFromCenter + 0.0001); // Prevent div by zero | |
| 29 | + | vec2 offset = dir * falloff * STRENGTH; | |
| 30 | + | offset.x /= ASPECT_RATIO; // Correct back for sampling | |
| 31 | + | ||
| 32 | + | // Sample with clamped coordinates to prevent edge artifacts | |
| 33 | + | vec2 redCoord = clamp(v_texcoord - offset, 0.0, 1.0); | |
| 34 | + | vec2 blueCoord = clamp(v_texcoord + offset, 0.0, 1.0); | |
| 35 | + | ||
| 36 | + | float r = texture(tex, redCoord).r; | |
| 37 | + | vec4 centerPixel = texture(tex, v_texcoord); | |
| 38 | + | float g = centerPixel.g; | |
| 39 | + | float b = texture(tex, blueCoord).b; | |
| 40 | + | ||
| 41 | + | // Preserve alpha from center sample | |
| 42 | + | fragColor = vec4(r, g, b, centerPixel.a); | |
| 43 | + | } | |
| @@ -0,0 +1,114 @@ | |||
| 1 | + | #version 300 es | |
| 2 | + | precision highp float; // CRITICAL: Prevents many artifacts | |
| 3 | + | ||
| 4 | + | in vec2 v_texcoord; | |
| 5 | + | uniform sampler2D tex; | |
| 6 | + | out vec4 fragColor; | |
| 7 | + | ||
| 8 | + | // --- CONFIGURATION --- | |
| 9 | + | const float dot_spacing = 4.0; // 3.0-6.0 recommended | |
| 10 | + | const int color_levels = 4; // Posterization levels | |
| 11 | + | const vec3 paper_color = vec3(0.95, 0.92, 0.85); | |
| 12 | + | const float paper_texture_strength = 0.04; | |
| 13 | + | const float dot_softness = 1.5; // Higher = softer dot edges (anti-aliasing) | |
| 14 | + | const float ink_darkness = 0.95; // How dark the ink appears (0.0-1.0) | |
| 15 | + | const bool use_dithering = true; // Reduces posterization banding | |
| 16 | + | // --------------------- | |
| 17 | + | ||
| 18 | + | // Improved hash function - less pattern artifacts than sin-based | |
| 19 | + | float hash12(vec2 p) { | |
| 20 | + | vec3 p3 = fract(vec3(p.xyx) * 0.1031); | |
| 21 | + | p3 += dot(p3, p3.yzx + 33.33); | |
| 22 | + | return fract((p3.x + p3.y) * p3.z); | |
| 23 | + | } | |
| 24 | + | ||
| 25 | + | // Smoother 2D noise for paper texture | |
| 26 | + | float valueNoise(vec2 p) { | |
| 27 | + | vec2 i = floor(p); | |
| 28 | + | vec2 f = fract(p); | |
| 29 | + | ||
| 30 | + | // Smooth interpolation | |
| 31 | + | vec2 u = f * f * (3.0 - 2.0 * f); | |
| 32 | + | ||
| 33 | + | float a = hash12(i); | |
| 34 | + | float b = hash12(i + vec2(1.0, 0.0)); | |
| 35 | + | float c = hash12(i + vec2(0.0, 1.0)); | |
| 36 | + | float d = hash12(i + vec2(1.0, 1.0)); | |
| 37 | + | ||
| 38 | + | return mix(mix(a, b, u.x), mix(c, d, u.x), u.y); | |
| 39 | + | } | |
| 40 | + | ||
| 41 | + | float luminance(vec3 color) { | |
| 42 | + | return dot(color, vec3(0.2126, 0.7152, 0.0722)); | |
| 43 | + | } | |
| 44 | + | ||
| 45 | + | // Bayer 4x4 dithering matrix - reduces posterization banding | |
| 46 | + | float bayerDither(vec2 pos) { | |
| 47 | + | ivec2 p = ivec2(mod(pos, 4.0)); | |
| 48 | + | int index = p.x + p.y * 4; | |
| 49 | + | ||
| 50 | + | // Bayer matrix values | |
| 51 | + | float matrix[16] = float[16]( | |
| 52 | + | 0.0, 8.0, 2.0, 10.0, | |
| 53 | + | 12.0, 4.0, 14.0, 6.0, | |
| 54 | + | 3.0, 11.0, 1.0, 9.0, | |
| 55 | + | 15.0, 7.0, 13.0, 5.0 | |
| 56 | + | ); | |
| 57 | + | ||
| 58 | + | return (matrix[index] / 16.0) - 0.5; | |
| 59 | + | } | |
| 60 | + | ||
| 61 | + | void main() { | |
| 62 | + | vec2 screen_res = vec2(textureSize(tex, 0)); | |
| 63 | + | vec2 pixel_coords = v_texcoord * screen_res; | |
| 64 | + | ||
| 65 | + | // 1. Sample original with clamped coordinates (prevents edge artifacts) | |
| 66 | + | vec2 safe_uv = clamp(v_texcoord, 0.0, 1.0); | |
| 67 | + | vec3 original_color = texture(tex, safe_uv).rgb; | |
| 68 | + | ||
| 69 | + | // 2. Posterize with optional dithering to reduce banding | |
| 70 | + | float levels = float(color_levels); | |
| 71 | + | vec3 posterized_color; | |
| 72 | + | ||
| 73 | + | if (use_dithering) { | |
| 74 | + | // Add dither before quantization | |
| 75 | + | float dither = bayerDither(pixel_coords) / (levels * 2.0); | |
| 76 | + | posterized_color = floor((original_color + dither) * levels) / (levels - 1.0); | |
| 77 | + | } else { | |
| 78 | + | posterized_color = floor(original_color * levels) / (levels - 1.0); | |
| 79 | + | } | |
| 80 | + | posterized_color = clamp(posterized_color, 0.0, 1.0); | |
| 81 | + | ||
| 82 | + | // 3. Create layered paper texture (more natural looking) | |
| 83 | + | float paper_noise = 0.0; | |
| 84 | + | paper_noise += valueNoise(pixel_coords * 0.5) * 0.6; // Large grain | |
| 85 | + | paper_noise += valueNoise(pixel_coords * 1.5) * 0.3; // Medium grain | |
| 86 | + | paper_noise += hash12(pixel_coords) * 0.1; // Fine grain | |
| 87 | + | paper_noise *= paper_texture_strength; | |
| 88 | + | ||
| 89 | + | vec3 textured_paper = max(paper_color - paper_noise, 0.0); // Prevent negative | |
| 90 | + | ||
| 91 | + | // 4. Create halftone grid | |
| 92 | + | vec2 cell_coords = pixel_coords / dot_spacing; | |
| 93 | + | vec2 grid_uv = fract(cell_coords); | |
| 94 | + | ||
| 95 | + | // 5. Calculate halftone dot | |
| 96 | + | // Use sqrt for area-proportional dots (perceptually correct) | |
| 97 | + | float lum = luminance(posterized_color); | |
| 98 | + | float darkness = 1.0 - lum; | |
| 99 | + | float dot_radius = sqrt(darkness) * 0.5; // Area proportional to darkness | |
| 100 | + | ||
| 101 | + | // Distance from cell center | |
| 102 | + | float dist = length(grid_uv - 0.5); | |
| 103 | + | ||
| 104 | + | // Anti-aliased dot edge using screen-space derivatives | |
| 105 | + | // This adapts to any resolution automatically | |
| 106 | + | float pixel_width = fwidth(dist) * dot_softness; | |
| 107 | + | float dot_mask = smoothstep(dot_radius - pixel_width, dot_radius + pixel_width, dist); | |
| 108 | + | ||
| 109 | + | // 6. Combine: ink color where dots are, paper elsewhere | |
| 110 | + | vec3 ink_color = posterized_color * ink_darkness; | |
| 111 | + | vec3 final_color = mix(ink_color, textured_paper, dot_mask); | |
| 112 | + | ||
| 113 | + | fragColor = vec4(final_color, 1.0); | |
| 114 | + | } | |
| @@ -0,0 +1,28 @@ | |||
| 1 | + | #version 300 es | |
| 2 | + | // Pixelation Shader - OPTIMIZED | |
| 3 | + | // Fixes: Sample from pixel CENTER (not corner), aspect ratio support | |
| 4 | + | ||
| 5 | + | precision highp float; | |
| 6 | + | ||
| 7 | + | in vec2 v_texcoord; | |
| 8 | + | uniform sampler2D tex; | |
| 9 | + | out vec4 fragColor; | |
| 10 | + | ||
| 11 | + | // --- CONFIGURATION --- | |
| 12 | + | // Pixels across the shorter dimension (height usually) | |
| 13 | + | const float PIXEL_COUNT = 350.0; | |
| 14 | + | // Set to your aspect ratio, or 1.0 for square pixels | |
| 15 | + | const float ASPECT_RATIO = 16.0 / 9.0; | |
| 16 | + | ||
| 17 | + | void main() { | |
| 18 | + | // Calculate pixel dimensions accounting for aspect ratio | |
| 19 | + | vec2 pixelCount = vec2(PIXEL_COUNT * ASPECT_RATIO, PIXEL_COUNT); | |
| 20 | + | vec2 pixelSize = 1.0 / pixelCount; | |
| 21 | + | ||
| 22 | + | // FIXED: Sample from pixel CENTER, not corner | |
| 23 | + | // This prevents the "swimming" artifact when content moves | |
| 24 | + | vec2 pixelCoord = floor(v_texcoord * pixelCount) + 0.5; | |
| 25 | + | vec2 sampleCoord = pixelCoord / pixelCount; | |
| 26 | + | ||
| 27 | + | fragColor = texture(tex, sampleCoord); | |
| 28 | + | } | |
| @@ -0,0 +1,40 @@ | |||
| 1 | + | #version 300 es | |
| 2 | + | // Grayscale Shader for Hyprland - OPTIMIZED | |
| 3 | + | // Added: Optional gamma-correct conversion for accurate luminance | |
| 4 | + | ||
| 5 | + | precision highp float; | |
| 6 | + | ||
| 7 | + | in vec2 v_texcoord; | |
| 8 | + | uniform sampler2D tex; | |
| 9 | + | out vec4 fragColor; | |
| 10 | + | ||
| 11 | + | // Rec. 709 Luma coefficients (sRGB/HDTV standard) | |
| 12 | + | const vec3 LUMA_709 = vec3(0.2126, 0.7152, 0.0722); | |
| 13 | + | ||
| 14 | + | // Set to true for gamma-correct grayscale (more accurate but slightly slower) | |
| 15 | + | const bool GAMMA_CORRECT = false; | |
| 16 | + | ||
| 17 | + | // sRGB gamma functions | |
| 18 | + | float toLinear(float c) { | |
| 19 | + | return c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4); | |
| 20 | + | } | |
| 21 | + | float toSRGB(float c) { | |
| 22 | + | return c <= 0.0031308 ? c * 12.92 : 1.055 * pow(c, 1.0/2.4) - 0.055; | |
| 23 | + | } | |
| 24 | + | ||
| 25 | + | void main() { | |
| 26 | + | vec4 pixColor = texture(tex, v_texcoord); | |
| 27 | + | ||
| 28 | + | float gray; | |
| 29 | + | if (GAMMA_CORRECT) { | |
| 30 | + | // Convert to linear space, compute luminance, convert back | |
| 31 | + | vec3 linear = vec3(toLinear(pixColor.r), toLinear(pixColor.g), toLinear(pixColor.b)); | |
| 32 | + | float luminance = dot(linear, LUMA_709); | |
| 33 | + | gray = toSRGB(luminance); | |
| 34 | + | } else { | |
| 35 | + | // Fast path: direct computation in gamma space | |
| 36 | + | gray = dot(pixColor.rgb, LUMA_709); | |
| 37 | + | } | |
| 38 | + | ||
| 39 | + | fragColor = vec4(vec3(gray), pixColor.a); | |
| 40 | + | } | |
| @@ -0,0 +1,30 @@ | |||
| 1 | + | #version 300 es | |
| 2 | + | // Invert Colors Shader - OPTIMIZED | |
| 3 | + | // Added: Optional luminance-preserving mode | |
| 4 | + | ||
| 5 | + | precision highp float; | |
| 6 | + | ||
| 7 | + | in vec2 v_texcoord; | |
| 8 | + | uniform sampler2D tex; | |
| 9 | + | out vec4 fragColor; | |
| 10 | + | ||
| 11 | + | // Set true for "smart invert" that preserves relative brightness | |
| 12 | + | const bool PRESERVE_LUMINANCE = false; | |
| 13 | + | const vec3 LUMA = vec3(0.2126, 0.7152, 0.0722); | |
| 14 | + | ||
| 15 | + | void main() { | |
| 16 | + | vec4 color = texture(tex, v_texcoord); | |
| 17 | + | vec3 inverted = 1.0 - color.rgb; | |
| 18 | + | ||
| 19 | + | if (PRESERVE_LUMINANCE) { | |
| 20 | + | // Adjust inverted colors to match original luminance | |
| 21 | + | float origLuma = dot(color.rgb, LUMA); | |
| 22 | + | float invLuma = dot(inverted, LUMA); | |
| 23 | + | if (invLuma > 0.001) { | |
| 24 | + | inverted *= origLuma / invLuma; | |
| 25 | + | inverted = clamp(inverted, 0.0, 1.0); | |
| 26 | + | } | |
| 27 | + | } | |
| 28 | + | ||
| 29 | + | fragColor = vec4(inverted, color.a); | |
| 30 | + | } | |
| @@ -0,0 +1,39 @@ | |||
| 1 | + | #version 300 es | |
| 2 | + | // Posterization Shader - OPTIMIZED | |
| 3 | + | // Fixes: Proper rounding, optional dithering to reduce banding | |
| 4 | + | ||
| 5 | + | precision highp float; | |
| 6 | + | ||
| 7 | + | in vec2 v_texcoord; | |
| 8 | + | uniform sampler2D tex; | |
| 9 | + | out vec4 fragColor; | |
| 10 | + | ||
| 11 | + | // --- CONFIGURATION --- | |
| 12 | + | const float COLOR_LEVELS = 4.0; | |
| 13 | + | // Enable dithering to reduce visible banding | |
| 14 | + | const bool DITHER = true; | |
| 15 | + | ||
| 16 | + | // Simple dither pattern | |
| 17 | + | float dither(vec2 pos) { | |
| 18 | + | // 4x4 Bayer matrix approximation | |
| 19 | + | vec2 p = fract(pos * 0.5); | |
| 20 | + | float d = fract(dot(p, vec2(0.75, 0.5))); | |
| 21 | + | return (d - 0.5) / COLOR_LEVELS; | |
| 22 | + | } | |
| 23 | + | ||
| 24 | + | void main() { | |
| 25 | + | vec4 color = texture(tex, v_texcoord); | |
| 26 | + | ||
| 27 | + | vec3 posterized; | |
| 28 | + | if (DITHER) { | |
| 29 | + | // Add dither noise before quantization | |
| 30 | + | float ditherValue = dither(gl_FragCoord.xy); | |
| 31 | + | posterized = floor((color.rgb + ditherValue) * COLOR_LEVELS + 0.5) / COLOR_LEVELS; | |
| 32 | + | } else { | |
| 33 | + | // FIXED: Use round() behavior instead of floor() for better color accuracy | |
| 34 | + | posterized = floor(color.rgb * COLOR_LEVELS + 0.5) / COLOR_LEVELS; | |
| 35 | + | } | |
| 36 | + | ||
| 37 | + | posterized = clamp(posterized, 0.0, 1.0); | |
| 38 | + | fragColor = vec4(posterized, color.a); | |
| 39 | + | } | |
| @@ -0,0 +1,33 @@ | |||
| 1 | + | #version 300 es | |
| 2 | + | // Sepia Tone Shader - OPTIMIZED | |
| 3 | + | // Fixes: Clamping to prevent overflow on bright pixels | |
| 4 | + | ||
| 5 | + | precision highp float; | |
| 6 | + | ||
| 7 | + | in vec2 v_texcoord; | |
| 8 | + | uniform sampler2D tex; | |
| 9 | + | out vec4 fragColor; | |
| 10 | + | ||
| 11 | + | // W3C standard Sepia Matrix (column-major for GLSL) | |
| 12 | + | const mat3 SEPIA_MATRIX = mat3( | |
| 13 | + | 0.393, 0.769, 0.189, // Red output weights | |
| 14 | + | 0.349, 0.686, 0.168, // Green output weights | |
| 15 | + | 0.272, 0.534, 0.131 // Blue output weights | |
| 16 | + | ); | |
| 17 | + | ||
| 18 | + | // Sepia intensity (0.0 = no effect, 1.0 = full sepia) | |
| 19 | + | const float INTENSITY = 1.0; | |
| 20 | + | ||
| 21 | + | void main() { | |
| 22 | + | vec4 color = texture(tex, v_texcoord); | |
| 23 | + | ||
| 24 | + | vec3 sepia = color.rgb * SEPIA_MATRIX; | |
| 25 | + | ||
| 26 | + | // FIXED: Clamp to prevent overflow artifacts on bright pixels | |
| 27 | + | sepia = clamp(sepia, 0.0, 1.0); | |
| 28 | + | ||
| 29 | + | // Optional: blend with original for partial effect | |
| 30 | + | vec3 final = mix(color.rgb, sepia, INTENSITY); | |
| 31 | + | ||
| 32 | + | fragColor = vec4(final, color.a); | |
| 33 | + | } | |
| @@ -0,0 +1,37 @@ | |||
| 1 | + | #version 300 es | |
| 2 | + | // Vignette Shader - OPTIMIZED | |
| 3 | + | // Fixes: Aspect ratio correction for circular vignette, safe smoothstep bounds | |
| 4 | + | ||
| 5 | + | precision highp float; | |
| 6 | + | ||
| 7 | + | in vec2 v_texcoord; | |
| 8 | + | uniform sampler2D tex; | |
| 9 | + | out vec4 fragColor; | |
| 10 | + | ||
| 11 | + | // --- CONFIGURATION --- | |
| 12 | + | const float RADIUS = 0.65; | |
| 13 | + | const float SOFTNESS = 0.45; | |
| 14 | + | const float STRENGTH = 0.5; | |
| 15 | + | // Set to your monitor's aspect ratio for circular vignette | |
| 16 | + | const float ASPECT_RATIO = 16.0 / 9.0; | |
| 17 | + | ||
| 18 | + | void main() { | |
| 19 | + | vec4 color = texture(tex, v_texcoord); | |
| 20 | + | ||
| 21 | + | // FIXED: Aspect-corrected distance for circular (not elliptical) vignette | |
| 22 | + | vec2 centered = v_texcoord - 0.5; | |
| 23 | + | centered.x *= ASPECT_RATIO; | |
| 24 | + | float dist = length(centered); | |
| 25 | + | // Normalize so corner distance is ~1.0 regardless of aspect ratio | |
| 26 | + | dist /= length(vec2(ASPECT_RATIO * 0.5, 0.5)); | |
| 27 | + | ||
| 28 | + | // FIXED: Ensure smoothstep has valid bounds (edge1 > edge0) | |
| 29 | + | float innerEdge = RADIUS; | |
| 30 | + | float outerEdge = RADIUS + SOFTNESS; | |
| 31 | + | float vignette = 1.0 - smoothstep(innerEdge, outerEdge, dist); | |
| 32 | + | ||
| 33 | + | // Apply with strength control | |
| 34 | + | color.rgb = mix(color.rgb, color.rgb * vignette, STRENGTH); | |
| 35 | + | ||
| 36 | + | fragColor = color; | |
| 37 | + | } | |
| @@ -0,0 +1,35 @@ | |||
| 1 | + | #version 300 es | |
| 2 | + | // Anaglyph 3D Shader - OPTIMIZED | |
| 3 | + | // Fixes: Edge clamping, alpha preservation, depth-aware separation | |
| 4 | + | ||
| 5 | + | precision highp float; | |
| 6 | + | ||
| 7 | + | in vec2 v_texcoord; | |
| 8 | + | uniform sampler2D tex; | |
| 9 | + | out vec4 fragColor; | |
| 10 | + | ||
| 11 | + | // --- CONFIGURATION --- | |
| 12 | + | const float SEPARATION = 0.003; | |
| 13 | + | // Make separation stronger at edges (simulates depth from screen curvature) | |
| 14 | + | const bool DEPTH_AWARE = true; | |
| 15 | + | ||
| 16 | + | void main() { | |
| 17 | + | vec2 offset = vec2(SEPARATION, 0.0); | |
| 18 | + | ||
| 19 | + | // Optional: Increase separation toward screen edges for more depth | |
| 20 | + | if (DEPTH_AWARE) { | |
| 21 | + | float edgeFactor = abs(v_texcoord.x - 0.5) * 2.0; // 0 at center, 1 at edges | |
| 22 | + | offset.x *= 1.0 + edgeFactor * 0.5; | |
| 23 | + | } | |
| 24 | + | ||
| 25 | + | // Clamp coordinates to prevent edge sampling artifacts | |
| 26 | + | vec2 leftCoord = clamp(v_texcoord - offset, 0.0, 1.0); | |
| 27 | + | vec2 rightCoord = clamp(v_texcoord + offset, 0.0, 1.0); | |
| 28 | + | ||
| 29 | + | vec4 leftEye = texture(tex, leftCoord); | |
| 30 | + | vec4 rightEye = texture(tex, rightCoord); | |
| 31 | + | vec4 center = texture(tex, v_texcoord); | |
| 32 | + | ||
| 33 | + | // Combine: Red from left, Cyan (GB) from right | |
| 34 | + | fragColor = vec4(leftEye.r, rightEye.g, rightEye.b, center.a); | |
| 35 | + | } | |
| @@ -0,0 +1,37 @@ | |||
| 1 | + | #version 300 es | |
| 2 | + | // Vignette Shader for Hyprland | |
| 3 | + | // Description: Darkens the edges of the screen to draw focus to the center. | |
| 4 | + | // Uses smoothstep for a high-quality, organic falloff. | |
| 5 | + | ||
| 6 | + | precision highp float; | |
| 7 | + | ||
| 8 | + | in vec2 v_texcoord; | |
| 9 | + | uniform sampler2D tex; | |
| 10 | + | out vec4 fragColor; | |
| 11 | + | ||
| 12 | + | // --- CONFIGURATION --- | |
| 13 | + | // The radius where the darkening begins (0.0 is center, 0.8 is near corners) | |
| 14 | + | const float RADIUS = 0.85; | |
| 15 | + | // How soft the transition is (higher = smoother gradient) | |
| 16 | + | const float SOFTNESS = 0.85; | |
| 17 | + | // The strength of the darkness (0.0 = no vignette, 1.0 = pitch black corners) | |
| 18 | + | const float STRENGTH = 0.8; | |
| 19 | + | ||
| 20 | + | void main() { | |
| 21 | + | // 1. Sample the original screen color | |
| 22 | + | vec4 color = texture(tex, v_texcoord); | |
| 23 | + | ||
| 24 | + | // 2. Calculate distance from center (0.5, 0.5) | |
| 25 | + | float dist = distance(v_texcoord, vec2(0.5)); | |
| 26 | + | ||
| 27 | + | // 3. Calculate vignette factor using smoothstep for high-quality falloff | |
| 28 | + | // We invert the smoothstep range so 1.0 is center and 0.0 is edges | |
| 29 | + | float vignette = smoothstep(RADIUS, RADIUS - SOFTNESS, dist); | |
| 30 | + | ||
| 31 | + | // 4. Apply the vignette strength | |
| 32 | + | // Mix between the original color and the darkened version | |
| 33 | + | // This allows us to control intensity without changing the geometry of the falloff | |
| 34 | + | color.rgb = mix(color.rgb, color.rgb * vignette, STRENGTH); | |
| 35 | + | ||
| 36 | + | fragColor = color; | |
| 37 | + | } | |
| @@ -0,0 +1,40 @@ | |||
| 1 | + | #version 300 es | |
| 2 | + | // Saturation & Contrast Shader for Hyprland | |
| 3 | + | // Description: Allows fine-tuning of screen vibrancy and dynamic range. | |
| 4 | + | // Efficiently applies saturation followed by contrast. | |
| 5 | + | ||
| 6 | + | precision highp float; | |
| 7 | + | ||
| 8 | + | in vec2 v_texcoord; | |
| 9 | + | uniform sampler2D tex; | |
| 10 | + | out vec4 fragColor; | |
| 11 | + | ||
| 12 | + | // --- CONFIGURATION --- | |
| 13 | + | // 0.0 = Grayscale, 1.0 = Normal, 1.5 = Vibrant, 2.0 = Deep Fried | |
| 14 | + | const float SATURATION = 3.0; | |
| 15 | + | ||
| 16 | + | // 1.0 = Normal, 1.2 = High Contrast, 0.8 = Low Contrast (Faded) | |
| 17 | + | const float CONTRAST = 1.0; | |
| 18 | + | // --------------------- | |
| 19 | + | ||
| 20 | + | // Rec. 709 Luma coefficients for accurate saturation calculations | |
| 21 | + | const vec3 luma = vec3(0.2126, 0.7152, 0.0722); | |
| 22 | + | ||
| 23 | + | void main() { | |
| 24 | + | // 1. Sample texture | |
| 25 | + | vec4 color = texture(tex, v_texcoord); | |
| 26 | + | ||
| 27 | + | // 2. Apply Saturation | |
| 28 | + | // Calculate the grayscale value (luminance) | |
| 29 | + | float gray = dot(color.rgb, luma); | |
| 30 | + | // Interpolate between grayscale and original color | |
| 31 | + | vec3 satColor = mix(vec3(gray), color.rgb, SATURATION); | |
| 32 | + | ||
| 33 | + | // 3. Apply Contrast | |
| 34 | + | // We shift color values so 0.5 is the "pivot" point. | |
| 35 | + | // Values > 0.5 get pushed up, values < 0.5 get pushed down. | |
| 36 | + | vec3 finalColor = (satColor - 0.5) * CONTRAST + 0.5; | |
| 37 | + | ||
| 38 | + | // 4. Output | |
| 39 | + | fragColor = vec4(finalColor, color.a); | |
| 40 | + | } | |
| @@ -76,18 +76,24 @@ bind = $mainMod SHIFT, S, movetoworkspace, special:magic | |||
| 76 | 76 | workspace = special:h, on-created-empty: $terminal | |
| 77 | 77 | bind = $mainMod SHIFT, Return, togglespecialworkspace, h | |
| 78 | 78 | ||
| 79 | − | # Screen Rotate | |
| 80 | − | bindld = CTRL ALT, R, Rotate Screen Clockwise, exec, hypr_screen_rotate.sh -90 | |
| 81 | − | bindld = CTRL ALT SHIFT, R, Rotate Screen Anti-Clockwise, exec, hypr_screen_rotate.sh +90 | |
| 82 | 79 | ||
| 83 | 80 | # Accessibility: Zoom | |
| 84 | 81 | cursor:zoom_disable_aa = true | |
| 85 | 82 | # Zoom In | |
| 86 | − | binded = SUPER SHIFT, equal, Zoom In, exec, sh -c "hyprctl keyword cursor:zoom_factor \"$(hyprctl getoption cursor:zoom_factor | awk 'NR==1 {print $2 * 1.25}')\"" | |
| 83 | + | binded = SUPER, equal, Zoom In, exec, sh -c "hyprctl keyword cursor:zoom_factor \"$(hyprctl getoption cursor:zoom_factor | awk 'NR==1 {print $2 * 1.25}')\"" | |
| 87 | 84 | # Zoom Out | |
| 88 | − | binded = SUPER SHIFT, minus, Zoom Out, exec, sh -c "hyprctl keyword cursor:zoom_factor \"$(hyprctl getoption cursor:zoom_factor | awk 'NR==1 {val = $2 / 1.25; if (val < 1.0) val = 1.0; print val}')\"" | |
| 85 | + | binded = SUPER, minus, Zoom Out, exec, sh -c "hyprctl keyword cursor:zoom_factor \"$(hyprctl getoption cursor:zoom_factor | awk 'NR==1 {val = $2 / 1.25; if (val < 1.0) val = 1.0; print val}')\"" | |
| 89 | 86 | # Reset Zoom | |
| 90 | − | bindld = SUPER SHIFT, BACKSPACE, Reset Zoom, exec, hyprctl keyword cursor:zoom_factor 1.0 | |
| 87 | + | bindld = SUPER, BACKSPACE, Reset Zoom, exec, hyprctl keyword cursor:zoom_factor 1.0 | |
| 88 | + | ||
| 89 | + | # Screen Rotate | |
| 90 | + | bindld = $mainMod CTRL, comma, Rotate Screen Anti-Clockwise, exec, hypr_screen_rotate.sh +90 | |
| 91 | + | bindld = $mainMod CTRL, period, Rotate Screen Clockwise, exec, hypr_screen_rotate.sh -90 | |
| 92 | + | ||
| 93 | + | # --- Hyprshade (Visual Filters) --- | |
| 94 | + | bindd = $mainMod CTRL, S, Shader Menu, exec, hypr_shader_menu.sh | |
| 95 | + | bindld = $mainMod CTRL, X, Disable Shader, exec, hyprshade off | |
| 96 | + | bindld = $mainMod CTRL, V, Vibrant Shader, exec, hyprshade on vibrance | |
| 91 | 97 | ||
| 92 | 98 | # Scroll through existing workspaces with mainMod + scroll | |
| 93 | 99 | bind = $mainMod, mouse_down, workspace, e+1 | |
| @@ -107,6 +107,7 @@ | |||
| 107 | 107 | "format-alt": "{icon} ", | |
| 108 | 108 | "format-good": "{icon} {capacity:3}%", | |
| 109 | 109 | "format-full": "{icon} {capacity:3}%", | |
| 110 | + | "tooltip-format": "{timeTo}\nHealth: {health}%\nPower Draw: {power:.2f} W\nCycles: {cycles}\n\nLMB: Toggle Format\nRMB: Timeout Settings", | |
| 110 | 111 | "format-icons": [ | |
| 111 | 112 | "", | |
| 112 | 113 | "", | |
| @@ -0,0 +1,31 @@ | |||
| 1 | + | #!/usr/bin/env bash | |
| 2 | + | set -euo pipefail | |
| 3 | + | ||
| 4 | + | # Check deps | |
| 5 | + | command -v fuzzel >/dev/null || { echo "fuzzel not found"; exit 1; } | |
| 6 | + | command -v hyprshade >/dev/null || { echo "hyprshade not found"; exit 1; } | |
| 7 | + | ||
| 8 | + | # Get shader list | |
| 9 | + | mapfile -t SHADERS < <(hyprshade ls) | |
| 10 | + | ||
| 11 | + | # Add "off" at top | |
| 12 | + | SHADERS=("off" "${SHADERS[@]}") | |
| 13 | + | ||
| 14 | + | # Show in fuzzel | |
| 15 | + | CHOICE=$(printf "%s\n" "${SHADERS[@]}" \ | |
| 16 | + | | fuzzel --dmenu --prompt "Hyprshade > " \ | |
| 17 | + | | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') | |
| 18 | + | ||
| 19 | + | # User cancelled | |
| 20 | + | [[ -z "$CHOICE" ]] && exit 0 | |
| 21 | + | ||
| 22 | + | # Apply | |
| 23 | + | if [[ "$CHOICE" == "off" ]]; then | |
| 24 | + | hyprshade off | |
| 25 | + | else | |
| 26 | + | hyprshade on "$CHOICE" | |
| 27 | + | fi | |
| 28 | + | ||
| 29 | + | # Optional notification | |
| 30 | + | command -v notify-send >/dev/null && notify-send "Hyprshade" "Applied: $CHOICE" | |
| 31 | + | ||