]> git.tdb.fi Git - libs/gl.git/blob - source/bloom.cpp
Restructure ProgramData to support sharing between Programs
[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 "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         combine_shader(combine_vs, combine_fs),
61         quad(VERTEX2)
62 {
63         blur_shdata[0].uniform("delta", 1.0f/w, 0.0f);
64         blur_shdata[1].uniform("delta", 0.0f, 1.0f/h);
65
66         blur_shdata_common.uniform("source", 0);
67         for(unsigned i=0; i<2; ++i)
68         {
69                 tex[i].set_min_filter(NEAREST);
70                 tex[i].storage(RGB16F, w, h);
71         }
72
73         combine_shdata.uniform("source", 1);
74         combine_shdata.uniform("blurred", 0);
75
76         combine_texturing.attach(0, tex[1]);
77
78         set_radius(2.0f);
79         set_strength(0.2f);
80
81         MeshBuilder mbld(quad);
82         mbld.begin(TRIANGLE_STRIP);
83         mbld.vertex(0, 1);
84         mbld.vertex(0, 0);
85         mbld.vertex(1, 1);
86         mbld.vertex(1, 0);
87         mbld.end();
88 }
89
90 void Bloom::set_radius(float r)
91 {
92         if(r<=0.0f)
93                 throw out_of_range("Bloom::set_radius");
94
95         int size = min(static_cast<int>(r*3.0f), 9);
96         blur_shdata_common.uniform("size", size);
97
98         vector<float> factors(size*2+1);
99         float sum = 0.0f;
100         r = 2*r*r;
101         for(int i=-size; i<=size; ++i)
102                 sum += (factors[size+i] = exp(-i*i/r));
103
104         for(int i=0; i<=size*2; ++i)
105                 blur_shdata_common.uniform(format("factors[%d]", i), factors[i]/sum);
106 }
107
108 void Bloom::set_strength(float s)
109 {
110         if(s<0.0f || s>1.0f)
111                 throw out_of_range("Bloom::set_strength");
112         combine_shdata.uniform("strength", s);
113 }
114
115 void Bloom::render(const Texture2D &src, const Texture2D &)
116 {
117         Bind unbind_dtest(static_cast<DepthTest *>(0), true);
118         Bind unbind_blend(static_cast<Blend *>(0), true);
119
120         {
121                 Bind bind_shader(blur_shader);
122                 blur_shdata_common.apply();
123                 Bind bind_fbo(fbo, true);
124                 for(unsigned i=0; i<2; ++i)
125                 {
126                         Bind bind_tex(i ? tex[0] : src);
127                         fbo.attach(COLOR_ATTACHMENT0, tex[i], 0);
128                         blur_shdata[i].apply();
129                         quad.draw();
130                 }
131         }
132
133         combine_texturing.attach(1, src);
134         Bind bind_texturing(combine_texturing);
135         Bind bind_shader(combine_shader);
136         combine_shdata.apply();
137         quad.draw();
138 }
139
140 } // namespace GL
141 } // namespace Msp