Try to adjust the mip levels to get box blur for free as needed.
[movit] / blur_effect.cpp
1 #define GL_GLEXT_PROTOTYPES 1
2
3 #include <math.h>
4 #include <GL/gl.h>
5 #include <GL/glext.h>
6
7 #include "blur_effect.h"
8 #include "util.h"
9
10 BlurEffect::BlurEffect()
11         : radius(3.0f)
12 {
13         register_float("radius", (float *)&radius);
14 }
15
16 std::string BlurEffect::output_fragment_shader()
17 {
18         return read_file("blur_effect.frag");
19 }
20
21 void BlurEffect::set_uniforms(GLuint glsl_program_num, const std::string &prefix, unsigned *sampler_num)
22 {
23         Effect::set_uniforms(glsl_program_num, prefix, sampler_num);
24
25         // We only have 15 taps to work with, and we want that to reach out to about 2.5*sigma.
26         // Bump up the mipmap levels (giving us box blurs) until we have what we need.
27         unsigned base_mipmap_level = 0;
28         float adjusted_radius = radius;
29         float pixel_size = 1.0f;
30         while (adjusted_radius * 2.5f > 7.0f) {
31                 ++base_mipmap_level;
32                 adjusted_radius *= 0.5f;
33                 pixel_size *= 2.0f;
34         }       
35
36         glActiveTexture(GL_TEXTURE0);
37         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, base_mipmap_level);
38         check_error();
39
40         set_uniform_float(glsl_program_num, prefix, "pixel_offset", pixel_size / 1280.0f);  // FIXME
41
42         // Simple Gaussian weights for now.
43         float weight[15], total = 0.0f;
44         for (unsigned i = 0; i < 15; ++i) {
45                 float z = (i - 7.0f) / adjusted_radius;
46                 weight[i] = exp(-(z*z));
47                 total += weight[i];
48         }
49         printf("[mip level %d] ", base_mipmap_level);
50         for (unsigned i = 0; i < 15; ++i) {
51                 weight[i] /= total;
52                 printf("%f ", weight[i]);
53         }
54         printf("\n");
55         set_uniform_float_array(glsl_program_num, prefix, "weight", weight, 15);
56 }