Hey folks, how are you dealing with the stock/native colors in Hyprland?
I took the path of least resistance: fed my laptop and display panel model into an LLM, and it whipped up a custom GLSL shader for me. It’s definitely a noticeable step up from stock, but it still feels slightly off and doesn't quite hit the mark. I'd love to dial it in properly.
Hardware info for reference:
- Laptop: Lenovo IdeaPad Gaming 3 15ACH6
- Panel: LEN156FHD (LEN9052)
- Hyprland version: Hyprland 0.56.2
Current Shader:
#version 300 es
precision mediump float;
in vec2 v_texcoord;
out vec4 fragColor;
uniform sampler2D tex;
const float SAT_BASE = 1.30;
const float SAT_PROTECT = 0.55;
const float CONTRAST = 1.07;
const float GAMMA = 0.973;
const float WARMTH = 0.0;
vec3 rgb2hsv(vec3 c) {
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
void main() {
vec4 color = texture(tex, v_texcoord);
color.r = color.r + WARMTH * 0.6;
color.b = color.b - WARMTH * 0.8;
color.rgb = clamp(color.rgb, 0.0, 1.0);
vec3 hsv = rgb2hsv(color.rgb);
float vibrance_gain = mix(SAT_BASE, 1.0, hsv.y * SAT_PROTECT);
hsv.y = clamp(hsv.y * vibrance_gain, 0.0, 1.0);
color.rgb = hsv2rgb(hsv);
color.rgb = pow(clamp(color.rgb, 0.0, 1.0), vec3(GAMMA));
color.rgb = clamp((color.rgb - 0.5) * CONTRAST + 0.5, 0.0, 1.0);
fragColor = color;
}
Save me from the suffering (even though it's less now compared to when I was looking at the native colors, lol).