Constant HUE_SHIFT

Source
const HUE_SHIFT: &str = r#"
vec3 fx_rgb2hsl(vec3 c) {
    float mx = max(c.r, max(c.g, c.b));
    float mn = min(c.r, min(c.g, c.b));
    float l = (mx + mn) * 0.5;
    float h = 0.0;
    float s = 0.0;
    float d = mx - mn;
    if (d > 1e-5) {
        s = d / max(1.0 - abs(2.0 * l - 1.0), 1e-5);
        if (mx == c.r) {
            h = mod((c.g - c.b) / d, 6.0);
        } else if (mx == c.g) {
            h = (c.b - c.r) / d + 2.0;
        } else {
            h = (c.r - c.g) / d + 4.0;
        }
        h /= 6.0;
    }
    return vec3(h, s, l);
}
float fx_h2c(float a, float b, float t) {
    float u = fract(t);
    if (u < 1.0 / 6.0) return a + (b - a) * 6.0 * u;
    if (u < 0.5) return b;
    if (u < 2.0 / 3.0) return a + (b - a) * (2.0 / 3.0 - u) * 6.0;
    return a;
}
vec3 fx_hsl2rgb(vec3 hsl) {
    float l = clamp(hsl.z, 0.0, 1.0);
    float s = clamp(hsl.y, 0.0, 1.0);
    if (s <= 0.0) return vec3(l);
    float q = l < 0.5 ? l * (1.0 + s) : l + s - l * s;
    float a = 2.0 * l - q;
    return vec3(fx_h2c(a, q, hsl.x + 1.0 / 3.0), fx_h2c(a, q, hsl.x), fx_h2c(a, q, hsl.x - 1.0 / 3.0));
}
void main() {
    vec2 uv = gl_FragCoord.xy / u_res;
    vec4 src = texture(tex, uv);
    vec3 hsl = fx_rgb2hsl(clamp(src.rgb, 0.0, 1.0));
    hsl.x = fract(hsl.x + p0 / 360.0);
    hsl.y = clamp(hsl.y * max(p1, 0.0), 0.0, 1.0);
    hsl.z = clamp(hsl.z + p2, 0.0, 1.0);
    vec4 res = vec4(clamp(fx_hsl2rgb(hsl), 0.0, 1.0), src.a);
    float m = u_has_mask > 0.5 ? texture(u_mask, uv).r : 1.0;
    out_color = mix(src, res, m);
}
"#;
Expand description

Hue rotate (p0 degrees), saturation multiply (p1) and lightness offset (p2) in HSL.