51 lines
2.1 KiB
GLSL
51 lines
2.1 KiB
GLSL
#version 330 core
|
|
out vec4 FragColor;
|
|
in vec2 TexCoord;
|
|
|
|
uniform sampler2D InputTexture;
|
|
uniform float whitesValue; // -100 (pull down) to 100 (push up)
|
|
uniform float blacksValue; // -100 (lift up) to 100 (push down)
|
|
|
|
const vec3 luminanceWeight = vec3(0.2126, 0.7152, 0.0722);
|
|
|
|
// Helper function to preserve color relationships when adjusting luminance
|
|
vec3 preserveColor(vec3 color, float newLum) {
|
|
float oldLum = dot(color, luminanceWeight);
|
|
return oldLum > 0.0 ? color * (newLum / oldLum) : vec3(newLum);
|
|
}
|
|
|
|
vec3 applyWhitesBlacks(vec3 color, float whites, float blacks) {
|
|
float lum = dot(color, luminanceWeight);
|
|
|
|
// Map slider values to more appropriate adjustment strengths
|
|
float whitesStrength = whites / 100.0;
|
|
float blacksStrength = blacks / 100.0;
|
|
|
|
// Create better perceptual masks with wider, smoother influence
|
|
// Whites affect primarily highlights but have some influence into midtones
|
|
float whiteMask = smoothstep(0.25, 1.0, lum);
|
|
whiteMask = pow(whiteMask, 2.0 - max(0.0, whitesStrength)); // Dynamic falloff
|
|
|
|
// Blacks affect primarily shadows but have some influence into midtones
|
|
float blackMask = 1.0 - smoothstep(0.0, 0.5, lum);
|
|
blackMask = pow(blackMask, 2.0 - max(0.0, -blacksStrength)); // Dynamic falloff
|
|
|
|
// Calculate adjustment curves with proper toe/shoulder response
|
|
float whitesAdj = 1.0 + whitesStrength * whiteMask * (1.0 - pow(1.0 - whiteMask, 3.0));
|
|
float blacksAdj = 1.0 - blacksStrength * blackMask * (1.0 - pow(1.0 - blackMask, 3.0));
|
|
|
|
// Apply adjustments with color preservation
|
|
float adjustedLum = lum * whitesAdj * blacksAdj;
|
|
adjustedLum = clamp(adjustedLum, 0.0, 2.0); // Allow some headroom for highlights
|
|
|
|
// Preserve color relationships by scaling RGB proportionally
|
|
vec3 result = preserveColor(color, adjustedLum);
|
|
|
|
return result;
|
|
}
|
|
|
|
void main() {
|
|
vec4 color = texture(InputTexture, TexCoord);
|
|
color.rgb = applyWhitesBlacks(color.rgb, whitesValue, blacksValue);
|
|
FragColor = vec4(max(color.rgb, vec3(0.0)), color.a); // Ensure non-negative
|
|
} |