From: Mikko Rasa Date: Tue, 30 Nov 2010 14:38:11 +0000 (+0000) Subject: Give both color and depth buffers to postprocessors X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=c216893af147042e40c389e2530e71277c343044 Give both color and depth buffers to postprocessors Add SSAO postprocessor --- diff --git a/source/ambientocclusion.cpp b/source/ambientocclusion.cpp new file mode 100644 index 00000000..a3d8894c --- /dev/null +++ b/source/ambientocclusion.cpp @@ -0,0 +1,166 @@ +/* $Id$ + +This file is part of libmspgl +Copyright © 2010 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include +#include "ambientocclusion.h" +#include "blend.h" +#include "meshbuilder.h" +#include "tests.h" + +namespace { + +const char vertex_shader[] = + "varying vec2 texcoord;\n" + "void main()\n" + "{\n" + " gl_Position = gl_Vertex;\n" + " texcoord = gl_Vertex.xy*0.5+0.5;\n" + "}\n"; + +const char occlude_fs[] = + "uniform sampler2D depth;\n" + "uniform sampler2D rotate;\n" + "uniform vec2 screen_size;\n" + "uniform vec2 depth_ratio;\n" + "uniform float darkness;\n" + "varying vec2 texcoord;\n" + "void main()\n" + "{\n" + " mat2 transform = mat2(texture2D(rotate, texcoord*screen_size/4.0)*2.0-1.0)\n" + " *mat2(screen_size.y/screen_size.x, 0.0, 0.0, 1.0)*0.02;\n" + " float depth_avg = 0.0;\n" + " for(int i=0; i<=3; ++i)\n" + " for(int j=0; j<=3; ++j)\n" + " {\n" + " vec2 offs = transform*vec2(float(i)-1.5, float(j)-1.5);\n" + " depth_avg += depth_ratio.x/(texture2D(depth, texcoord+offs).r-depth_ratio.y);\n" + " }\n" + " depth_avg /= 16;\n" + " float sample = depth_ratio.x/(texture2D(depth, texcoord).r-depth_ratio.y);\n" + " float diff = sample-depth_avg;\n" + " float shade = min(diff*darkness, 0.0)+1.0;\n" + " gl_FragColor = vec4(shade, 0.0, 0.0, 1.0);\n" + "}\n"; + +const char combine_fs[] = + "uniform sampler2D color;\n" + "uniform sampler2D depth;\n" + "uniform sampler2D occlusion;\n" + "uniform vec2 screen_size;\n" + "uniform vec2 depth_ratio;\n" + "uniform float edge_threshold;\n" + "varying vec2 texcoord;\n" + "void main()\n" + "{\n" + " float sample = depth_ratio.x/(texture2D(depth, texcoord).r-depth_ratio.y);\n" + " float sum = 1.0;\n" + " float count = 1.0;\n" + " for(int i=0; i<=3; ++i)\n" + " for(int j=0; j<=3; ++j)\n" + " {\n" + " vec2 offs = vec2(float(i)-1.5, float(j)-1.5)/screen_size;\n" + " float depth = depth_ratio.x/(texture2D(depth, texcoord+offs).r-depth_ratio.y);\n" + " if(abs(depth-sample)(127+c*127); + data[i*3+1] = static_cast(127+s*127); + data[i*3+2] = static_cast(127-s*127); + data[i*3+4] = static_cast(127+c*127); + } + rotate_lookup.image(0, GL::RGBA, GL::UNSIGNED_BYTE, data); + + occlude_texturing.attach(1, rotate_lookup); + + depth_ratio = 1/depth_ratio; + + occlude_shdata.uniform(occlude_shader.get_uniform_location("depth"), 0); + occlude_shdata.uniform(occlude_shader.get_uniform_location("rotate"), 1); + occlude_shdata.uniform(occlude_shader.get_uniform_location("screen_size"), w, h); + occlude_shdata.uniform(occlude_shader.get_uniform_location("depth_ratio"), depth_ratio, 1+depth_ratio); + + combine_shdata.uniform(combine_shader.get_uniform_location("color"), 1); + combine_shdata.uniform(combine_shader.get_uniform_location("depth"), 0); + combine_shdata.uniform(combine_shader.get_uniform_location("occlusion"), 2); + combine_shdata.uniform(combine_shader.get_uniform_location("screen_size"), w, h); + combine_shdata.uniform(combine_shader.get_uniform_location("depth_ratio"), depth_ratio, 1+depth_ratio); + combine_shdata.uniform(combine_shader.get_uniform_location("edge_threshold"), 0.05f); + + set_darkness(15); + + MeshBuilder bld(quad); + bld.begin(TRIANGLE_STRIP); + bld.vertex(-1, -1); + bld.vertex(-1, 1); + bld.vertex(1, -1); + bld.vertex(1, 1); + bld.end(); +} + +void AmbientOcclusion::set_darkness(float d) +{ + darkness = d; + occlude_shdata.uniform(occlude_shader.get_uniform_location("darkness"), darkness); +} + +void AmbientOcclusion::render(const Texture2D &color, const Texture2D &depth) +{ + occlude_texturing.attach(0, depth); + combine_texturing.attach(0, depth); + combine_texturing.attach(1, color); + + Bind unbind_dtest(static_cast(0), true); + Bind unbind_blend(static_cast(0), true); + + { + GL::Bind bind_fbo(fbo, true); + GL::Bind bind_tex(occlude_texturing); + GL::Bind bind_shader(occlude_shader); + occlude_shdata.apply(); + quad.draw(); + } + + GL::Bind bind_tex(combine_texturing); + GL::Bind bind_shader(combine_shader); + combine_shdata.apply(); + quad.draw(); +} + +} // namespace GL +} // namespace Msp diff --git a/source/ambientocclusion.h b/source/ambientocclusion.h new file mode 100644 index 00000000..1866baee --- /dev/null +++ b/source/ambientocclusion.h @@ -0,0 +1,53 @@ +/* $Id$ + +This file is part of libmspgl +Copyright © 2010 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#ifndef MSP_GL_AMBIENTOCCLUSION_H_ +#define MSP_GL_AMBIENTOCCLUSION_H_ + +#include "framebuffer.h" +#include "mesh.h" +#include "postprocessor.h" +#include "program.h" +#include "programdata.h" +#include "texture2d.h" +#include "texturing.h" + +namespace Msp { +namespace GL { + +/** +Implements screen-space ambient occlusion. + +http://en.wikipedia.org/wiki/Screen_Space_Ambient_Occlusion +*/ +class AmbientOcclusion: public PostProcessor +{ +private: + Texture2D occlusion; + Texture2D rotate_lookup; + Framebuffer fbo; + Texturing occlude_texturing; + Program occlude_shader; + ProgramData occlude_shdata; + Texturing combine_texturing; + Program combine_shader; + ProgramData combine_shdata; + Mesh quad; + float darkness; + +public: + AmbientOcclusion(unsigned, unsigned, float); + + void set_darkness(float); + + virtual void render(const Texture2D &, const Texture2D &); +}; + +} // namespace GL +} // namespace Msp + +#endif diff --git a/source/bloom.cpp b/source/bloom.cpp index 0e5ce9d6..db10c3b2 100644 --- a/source/bloom.cpp +++ b/source/bloom.cpp @@ -126,7 +126,7 @@ void Bloom::set_strength(float s) combine_shdata.uniform(combine_shader.get_uniform_location("strength"), s); } -void Bloom::render(const Texture2D &src) +void Bloom::render(const Texture2D &src, const Texture2D &) { const Framebuffer *dest = Framebuffer::current(); blur_shader.bind(); diff --git a/source/bloom.h b/source/bloom.h index c02604af..b763809a 100644 --- a/source/bloom.h +++ b/source/bloom.h @@ -48,7 +48,7 @@ public: values mean more blurriness. */ void set_strength(float); - virtual void render(const Texture2D &); + virtual void render(const Texture2D &, const Texture2D &); }; } // namespace GL diff --git a/source/pipeline.cpp b/source/pipeline.cpp index 62aeaab9..63bdc4e8 100644 --- a/source/pipeline.cpp +++ b/source/pipeline.cpp @@ -116,14 +116,18 @@ void Pipeline::add_postprocessor(PostProcessor &pp) if(!fbo) { fbo = new Framebuffer; + color_buf = new Texture2D; color_buf->set_min_filter(NEAREST); color_buf->set_mag_filter(NEAREST); color_buf->storage((hdr ? RGB16F : RGB), width, height); fbo->attach(COLOR_ATTACHMENT0, *color_buf, 0); - depth_buf = new Renderbuffer; + + depth_buf = new Texture2D; + depth_buf->set_min_filter(NEAREST); + depth_buf->set_mag_filter(NEAREST); depth_buf->storage(DEPTH_COMPONENT, width, height); - fbo->attach(DEPTH_ATTACHMENT, *depth_buf); + fbo->attach(DEPTH_ATTACHMENT, *depth_buf, 0); } } @@ -171,7 +175,7 @@ void Pipeline::render_all() const // XXX Need two color buffer textures to handle multiple post-processors correctly for(vector::const_iterator i=postproc.begin(); i!=postproc.end(); ++i) - (*i)->render(*color_buf); + (*i)->render(*color_buf, *depth_buf); } diff --git a/source/pipeline.h b/source/pipeline.h index 3f0ea2fa..a63eeb5f 100644 --- a/source/pipeline.h +++ b/source/pipeline.h @@ -47,7 +47,7 @@ private: bool hdr; Framebuffer *fbo; Texture2D *color_buf; - Renderbuffer *depth_buf; + Texture2D *depth_buf; public: Pipeline(unsigned, unsigned, bool); diff --git a/source/postprocessor.h b/source/postprocessor.h index 25ed150a..f835e5af 100644 --- a/source/postprocessor.h +++ b/source/postprocessor.h @@ -21,12 +21,12 @@ class PostProcessor protected: PostProcessor() { } public: - virtual ~PostProcessor(); + virtual ~PostProcessor() { } /** Renders the effect. Takes the source texture as a parameter. */ - virtual void render(const Texture2D &) =0; + virtual void render(const Texture2D &, const Texture2D &) = 0; }; } // namespace GL