From 9a54442d865974ac8785988e7e740480e72ab24c Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 20 Aug 2012 23:30:51 +0300 Subject: [PATCH] Add a color curve post-processor --- source/colorcurve.cpp | 77 +++++++++++++++++++++++++++++++++++++++++++ source/colorcurve.h | 42 +++++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 source/colorcurve.cpp create mode 100644 source/colorcurve.h diff --git a/source/colorcurve.cpp b/source/colorcurve.cpp new file mode 100644 index 00000000..95c82491 --- /dev/null +++ b/source/colorcurve.cpp @@ -0,0 +1,77 @@ +#include "colorcurve.h" +#include "mesh.h" +#include "shader.h" +#include "texture2d.h" + +using namespace std; + +namespace { + +static const char fragment_src[] = + "uniform sampler2D texture;\n" + "uniform float peak;\n" + "uniform float brightness;\n" + "varying vec2 texcoord;\n" + "void main()\n" + "{\n" + " vec4 sample = texture2D(texture, texcoord);\n" + " float maxc = max(sample.r, max(sample.g, sample.b));\n" + " if(maxc>1.0-peak)\n" + " {\n" + " vec3 saturated = sample.rgb/maxc;\n" + " if(maxc>1.0+peak)\n" + " {\n" + " gl_FragColor.rgb = mix(vec3(1.0), saturated, 1.0/pow(brightness, maxc-1-peak));\n" + " }\n" + " else\n" + " {\n" + " float x = (1.0+peak-maxc)/(2.0*peak);\n" + " gl_FragColor.rgb = saturated.rgb*(1.0-peak+(1-x*x)*peak);\n" + " }\n" + " gl_FragColor.a = sample.a;\n" + " }\n" + " else\n" + " gl_FragColor = sample;\n" + "}"; + +} + +namespace Msp { +namespace GL { + +ColorCurve::ColorCurve(): + quad(get_fullscreen_quad()) +{ + shprog.attach_shader(get_fullscreen_vertex_shader()); + Shader *fs = new Shader(FRAGMENT_SHADER, fragment_src); + shprog.attach_shader_owned(fs); + shprog.link(); + + set_peak(0.2); + set_brightness(1.5); +} + +void ColorCurve::set_peak(float p) +{ + 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); +} + +void ColorCurve::render(const Texture2D &color_buf, const Texture2D &) +{ + Bind _bind_shader(shprog); + shdata.apply(); + Bind _bind_tex(color_buf); + quad.draw(); +} + +} // namespace GL +} // namespace Msp diff --git a/source/colorcurve.h b/source/colorcurve.h new file mode 100644 index 00000000..82a8526f --- /dev/null +++ b/source/colorcurve.h @@ -0,0 +1,42 @@ +#ifndef COLORCURVE_H_ +#define COLORCURVE_H_ + +#include "postprocessor.h" +#include "program.h" +#include "programdata.h" + +namespace Msp { +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. + +Only makes sense when used in an HDR framebuffer. +*/ +class ColorCurve: public PostProcessor +{ +private: + Program shprog; + ProgramData shdata; + const Mesh &quad; + +public: + ColorCurve(); + + /// Sets the size of the peak zone. Must be between 0 and 1, inclusive. + void set_peak(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. */ + void set_brightness(float); + + virtual void render(const Texture2D &, const Texture2D &); +}; + +} // namespace GL +} // namespace Msp + +#endif -- 2.45.2