]> git.tdb.fi Git - libs/gl.git/blob - source/bloom.cpp
Use CLAMP_TO_EDGE on postprocessing textures
[libs/gl.git] / source / bloom.cpp
1 #include <cmath>
2 #include <msp/strings/format.h>
3 #include "blend.h"
4 #include "bloom.h"
5 #include "misc.h"
6 #include "shader.h"
7 #include "tests.h"
8 #include "texunit.h"
9
10 using namespace std;
11
12 namespace {
13
14 static const char blur_fs[]=
15         "uniform sampler2D source;\n"
16         "uniform vec2 delta;\n"
17         "uniform float factors[19];\n"
18         "uniform int size;\n"
19         "varying vec2 texcoord;\n"
20         "void main()\n"
21         "{\n"
22         "       gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n"
23         "       for(int i=0; i<=size*2; ++i)\n"
24         "               gl_FragColor += texture2D(source, texcoord+delta*float(i-size))*factors[i];\n"
25         "}";
26
27 static const char combine_fs[]=
28         "uniform sampler2D source;\n"
29         "uniform sampler2D blurred;\n"
30         "uniform float strength;\n"
31         "varying vec2 texcoord;\n"
32         "void main()\n"
33         "{\n"
34         "       gl_FragColor = mix(texture2D(source, texcoord), texture2D(blurred, texcoord), strength);\n"
35         "}";
36
37 }
38
39 namespace Msp {
40 namespace GL {
41
42 Bloom::Bloom(unsigned w, unsigned h):
43         quad(get_fullscreen_quad())
44 {
45         blur_shader.attach_shader(get_fullscreen_vertex_shader());
46         blur_shader.attach_shader_owned(new FragmentShader(blur_fs));
47         blur_shader.link();
48
49         combine_shader.attach_shader(get_fullscreen_vertex_shader());
50         combine_shader.attach_shader_owned(new FragmentShader(combine_fs));
51         combine_shader.link();
52
53         blur_shdata[0].uniform("delta", 1.0f/w, 0.0f);
54         blur_shdata[1].uniform("delta", 0.0f, 1.0f/h);
55
56         blur_shdata_common.uniform("source", 0);
57         for(unsigned i=0; i<2; ++i)
58         {
59                 tex[i].set_min_filter(NEAREST);
60                 tex[i].set_wrap(CLAMP_TO_EDGE);
61                 tex[i].storage(RGB16F, w, h);
62         }
63
64         combine_shdata.uniform("source", 1);
65         combine_shdata.uniform("blurred", 0);
66
67         combine_texturing.attach(0, tex[1]);
68
69         set_radius(2.0f);
70         set_strength(0.2f);
71 }
72
73 void Bloom::set_radius(float r)
74 {
75         if(r<=0.0f)
76                 throw invalid_argument("Bloom::set_radius");
77
78         int size = min(static_cast<int>(r*3.0f), 9);
79         blur_shdata_common.uniform("size", size);
80
81         vector<float> factors(size*2+1);
82         float sum = 0.0f;
83         r = 2*r*r;
84         for(int i=-size; i<=size; ++i)
85                 sum += (factors[size+i] = exp(-i*i/r));
86         for(int i=0; i<=size*2; ++i)
87                 factors[i] /= sum;
88
89         blur_shdata_common.uniform1_array("factors[0]", size*2+1, &factors.front());
90 }
91
92 void Bloom::set_strength(float s)
93 {
94         if(s<0.0f || s>1.0f)
95                 throw invalid_argument("Bloom::set_strength");
96         combine_shdata.uniform("strength", s);
97 }
98
99 void Bloom::render(const Texture2D &src, const Texture2D &)
100 {
101         Bind unbind_dtest(static_cast<DepthTest *>(0), true);
102         Bind unbind_blend(static_cast<Blend *>(0), true);
103
104         {
105                 Bind bind_shader(blur_shader);
106                 blur_shdata_common.apply();
107                 Bind bind_fbo(fbo, true);
108                 for(unsigned i=0; i<2; ++i)
109                 {
110                         Bind bind_tex(i ? tex[0] : src);
111                         fbo.attach(COLOR_ATTACHMENT0, tex[i], 0);
112                         blur_shdata[i].apply();
113                         quad.draw();
114                 }
115         }
116
117         combine_texturing.attach(1, src);
118         Bind bind_texturing(combine_texturing);
119         Bind bind_shader(combine_shader);
120         combine_shdata.apply();
121         quad.draw();
122 }
123
124 } // namespace GL
125 } // namespace Msp