--- /dev/null
+#ifndef MSP_DEMOSCENE_FILMGRAIN_H_
+#define MSP_DEMOSCENE_FILMGRAIN_H_
+
+#include <msp/gl/mesh.h>
+#include <msp/gl/postprocessor.h>
+#include <msp/gl/program.h>
+#include <msp/gl/programdata.h>
+#include <msp/gl/texture2darray.h>
+#include <msp/gl/texturing.h>
+
+namespace Msp {
+namespace DemoScene {
+
+class FilmGrain: public GL::PostProcessor
+{
+public:
+ struct Template: public PostProcessor::Template
+ {
+ class Loader: public DataFile::DerivedObjectLoader<Template, PostProcessor::Template::Loader>
+ {
+ 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