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