From 444151a0c0c31eac99663c19dda87a7c543bee84 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 28 Nov 2016 23:31:19 +0200 Subject: [PATCH] Improve the color curve postprocessor --- shaderlib/colorcurve.glsl | 27 +++++++++++---------------- source/colorcurve.cpp | 26 +++++++++++++++++--------- source/colorcurve.h | 17 ++++++++++------- 3 files changed, 38 insertions(+), 32 deletions(-) diff --git a/shaderlib/colorcurve.glsl b/shaderlib/colorcurve.glsl index fa3ba510..63f63138 100644 --- a/shaderlib/colorcurve.glsl +++ b/shaderlib/colorcurve.glsl @@ -3,27 +3,22 @@ import postprocess; uniform sampler1D curve; uniform ToneMapping { - float peak; - float brightness; + float exposure; + vec3 brightness_response; }; ////// fragment void main() { - vec4 sample = texture(source, texcoord); - float maxc = max(sample.r, max(sample.g, sample.b)); - if(maxc>1.0-peak) + vec4 incoming = texture(source, texcoord); + float maxc = max(incoming.r, max(incoming.g, incoming.b)); + if(maxc>0.0) { - vec3 saturated = sample.rgb/maxc; - if(maxc>1.0+peak) - { - sample.rgb = mix(vec3(1.0), saturated, 1.0/pow(brightness, maxc-1.0-peak)); - } - else - { - float x = (1.0+peak-maxc)/(2.0*peak); - sample.rgb = saturated.rgb*(1.0-peak+(1.0-x*x)*peak); - } + vec3 saturated = incoming.rgb/maxc; + maxc = pow(maxc*exposure+brightness_response.y, brightness_response.x)-brightness_response.z; + float c = min(maxc, 1.0); + float minc = min(saturated.r, min(saturated.g, saturated.b)); + incoming.rgb = mix(saturated, vec3(1.0), min((maxc-c)/(1.0-minc), 1.0))*c; } - frag_color = vec4(texture(curve, sample.r).r, texture(curve, sample.g).r, texture(curve, sample.b).r, sample.a); + frag_color = vec4(texture(curve, incoming.r).r, texture(curve, incoming.g).r, texture(curve, incoming.b).r, incoming.a); } diff --git a/source/colorcurve.cpp b/source/colorcurve.cpp index 81b5a43e..f1c09030 100644 --- a/source/colorcurve.cpp +++ b/source/colorcurve.cpp @@ -23,23 +23,31 @@ ColorCurve::ColorCurve(): curve.set_wrap(CLAMP_TO_EDGE); texturing.attach(1, curve); - set_peak(0.2); - set_brightness(1.5); + set_exposure_adjust(0.0f); + set_brightness_response(0.4f); set_linear(); } -void ColorCurve::set_peak(float p) +void ColorCurve::set_exposure_adjust(float e) +{ + shdata.uniform("exposure", pow(2.0f, e)); +} + +void ColorCurve::set_brightness_response(float b) +{ + if(b<=0 || b>1) + throw invalid_argument("ColorCurve::set_brightness_response"); + float t = (b<1 ? pow(b, 1/(1-b)) : 0.0f); + shdata.uniform("brightness_response", b, t, pow(t, b)); +} + +void ColorCurve::set_peak(float) { - if(p<0 || p>1) - throw invalid_argument("ColorCurve::set_peak"); - shdata.uniform("peak", p); } void ColorCurve::set_brightness(float b) { - if(b<1) - throw invalid_argument("ColorCurve::set_brightness"); - shdata.uniform("brightness", b); + set_brightness_response(1/b); } void ColorCurve::set_gamma(float g) diff --git a/source/colorcurve.h b/source/colorcurve.h index 2b854bec..608af448 100644 --- a/source/colorcurve.h +++ b/source/colorcurve.h @@ -12,8 +12,8 @@ namespace GL { /** Processes oversaturated colors to preserve hues. When one color component -exceeds 1.0, the others are scaled towards white. A transition curve is also -applied near 1.0 to prevent the abrupt change in the gradient. +exceeds 1.0, the overflow is distributed to the other components, scaling the +color towards white. Gamma or sRGB correction can also be applied to the output. It can be used to improve color reproduction by performing lighting calculations in linear color @@ -31,12 +31,15 @@ private: public: ColorCurve(); - /// Sets the size of the peak zone. Must be between 0 and 1, inclusive. - void set_peak(float); + /** Set exposure adjustment in EV units. Positive values brighten the + image, negative values darken it. Zero is neutral. */ + void set_exposure_adjust(float); + + /** Sets the exponent of the */ + void set_brightness_response(float); - /** Sets brightness for oversaturated colors. Must be >= 1. Suggested - values are between 1.5 and 2.0; a value of 1.0 will clamp colors to the - saturated value. */ + // Deprecated functions + void set_peak(float); void set_brightness(float); /** Sets the gamma value used for mapping output colors. Allowed range is -- 2.43.0