]> git.tdb.fi Git - libs/gl.git/blob - source/bloom.cpp
Roll the various changed flags into a single mask
[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                 fbo[i].attach(COLOR_ATTACHMENT0, tex[i], 0);
63                 fbo[i].require_complete();
64         }
65
66         combine_shdata.uniform("source", 1);
67         combine_shdata.uniform("blurred", 0);
68
69         combine_texturing.attach(0, tex[1]);
70
71         set_radius(2.0f);
72         set_strength(0.2f);
73 }
74
75 void Bloom::set_radius(float r)
76 {
77         if(r<=0.0f)
78                 throw invalid_argument("Bloom::set_radius");
79
80         int size = min(static_cast<int>(r*3.0f), 9);
81         blur_shdata_common.uniform("size", size);
82
83         vector<float> factors(size*2+1);
84         float sum = 0.0f;
85         r = 2*r*r;
86         for(int i=-size; i<=size; ++i)
87                 sum += (factors[size+i] = exp(-i*i/r));
88         for(int i=0; i<=size*2; ++i)
89                 factors[i] /= sum;
90
91         blur_shdata_common.uniform1_array("factors", size*2+1, &factors.front());
92 }
93
94 void Bloom::set_strength(float s)
95 {
96         if(s<0.0f || s>1.0f)
97                 throw invalid_argument("Bloom::set_strength");
98         combine_shdata.uniform("strength", s);
99 }
100
101 void Bloom::render(const Texture2D &src, const Texture2D &)
102 {
103         BindRestore unbind_dtest(static_cast<DepthTest *>(0));
104         BindRestore unbind_blend(static_cast<Blend *>(0));
105
106         {
107                 Bind bind_shader(blur_shader);
108                 blur_shdata_common.apply();
109                 for(unsigned i=0; i<2; ++i)
110                 {
111                         BindRestore bind_fbo(fbo[i]);
112                         Bind bind_tex(i ? tex[0] : src);
113                         blur_shdata[i].apply();
114                         quad.draw();
115                 }
116         }
117
118         combine_texturing.attach(1, src);
119         Bind bind_texturing(combine_texturing);
120         Bind bind_shader(combine_shader);
121         combine_shdata.apply();
122         quad.draw();
123 }
124
125 } // namespace GL
126 } // namespace Msp