Add vertical blurring, and fix a bug where not all taps would be used.
[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 #include <assert.h>
7
8 #include "blur_effect.h"
9 #include "util.h"
10
11 BlurEffect::BlurEffect()
12         : radius(3.0f),
13           direction(HORIZONTAL)
14 {
15         register_float("radius", (float *)&radius);
16         register_int("direction", (int *)&direction);
17 }
18
19 std::string BlurEffect::output_fragment_shader()
20 {
21         return read_file("blur_effect.frag");
22 }
23
24 void BlurEffect::set_uniforms(GLuint glsl_program_num, const std::string &prefix, unsigned *sampler_num)
25 {
26         Effect::set_uniforms(glsl_program_num, prefix, sampler_num);
27
28         // We only have 15 taps to work with, and we want that to reach out to about 2.5*sigma.
29         // Bump up the mipmap levels (giving us box blurs) until we have what we need.
30         unsigned base_mipmap_level = 0;
31         float adjusted_radius = radius;
32         float pixel_size = 1.0f;
33         while (adjusted_radius * 2.5f > 7.0f) {
34                 ++base_mipmap_level;
35                 adjusted_radius *= 0.5f;
36                 pixel_size *= 2.0f;
37         }       
38
39         glActiveTexture(GL_TEXTURE0);
40         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, base_mipmap_level);
41         check_error();
42
43         // FIXME
44         if (direction == HORIZONTAL) {
45                 float ps[] = { pixel_size / 1280.0f, 0.0f };
46                 set_uniform_vec2(glsl_program_num, prefix, "pixel_offset", ps);
47         } else if (direction == VERTICAL) {
48                 float ps[] = { 0.0f, pixel_size / 720.0f };
49                 set_uniform_vec2(glsl_program_num, prefix, "pixel_offset", ps);
50         } else {
51                 assert(false);
52         }
53
54         // Simple Gaussian weights for now.
55         float weight[15], total = 0.0f;
56         for (unsigned i = 0; i < 15; ++i) {
57                 float z = (i - 7.0f) / adjusted_radius;
58                 weight[i] = exp(-(z*z));
59                 total += weight[i];
60         }
61         printf("[mip level %d] ", base_mipmap_level);
62         for (unsigned i = 0; i < 15; ++i) {
63                 weight[i] /= total;
64                 printf("%f ", weight[i]);
65         }
66         printf("\n");
67         set_uniform_float_array(glsl_program_num, prefix, "weight", weight, 15);
68 }