1 #include "blur.hpp"
2 
3 static const char *gaussian_vertex_shader =
4     R"(
5 #version 100
6 
7 attribute mediump vec2 position;
8 uniform vec2 size;
9 uniform float offset;
10 
11 varying highp vec2 blurcoord[5];
12 
13 void main() {
14     gl_Position = vec4(position.xy, 0.0, 1.0);
15 
16     vec2 texcoord = (position.xy + vec2(1.0, 1.0)) / 2.0;
17 
18     blurcoord[0] = texcoord;
19     blurcoord[1] = texcoord + vec2(1.5 * offset) / size;
20     blurcoord[2] = texcoord - vec2(1.5 * offset) / size;
21     blurcoord[3] = texcoord + vec2(3.5 * offset) / size;
22     blurcoord[4] = texcoord - vec2(3.5 * offset) / size;
23 }
24 )";
25 
26 static const char *gaussian_fragment_shader_horz =
27     R"(
28 #version 100
29 precision mediump float;
30 
31 uniform sampler2D bg_texture;
32 uniform int mode;
33 
34 varying highp vec2 blurcoord[5];
35 
36 void main()
37 {
38     vec2 uv = blurcoord[0];
39     vec4 bp = vec4(0.0);
40     bp += texture2D(bg_texture, vec2(blurcoord[0].x, uv.y)) * 0.204164;
41     bp += texture2D(bg_texture, vec2(blurcoord[1].x, uv.y)) * 0.304005;
42     bp += texture2D(bg_texture, vec2(blurcoord[2].x, uv.y)) * 0.304005;
43     bp += texture2D(bg_texture, vec2(blurcoord[3].x, uv.y)) * 0.093913;
44     bp += texture2D(bg_texture, vec2(blurcoord[4].x, uv.y)) * 0.093913;
45     gl_FragColor = bp;
46 })";
47 
48 static const char *gaussian_fragment_shader_vert =
49     R"(
50 #version 100
51 precision mediump float;
52 
53 uniform sampler2D bg_texture;
54 uniform int mode;
55 
56 varying highp vec2 blurcoord[5];
57 
58 void main()
59 {
60     vec2 uv = blurcoord[0];
61     vec4 bp = vec4(0.0);
62     bp += texture2D(bg_texture, vec2(uv.x, blurcoord[0].y)) * 0.204164;
63     bp += texture2D(bg_texture, vec2(uv.x, blurcoord[1].y)) * 0.304005;
64     bp += texture2D(bg_texture, vec2(uv.x, blurcoord[2].y)) * 0.304005;
65     bp += texture2D(bg_texture, vec2(uv.x, blurcoord[3].y)) * 0.093913;
66     bp += texture2D(bg_texture, vec2(uv.x, blurcoord[4].y)) * 0.093913;
67     gl_FragColor = bp;
68 })";
69 
70 class wf_gaussian_blur : public wf_blur_base
71 {
72   public:
wf_gaussian_blur(wf::output_t * output)73     wf_gaussian_blur(wf::output_t *output) : wf_blur_base(output, "gaussian")
74     {
75         OpenGL::render_begin();
76         program[0].set_simple(OpenGL::compile_program(
77             gaussian_vertex_shader, gaussian_fragment_shader_horz));
78         program[1].set_simple(OpenGL::compile_program(
79             gaussian_vertex_shader, gaussian_fragment_shader_vert));
80         OpenGL::render_end();
81     }
82 
upload_data(int i,int width,int height)83     void upload_data(int i, int width, int height)
84     {
85         float offset = offset_opt;
86         static const float vertexData[] = {
87             -1.0f, -1.0f,
88             1.0f, -1.0f,
89             1.0f, 1.0f,
90             -1.0f, 1.0f
91         };
92 
93         program[i].use(wf::TEXTURE_TYPE_RGBA);
94         program[i].uniform2f("size", width, height);
95         program[i].uniform1f("offset", offset);
96         program[i].attrib_pointer("position", 2, 0, vertexData);
97     }
98 
blur(const wf::region_t & blur_region,int i,int width,int height)99     void blur(const wf::region_t& blur_region, int i, int width, int height)
100     {
101         program[i].use(wf::TEXTURE_TYPE_RGBA);
102         render_iteration(blur_region, fb[i], fb[!i], width, height);
103     }
104 
blur_fb0(const wf::region_t & blur_region,int width,int height)105     int blur_fb0(const wf::region_t& blur_region, int width, int height) override
106     {
107         int i, iterations = iterations_opt;
108 
109         OpenGL::render_begin();
110         GL_CALL(glDisable(GL_BLEND));
111         /* Enable our shader and pass some data to it. The shader
112          * does gaussian blur on the background texture in two passes,
113          * one horizontal and one vertical */
114         upload_data(0, width, height);
115         upload_data(1, width, height);
116 
117         for (i = 0; i < iterations; i++)
118         {
119             /* Blur horizontally */
120             blur(blur_region, 0, width, height);
121 
122             /* Blur vertically */
123             blur(blur_region, 1, width, height);
124         }
125 
126         /* Reset gl state */
127         GL_CALL(glEnable(GL_BLEND));
128         GL_CALL(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
129 
130         GL_CALL(glBindTexture(GL_TEXTURE_2D, 0));
131         program[1].deactivate();
132         OpenGL::render_end();
133 
134         return 0;
135     }
136 
calculate_blur_radius()137     int calculate_blur_radius() override
138     {
139         return 4 * wf_blur_base::calculate_blur_radius();
140     }
141 };
142 
create_gaussian_blur(wf::output_t * output)143 std::unique_ptr<wf_blur_base> create_gaussian_blur(wf::output_t *output)
144 {
145     return std::make_unique<wf_gaussian_blur>(output);
146 }
147