]> git.tdb.fi Git - libs/gl.git/blob - source/bloom.cpp
Drop Id tags and copyright notices from files
[libs/gl.git] / source / bloom.cpp
1 #include <cmath>
2 #include <msp/strings/formatter.h>
3 #include "blend.h"
4 #include "bloom.h"
5 #include "meshbuilder.h"
6 #include "misc.h"
7 #include "tests.h"
8 #include "texunit.h"
9
10 using namespace std;
11
12 namespace {
13
14 static const char blur_vs[]=
15         "varying vec2 texcoord;\n"
16         "void main()\n"
17         "{\n"
18         "       gl_Position = vec4(gl_Vertex.xy*2.0-1.0, 0.0, 1.0);\n"
19         "       texcoord = gl_Vertex.xy;\n"
20         "}";
21
22 static const char blur_fs[]=
23         "uniform sampler2D source;\n"
24         "uniform vec2 delta;\n"
25         "uniform float factors[19];\n"
26         "uniform int size;\n"
27         "varying vec2 texcoord;\n"
28         "void main()\n"
29         "{\n"
30         "       gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n"
31         "       for(int i=0; i<=size*2; ++i)\n"
32         "               gl_FragColor += texture2D(source, texcoord+delta*float(i-size))*factors[i];\n"
33         "}";
34
35 static const char combine_vs[]=
36         "varying vec2 texcoord;\n"
37         "void main()\n"
38         "{\n"
39         "       gl_Position = vec4(gl_Vertex.xy*2.0-1.0, 0.0, 1.0);\n"
40         "       texcoord = gl_Vertex.xy;\n"
41         "}";
42
43 static const char combine_fs[]=
44         "uniform sampler2D source;\n"
45         "uniform sampler2D blurred;\n"
46         "uniform float strength;\n"
47         "varying vec2 texcoord;\n"
48         "void main()\n"
49         "{\n"
50         "       gl_FragColor = mix(texture2D(source, texcoord), texture2D(blurred, texcoord), strength);\n"
51         "}";
52
53 }
54
55 namespace Msp {
56 namespace GL {
57
58 Bloom::Bloom(unsigned w, unsigned h):
59         blur_shader(blur_vs, blur_fs),
60         blur_shdata_common(blur_shader),
61         blur_shdata_x(blur_shader),
62         blur_shdata_y(blur_shader),
63         combine_shader(combine_vs, combine_fs),
64         combine_shdata(combine_shader),
65         quad(VERTEX2)
66 {
67         int loc = blur_shader.get_uniform_location("delta");
68         blur_shdata_x.uniform(loc, 1.0f/w, 0.0f);
69         blur_shdata_y.uniform(loc, 0.0f, 1.0f/h);
70
71         blur_shdata_common.uniform("source", 0);
72         for(unsigned i=0; i<2; ++i)
73         {
74                 tex[i].set_min_filter(NEAREST);
75                 tex[i].storage(RGB16F, w, h);
76         }
77
78         combine_shdata.uniform("source", 1);
79         combine_shdata.uniform("blurred", 0);
80
81         combine_texturing.attach(0, tex[1]);
82
83         set_radius(2.0f);
84         set_strength(0.2f);
85
86         MeshBuilder mbld(quad);
87         mbld.begin(TRIANGLE_STRIP);
88         mbld.vertex(0, 1);
89         mbld.vertex(0, 0);
90         mbld.vertex(1, 1);
91         mbld.vertex(1, 0);
92         mbld.end();
93 }
94
95 void Bloom::set_radius(float r)
96 {
97         if(r<=0.0f)
98                 throw InvalidParameterValue("Radius must be positive");
99
100         int size = min(static_cast<int>(r*3.0f), 9);
101         blur_shdata_common.uniform("size", size);
102
103         vector<float> factors(size*2+1);
104         float sum = 0.0f;
105         r = 2*r*r;
106         for(int i=-size; i<=size; ++i)
107                 sum += (factors[size+i] = exp(-i*i/r));
108
109         for(int i=0; i<=size*2; ++i)
110                 blur_shdata_common.uniform(format("factors[%d]", i), factors[i]/sum);
111 }
112
113 void Bloom::set_strength(float s)
114 {
115         if(s<0.0f || s>1.0f)
116                 throw InvalidParameterValue("Strength must be in the range [0.0, 1.0]");
117         combine_shdata.uniform("strength", s);
118 }
119
120 void Bloom::render(const Texture2D &src, const Texture2D &)
121 {
122         Bind unbind_dtest(static_cast<DepthTest *>(0), true);
123         Bind unbind_blend(static_cast<Blend *>(0), true);
124
125         {
126                 Bind bind_shader(blur_shader);
127                 blur_shdata_common.apply();
128                 Bind bind_fbo(fbo, true);
129                 for(unsigned i=0; i<2; ++i)
130                 {
131                         Bind bind_tex(i ? tex[0] : src);
132                         fbo.attach(COLOR_ATTACHMENT0, tex[i], 0);
133                         (i ? blur_shdata_y : blur_shdata_x).apply();
134                         quad.draw();
135                 }
136         }
137
138         combine_texturing.attach(1, src);
139         Bind bind_texturing(combine_texturing);
140         Bind bind_shader(combine_shader);
141         combine_shdata.apply();
142         quad.draw();
143 }
144
145 } // namespace GL
146 } // namespace Msp