From 77d0c7ac9e3ebe1cecaf0c84e1501d3b6459055f Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 15 Jun 2019 14:21:53 +0300 Subject: [PATCH] Add a film grain postprocessor --- data/filmgrain.glsl | 17 +++++ source/filmgrain.cpp | 156 +++++++++++++++++++++++++++++++++++++++++++ source/filmgrain.h | 63 +++++++++++++++++ source/launcher.cpp | 2 + 4 files changed, 238 insertions(+) create mode 100644 data/filmgrain.glsl create mode 100644 source/filmgrain.cpp create mode 100644 source/filmgrain.h diff --git a/data/filmgrain.glsl b/data/filmgrain.glsl new file mode 100644 index 0000000..9ae3d8f --- /dev/null +++ b/data/filmgrain.glsl @@ -0,0 +1,17 @@ +import postprocess; + +uniform sampler2DArray grain; +uniform GrainParams +{ + float coarseness; + float strength; +}; +uniform int grain_layer; + +#pragma MSP stage(fragment) +void main() +{ + vec3 gcoord = vec3(gl_FragCoord.xy/textureSize(grain, 0).xy/coarseness, grain_layer); + vec4 incoming = texture(source, texcoord); + frag_color = vec4(incoming.rgb*mix(1.0, texture(grain, gcoord).r, strength), incoming.a); +} diff --git a/source/filmgrain.cpp b/source/filmgrain.cpp new file mode 100644 index 0000000..151daf5 --- /dev/null +++ b/source/filmgrain.cpp @@ -0,0 +1,156 @@ +#include +#include +#include +#include "filmgrain.h" +#include "resources.h" + +using namespace std; + +namespace Msp { +namespace DemoScene { + +FilmGrain::FilmGrain(unsigned s, unsigned l): + mesh(get_fullscreen_quad()), + shprog(Resources::get_builtins().get("filmgrain.glsl")), + size(s), + layers(l), + current_layer(0) +{ + grain.set_min_filter(GL::LINEAR); + grain.set_mag_filter(GL::LINEAR); + grain.set_wrap(GL::REPEAT); + grain.storage(GL::R8, size, size, layers, 1); + + generate_grain(); + + texturing.attach(1, grain); + shdata.uniform("grain", 1); + + set_coarseness(2.0f); + set_strength(0.1f); +} + +void FilmGrain::generate_grain() +{ + UInt8 *data = new UInt8[size*size*layers]; + + unsigned noise_size = size/2; + UInt8 *noise = new UInt8[noise_size*noise_size]; + Int16 *dbuf = new Int16[3*noise_size*noise_size]; + minstd_rand random; + + for(unsigned i=0; i(current_layer)); + texturing.attach(0, color); + renderer.set_texturing(&texturing); + renderer.set_shader_program(&shprog, &shdata); + mesh.draw(renderer); +} + + +FilmGrain::Template::Template(): + size(256), + layers(16), + coarseness(2.0f), + strength(0.1f) +{ } + +FilmGrain *FilmGrain::Template::create(unsigned, unsigned) const +{ + FilmGrain *grain = new FilmGrain(size, layers); + grain->set_coarseness(coarseness); + grain->set_strength(strength); + return grain; +} + + +FilmGrain::Template::Loader::Loader(Template &t): + DerivedObjectLoader(t) +{ + add("coarseness", &Template::coarseness); + add("layers", &Template::layers); + add("size", &Template::size); + add("strength", &Template::strength); +} + +} // namespace DemoScene +} // namespace Msp diff --git a/source/filmgrain.h b/source/filmgrain.h new file mode 100644 index 0000000..810b9a4 --- /dev/null +++ b/source/filmgrain.h @@ -0,0 +1,63 @@ +#ifndef MSP_DEMOSCENE_FILMGRAIN_H_ +#define MSP_DEMOSCENE_FILMGRAIN_H_ + +#include +#include +#include +#include +#include +#include + +namespace Msp { +namespace DemoScene { + +class FilmGrain: public GL::PostProcessor +{ +public: + struct Template: public PostProcessor::Template + { + class Loader: public DataFile::DerivedObjectLoader + { + public: + Loader(Template &t); + }; + + unsigned size; + unsigned layers; + float coarseness; + float strength; + + Template(); + + virtual FilmGrain *create(unsigned, unsigned) const; + }; + +private: + const Msp::GL::Mesh &mesh; + const Msp::GL::Program &shprog; + Msp::GL::ProgramData shdata; + Msp::GL::Texturing texturing; + unsigned size; + unsigned layers; + Msp::GL::Texture2DArray grain; + unsigned current_layer; + +public: + FilmGrain(unsigned = 256, unsigned = 16); + +private: + void generate_grain(); + void bicubic2x(const UInt8 *, UInt8 *, Int16 *); + static UInt8 clamp(int); + +public: + void set_coarseness(float); + void set_strength(float); + + virtual void render(GL::Renderer &, const GL::Texture2D &, const GL::Texture2D &); +}; + +} // namespace DemoScene +} // namespace Msp + +#endif diff --git a/source/launcher.cpp b/source/launcher.cpp index 7dc9b98..aefa1be 100644 --- a/source/launcher.cpp +++ b/source/launcher.cpp @@ -7,6 +7,7 @@ #include #include #include "demo.h" +#include "filmgrain.h" #include "launcher.h" #include "launchscreen.h" #include "vignette.h" @@ -105,6 +106,7 @@ LauncherBase::LauncherBase(int argc, char **argv): 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("film_grain"); GL::PipelineTemplate::register_postprocessor("vignette"); } -- 2.43.0