Depth of field high quality:
[blender.git] / source / blender / gpu / intern / gpu_compositing.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2006 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Antony Riakiotakis.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/gpu/intern/gpu_compositing.c
29  *  \ingroup gpu
30  *
31  * System that manages framebuffer compositing.
32  */
33
34 #include "BLI_sys_types.h"
35 #include "BLI_rect.h"
36 #include "BLI_math.h"
37 #include "BLI_listbase.h"
38 #include "BLI_linklist.h"
39
40 #include "BLI_rand.h"
41 #include "BLI_listbase.h"
42
43 #include "DNA_vec_types.h"
44 #include "DNA_view3d_types.h"
45 #include "DNA_scene_types.h"
46 #include "DNA_object_types.h"
47 #include "DNA_camera_types.h"
48 #include "DNA_gpu_types.h"
49
50 #include "GPU_extensions.h"
51 #include "GPU_compositing.h"
52
53 #include "GL/glew.h"
54
55 #include "MEM_guardedalloc.h"
56
57 static const float fullscreencos[4][2] = {{-1.0f, -1.0f}, {1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}};
58 static const float fullscreenuvs[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}};
59
60 struct GPUFX {
61         /* we borrow the term gbuffer from deferred rendering however this is just a regular
62          * depth/color framebuffer. Could be extended later though */
63         GPUFrameBuffer *gbuffer;
64
65         /* dimensions of the gbuffer */
66         int gbuffer_dim[2];
67
68         /* texture bound to the first color attachment of the gbuffer */
69         GPUTexture *color_buffer;
70
71         /* second texture used for ping-pong compositing */
72         GPUTexture *color_buffer_sec;
73         /* texture bound to the depth attachment of the gbuffer */
74         GPUTexture *depth_buffer;
75         GPUTexture *depth_buffer_xray;
76
77         /* texture used for jittering for various effects */
78         GPUTexture *jitter_buffer;
79
80         /* all those buffers below have to coexist. Fortunately they are all quarter sized (1/16th of memory) of original framebuffer */
81         int dof_downsampled_w;
82         int dof_downsampled_h;
83
84         /* texture used for near coc and color blurring calculation */
85         GPUTexture *dof_near_coc_buffer;
86         /* blurred near coc buffer. */
87         GPUTexture *dof_near_coc_blurred_buffer;
88         /* final near coc buffer. */
89         GPUTexture *dof_near_coc_final_buffer;
90
91         /* half size blur buffer */
92         GPUTexture *dof_half_downsampled_near;
93         GPUTexture *dof_half_downsampled_far;
94         /* high quality dof texture downsamplers. 6 levels means 64 pixels wide - should be enough */
95         GPUTexture *dof_nearfar_coc;
96         GPUTexture *dof_near_blur;
97         GPUTexture *dof_far_blur;
98
99         /* for high quality we use again a spiral texture with radius adapted */
100         bool dof_high_quality;
101
102         /* texture used for ssao */
103         int ssao_sample_count_cache;
104         GPUTexture *ssao_spiral_samples_tex;
105
106
107         GPUFXSettings settings;
108
109         /* or-ed flags of enabled effects */
110         int effects;
111
112         /* number of passes, needed to detect if ping pong buffer allocation is needed */
113         int num_passes;
114
115         /* we have a stencil, restore the previous state */
116         bool restore_stencil;
117 };
118
119 #if 0
120 /* concentric mapping, see "A Low Distortion Map Between Disk and Square" and
121  * http://psgraphics.blogspot.nl/2011/01/improved-code-for-concentric-map.html */
122 static GPUTexture * create_concentric_sample_texture(int side)
123 {
124         GPUTexture *tex;
125         float midpoint = 0.5f * (side - 1);
126         float *texels = (float *)MEM_mallocN(sizeof(float) * 2 * side * side, "concentric_tex");
127         int i, j;
128
129         for (i = 0; i < side; i++) {
130                 for (j = 0; j < side; j++) {
131                         int index = (i * side + j) * 2;
132                         float a = 1.0f - i / midpoint;
133                         float b = 1.0f - j / midpoint;
134                         float phi, r;
135                         if (a * a > b * b) {
136                                 r = a;
137                                 phi = (M_PI_4) * (b / a);
138                         }
139                         else {
140                                 r = b;
141                                 phi = M_PI_2 - (M_PI_4) * (a / b);
142                         }
143                         texels[index] = r * cos(phi);
144                         texels[index + 1] = r * sin(phi);
145                 }
146         }
147
148         tex = GPU_texture_create_1D_procedural(side * side, texels, NULL);
149         MEM_freeN(texels);
150         return tex;
151 }
152 #endif
153
154 static GPUTexture *create_spiral_sample_texture(int numsaples)
155 {
156         GPUTexture *tex;
157         float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * numsaples, "concentric_tex");
158         const float numsaples_inv = 1.0f / numsaples;
159         int i;
160         /* arbitrary number to ensure we don't get conciding samples every circle */
161         const float spirals = 7.357;
162
163         for (i = 0; i < numsaples; i++) {
164                 float r = (i + 0.5f) * numsaples_inv;
165                 float phi = r * spirals * (float)(2.0 * M_PI);
166                 texels[i][0] = r * cosf(phi);
167                 texels[i][1] = r * sinf(phi);
168         }
169
170         tex = GPU_texture_create_1D_procedural(numsaples, (float *)texels, NULL);
171         MEM_freeN(texels);
172         return tex;
173 }
174
175 /* generate a new FX compositor */
176 GPUFX *GPU_fx_compositor_create(void)
177 {
178         GPUFX *fx = MEM_callocN(sizeof(GPUFX), "GPUFX compositor");
179
180         return fx;
181 }
182
183 static void cleanup_fx_dof_buffers(GPUFX *fx)
184 {
185         if (fx->dof_near_coc_blurred_buffer) {
186                 GPU_texture_free(fx->dof_near_coc_blurred_buffer);
187                 fx->dof_near_coc_blurred_buffer = NULL;
188         }
189         if (fx->dof_near_coc_buffer) {
190                 GPU_texture_free(fx->dof_near_coc_buffer);
191                 fx->dof_near_coc_buffer = NULL;
192         }
193         if (fx->dof_near_coc_final_buffer) {
194                 GPU_texture_free(fx->dof_near_coc_final_buffer);
195                 fx->dof_near_coc_final_buffer = NULL;
196         }
197
198         if (fx->dof_half_downsampled_near) {
199                 GPU_texture_free(fx->dof_half_downsampled_near);
200                 fx->dof_half_downsampled_near = NULL;
201         }
202         if (fx->dof_half_downsampled_far) {
203                 GPU_texture_free(fx->dof_half_downsampled_far);
204                 fx->dof_half_downsampled_far = NULL;
205         }
206         if (fx->dof_nearfar_coc) {
207                 GPU_texture_free(fx->dof_nearfar_coc);
208                 fx->dof_nearfar_coc = NULL;
209         }
210         if (fx->dof_near_blur) {
211                 GPU_texture_free(fx->dof_near_blur);
212                 fx->dof_near_blur = NULL;
213         }
214         if (fx->dof_far_blur) {
215                 GPU_texture_free(fx->dof_far_blur);
216                 fx->dof_far_blur = NULL;
217         }
218 }
219
220 static void cleanup_fx_gl_data(GPUFX *fx, bool do_fbo)
221 {
222         if (fx->color_buffer) {
223                 GPU_framebuffer_texture_detach(fx->color_buffer);
224                 GPU_texture_free(fx->color_buffer);
225                 fx->color_buffer = NULL;
226         }
227
228         if (fx->color_buffer_sec) {
229                 GPU_framebuffer_texture_detach(fx->color_buffer_sec);
230                 GPU_texture_free(fx->color_buffer_sec);
231                 fx->color_buffer_sec = NULL;
232         }
233
234         if (fx->depth_buffer) {
235                 GPU_framebuffer_texture_detach(fx->depth_buffer);
236                 GPU_texture_free(fx->depth_buffer);
237                 fx->depth_buffer = NULL;
238         }
239
240         if (fx->depth_buffer_xray) {
241                 GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
242                 GPU_texture_free(fx->depth_buffer_xray);
243                 fx->depth_buffer_xray = NULL;
244         }
245
246         cleanup_fx_dof_buffers(fx);
247
248         if (fx->ssao_spiral_samples_tex) {
249                 GPU_texture_free(fx->ssao_spiral_samples_tex);
250                 fx->ssao_spiral_samples_tex = NULL;
251         }
252
253         if (fx->jitter_buffer && do_fbo) {
254                 GPU_texture_free(fx->jitter_buffer);
255                 fx->jitter_buffer = NULL;
256         }
257
258         if (fx->gbuffer && do_fbo) {
259                 GPU_framebuffer_free(fx->gbuffer);
260                 fx->gbuffer = NULL;
261         }
262 }
263
264 /* destroy a text compositor */
265 void GPU_fx_compositor_destroy(GPUFX *fx)
266 {
267         cleanup_fx_gl_data(fx, true);
268         MEM_freeN(fx);
269 }
270
271 static GPUTexture * create_jitter_texture(void)
272 {
273         float jitter [64 * 64][2];
274         int i;
275
276         for (i = 0; i < 64 * 64; i++) {
277                 jitter[i][0] = 2.0f * BLI_frand() - 1.0f;
278                 jitter[i][1] = 2.0f * BLI_frand() - 1.0f;
279                 normalize_v2(jitter[i]);
280         }
281
282         return GPU_texture_create_2D_procedural(64, 64, &jitter[0][0], true, NULL);
283 }
284
285
286 bool GPU_fx_compositor_initialize_passes(
287         GPUFX *fx, const rcti *rect, const rcti *scissor_rect,
288         const GPUFXSettings *fx_settings)
289 {
290         int w = BLI_rcti_size_x(rect), h = BLI_rcti_size_y(rect);
291         char err_out[256];
292         int num_passes = 0;
293         char fx_flag;
294
295         fx->effects = 0;
296
297         if (!fx_settings) {
298                 cleanup_fx_gl_data(fx, true);
299                 return false;
300         }
301
302         fx_flag = fx_settings->fx_flag;
303
304         /* disable effects if no options passed for them */
305         if (!fx_settings->dof) {
306                 fx_flag &= ~GPU_FX_FLAG_DOF;
307         }
308         if (!fx_settings->ssao || fx_settings->ssao->samples < 1) {
309                 fx_flag &= ~GPU_FX_FLAG_SSAO;
310         }
311
312         if (!fx_flag) {
313                 cleanup_fx_gl_data(fx, true);
314                 return false;
315         }
316
317         /* scissor is missing when drawing offscreen, in that case, dimensions match exactly. In opposite case
318          * add one to match viewport dimensions */
319         if (scissor_rect) {
320                 w++, h++;
321         }
322
323         fx->num_passes = 0;
324         /* dof really needs a ping-pong buffer to work */
325         if (fx_flag & GPU_FX_FLAG_DOF)
326                 num_passes++;
327
328         if (fx_flag & GPU_FX_FLAG_SSAO)
329                 num_passes++;
330
331         if (!fx->gbuffer)
332                 fx->gbuffer = GPU_framebuffer_create();
333
334         /* try creating the jitter texture */
335         if (!fx->jitter_buffer)
336                 fx->jitter_buffer = create_jitter_texture();
337
338         if (!fx->gbuffer)
339                 return false;
340
341         /* check if color buffers need recreation */
342         if (!fx->color_buffer || !fx->depth_buffer || w != fx->gbuffer_dim[0] || h != fx->gbuffer_dim[1]) {
343                 cleanup_fx_gl_data(fx, false);
344
345                 if (!(fx->color_buffer = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) {
346                         printf(".256%s\n", err_out);
347                         cleanup_fx_gl_data(fx, true);
348                         return false;
349                 }
350
351                 if (!(fx->depth_buffer = GPU_texture_create_depth(w, h, err_out))) {
352                         printf("%.256s\n", err_out);
353                         cleanup_fx_gl_data(fx, true);
354                         return false;
355                 }
356         }
357
358         if (fx_flag & GPU_FX_FLAG_SSAO) {
359                 if (fx_settings->ssao->samples != fx->ssao_sample_count_cache || !fx->ssao_spiral_samples_tex) {
360                         if (fx_settings->ssao->samples < 1)
361                                 fx_settings->ssao->samples = 1;
362
363                         fx->ssao_sample_count_cache = fx_settings->ssao->samples;
364
365                         if (fx->ssao_spiral_samples_tex) {
366                                 GPU_texture_free(fx->ssao_spiral_samples_tex);
367                         }
368
369                         fx->ssao_spiral_samples_tex = create_spiral_sample_texture(fx_settings->ssao->samples);
370                 }
371         }
372         else {
373                 if (fx->ssao_spiral_samples_tex) {
374                         GPU_texture_free(fx->ssao_spiral_samples_tex);
375                         fx->ssao_spiral_samples_tex = NULL;
376                 }
377         }
378
379         /* create textures for dof effect */
380         if (fx_flag & GPU_FX_FLAG_DOF) {
381                 bool dof_high_quality = (fx_settings->dof->high_quality != 0);
382
383                 if (dof_high_quality) {
384                         fx->dof_downsampled_w = w / 2;
385                         fx->dof_downsampled_h = h / 2;
386
387                         if (!fx->dof_half_downsampled_near || !fx->dof_nearfar_coc || !fx->dof_near_blur ||
388                             !fx->dof_far_blur || !fx->dof_half_downsampled_far) {
389
390                                 if (!(fx->dof_half_downsampled_near = GPU_texture_create_2D(
391                                       fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
392                                 {
393                                         printf("%.256s\n", err_out);
394                                         cleanup_fx_gl_data(fx, true);
395                                         return false;
396                                 }
397                                 if (!(fx->dof_half_downsampled_far = GPU_texture_create_2D(
398                                       fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
399                                 {
400                                         printf("%.256s\n", err_out);
401                                         cleanup_fx_gl_data(fx, true);
402                                         return false;
403                                 }
404                                 if (!(fx->dof_nearfar_coc = GPU_texture_create_2D_procedural(
405                                       fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, false, err_out)))
406                                 {
407                                         printf("%.256s\n", err_out);
408                                         cleanup_fx_gl_data(fx, true);
409                                         return false;
410                                 }
411
412
413                                 if (!(fx->dof_near_blur = GPU_texture_create_2D(
414                                     fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out)))
415                                 {
416                                         printf("%.256s\n", err_out);
417                                         cleanup_fx_gl_data(fx, true);
418                                         return false;
419                                 }
420
421                                 if (!(fx->dof_far_blur = GPU_texture_create_2D(
422                                     fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out)))
423                                 {
424                                         printf("%.256s\n", err_out);
425                                         cleanup_fx_gl_data(fx, true);
426                                         return false;
427                                 }
428                         }
429                 }
430                 else {
431                         fx->dof_downsampled_w = w / 4;
432                         fx->dof_downsampled_h = h / 4;
433
434                         if (!fx->dof_near_coc_buffer || !fx->dof_near_coc_blurred_buffer || !fx->dof_near_coc_final_buffer) {
435
436                                 if (!(fx->dof_near_coc_buffer = GPU_texture_create_2D(
437                                           fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
438                                 {
439                                         printf("%.256s\n", err_out);
440                                         cleanup_fx_gl_data(fx, true);
441                                         return false;
442                                 }
443                                 if (!(fx->dof_near_coc_blurred_buffer = GPU_texture_create_2D(
444                                           fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
445                                 {
446                                         printf("%.256s\n", err_out);
447                                         cleanup_fx_gl_data(fx, true);
448                                         return false;
449                                 }
450                                 if (!(fx->dof_near_coc_final_buffer = GPU_texture_create_2D(
451                                           fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
452                                 {
453                                         printf("%.256s\n", err_out);
454                                         cleanup_fx_gl_data(fx, true);
455                                         return false;
456                                 }
457                         }
458                 }
459
460                 fx->dof_high_quality = dof_high_quality;
461         }
462         else {
463                 /* cleanup unnecessary buffers */
464                 cleanup_fx_dof_buffers(fx);
465         }
466
467         /* we need to pass data between shader stages, allocate an extra color buffer */
468         if (num_passes > 1) {
469                 if(!fx->color_buffer_sec) {
470                         if (!(fx->color_buffer_sec = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) {
471                                 printf(".256%s\n", err_out);
472                                 cleanup_fx_gl_data(fx, true);
473                                 return false;
474                         }
475                 }
476         }
477         else {
478                 if (fx->color_buffer_sec) {
479                         GPU_framebuffer_texture_detach(fx->color_buffer_sec);
480                         GPU_texture_free(fx->color_buffer_sec);
481                         fx->color_buffer_sec = NULL;
482                 }
483         }
484
485         /* bind the buffers */
486
487         /* first depth buffer, because system assumes read/write buffers */
488         if(!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, err_out))
489                 printf("%.256s\n", err_out);
490
491         if(!GPU_framebuffer_texture_attach(fx->gbuffer, fx->color_buffer, 0, err_out))
492                 printf("%.256s\n", err_out);
493
494         if(!GPU_framebuffer_check_valid(fx->gbuffer, err_out))
495                 printf("%.256s\n", err_out);
496
497         GPU_texture_bind_as_framebuffer(fx->color_buffer);
498
499         /* enable scissor test. It's needed to ensure sculpting works correctly */
500         if (scissor_rect) {
501                 int w_sc = BLI_rcti_size_x(scissor_rect) + 1;
502                 int h_sc = BLI_rcti_size_y(scissor_rect) + 1;
503                 glPushAttrib(GL_SCISSOR_BIT);
504                 glEnable(GL_SCISSOR_TEST);
505                 glScissor(scissor_rect->xmin - rect->xmin, scissor_rect->ymin - rect->ymin,
506                                   w_sc, h_sc);
507                 fx->restore_stencil = true;
508         }
509         else {
510                 fx->restore_stencil = false;
511         }
512
513         fx->effects = fx_flag;
514
515         if (fx_settings)
516                 fx->settings = *fx_settings;
517         fx->gbuffer_dim[0] = w;
518         fx->gbuffer_dim[1] = h;
519
520         fx->num_passes = num_passes;
521
522         return true;
523 }
524
525 static void gpu_fx_bind_render_target(int *passes_left, GPUFX *fx, struct GPUOffScreen *ofs, GPUTexture *target)
526 {
527         if ((*passes_left)-- == 1) {
528                 GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
529                 if (ofs) {
530                         GPU_offscreen_bind(ofs, false);
531                 }
532                 else
533                         GPU_framebuffer_restore();
534         }
535         else {
536                 /* bind the ping buffer to the color buffer */
537                 GPU_framebuffer_texture_attach(fx->gbuffer, target, 0, NULL);
538         }
539 }
540
541 void GPU_fx_compositor_setup_XRay_pass(GPUFX *fx, bool do_xray)
542 {
543         char err_out[256];
544
545         if (do_xray) {
546                 if (!fx->depth_buffer_xray && !(fx->depth_buffer_xray = GPU_texture_create_depth(fx->gbuffer_dim[0], fx->gbuffer_dim[1], err_out))) {
547                         printf("%.256s\n", err_out);
548                         cleanup_fx_gl_data(fx, true);
549                         return;
550                 }
551         }
552         else {
553                 if (fx->depth_buffer_xray) {
554                         GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
555                         GPU_texture_free(fx->depth_buffer_xray);
556                         fx->depth_buffer_xray = NULL;
557                 }
558                 return;
559         }
560
561         GPU_framebuffer_texture_detach(fx->depth_buffer);
562
563         /* first depth buffer, because system assumes read/write buffers */
564         if(!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer_xray, 0, err_out))
565                 printf("%.256s\n", err_out);
566 }
567
568
569 void GPU_fx_compositor_XRay_resolve(GPUFX *fx)
570 {
571         GPUShader *depth_resolve_shader;
572         GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
573
574         /* attach regular framebuffer */
575         GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, NULL);
576
577         /* full screen quad where we will always write to depth buffer */
578         glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT);
579         glDepthFunc(GL_ALWAYS);
580         /* disable scissor from sculpt if any */
581         glDisable(GL_SCISSOR_TEST);
582         /* disable writing to color buffer, it's depth only pass */
583         glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
584
585         /* set up quad buffer */
586         glVertexPointer(2, GL_FLOAT, 0, fullscreencos);
587         glTexCoordPointer(2, GL_FLOAT, 0, fullscreenuvs);
588         glEnableClientState(GL_VERTEX_ARRAY);
589         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
590
591         depth_resolve_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_RESOLVE, false);
592
593         if (depth_resolve_shader) {
594                 int depth_uniform;
595
596                 depth_uniform = GPU_shader_get_uniform(depth_resolve_shader, "depthbuffer");
597
598                 GPU_shader_bind(depth_resolve_shader);
599
600                 GPU_texture_bind(fx->depth_buffer_xray, 0);
601                 GPU_texture_filter_mode(fx->depth_buffer_xray, false, true);
602                 GPU_shader_uniform_texture(depth_resolve_shader, depth_uniform, fx->depth_buffer_xray);
603
604                 /* draw */
605                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
606
607                 /* disable bindings */
608                 GPU_texture_filter_mode(fx->depth_buffer_xray, true, false);
609                 GPU_texture_unbind(fx->depth_buffer_xray);
610
611                 GPU_shader_unbind();
612         }
613
614         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
615
616         glDisableClientState(GL_VERTEX_ARRAY);
617         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
618
619         glPopAttrib();
620 }
621
622
623 bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, struct Scene *scene, struct GPUOffScreen *ofs)
624 {
625         GPUTexture *src, *target;
626         int numslots = 0;
627         float invproj[4][4];
628         int i;
629         /* number of passes left. when there are no more passes, the result is passed to the frambuffer */
630         int passes_left = fx->num_passes;
631         /* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */
632         float viewvecs[3][4] = {
633             {-1.0f, -1.0f, -1.0f, 1.0f},
634             {1.0f, -1.0f, -1.0f, 1.0f},
635             {-1.0f, 1.0f, -1.0f, 1.0f}
636         };
637
638         if (fx->effects == 0)
639                 return false;
640
641         /* first, unbind the render-to-texture framebuffer */
642         GPU_framebuffer_texture_detach(fx->color_buffer);
643         GPU_framebuffer_texture_detach(fx->depth_buffer);
644
645         if (fx->restore_stencil)
646                 glPopAttrib();
647
648         src = fx->color_buffer;
649         target = fx->color_buffer_sec;
650
651         /* set up quad buffer */
652         glVertexPointer(2, GL_FLOAT, 0, fullscreencos);
653         glTexCoordPointer(2, GL_FLOAT, 0, fullscreenuvs);
654         glEnableClientState(GL_VERTEX_ARRAY);
655         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
656
657         /* full screen FX pass */
658
659         /* invert the view matrix */
660         invert_m4_m4(invproj, projmat);
661
662         /* convert the view vectors to view space */
663         for (i = 0; i < 3; i++) {
664                 mul_m4_v4(invproj, viewvecs[i]);
665                 /* normalized trick see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
666                 mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
667                 if (is_persp)
668                         mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
669                 viewvecs[i][3] = 1.0;
670         }
671
672         /* we need to store the differences */
673         viewvecs[1][0] -= viewvecs[0][0];
674         viewvecs[1][1] = viewvecs[2][1] - viewvecs[0][1];
675
676         /* calculate a depth offset as well */
677         if (!is_persp) {
678                 float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
679                 mul_m4_v4(invproj, vec_far);
680                 mul_v3_fl(vec_far, 1.0f / vec_far[3]);
681                 viewvecs[1][2] = vec_far[2] - viewvecs[0][2];
682         }
683
684         /* set invalid color in case shader fails */
685         glColor3f(1.0, 0.0, 1.0);
686         glDisable(GL_DEPTH_TEST);
687
688         /* ssao pass */
689         if (fx->effects & GPU_FX_FLAG_SSAO) {
690                 GPUShader *ssao_shader;
691                 ssao_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_SSAO, is_persp);
692                 if (ssao_shader) {
693                         const GPUSSAOSettings *fx_ssao = fx->settings.ssao;
694                         int color_uniform, depth_uniform;
695                         int ssao_uniform, ssao_color_uniform, viewvecs_uniform, ssao_sample_params_uniform;
696                         int ssao_jitter_uniform, ssao_concentric_tex;
697                         float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, fx_ssao->attenuation, 0.0f};
698                         float sample_params[4];
699
700                         sample_params[0] = fx->ssao_sample_count_cache;
701                         /* multiplier so we tile the random texture on screen */
702                         sample_params[2] = fx->gbuffer_dim[0] / 64.0;
703                         sample_params[3] = fx->gbuffer_dim[1] / 64.0;
704
705                         ssao_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_params");
706                         ssao_color_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_color");
707                         color_uniform = GPU_shader_get_uniform(ssao_shader, "colorbuffer");
708                         depth_uniform = GPU_shader_get_uniform(ssao_shader, "depthbuffer");
709                         viewvecs_uniform = GPU_shader_get_uniform(ssao_shader, "viewvecs");
710                         ssao_sample_params_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_sample_params");
711                         ssao_concentric_tex = GPU_shader_get_uniform(ssao_shader, "ssao_concentric_tex");
712                         ssao_jitter_uniform = GPU_shader_get_uniform(ssao_shader, "jitter_tex");
713
714                         GPU_shader_bind(ssao_shader);
715
716                         GPU_shader_uniform_vector(ssao_shader, ssao_uniform, 4, 1, ssao_params);
717                         GPU_shader_uniform_vector(ssao_shader, ssao_color_uniform, 4, 1, fx_ssao->color);
718                         GPU_shader_uniform_vector(ssao_shader, viewvecs_uniform, 4, 3, viewvecs[0]);
719                         GPU_shader_uniform_vector(ssao_shader, ssao_sample_params_uniform, 4, 1, sample_params);
720
721                         GPU_texture_bind(src, numslots++);
722                         GPU_shader_uniform_texture(ssao_shader, color_uniform, src);
723
724                         GPU_texture_bind(fx->depth_buffer, numslots++);
725                         GPU_texture_filter_mode(fx->depth_buffer, false, true);
726                         GPU_shader_uniform_texture(ssao_shader, depth_uniform, fx->depth_buffer);
727
728                         GPU_texture_bind(fx->jitter_buffer, numslots++);
729                         GPU_shader_uniform_texture(ssao_shader, ssao_jitter_uniform, fx->jitter_buffer);
730
731                         GPU_texture_bind(fx->ssao_spiral_samples_tex, numslots++);
732                         GPU_shader_uniform_texture(ssao_shader, ssao_concentric_tex, fx->ssao_spiral_samples_tex);
733
734                         /* draw */
735                         gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
736
737                         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
738
739                         /* disable bindings */
740                         GPU_texture_unbind(src);
741                         GPU_texture_filter_mode(fx->depth_buffer, true, false);
742                         GPU_texture_unbind(fx->depth_buffer);
743                         GPU_texture_unbind(fx->jitter_buffer);
744                         GPU_texture_unbind(fx->ssao_spiral_samples_tex);
745
746                         /* may not be attached, in that case this just returns */
747                         if (target) {
748                                 GPU_framebuffer_texture_detach(target);
749                                 if (ofs) {
750                                         GPU_offscreen_bind(ofs, false);
751                                 }
752                                 else {
753                                         GPU_framebuffer_restore();
754                                 }
755                         }
756
757                         /* swap here, after src/target have been unbound */
758                         SWAP(GPUTexture *, target, src);
759                         numslots = 0;
760                 }
761         }
762
763         /* second pass, dof */
764         if (fx->effects & GPU_FX_FLAG_DOF) {
765                 const GPUDOFSettings *fx_dof = fx->settings.dof;
766                 float dof_params[4];
767                 float scale = scene->unit.system ? scene->unit.scale_length : 1.0f;
768                 /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm
769                  * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though
770                  * because the shader reads coordinates in world space, which is in blender units. */
771                 float scale_camera = 0.001f / scale;
772                 /* we want radius here for the aperture number  */
773                 float aperture = 0.5f * scale_camera * fx_dof->focal_length / fx_dof->fstop;
774
775                 dof_params[0] = aperture * fabsf(scale_camera * fx_dof->focal_length / ((fx_dof->focus_distance / scale) - scale_camera * fx_dof->focal_length));
776                 dof_params[1] = fx_dof->focus_distance / scale;
777                 dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
778                 dof_params[3] = fx_dof->num_blades;
779
780                 if (fx->dof_high_quality) {
781                         GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3;
782
783                         /* custom shaders close to the effect described in CryEngine 3 Graphics Gems */
784                         dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE, is_persp);
785                         dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO, is_persp);
786                         dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE, is_persp);
787
788                         /* error occured, restore framebuffers and return */
789                         if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3)) {
790                                 GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
791                                 GPU_framebuffer_restore();
792                                 glDisableClientState(GL_VERTEX_ARRAY);
793                                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
794
795                                 GPU_shader_unbind();
796                                 return false;
797                         }
798
799                         /* pass first, downsample the color buffer to near/far targets and calculate coc texture */
800                         {
801                                 int depth_uniform, dof_uniform;
802                                 int viewvecs_uniform;
803                                 int invrendertargetdim_uniform, color_uniform;
804
805                                 float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h};
806
807                                 invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim");
808                                 color_uniform = GPU_shader_get_uniform(dof_shader_pass1, "colorbuffer");
809                                 dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params");
810                                 invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim");
811                                 depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer");
812                                 viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs");
813
814                                 GPU_shader_bind(dof_shader_pass1);
815
816                                 GPU_shader_uniform_vector(dof_shader_pass1, dof_uniform, 4, 1, dof_params);
817                                 GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
818                                 GPU_shader_uniform_vector(dof_shader_pass1, viewvecs_uniform, 4, 3, viewvecs[0]);
819
820                                 GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
821
822                                 GPU_texture_bind(fx->depth_buffer, numslots++);
823                                 GPU_texture_filter_mode(fx->depth_buffer, false, false);
824                                 GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer);
825
826                                 GPU_texture_bind(src, numslots++);
827                                 /* disable filtering for the texture so custom downsample can do the right thing */
828                                 GPU_texture_filter_mode(src, false, false);
829                                 GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, src);
830
831                                 /* target is the downsampled coc buffer */
832                                 GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_near, 0, NULL);
833                                 GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_far, 1, NULL);
834                                 GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_nearfar_coc, 2, NULL);
835                                 /* binding takes care of setting the viewport to the downsampled size */
836                                 GPU_framebuffer_slots_bind(fx->gbuffer, 0);
837
838                                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
839                                 /* disable bindings */
840                                 GPU_texture_filter_mode(src, false, true);
841                                 GPU_texture_unbind(src);
842                                 GPU_texture_filter_mode(fx->depth_buffer, true, false);
843                                 GPU_texture_unbind(fx->depth_buffer);
844
845                                 GPU_framebuffer_texture_detach(fx->dof_half_downsampled_near);
846                                 GPU_framebuffer_texture_detach(fx->dof_half_downsampled_far);
847                                 GPU_framebuffer_texture_detach(fx->dof_nearfar_coc);
848                                 GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_half_downsampled_near);
849
850                                 numslots = 0;
851                         }
852
853                         /* second pass, shoot quads for every pixel in the downsampled buffers, scaling according
854                          * to circle of confusion */
855                         {
856                                 int rendertargetdim_uniform, coc_uniform, color_uniform, select_uniform, dof_uniform;
857                                 int rendertargetdim[2] = {fx->dof_downsampled_w, fx->dof_downsampled_h};
858                                 float selection[2] = {0.0f, 1.0f};
859
860                                 rendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass2, "rendertargetdim");
861
862                                 color_uniform = GPU_shader_get_uniform(dof_shader_pass2, "colorbuffer");
863                                 coc_uniform = GPU_shader_get_uniform(dof_shader_pass2, "cocbuffer");
864                                 select_uniform = GPU_shader_get_uniform(dof_shader_pass2, "layerselection");
865                                 dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params");
866
867                                 GPU_shader_bind(dof_shader_pass2);
868
869                                 GPU_shader_uniform_vector(dof_shader_pass2, dof_uniform, 4, 1, dof_params);
870                                 GPU_shader_uniform_vector_int(dof_shader_pass2, rendertargetdim_uniform, 2, 1, rendertargetdim);
871                                 GPU_shader_uniform_vector(dof_shader_pass2, select_uniform, 2, 1, selection);
872
873                                 GPU_texture_bind(fx->dof_nearfar_coc, numslots++);
874                                 GPU_shader_uniform_texture(dof_shader_pass2, coc_uniform, fx->dof_nearfar_coc);
875
876                                 GPU_texture_bind(fx->dof_half_downsampled_far, numslots++);
877                                 GPU_texture_bind(fx->dof_half_downsampled_near, numslots++);
878                                 GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_half_downsampled_far);
879                                 GPU_texture_filter_mode(fx->dof_half_downsampled_far, false, false);
880
881                                 /* target is the downsampled coc buffer */
882                                 GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_far_blur, 0, NULL);
883                                 GPU_texture_bind_as_framebuffer(fx->dof_far_blur);
884
885                                 glEnable(GL_BLEND);
886                                 glBlendFunc(GL_ONE, GL_ONE);
887                                 /* have to clear the buffer unfortunately */
888                                 glClearColor(0.0, 0.0, 0.0, 0.0);
889                                 glClear(GL_COLOR_BUFFER_BIT);
890                                 /* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */
891                                 glDrawArraysInstancedEXT(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h);
892
893                                 GPU_texture_unbind(fx->dof_half_downsampled_far);
894                                 GPU_framebuffer_texture_detach(fx->dof_far_blur);
895
896                                 GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_half_downsampled_near);
897                                 GPU_texture_filter_mode(fx->dof_half_downsampled_near, false, false);
898
899                                 selection[0] = 1.0f;
900                                 selection[1] = 0.0f;
901
902                                 GPU_shader_uniform_vector(dof_shader_pass2, select_uniform, 2, 1, selection);
903
904                                 GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_blur, 0, NULL);
905                                 /* have to clear the buffer unfortunately */
906                                 glClear(GL_COLOR_BUFFER_BIT);
907                                 /* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */
908                                 glDrawArraysInstancedEXT(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h);
909
910                                 /* disable bindings */
911                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
912                                 glDisable(GL_BLEND);
913
914                                 GPU_framebuffer_texture_detach(fx->dof_near_blur);
915
916                                 GPU_texture_unbind(fx->dof_half_downsampled_near);
917                                 GPU_texture_unbind(fx->dof_nearfar_coc);
918
919                                 GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_far_blur);
920                         }
921
922                         /* third pass, accumulate the near/far blur fields */
923                         {
924                                 int invrendertargetdim_uniform, near_uniform, color_uniform;
925                                 int dof_uniform, far_uniform, viewvecs_uniform, depth_uniform;
926
927                                 float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h};
928
929                                 dof_uniform = GPU_shader_get_uniform(dof_shader_pass3, "dof_params");
930                                 invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass3, "invrendertargetdim");
931                                 color_uniform = GPU_shader_get_uniform(dof_shader_pass3, "colorbuffer");
932                                 far_uniform = GPU_shader_get_uniform(dof_shader_pass3, "farbuffer");
933                                 near_uniform = GPU_shader_get_uniform(dof_shader_pass3, "nearbuffer");
934                                 viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs");
935                                 depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer");
936
937                                 GPU_shader_bind(dof_shader_pass3);
938
939                                 GPU_shader_uniform_vector(dof_shader_pass3, dof_uniform, 4, 1, dof_params);
940
941                                 GPU_shader_uniform_vector(dof_shader_pass3, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
942                                 GPU_shader_uniform_vector(dof_shader_pass3, viewvecs_uniform, 4, 3, viewvecs[0]);
943
944                                 GPU_texture_bind(fx->dof_near_blur, numslots++);
945                                 GPU_shader_uniform_texture(dof_shader_pass3, near_uniform, fx->dof_near_blur);
946                                 GPU_texture_filter_mode(fx->dof_near_blur, false, false);
947
948                                 GPU_texture_bind(fx->dof_far_blur, numslots++);
949                                 GPU_shader_uniform_texture(dof_shader_pass3, far_uniform, fx->dof_far_blur);
950                                 GPU_texture_filter_mode(fx->dof_far_blur, false, false);
951
952                                 GPU_texture_bind(fx->depth_buffer, numslots++);
953                                 GPU_texture_filter_mode(fx->depth_buffer, false, false);
954                                 GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer);
955
956                                 GPU_texture_bind(src, numslots++);
957                                 GPU_shader_uniform_texture(dof_shader_pass3, color_uniform, src);
958
959                                 /* if this is the last pass, prepare for rendering on the frambuffer */
960                                 gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
961
962                                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
963
964                                 /* disable bindings */
965                                 GPU_texture_unbind(fx->dof_near_blur);
966                                 GPU_texture_unbind(fx->dof_far_blur);
967                                 GPU_texture_unbind(src);
968                                 GPU_texture_filter_mode(fx->depth_buffer, true, false);
969                                 GPU_texture_unbind(fx->depth_buffer);
970
971                                 /* may not be attached, in that case this just returns */
972                                 if (target) {
973                                         GPU_framebuffer_texture_detach(target);
974                                         if (ofs) {
975                                                 GPU_offscreen_bind(ofs, false);
976                                         }
977                                         else {
978                                                 GPU_framebuffer_restore();
979                                         }
980                                 }
981
982                                 numslots = 0;
983                         }
984                 }
985                 else {
986                         GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3, *dof_shader_pass4, *dof_shader_pass5;
987
988                         /* DOF effect has many passes but most of them are performed on a texture whose dimensions are 4 times less than the original
989                          * (16 times lower than original screen resolution). Technique used is not very exact but should be fast enough and is based
990                          * on "Practical Post-Process Depth of Field" see http://http.developer.nvidia.com/GPUGems3/gpugems3_ch28.html */
991                         dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE, is_persp);
992                         dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO, is_persp);
993                         dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE, is_persp);
994                         dof_shader_pass4 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR, is_persp);
995                         dof_shader_pass5 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE, is_persp);
996
997                         /* error occured, restore framebuffers and return */
998                         if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3 && dof_shader_pass4 && dof_shader_pass5)) {
999                                 GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
1000                                 GPU_framebuffer_restore();
1001                                 glDisableClientState(GL_VERTEX_ARRAY);
1002                                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1003
1004                                 GPU_shader_unbind();
1005                                 return false;
1006                         }
1007
1008                         /* pass first, first level of blur in low res buffer */
1009                         {
1010                                 int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform;
1011                                 int viewvecs_uniform;
1012
1013                                 float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
1014
1015                                 dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params");
1016                                 invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim");
1017                                 color_uniform = GPU_shader_get_uniform(dof_shader_pass1, "colorbuffer");
1018                                 depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer");
1019                                 viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs");
1020
1021                                 GPU_shader_bind(dof_shader_pass1);
1022
1023                                 GPU_shader_uniform_vector(dof_shader_pass1, dof_uniform, 4, 1, dof_params);
1024                                 GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
1025                                 GPU_shader_uniform_vector(dof_shader_pass1, viewvecs_uniform, 4, 3, viewvecs[0]);
1026
1027                                 GPU_texture_bind(src, numslots++);
1028                                 GPU_shader_uniform_texture(dof_shader_pass1, color_uniform, src);
1029
1030                                 GPU_texture_bind(fx->depth_buffer, numslots++);
1031                                 GPU_texture_filter_mode(fx->depth_buffer, false, true);
1032                                 GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer);
1033
1034                                 /* target is the downsampled coc buffer */
1035                                 GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
1036                                 /* binding takes care of setting the viewport to the downsampled size */
1037                                 GPU_texture_bind_as_framebuffer(fx->dof_near_coc_buffer);
1038
1039                                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1040                                 /* disable bindings */
1041                                 GPU_texture_unbind(src);
1042                                 GPU_texture_filter_mode(fx->depth_buffer, true, false);
1043                                 GPU_texture_unbind(fx->depth_buffer);
1044
1045                                 GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
1046                                 numslots = 0;
1047                         }
1048
1049                         /* second pass, gaussian blur the downsampled image */
1050                         {
1051                                 int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform;
1052                                 int viewvecs_uniform;
1053                                 float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer),
1054                                                                1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)};
1055                                 float tmp = invrendertargetdim[0];
1056                                 invrendertargetdim[0] = 0.0f;
1057
1058                                 dof_params[2] = GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor);
1059
1060                                 dof_uniform = GPU_shader_get_uniform(dof_shader_pass2, "dof_params");
1061                                 invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass2, "invrendertargetdim");
1062                                 color_uniform = GPU_shader_get_uniform(dof_shader_pass2, "colorbuffer");
1063                                 depth_uniform = GPU_shader_get_uniform(dof_shader_pass2, "depthbuffer");
1064                                 viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass2, "viewvecs");
1065
1066                                 /* Blurring vertically */
1067                                 GPU_shader_bind(dof_shader_pass2);
1068
1069                                 GPU_shader_uniform_vector(dof_shader_pass2, dof_uniform, 4, 1, dof_params);
1070                                 GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
1071                                 GPU_shader_uniform_vector(dof_shader_pass2, viewvecs_uniform, 4, 3, viewvecs[0]);
1072
1073                                 GPU_texture_bind(fx->depth_buffer, numslots++);
1074                                 GPU_texture_filter_mode(fx->depth_buffer, false, true);
1075                                 GPU_shader_uniform_texture(dof_shader_pass2, depth_uniform, fx->depth_buffer);
1076
1077                                 GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
1078                                 GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_buffer);
1079
1080                                 /* use final buffer as a temp here */
1081                                 GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
1082
1083                                 /* Drawing quad */
1084                                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1085
1086                                 /* *unbind/detach */
1087                                 GPU_texture_unbind(fx->dof_near_coc_buffer);
1088                                 GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
1089
1090                                 /* Blurring horizontally */
1091                                 invrendertargetdim[0] = tmp;
1092                                 invrendertargetdim[1] = 0.0f;
1093                                 GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
1094
1095                                 GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
1096                                 GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_final_buffer);
1097
1098                                 GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0, NULL);
1099                                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1100
1101                                 /* *unbind/detach */
1102                                 GPU_texture_filter_mode(fx->depth_buffer, true, false);
1103                                 GPU_texture_unbind(fx->depth_buffer);
1104
1105                                 GPU_texture_unbind(fx->dof_near_coc_final_buffer);
1106                                 GPU_framebuffer_texture_detach(fx->dof_near_coc_blurred_buffer);
1107
1108                                 dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
1109
1110                                 numslots = 0;
1111                         }
1112
1113                         /* third pass, calculate near coc */
1114                         {
1115                                 int near_coc_downsampled, near_coc_blurred;
1116
1117                                 near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass3, "colorbuffer");
1118                                 near_coc_blurred = GPU_shader_get_uniform(dof_shader_pass3, "blurredcolorbuffer");
1119
1120                                 GPU_shader_bind(dof_shader_pass3);
1121
1122                                 GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
1123                                 GPU_shader_uniform_texture(dof_shader_pass3, near_coc_downsampled, fx->dof_near_coc_buffer);
1124
1125                                 GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
1126                                 GPU_shader_uniform_texture(dof_shader_pass3, near_coc_blurred, fx->dof_near_coc_blurred_buffer);
1127
1128                                 GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
1129
1130                                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1131                                 /* disable bindings */
1132                                 GPU_texture_unbind(fx->dof_near_coc_buffer);
1133                                 GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
1134
1135                                 /* unbinding here restores the size to the original */
1136                                 GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
1137
1138                                 numslots = 0;
1139                         }
1140
1141                         /* fourth pass blur final coc once to eliminate discontinuities */
1142                         {
1143                                 int near_coc_downsampled;
1144                                 int invrendertargetdim_uniform;
1145                                 float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer),
1146                                                                1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)};
1147
1148                                 near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass4, "colorbuffer");
1149                                 invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass4, "invrendertargetdim");
1150
1151                                 GPU_shader_bind(dof_shader_pass4);
1152
1153                                 GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
1154                                 GPU_shader_uniform_texture(dof_shader_pass4, near_coc_downsampled, fx->dof_near_coc_final_buffer);
1155                                 GPU_shader_uniform_vector(dof_shader_pass4, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
1156
1157                                 GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
1158
1159                                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1160                                 /* disable bindings */
1161                                 GPU_texture_unbind(fx->dof_near_coc_final_buffer);
1162
1163                                 /* unbinding here restores the size to the original */
1164                                 GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_near_coc_buffer);
1165                                 GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
1166
1167                                 numslots = 0;
1168                         }
1169
1170                         /* final pass, merge blurred layers according to final calculated coc */
1171                         {
1172                                 int medium_blurred_uniform, high_blurred_uniform, original_uniform, depth_uniform, dof_uniform;
1173                                 int invrendertargetdim_uniform, viewvecs_uniform;
1174                                 float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
1175
1176                                 medium_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "mblurredcolorbuffer");
1177                                 high_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "blurredcolorbuffer");
1178                                 dof_uniform = GPU_shader_get_uniform(dof_shader_pass5, "dof_params");
1179                                 invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass5, "invrendertargetdim");
1180                                 original_uniform = GPU_shader_get_uniform(dof_shader_pass5, "colorbuffer");
1181                                 depth_uniform = GPU_shader_get_uniform(dof_shader_pass5, "depthbuffer");
1182                                 viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass5, "viewvecs");
1183
1184                                 GPU_shader_bind(dof_shader_pass5);
1185
1186                                 GPU_shader_uniform_vector(dof_shader_pass5, dof_uniform, 4, 1, dof_params);
1187                                 GPU_shader_uniform_vector(dof_shader_pass5, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
1188                                 GPU_shader_uniform_vector(dof_shader_pass5, viewvecs_uniform, 4, 3, viewvecs[0]);
1189
1190                                 GPU_texture_bind(src, numslots++);
1191                                 GPU_shader_uniform_texture(dof_shader_pass5, original_uniform, src);
1192
1193                                 GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
1194                                 GPU_shader_uniform_texture(dof_shader_pass5, high_blurred_uniform, fx->dof_near_coc_blurred_buffer);
1195
1196                                 GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
1197                                 GPU_shader_uniform_texture(dof_shader_pass5, medium_blurred_uniform, fx->dof_near_coc_buffer);
1198
1199                                 GPU_texture_bind(fx->depth_buffer, numslots++);
1200                                 GPU_texture_filter_mode(fx->depth_buffer, false, true);
1201                                 GPU_shader_uniform_texture(dof_shader_pass5, depth_uniform, fx->depth_buffer);
1202
1203                                 /* if this is the last pass, prepare for rendering on the frambuffer */
1204                                 gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
1205
1206                                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1207                                 /* disable bindings */
1208                                 GPU_texture_unbind(fx->dof_near_coc_buffer);
1209                                 GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
1210                                 GPU_texture_unbind(src);
1211                                 GPU_texture_filter_mode(fx->depth_buffer, true, false);
1212                                 GPU_texture_unbind(fx->depth_buffer);
1213
1214                                 /* may not be attached, in that case this just returns */
1215                                 if (target) {
1216                                         GPU_framebuffer_texture_detach(target);
1217                                         if (ofs) {
1218                                                 GPU_offscreen_bind(ofs, false);
1219                                         }
1220                                         else {
1221                                                 GPU_framebuffer_restore();
1222                                         }
1223                                 }
1224
1225                                 SWAP(GPUTexture *, target, src);
1226                                 numslots = 0;
1227                         }
1228                 }
1229         }
1230
1231         glDisableClientState(GL_VERTEX_ARRAY);
1232         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1233
1234         GPU_shader_unbind();
1235
1236         return true;
1237 }
1238
1239 void GPU_fx_compositor_init_dof_settings(GPUDOFSettings *fx_dof)
1240 {
1241         fx_dof->fstop = 128.0f;
1242         fx_dof->focal_length = 1.0f;
1243         fx_dof->focus_distance = 1.0f;
1244         fx_dof->sensor = 1.0f;
1245         fx_dof->num_blades = 6;
1246 }
1247
1248 void GPU_fx_compositor_init_ssao_settings(GPUSSAOSettings *fx_ssao)
1249 {
1250         fx_ssao->factor = 1.0f;
1251         fx_ssao->distance_max = 0.2f;
1252         fx_ssao->attenuation = 1.0f;
1253         fx_ssao->samples = 20;
1254 }