Merge lp:~unity-team/nux/linear-sample-blur into lp:nux
- linear-sample-blur
- Merge into trunk
Proposed by
Nicolas d'Offay
Status: | Merged |
---|---|
Approved by: | Nicolas d'Offay |
Approved revision: | 725 |
Merged at revision: | 751 |
Proposed branch: | lp:~unity-team/nux/linear-sample-blur |
Merge into: | lp:nux |
Diff against target: |
551 lines (+465/-5) 3 files modified
NuxGraphics/GraphicsEngine.cpp (+42/-0) NuxGraphics/GraphicsEngine.h (+26/-0) NuxGraphics/RenderingPipeGLSL.cpp (+397/-5) |
To merge this branch: | bzr merge lp:~unity-team/nux/linear-sample-blur |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Nicolas d'Offay (community) | Approve | ||
PS Jenkins bot | continuous-integration | Pending | |
Review via email: mp+144099@code.launchpad.net |
Commit message
Added linear sample gaussian blur shader which halves the loop count of our vertical and horizontal blur drastically improving performance.
Description of the change
To post a comment you must log in.
Revision history for this message
Nicolas d'Offay (nicolas-doffay) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'NuxGraphics/GraphicsEngine.cpp' |
2 | --- NuxGraphics/GraphicsEngine.cpp 2012-11-28 15:16:41 +0000 |
3 | +++ NuxGraphics/GraphicsEngine.cpp 2013-01-21 12:52:20 +0000 |
4 | @@ -1335,6 +1335,48 @@ |
5 | SetViewport(0, 0, width, height); |
6 | Push2DWindow(width, height); |
7 | } |
8 | + |
9 | + /*! Description - This function calculates position offsets for our gaussian weight values to utilise the GPU bilinear sampling |
10 | + * which gets neighbouring pixel's data in just one sample. This serves to halve the loop for both vertical and |
11 | + * horizontal blur shaders. |
12 | + * Params - First two parameters are the weight and weight offsets which are passed as uniforms to our shader. |
13 | + * our sigma dictates how strong our blur will be. |
14 | + * Return - We return our loop count which is a #define in our vertical and horizontal shaders. |
15 | + */ |
16 | + int GraphicsEngine::LinearSampleGaussianWeights(std::vector<float>& weights, std::vector<float>& offsets, |
17 | + float sigma) |
18 | + { |
19 | + //Calculate our support which is used as our loop count. |
20 | + int support = int(sigma * 3.0f); |
21 | + |
22 | + weights.push_back(exp(-(0*0)/(2*sigma*sigma))/(sqrt(2*constants::pi)*sigma)); |
23 | + |
24 | + float total = weights.back(); |
25 | + |
26 | + //Our first weight has an offset of 0. |
27 | + offsets.push_back(0); |
28 | + |
29 | + for (int i = 1; i <= support; i++) |
30 | + { |
31 | + float w1 = exp(-(i*i)/(2*sigma*sigma))/(sqrt(2*constants::pi)*sigma); |
32 | + float w2 = exp(-((i+1)*(i+1))/(2*sigma*sigma))/(sqrt(2*constants::pi)*sigma); |
33 | + |
34 | + weights.push_back(w1 + w2); |
35 | + total += 2.0f * weights[i]; |
36 | + |
37 | + //Calculate our offset to utilise our GPU's bilinear sampling capability. By sampling in between texel we get the data of |
38 | + //neighbouring pixels with only one sample. |
39 | + offsets.push_back((i * w1 + (i + 1) * w2) / weights[i]); |
40 | + } |
41 | + |
42 | + //Normalise our weights. |
43 | + for (int i = 0; i < support; i++) |
44 | + { |
45 | + weights[i] /= total; |
46 | + } |
47 | + |
48 | + return support; |
49 | + } |
50 | |
51 | void GraphicsEngine::GaussianWeights(float **weights, float sigma, unsigned int num_tap) |
52 | { |
53 | |
54 | === modified file 'NuxGraphics/GraphicsEngine.h' |
55 | --- NuxGraphics/GraphicsEngine.h 2012-11-12 20:59:56 +0000 |
56 | +++ NuxGraphics/GraphicsEngine.h 2013-01-21 12:52:20 +0000 |
57 | @@ -434,6 +434,8 @@ |
58 | void QRP_GLSL_VerticalGauss (int x, int y, int width, int height, ObjectPtr<IOpenGLBaseTexture> device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f); |
59 | void QRP_GLSL_HorizontalHQGauss(int x, int y, int width, int height, ObjectPtr<IOpenGLBaseTexture> device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f); |
60 | void QRP_GLSL_VerticalHQGauss (int x, int y, int width, int height, ObjectPtr<IOpenGLBaseTexture> device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f); |
61 | + void QRP_GLSL_HorizontalLSGauss(int x, int y, int width, int height, ObjectPtr<IOpenGLBaseTexture> device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f); |
62 | + void QRP_GLSL_VerticalLSGauss (int x, int y, int width, int height, ObjectPtr<IOpenGLBaseTexture> device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f); |
63 | void QRP_GLSL_ColorMatrix (int x, int y, int width, int height, ObjectPtr<IOpenGLBaseTexture> device_texture, TexCoordXForm& texxform, const Color& c0, Matrix4 color_matrix, Vector4 offset); |
64 | |
65 | /*! |
66 | @@ -450,6 +452,13 @@ |
67 | ObjectPtr<IOpenGLBaseTexture> device_texture, TexCoordXForm& texxform, |
68 | const Color& c0, |
69 | float sigma = 1.0f, int num_pass = 1); |
70 | + |
71 | + ObjectPtr<IOpenGLBaseTexture> QRP_GLSL_GetLSBlurTexture( |
72 | + int x, int y, |
73 | + int buffer_width, int buffer_height, |
74 | + ObjectPtr<IOpenGLBaseTexture> device_texture, TexCoordXForm& texxform, |
75 | + const Color& c0, |
76 | + float sigma = 1.0f, int num_pass = 1); |
77 | |
78 | ObjectPtr<IOpenGLBaseTexture> QRP_GLSL_GetAlphaTexture( |
79 | ObjectPtr<IOpenGLBaseTexture> device_texture, TexCoordXForm& texxform, |
80 | @@ -480,6 +489,12 @@ |
81 | int buffer_width, int buffer_height, |
82 | FxStructure* fx_structure, TexCoordXForm& texxform, |
83 | const Color& c0, float sigma = 1.0f, int num_pass = 1); |
84 | + |
85 | + void QRP_GLSL_GetLSBlurFx( |
86 | + int x, int y, |
87 | + int buffer_width, int buffer_height, |
88 | + FxStructure *fx_structure, TexCoordXForm &texxform, |
89 | + const Color& c0, float sigma = 1.0f, int num_pass = 1); |
90 | |
91 | void QRP_GLSL_DisturbedTexture( |
92 | int x, int y, int width, int height, |
93 | @@ -842,6 +857,9 @@ |
94 | |
95 | //! Helper function to compute a Gaussian filter weights |
96 | void GaussianWeights(float **weights, float sigma, unsigned int num_tap); |
97 | + |
98 | + int LinearSampleGaussianWeights(std::vector<float>& weights, std::vector<float>& offsets, |
99 | + float sigma); |
100 | |
101 | //! Helper function to set an fbo |
102 | void SetFrameBufferHelper( |
103 | @@ -1009,6 +1027,14 @@ |
104 | void InitSLVerticalHQGaussFilter(int sigma); |
105 | //! Gauss vertical filter. |
106 | ObjectPtr<IOpenGLShaderProgram> _vertical_hq_gauss_filter_prog[NUX_MAX_GAUSSIAN_SIGMA]; |
107 | + |
108 | + void InitSLHorizontalLSGaussFilter(int k); |
109 | + //! Gauss horizontal filter. |
110 | + ObjectPtr<IOpenGLShaderProgram> _horizontal_ls_gauss_filter_prog[NUX_MAX_GAUSSIAN_SIGMA]; |
111 | + |
112 | + void InitSLVerticalLSGaussFilter(int k); |
113 | + //! Gauss vertical filter. |
114 | + ObjectPtr<IOpenGLShaderProgram> _vertical_ls_gauss_filter_prog[NUX_MAX_GAUSSIAN_SIGMA]; |
115 | |
116 | void InitSLColorMatrixFilter(); |
117 | //! Color matrix filter. |
118 | |
119 | === modified file 'NuxGraphics/RenderingPipeGLSL.cpp' |
120 | --- NuxGraphics/RenderingPipeGLSL.cpp 2012-11-12 20:59:56 +0000 |
121 | +++ NuxGraphics/RenderingPipeGLSL.cpp 2013-01-21 12:52:20 +0000 |
122 | @@ -629,6 +629,118 @@ |
123 | CHECKGL(glBindAttribLocation(_vertical_hq_gauss_filter_prog[k-1]->GetOpenGLID(), 0, "AVertex")); |
124 | _vertical_hq_gauss_filter_prog[k-1]->Link(); |
125 | } |
126 | + |
127 | + void GraphicsEngine::InitSLHorizontalLSGaussFilter(int k) |
128 | + { |
129 | + if (_horizontal_ls_gauss_filter_prog[k-1].IsValid()) |
130 | + { |
131 | + // Shader program already compiled |
132 | + return; |
133 | + } |
134 | + |
135 | + ObjectPtr<IOpenGLVertexShader> vs = _graphics_display.m_DeviceFactory->CreateVertexShader(); |
136 | + ObjectPtr<IOpenGLPixelShader> ps = _graphics_display.m_DeviceFactory->CreatePixelShader(); |
137 | + |
138 | + std::string vs_string = NUX_VERTEX_SHADER_HEADER |
139 | + "uniform mat4 view_projection_matrix; \n\ |
140 | + attribute vec4 vertex; \n\ |
141 | + attribute vec4 tex_coord; \n\ |
142 | + varying vec4 v_tex_coord; \n\ |
143 | + void main() \n\ |
144 | + { \n\ |
145 | + v_tex_coord = tex_coord; \n\ |
146 | + gl_Position = view_projection_matrix * vertex; \n\ |
147 | + }"; |
148 | + |
149 | + std::string ps_string = NUX_FRAGMENT_SHADER_HEADER |
150 | + "varying vec4 v_tex_coord; \n\ |
151 | + uniform sampler2D tex_object; \n\ |
152 | + uniform vec2 tex_size; \n\ |
153 | + #define NUM_SAMPLES %d \n\ |
154 | + uniform float weights[NUM_SAMPLES]; \n\ |
155 | + uniform float offsets[NUM_SAMPLES]; \n\ |
156 | + void main() \n\ |
157 | + { \n\ |
158 | + vec3 acc = texture2D(tex_object, v_tex_coord.st).rgb*weights[0];\n\ |
159 | + for (int i = 1; i < NUM_SAMPLES; i++) \n\ |
160 | + { \n\ |
161 | + acc += texture2D(tex_object, (v_tex_coord.st+(vec2(offsets[i], 0.0)/tex_size))).rgb*weights[i]; \n\ |
162 | + acc += texture2D(tex_object, (v_tex_coord.st-(vec2(offsets[i], 0.0)/tex_size))).rgb*weights[i]; \n\ |
163 | + } \n\ |
164 | + gl_FragColor = vec4(acc, 1.0); \n\ |
165 | + }"; |
166 | + |
167 | + int l = ps_string.length(); |
168 | + char* shader_prog = new char[l+10]; |
169 | + sprintf(shader_prog, ps_string.c_str(), k); |
170 | + |
171 | + _horizontal_ls_gauss_filter_prog[k-1] = _graphics_display.m_DeviceFactory->CreateShaderProgram(); |
172 | + vs->SetShaderCode(vs_string.c_str()); |
173 | + ps->SetShaderCode(shader_prog); |
174 | + delete[] shader_prog; |
175 | + |
176 | + _horizontal_ls_gauss_filter_prog[k-1]->ClearShaderObjects(); |
177 | + _horizontal_ls_gauss_filter_prog[k-1]->AddShaderObject(vs); |
178 | + _horizontal_ls_gauss_filter_prog[k-1]->AddShaderObject(ps); |
179 | + CHECKGL(glBindAttribLocation(_horizontal_ls_gauss_filter_prog[k-1]->GetOpenGLID(), 0, "vertex")); |
180 | + _horizontal_ls_gauss_filter_prog[k-1]->Link(); |
181 | + } |
182 | + |
183 | + void GraphicsEngine::InitSLVerticalLSGaussFilter(int k) |
184 | + { |
185 | + if (_vertical_ls_gauss_filter_prog[k-1].IsValid()) |
186 | + { |
187 | + // Shader program already compiled |
188 | + return; |
189 | + } |
190 | + |
191 | + ObjectPtr<IOpenGLVertexShader> vs = _graphics_display.m_DeviceFactory->CreateVertexShader(); |
192 | + ObjectPtr<IOpenGLPixelShader> ps = _graphics_display.m_DeviceFactory->CreatePixelShader(); |
193 | + |
194 | + std::string vs_string = NUX_VERTEX_SHADER_HEADER |
195 | + "uniform mat4 view_projection_matrix; \n\ |
196 | + attribute vec4 vertex; \n\ |
197 | + attribute vec4 tex_coord; \n\ |
198 | + varying vec4 v_tex_coord; \n\ |
199 | + void main() \n\ |
200 | + { \n\ |
201 | + v_tex_coord = tex_coord; \n\ |
202 | + gl_Position = view_projection_matrix * vertex; \n\ |
203 | + }"; |
204 | + |
205 | + std::string ps_string = NUX_FRAGMENT_SHADER_HEADER |
206 | + "varying vec4 v_tex_coord; \n\ |
207 | + uniform sampler2D tex_object; \n\ |
208 | + uniform vec2 tex_size; \n\ |
209 | + #define NUM_SAMPLES %d \n\ |
210 | + uniform float weights[NUM_SAMPLES]; \n\ |
211 | + uniform float offsets[NUM_SAMPLES]; \n\ |
212 | + void main() \n\ |
213 | + { \n\ |
214 | + vec3 acc = texture2D(tex_object, v_tex_coord.st).rgb*weights[0]; \n\ |
215 | + for (int i = 1; i < NUM_SAMPLES; i++) \n\ |
216 | + { \n\ |
217 | + acc += texture2D(tex_object, (v_tex_coord.st+(vec2(0.0, offsets[i])/tex_size))).rgb*weights[i]; \n\ |
218 | + acc += texture2D(tex_object, (v_tex_coord.st-(vec2(0.0, offsets[i])/tex_size))).rgb*weights[i]; \n\ |
219 | + } \n\ |
220 | + gl_FragColor = vec4(acc, 1.0); \n\ |
221 | + }"; |
222 | + |
223 | + int l = ps_string.length(); |
224 | + char* shader_prog = new char[l+10]; |
225 | + sprintf(shader_prog, ps_string.c_str(), k); |
226 | + |
227 | + _vertical_ls_gauss_filter_prog[k-1] = _graphics_display.m_DeviceFactory->CreateShaderProgram(); |
228 | + vs->SetShaderCode(vs_string.c_str()); |
229 | + ps->SetShaderCode(shader_prog); |
230 | + delete[] shader_prog; |
231 | + |
232 | + _vertical_ls_gauss_filter_prog[k-1]->ClearShaderObjects(); |
233 | + _vertical_ls_gauss_filter_prog[k-1]->AddShaderObject(vs); |
234 | + _vertical_ls_gauss_filter_prog[k-1]->AddShaderObject(ps); |
235 | + CHECKGL(glBindAttribLocation(_vertical_ls_gauss_filter_prog[k-1]->GetOpenGLID(), 0, "vertex")); |
236 | + _vertical_ls_gauss_filter_prog[k-1]->Link(); |
237 | + } |
238 | |
239 | void GraphicsEngine::InitSLColorMatrixFilter() |
240 | { |
241 | @@ -1982,6 +2094,155 @@ |
242 | |
243 | ShaderProg->End(); |
244 | } |
245 | + |
246 | + void GraphicsEngine::QRP_GLSL_HorizontalLSGauss(int x, int y, int width, int height, ObjectPtr<IOpenGLBaseTexture> device_texture, TexCoordXForm &texxform0, const Color & /* c0 */, float sigma) |
247 | + { |
248 | + std::vector<float> weights(0); |
249 | + std::vector<float> offsets(0); |
250 | + |
251 | + int num_samples = LinearSampleGaussianWeights(weights, offsets, sigma); |
252 | + |
253 | + if (_horizontal_ls_gauss_filter_prog[num_samples-1].IsValid() == false) |
254 | + { |
255 | + InitSLHorizontalLSGaussFilter(num_samples); |
256 | + } |
257 | + |
258 | + m_quad_tex_stats++; |
259 | + QRP_Compute_Texture_Coord(width, height, device_texture, texxform0); |
260 | + float fx = x, fy = y; |
261 | + float vtx_buffer[] = |
262 | + { |
263 | + fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0, 0, |
264 | + fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0, 0, |
265 | + fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0, 0, |
266 | + fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0, 0, |
267 | + }; |
268 | + |
269 | + ObjectPtr<IOpenGLShaderProgram> shader_prog; |
270 | + |
271 | + if (!device_texture->Type().IsDerivedFromType(IOpenGLTexture2D::StaticObjectType)) |
272 | + { |
273 | + return; |
274 | + } |
275 | + |
276 | + shader_prog = _horizontal_ls_gauss_filter_prog[num_samples-1]; |
277 | + |
278 | + CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); |
279 | + CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); |
280 | + shader_prog->Begin(); |
281 | + |
282 | + int tex_object_location = shader_prog->GetUniformLocationARB("tex_object"); |
283 | + int weights_location = shader_prog->GetUniformLocationARB("weights"); |
284 | + int offsets_location = shader_prog->GetUniformLocationARB("offsets"); |
285 | + int tex_size_location = shader_prog->GetUniformLocationARB("tex_size"); |
286 | + int vertex_location = shader_prog->GetAttributeLocation("vertex"); |
287 | + int tex_coord_location = shader_prog->GetAttributeLocation("tex_coord"); |
288 | + |
289 | + SetTexture(GL_TEXTURE0, device_texture); |
290 | + CHECKGL(glUniform1iARB(tex_object_location, 0)); |
291 | + |
292 | + CHECKGL(glUniform1fv(weights_location, weights.size(), &weights[0])); |
293 | + CHECKGL(glUniform1fv(offsets_location, offsets.size(), &offsets[0])); |
294 | + |
295 | + CHECKGL(glUniform2fARB(tex_size_location, width, height)); |
296 | + |
297 | + int VPMatrixLocation = shader_prog->GetUniformLocationARB("view_projection_matrix"); |
298 | + Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); |
299 | + shader_prog->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); |
300 | + |
301 | + CHECKGL(glEnableVertexAttribArrayARB(vertex_location)); |
302 | + CHECKGL(glVertexAttribPointerARB((GLuint) vertex_location, 4, GL_FLOAT, GL_FALSE, 32, vtx_buffer)); |
303 | + |
304 | + if (tex_coord_location != -1) |
305 | + { |
306 | + CHECKGL(glEnableVertexAttribArrayARB(tex_coord_location)); |
307 | + CHECKGL(glVertexAttribPointerARB((GLuint) tex_coord_location, 4, GL_FLOAT, GL_FALSE, 32, vtx_buffer + 4)); |
308 | + } |
309 | + |
310 | + CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); |
311 | + |
312 | + CHECKGL(glDisableVertexAttribArrayARB(vertex_location)); |
313 | + |
314 | + if (tex_coord_location != -1) |
315 | + CHECKGL(glDisableVertexAttribArrayARB(tex_coord_location)); |
316 | + |
317 | + shader_prog->End(); |
318 | + } |
319 | + |
320 | + void GraphicsEngine::QRP_GLSL_VerticalLSGauss(int x, int y, int width, int height, ObjectPtr<IOpenGLBaseTexture> device_texture, TexCoordXForm &texxform0, const Color & /* c0 */, float sigma) |
321 | + { |
322 | + std::vector<float> weights(0); |
323 | + std::vector<float> offsets(0); |
324 | + |
325 | + int num_samples = LinearSampleGaussianWeights(weights, offsets, sigma); |
326 | + |
327 | + if (_vertical_ls_gauss_filter_prog[num_samples-1].IsValid() == false) |
328 | + { |
329 | + InitSLVerticalLSGaussFilter(num_samples); |
330 | + } |
331 | + |
332 | + m_quad_tex_stats++; |
333 | + QRP_Compute_Texture_Coord(width, height, device_texture, texxform0); |
334 | + float fx = x, fy = y; |
335 | + float vtx_buffer[] = |
336 | + { |
337 | + fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0, 0, |
338 | + fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0, 0, |
339 | + fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0, 0, |
340 | + fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0, 0, |
341 | + }; |
342 | + |
343 | + ObjectPtr<IOpenGLShaderProgram> shader_prog; |
344 | + |
345 | + if (!device_texture->Type().IsDerivedFromType(IOpenGLTexture2D::StaticObjectType)) |
346 | + { |
347 | + return; |
348 | + } |
349 | + |
350 | + shader_prog = _vertical_ls_gauss_filter_prog[num_samples-1]; |
351 | + |
352 | + CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); |
353 | + CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); |
354 | + shader_prog->Begin(); |
355 | + |
356 | + int tex_object_location = shader_prog->GetUniformLocationARB("tex_object"); |
357 | + int weights_location = shader_prog->GetUniformLocationARB("weights"); |
358 | + int offsets_location = shader_prog->GetUniformLocationARB("offsets"); |
359 | + int tex_size_location = shader_prog->GetUniformLocationARB("tex_size"); |
360 | + int vertex_location = shader_prog->GetAttributeLocation("vertex"); |
361 | + int tex_coord_location = shader_prog->GetAttributeLocation("tex_coord"); |
362 | + |
363 | + SetTexture(GL_TEXTURE0, device_texture); |
364 | + |
365 | + CHECKGL(glUniform1iARB(tex_object_location, 0)); |
366 | + |
367 | + CHECKGL(glUniform1fv(weights_location, weights.size(), &weights[0])); |
368 | + CHECKGL(glUniform1fv(offsets_location, offsets.size(), &offsets[0])); |
369 | + |
370 | + CHECKGL(glUniform2fARB(tex_size_location, width, height)); |
371 | + |
372 | + int VPMatrixLocation = shader_prog->GetUniformLocationARB("view_projection_matrix"); |
373 | + Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); |
374 | + shader_prog->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); |
375 | + |
376 | + CHECKGL(glEnableVertexAttribArrayARB(vertex_location)); |
377 | + CHECKGL(glVertexAttribPointerARB((GLuint) vertex_location, 4, GL_FLOAT, GL_FALSE, 32, vtx_buffer)); |
378 | + |
379 | + if (tex_coord_location != -1) |
380 | + { |
381 | + CHECKGL(glEnableVertexAttribArrayARB(tex_coord_location)); |
382 | + CHECKGL(glVertexAttribPointerARB((GLuint) tex_coord_location, 4, GL_FLOAT, GL_FALSE, 32, vtx_buffer + 4)); |
383 | + } |
384 | + |
385 | + CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); |
386 | + |
387 | + CHECKGL(glDisableVertexAttribArrayARB(vertex_location)); |
388 | + |
389 | + if (tex_coord_location != -1) |
390 | + CHECKGL(glDisableVertexAttribArrayARB(tex_coord_location)); |
391 | + |
392 | + shader_prog->End(); |
393 | + } |
394 | |
395 | void GraphicsEngine::QRP_GLSL_ColorMatrix(int x, int y, int width, int height, ObjectPtr<IOpenGLBaseTexture> device_texture, TexCoordXForm &texxform0, |
396 | const Color &c0, |
397 | @@ -2133,6 +2394,72 @@ |
398 | |
399 | return _offscreen_color_rt0; |
400 | } |
401 | + |
402 | + ObjectPtr<IOpenGLBaseTexture> GraphicsEngine::QRP_GLSL_GetLSBlurTexture( |
403 | + int x, int y, |
404 | + int buffer_width, int buffer_height, |
405 | + ObjectPtr<IOpenGLBaseTexture> device_texture, TexCoordXForm &texxform, |
406 | + const Color& c0, |
407 | + float sigma, int num_pass) |
408 | + { |
409 | + int quad_width = device_texture->GetWidth(); |
410 | + int quad_height = device_texture->GetHeight(); |
411 | + |
412 | + num_pass = Clamp<int> (num_pass, 1, 50); |
413 | + |
414 | + ObjectPtr<IOpenGLFrameBufferObject> prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); |
415 | + int previous_width = 0; |
416 | + int previous_height = 0; |
417 | + if (prevFBO.IsValid()) |
418 | + { |
419 | + previous_width = prevFBO->GetWidth(); |
420 | + previous_height = prevFBO->GetHeight(); |
421 | + } |
422 | + else |
423 | + { |
424 | + previous_width = _graphics_display.GetWindowWidth(); |
425 | + previous_height = _graphics_display.GetWindowHeight(); |
426 | + } |
427 | + |
428 | + CHECKGL(glClearColor(0, 0, 0, 0)); |
429 | + _offscreen_color_rt0->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); |
430 | + _offscreen_color_rt0->SetFiltering(GL_NEAREST, GL_NEAREST); |
431 | + _offscreen_color_rt1->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); |
432 | + _offscreen_color_rt1->SetFiltering(GL_NEAREST, GL_NEAREST); |
433 | + |
434 | + SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, buffer_width, buffer_height); |
435 | + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
436 | + |
437 | + QRP_GLSL_1Tex(x, y, quad_width, quad_height, device_texture, texxform, color::White); |
438 | + |
439 | + TexCoordXForm texxform1; |
440 | + for (int i = 0; i < num_pass; i++) |
441 | + { |
442 | + SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt1, _offscreen_depth_rt1, buffer_width, buffer_height); |
443 | + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
444 | + QRP_GLSL_HorizontalLSGauss(0, 0, buffer_width, buffer_height, _offscreen_color_rt0, texxform1, c0, sigma); |
445 | + |
446 | + SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, buffer_width, buffer_height); |
447 | + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
448 | + QRP_GLSL_VerticalLSGauss(0, 0, buffer_width, buffer_height, _offscreen_color_rt1, texxform1, c0, sigma); |
449 | + } |
450 | + |
451 | + _offscreen_fbo->Deactivate(); |
452 | + |
453 | + if (prevFBO.IsValid()) |
454 | + { |
455 | + prevFBO->Activate(true); |
456 | + SetViewport(0, 0, previous_width, previous_height); |
457 | + SetOrthographicProjectionMatrix(previous_width, previous_height); |
458 | + } |
459 | + else |
460 | + { |
461 | + SetViewport(0, 0, previous_width, previous_height); |
462 | + SetOrthographicProjectionMatrix(previous_width, previous_height); |
463 | + } |
464 | + |
465 | + return _offscreen_color_rt0; |
466 | + } |
467 | |
468 | ObjectPtr<IOpenGLBaseTexture> GraphicsEngine::QRP_GLSL_GetPower( |
469 | ObjectPtr<IOpenGLBaseTexture> device_texture, TexCoordXForm &texxform, const Color &c0, const Vector4 &exponent) |
470 | @@ -2469,11 +2796,76 @@ |
471 | { |
472 | SetFrameBufferHelper(_offscreen_fbo, fx_structure->temp_texture, _offscreen_depth_rt1, buffer_width, buffer_height); |
473 | glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
474 | - QRP_GLSL_HorizontalHQGauss(0, 0, buffer_width, buffer_height, fx_structure->dst_texture, texxform1, c0, sigma); |
475 | - |
476 | - SetFrameBufferHelper(_offscreen_fbo, fx_structure->dst_texture, _offscreen_depth_rt0, buffer_width, buffer_height); |
477 | - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
478 | - QRP_GLSL_VerticalHQGauss(0, 0, buffer_width, buffer_height, fx_structure->temp_texture, texxform1, c0, sigma); |
479 | + QRP_GLSL_HorizontalGauss(0, 0, buffer_width, buffer_height, fx_structure->dst_texture, texxform1, c0, sigma); |
480 | + |
481 | + SetFrameBufferHelper(_offscreen_fbo, fx_structure->dst_texture, _offscreen_depth_rt0, buffer_width, buffer_height); |
482 | + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
483 | + QRP_GLSL_VerticalGauss(0, 0, buffer_width, buffer_height, fx_structure->temp_texture, texxform1, c0, sigma); |
484 | + } |
485 | + |
486 | + _offscreen_fbo->Deactivate(); |
487 | + |
488 | + if (prevFBO.IsValid()) |
489 | + { |
490 | + prevFBO->Activate(true); |
491 | + SetViewport(0, 0, previous_width, previous_height); |
492 | + SetOrthographicProjectionMatrix(previous_width, previous_height); |
493 | + } |
494 | + else |
495 | + { |
496 | + SetViewport(0, 0, previous_width, previous_height); |
497 | + SetOrthographicProjectionMatrix(previous_width, previous_height); |
498 | + } |
499 | + } |
500 | + |
501 | + void GraphicsEngine::QRP_GLSL_GetLSBlurFx( |
502 | + int x, int y, |
503 | + int buffer_width, int buffer_height, |
504 | + FxStructure *fx_structure, TexCoordXForm &texxform, |
505 | + const Color& c0, float sigma, int num_pass) |
506 | + { |
507 | + int quad_width = fx_structure->src_texture->GetWidth(); |
508 | + int quad_height = fx_structure->src_texture->GetHeight(); |
509 | + |
510 | + num_pass = Clamp<int> (num_pass, 1, 50); |
511 | + |
512 | + ObjectPtr<IOpenGLFrameBufferObject> prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); |
513 | + int previous_width = 0; |
514 | + int previous_height = 0; |
515 | + if (prevFBO.IsValid()) |
516 | + { |
517 | + previous_width = prevFBO->GetWidth(); |
518 | + previous_height = prevFBO->GetHeight(); |
519 | + } |
520 | + else |
521 | + { |
522 | + previous_width = _graphics_display.GetWindowWidth(); |
523 | + previous_height = _graphics_display.GetWindowHeight(); |
524 | + } |
525 | + |
526 | + CHECKGL(glClearColor(0, 0, 0, 0)); |
527 | + fx_structure->src_texture->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); |
528 | + fx_structure->src_texture->SetFiltering(GL_NEAREST, GL_NEAREST); |
529 | + fx_structure->dst_texture->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); |
530 | + fx_structure->dst_texture->SetFiltering(GL_NEAREST, GL_NEAREST); |
531 | + fx_structure->temp_texture->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); |
532 | + fx_structure->temp_texture->SetFiltering(GL_NEAREST, GL_NEAREST); |
533 | + |
534 | + SetFrameBufferHelper(_offscreen_fbo, fx_structure->dst_texture, _offscreen_depth_rt0, buffer_width, buffer_height); |
535 | + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
536 | + |
537 | + QRP_GLSL_1Tex(x, y, quad_width, quad_height, fx_structure->src_texture, texxform, color::White); |
538 | + |
539 | + TexCoordXForm texxform1; |
540 | + for (int i = 0; i < num_pass; i++) |
541 | + { |
542 | + SetFrameBufferHelper(_offscreen_fbo, fx_structure->temp_texture, _offscreen_depth_rt1, buffer_width, buffer_height); |
543 | + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
544 | + QRP_GLSL_HorizontalLSGauss(0, 0, buffer_width, buffer_height, fx_structure->dst_texture, texxform1, c0, sigma); |
545 | + |
546 | + SetFrameBufferHelper(_offscreen_fbo, fx_structure->dst_texture, _offscreen_depth_rt0, buffer_width, buffer_height); |
547 | + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
548 | + QRP_GLSL_VerticalLSGauss(0, 0, buffer_width, buffer_height, fx_structure->temp_texture, texxform1, c0, sigma); |
549 | } |
550 | |
551 | _offscreen_fbo->Deactivate(); |