From 1e3954a988c6d6d946260019f25a4ad3262e01c4 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 14 Jun 2019 23:25:52 +0300 Subject: [PATCH] Add a vignette postprocessor All real cameras have some amount of vignetting, so adding some to the rendered scene makes it feel more real. --- data/vignette.glsl | 32 +++++++++++++++++++ source/launcher.cpp | 4 +++ source/vignette.cpp | 76 +++++++++++++++++++++++++++++++++++++++++++++ source/vignette.h | 52 +++++++++++++++++++++++++++++++ 4 files changed, 164 insertions(+) create mode 100644 data/vignette.glsl create mode 100644 source/vignette.cpp create mode 100644 source/vignette.h diff --git a/data/vignette.glsl b/data/vignette.glsl new file mode 100644 index 0000000..58822c4 --- /dev/null +++ b/data/vignette.glsl @@ -0,0 +1,32 @@ +import postprocess; + +uniform Vignette +{ + vec2 coord_scale; + vec4 optical; + vec2 optical_range; + float natural; +}; + +#pragma MSP stage(fragment) +void main() +{ + vec4 incoming = texture(source, texcoord); + vec2 r = vertex.xy*coord_scale; + float r_sq = dot(r, r); + + float vignette = 1.0; + if(r_sq>=optical_range.y) + vignette = 0.0; + else if(r_sq>=optical_range.x) + { + float r = sqrt(r_sq)-optical.x; + float v = (optical.z*acos(r/optical.y)-sqrt(optical.z-r*r)*r); + vignette = v/optical.w; + } + + float c_sq = 1/(1+r_sq*natural); + vignette *= c_sq*c_sq; + + frag_color = vec4(incoming.rgb*vignette, incoming.a); +} diff --git a/source/launcher.cpp b/source/launcher.cpp index bad077d..7dc9b98 100644 --- a/source/launcher.cpp +++ b/source/launcher.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -8,6 +9,7 @@ #include "demo.h" #include "launcher.h" #include "launchscreen.h" +#include "vignette.h" using namespace std; @@ -102,6 +104,8 @@ LauncherBase::LauncherBase(int argc, char **argv): gl_context.set_swap_interval(options.no_vsync ? 0 : 1); window.signal_close.connect(sigc::bind(sigc::mem_fun(this, &LauncherBase::exit), 0)); keyboard.signal_button_press.connect(sigc::bind_return(sigc::mem_fun(this, &LauncherBase::key_press), false)); + + GL::PipelineTemplate::register_postprocessor("vignette"); } LauncherBase::~LauncherBase() diff --git a/source/vignette.cpp b/source/vignette.cpp new file mode 100644 index 0000000..e4d7de8 --- /dev/null +++ b/source/vignette.cpp @@ -0,0 +1,76 @@ +#include +#include +#include +#include +#include "resources.h" +#include "vignette.h" + +using namespace std; + +namespace Msp { +namespace DemoScene { + +Vignette::Vignette(float aspect): + mesh(get_fullscreen_quad()), + shprog(Resources::get_builtins().get("vignette.glsl")) +{ + shdata.uniform("coord_scale", min(aspect, 1.0f), min(1.0f/aspect, 1.0f)); + set_optical(1.0f, 0.5f); + set_natural(1.0f, 1.0f); +} + +void Vignette::set_optical(float pupil, float aperture) +{ + if(pupil<0.0f || aperture<0.0f || aperture>pupil) + throw std::invalid_argument("Vignette::set_optical"); + + float p_sq = pupil*pupil; + float a_sq = aperture*aperture; + float two_ap = 2*pupil*aperture; + shdata.uniform("optical", pupil, aperture, a_sq, a_sq*M_PI); + shdata.uniform("optical_range", p_sq-two_ap+a_sq, p_sq+two_ap+a_sq); +} + +void Vignette::set_natural(float radius, float darkening) +{ + if(radius<=0.0f || darkening<0.0f) + throw std::invalid_argument("Vignette::set_natural"); + + float v = pow(2.0f, -darkening); + float t_sq = 1/sqrt(v)-1; + shdata.uniform("natural", t_sq/(radius*radius)); +} + +void Vignette::render(GL::Renderer &renderer, const GL::Texture2D &color, const GL::Texture2D &) +{ + renderer.set_texture(&color); + renderer.set_shader_program(&shprog, &shdata); + mesh.draw(renderer); +} + + +Vignette::Template::Template(): + pupil(1.0f), + aperture(0.5f), + radius(1.0f), + darkening(1.0f) +{ } + +Vignette *Vignette::Template::create(unsigned w, unsigned h) const +{ + Vignette *vign = new Vignette(static_cast(w)/h); + vign->set_optical(pupil, aperture); + vign->set_natural(radius, darkening); + return vign; +} + + +Vignette::Template::Loader::Loader(Template &t): + DerivedObjectLoader(t) +{ + add("optical", &Template::pupil, &Template::aperture); + add("natural", &Template::radius, &Template::darkening); +} + +} // namespace DemoScene +} // namespace Msp diff --git a/source/vignette.h b/source/vignette.h new file mode 100644 index 0000000..0cad6bf --- /dev/null +++ b/source/vignette.h @@ -0,0 +1,52 @@ +#ifndef MSP_DEMOSCENE_VIGNETTE_H_ +#define MSP_DEMOSCENE_VIGNETTE_H_ + +#include +#include +#include + +namespace Msp { +namespace DemoScene { + +class Vignette: public Msp::GL::PostProcessor +{ +public: + struct Template: PostProcessor::Template + { + class Loader: public Msp::DataFile::DerivedObjectLoader + { + public: + Loader(Template &); + }; + + float pupil; + float aperture; + float radius; + float darkening; + + Template(); + + virtual Vignette *create(unsigned, unsigned) const; + }; + +private: + const Msp::GL::Mesh &mesh; + const Msp::GL::Program &shprog; + Msp::GL::ProgramData shdata; + +public: + Vignette(float); + + void set_optical(float, float); + void set_natural(float, float); +private: + void update_shdata(); + +public: + virtual void render(Msp::GL::Renderer &, const Msp::GL::Texture2D &, const Msp::GL::Texture2D &); +}; + +} // namespace DemoScene +} // namespace Msp + +#endif -- 2.43.0