tedit/shaders/saturation.frag
2025-04-07 20:08:16 -04:00

44 lines
1.4 KiB
GLSL

#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
uniform sampler2D InputTexture;
uniform float saturationValue; // -100 (grayscale) to 100 (double sat)
// Perceptual luminance weights (Rec. 709)
const vec3 luminanceWeight = vec3(0.2126, 0.7152, 0.0722);
vec3 applySaturation(vec3 color, float saturation) {
// Get original luminance
float lum = dot(color, luminanceWeight);
// Skip processing for very dark or very bright pixels
if (lum < 0.001 || lum > 0.999) return color;
// Non-linear saturation response curve (more natural-looking)
float factor;
if (saturation >= 0.0) {
// Positive saturation with highlight protection
factor = 1.0 + (saturation / 100.0) * (1.0 - 0.3 * smoothstep(0.7, 1.0, lum));
} else {
// Negative saturation with shadow protection
factor = 1.0 + (saturation / 100.0) * (1.0 - 0.1 * smoothstep(0.0, 0.2, lum));
}
// Apply saturation while preserving luminance
vec3 adjusted = mix(vec3(lum), color, factor);
// Ensure we maintain original luminance exactly
float newLum = dot(adjusted, luminanceWeight);
return adjusted * (lum / max(newLum, 0.001));
}
void main() {
vec4 color = texture(InputTexture, TexCoord);
// Apply saturation
color.rgb = applySaturation(color.rgb, saturationValue);
// Proper clamping to valid range
FragColor = vec4(clamp(color.rgb, 0.0, 1.0), color.a);
}