]> git.tdb.fi Git - libs/gl.git/blob - source/bloom.cpp
Do not attempt to unwatch a mesh that was already removed
[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.bind_attribute(get_component_type(VERTEX2), "vertex");
48         blur_shader.link();
49
50         combine_shader.attach_shader(get_fullscreen_vertex_shader());
51         combine_shader.attach_shader_owned(new FragmentShader(combine_fs));
52         combine_shader.bind_attribute(get_component_type(VERTEX2), "vertex");
53         combine_shader.link();
54
55         blur_shdata[0].uniform("delta", 1.0f/w, 0.0f);
56         blur_shdata[1].uniform("delta", 0.0f, 1.0f/h);
57
58         blur_shdata_common.uniform("source", 0);
59         for(unsigned i=0; i<2; ++i)
60         {
61                 tex[i].set_min_filter(NEAREST);
62                 tex[i].set_wrap(CLAMP_TO_EDGE);
63                 tex[i].storage(RGB16F, w, h);
64                 fbo[i].attach(COLOR_ATTACHMENT0, tex[i], 0);
65                 fbo[i].require_complete();
66         }
67
68         combine_shdata.uniform("source", 1);
69         combine_shdata.uniform("blurred", 0);
70
71         combine_texturing.attach(0, tex[1]);
72
73         set_radius(2.0f);
74         set_strength(0.2f);
75 }
76
77 void Bloom::set_radius(float r)
78 {
79         if(r<=0.0f)
80                 throw invalid_argument("Bloom::set_radius");
81
82         int size = min(static_cast<int>(r*3.0f), 9);
83         blur_shdata_common.uniform("size", size);
84
85         vector<float> factors(size*2+1);
86         float sum = 0.0f;
87         r = 2*r*r;
88         for(int i=-size; i<=size; ++i)
89                 sum += (factors[size+i] = exp(-i*i/r));
90         for(int i=0; i<=size*2; ++i)
91                 factors[i] /= sum;
92
93         blur_shdata_common.uniform1_array("factors", size*2+1, &factors.front());
94 }
95
96 void Bloom::set_strength(float s)
97 {
98         if(s<0.0f || s>1.0f)
99                 throw invalid_argument("Bloom::set_strength");
100         combine_shdata.uniform("strength", s);
101 }
102
103 void Bloom::render(const Texture2D &src, const Texture2D &)
104 {
105         BindRestore unbind_dtest(static_cast<DepthTest *>(0));
106         BindRestore unbind_blend(static_cast<Blend *>(0));
107         Bind bind_mesh(quad);
108
109         {
110                 Bind bind_shader(blur_shader);
111                 blur_shdata_common.apply();
112                 for(unsigned i=0; i<2; ++i)
113                 {
114                         BindRestore bind_fbo(fbo[i]);
115                         Bind bind_tex(i ? tex[0] : src);
116                         blur_shdata[i].apply();
117                         quad.draw();
118                 }
119         }
120
121         combine_texturing.attach(1, src);
122         Bind bind_texturing(combine_texturing);
123         Bind bind_shader(combine_shader);
124         combine_shdata.apply();
125         quad.draw();
126 }
127
128 } // namespace GL
129 } // namespace Msp