]> git.tdb.fi Git - libs/demoscene.git/commitdiff
Add a vignette postprocessor
authorMikko Rasa <tdb@tdb.fi>
Fri, 14 Jun 2019 20:25:52 +0000 (23:25 +0300)
committerMikko Rasa <tdb@tdb.fi>
Fri, 14 Jun 2019 21:21:22 +0000 (00:21 +0300)
All real cameras have some amount of vignetting, so adding some to the
rendered scene makes it feel more real.

data/vignette.glsl [new file with mode: 0644]
source/launcher.cpp
source/vignette.cpp [new file with mode: 0644]
source/vignette.h [new file with mode: 0644]

diff --git a/data/vignette.glsl b/data/vignette.glsl
new file mode 100644 (file)
index 0000000..58822c4
--- /dev/null
@@ -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);
+}
index bad077d03fa5df6fc29cb25d8ca2b4e82b0b5fb0..7dc9b9830eb0169148a3870f38a04cce7ab50011 100644 (file)
@@ -1,5 +1,6 @@
 #include <cmath>
 #include <msp/core/getopt.h>
+#include <msp/gl/pipelinetemplate.h>
 #include <msp/input/keys.h>
 #include <msp/io/console.h>
 #include <msp/io/file.h>
@@ -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>("vignette");
 }
 
 LauncherBase::~LauncherBase()
diff --git a/source/vignette.cpp b/source/vignette.cpp
new file mode 100644 (file)
index 0000000..e4d7de8
--- /dev/null
@@ -0,0 +1,76 @@
+#include <algorithm>
+#include <msp/gl/mesh.h>
+#include <msp/gl/renderer.h>
+#include <msp/gl/texture2d.h>
+#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<GL::Program>("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<float>(w)/h);
+       vign->set_optical(pupil, aperture);
+       vign->set_natural(radius, darkening);
+       return vign;
+}
+
+
+Vignette::Template::Loader::Loader(Template &t):
+       DerivedObjectLoader<Template, PostProcessor::Template::Loader>(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 (file)
index 0000000..0cad6bf
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef MSP_DEMOSCENE_VIGNETTE_H_
+#define MSP_DEMOSCENE_VIGNETTE_H_
+
+#include <msp/gl/postprocessor.h>
+#include <msp/gl/program.h>
+#include <msp/gl/programdata.h>
+
+namespace Msp {
+namespace DemoScene {
+
+class Vignette: public Msp::GL::PostProcessor
+{
+public:
+       struct Template: PostProcessor::Template
+       {
+               class Loader: public Msp::DataFile::DerivedObjectLoader<Template, PostProcessor::Template::Loader>
+               {
+               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