511167b775af8a8b5b17201ffc810e56be11bc2d
[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         /* texture bound to the first color attachment of the gbuffer */
66         GPUTexture *color_buffer;
67
68         /* second texture used for ping-pong compositing */
69         GPUTexture *color_buffer_sec;
70
71         /* all those buffers below have to coexist. Fortunately they are all quarter sized (1/16th of memory) of original framebuffer */
72         int dof_downsampled_w;
73         int dof_downsampled_h;
74
75         /* texture used for near coc and color blurring calculation */
76         GPUTexture *dof_near_coc_buffer;
77         /* blurred near coc buffer. */
78         GPUTexture *dof_near_coc_blurred_buffer;
79         /* final near coc buffer. */
80         GPUTexture *dof_near_coc_final_buffer;
81
82         /* half size blur buffer */
83         GPUTexture *dof_half_downsampled;
84         /* high quality dof texture downsamplers. 6 levels means 64 pixels wide */
85         GPUTexture *dof_nearfar_coc[6];
86         GPUTexture *dof_near_blur;
87         GPUTexture *dof_far_blur;
88         GPUTexture *dof_concentric_samples_tex;
89
90         /* texture bound to the depth attachment of the gbuffer */
91         GPUTexture *depth_buffer;
92         GPUTexture *depth_buffer_xray;
93
94         /* texture used for jittering for various effects */
95         GPUTexture *jitter_buffer;
96
97         /* texture used for ssao */
98         int ssao_sample_count;
99         GPUTexture *ssao_concentric_samples_tex;
100
101         /* dimensions of the gbuffer */
102         int gbuffer_dim[2];
103
104         GPUFXSettings settings;
105
106         /* or-ed flags of enabled effects */
107         int effects;
108
109         /* number of passes, needed to detect if ping pong buffer allocation is needed */
110         int num_passes;
111
112         /* we have a stencil, restore the previous state */
113         bool restore_stencil;
114 };
115
116 #if 0
117 /* concentric mapping, see "A Low Distortion Map Between Disk and Square" and
118  * http://psgraphics.blogspot.nl/2011/01/improved-code-for-concentric-map.html */
119 static GPUTexture * create_concentric_sample_texture(int side)
120 {
121         GPUTexture *tex;
122         float midpoint = 0.5f * (side - 1);
123         float *texels = (float *)MEM_mallocN(sizeof(float) * 2 * side * side, "concentric_tex");
124         int i, j;
125
126         for (i = 0; i < side; i++) {
127                 for (j = 0; j < side; j++) {
128                         int index = (i * side + j) * 2;
129                         float a = 1.0f - i / midpoint;
130                         float b = 1.0f - j / midpoint;
131                         float phi, r;
132                         if (a * a > b * b) {
133                                 r = a;
134                                 phi = (M_PI_4) * (b / a);
135                         }
136                         else {
137                                 r = b;
138                                 phi = M_PI_2 - (M_PI_4) * (a / b);
139                         }
140                         texels[index] = r * cos(phi);
141                         texels[index + 1] = r * sin(phi);
142                 }
143         }
144
145         tex = GPU_texture_create_1D_procedural(side * side, texels, NULL);
146         MEM_freeN(texels);
147         return tex;
148 }
149 #endif
150
151 static GPUTexture *create_spiral_sample_texture(int numsaples)
152 {
153         GPUTexture *tex;
154         float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * numsaples, "concentric_tex");
155         const float numsaples_inv = 1.0f / numsaples;
156         int i;
157         /* arbitrary number to ensure we don't get conciding samples every circle */
158         const float spirals = 7.357;
159
160         for (i = 0; i < numsaples; i++) {
161                 float r = (i + 0.5f) * numsaples_inv;
162                 float phi = r * spirals * (float)(2.0 * M_PI);
163                 texels[i][0] = r * cosf(phi);
164                 texels[i][1] = r * sinf(phi);
165         }
166
167         tex = GPU_texture_create_1D_procedural(numsaples, (float *)texels, NULL);
168         MEM_freeN(texels);
169         return tex;
170 }
171
172 /* generate a new FX compositor */
173 GPUFX *GPU_fx_compositor_create(void)
174 {
175         GPUFX *fx = MEM_callocN(sizeof(GPUFX), "GPUFX compositor");
176
177         return fx;
178 }
179
180 static void cleanup_fx_dof_buffers(GPUFX *fx)
181 {
182         if (fx->dof_near_coc_blurred_buffer) {
183                 GPU_texture_free(fx->dof_near_coc_blurred_buffer);
184                 fx->dof_near_coc_blurred_buffer = NULL;
185         }
186         if (fx->dof_near_coc_buffer) {
187                 GPU_texture_free(fx->dof_near_coc_buffer);
188                 fx->dof_near_coc_buffer = NULL;
189         }
190         if (fx->dof_near_coc_final_buffer) {
191                 GPU_texture_free(fx->dof_near_coc_final_buffer);
192                 fx->dof_near_coc_final_buffer = NULL;
193         }
194
195         if (fx->dof_half_downsampled) {
196                 GPU_texture_free(fx->dof_half_downsampled);
197                 fx->dof_half_downsampled = NULL;
198         }
199         if (fx->dof_nearfar_coc[0]) {
200                 int i;
201                 for (i = 0; i < 6; i++) {
202                         GPU_texture_free(fx->dof_nearfar_coc[i]);
203                         fx->dof_nearfar_coc[i] = NULL;
204                 }
205         }
206         if (fx->dof_near_blur) {
207                 GPU_texture_free(fx->dof_near_blur);
208                 fx->dof_near_blur = NULL;
209         }
210         if (fx->dof_far_blur) {
211                 GPU_texture_free(fx->dof_far_blur);
212                 fx->dof_far_blur = NULL;
213         }
214         if (fx->dof_concentric_samples_tex) {
215                 GPU_texture_free(fx->dof_concentric_samples_tex);
216                 fx->dof_concentric_samples_tex = 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_concentric_samples_tex) {
249                 GPU_texture_free(fx->ssao_concentric_samples_tex);
250                 fx->ssao_concentric_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], 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 || !fx->ssao_concentric_samples_tex) {
360                         if (fx_settings->ssao->samples < 1)
361                                 fx_settings->ssao->samples = 1;
362
363                         fx->ssao_sample_count = fx_settings->ssao->samples;
364
365                         if (fx->ssao_concentric_samples_tex) {
366                                 GPU_texture_free(fx->ssao_concentric_samples_tex);
367                         }
368
369                         fx->ssao_concentric_samples_tex = create_spiral_sample_texture(fx_settings->ssao->samples);
370                 }
371         }
372         else {
373                 if (fx->ssao_concentric_samples_tex) {
374                         GPU_texture_free(fx->ssao_concentric_samples_tex);
375                         fx->ssao_concentric_samples_tex = NULL;
376                 }
377         }
378
379         /* create textures for dof effect */
380         if (fx_flag & GPU_FX_FLAG_DOF) {
381                 if (!fx->dof_near_coc_buffer || !fx->dof_near_coc_blurred_buffer || !fx->dof_near_coc_final_buffer) {
382                         fx->dof_downsampled_w = w / 4;
383                         fx->dof_downsampled_h = h / 4;
384
385                         if (!(fx->dof_near_coc_buffer = GPU_texture_create_2D(
386                                   fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
387                         {
388                                 printf("%.256s\n", err_out);
389                                 cleanup_fx_gl_data(fx, true);
390                                 return false;
391                         }
392                         if (!(fx->dof_near_coc_blurred_buffer = GPU_texture_create_2D(
393                                   fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
394                         {
395                                 printf("%.256s\n", err_out);
396                                 cleanup_fx_gl_data(fx, true);
397                                 return false;
398                         }
399                         if (!(fx->dof_near_coc_final_buffer = GPU_texture_create_2D(
400                                   fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
401                         {
402                                 printf("%.256s\n", err_out);
403                                 cleanup_fx_gl_data(fx, true);
404                                 return false;
405                         }
406                 }
407         }
408         else {
409                 /* cleanup unnecessary buffers */
410                 cleanup_fx_dof_buffers(fx);
411         }
412
413         /* we need to pass data between shader stages, allocate an extra color buffer */
414         if (num_passes > 1) {
415                 if(!fx->color_buffer_sec) {
416                         if (!(fx->color_buffer_sec = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) {
417                                 printf(".256%s\n", err_out);
418                                 cleanup_fx_gl_data(fx, true);
419                                 return false;
420                         }
421                 }
422         }
423         else {
424                 if (fx->color_buffer_sec) {
425                         GPU_framebuffer_texture_detach(fx->color_buffer_sec);
426                         GPU_texture_free(fx->color_buffer_sec);
427                         fx->color_buffer_sec = NULL;
428                 }
429         }
430
431         /* bind the buffers */
432
433         /* first depth buffer, because system assumes read/write buffers */
434         if(!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, err_out))
435                 printf("%.256s\n", err_out);
436
437         if(!GPU_framebuffer_texture_attach(fx->gbuffer, fx->color_buffer, 0, err_out))
438                 printf("%.256s\n", err_out);
439
440         if(!GPU_framebuffer_check_valid(fx->gbuffer, err_out))
441                 printf("%.256s\n", err_out);
442
443         GPU_texture_bind_as_framebuffer(fx->color_buffer);
444
445         /* enable scissor test. It's needed to ensure sculpting works correctly */
446         if (scissor_rect) {
447                 int w_sc = BLI_rcti_size_x(scissor_rect) + 1;
448                 int h_sc = BLI_rcti_size_y(scissor_rect) + 1;
449                 glPushAttrib(GL_SCISSOR_BIT);
450                 glEnable(GL_SCISSOR_TEST);
451                 glScissor(scissor_rect->xmin - rect->xmin, scissor_rect->ymin - rect->ymin,
452                                   w_sc, h_sc);
453                 fx->restore_stencil = true;
454         }
455         else {
456                 fx->restore_stencil = false;
457         }
458
459         fx->effects = fx_flag;
460
461         if (fx_settings)
462                 fx->settings = *fx_settings;
463         fx->gbuffer_dim[0] = w;
464         fx->gbuffer_dim[1] = h;
465
466         fx->num_passes = num_passes;
467
468         return true;
469 }
470
471 static void gpu_fx_bind_render_target(int *passes_left, GPUFX *fx, struct GPUOffScreen *ofs, GPUTexture *target)
472 {
473         if ((*passes_left)-- == 1) {
474                 GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
475                 if (ofs) {
476                         GPU_offscreen_bind(ofs, false);
477                 }
478                 else
479                         GPU_framebuffer_restore();
480         }
481         else {
482                 /* bind the ping buffer to the color buffer */
483                 GPU_framebuffer_texture_attach(fx->gbuffer, target, 0, NULL);
484         }
485 }
486
487 void GPU_fx_compositor_setup_XRay_pass(GPUFX *fx, bool do_xray)
488 {
489         char err_out[256];
490
491         if (do_xray) {
492                 if (!fx->depth_buffer_xray && !(fx->depth_buffer_xray = GPU_texture_create_depth(fx->gbuffer_dim[0], fx->gbuffer_dim[1], err_out))) {
493                         printf("%.256s\n", err_out);
494                         cleanup_fx_gl_data(fx, true);
495                         return;
496                 }
497         }
498         else {
499                 if (fx->depth_buffer_xray) {
500                         GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
501                         GPU_texture_free(fx->depth_buffer_xray);
502                         fx->depth_buffer_xray = NULL;
503                 }
504                 return;
505         }
506
507         GPU_framebuffer_texture_detach(fx->depth_buffer);
508
509         /* first depth buffer, because system assumes read/write buffers */
510         if(!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer_xray, 0, err_out))
511                 printf("%.256s\n", err_out);
512 }
513
514
515 void GPU_fx_compositor_XRay_resolve(GPUFX *fx)
516 {
517         GPUShader *depth_resolve_shader;
518         GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
519
520         /* attach regular framebuffer */
521         GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, NULL);
522
523         /* full screen quad where we will always write to depth buffer */
524         glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT);
525         glDepthFunc(GL_ALWAYS);
526         /* disable scissor from sculpt if any */
527         glDisable(GL_SCISSOR_TEST);
528         /* disable writing to color buffer, it's depth only pass */
529         glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
530
531         /* set up quad buffer */
532         glVertexPointer(2, GL_FLOAT, 0, fullscreencos);
533         glTexCoordPointer(2, GL_FLOAT, 0, fullscreenuvs);
534         glEnableClientState(GL_VERTEX_ARRAY);
535         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
536
537         depth_resolve_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_RESOLVE, false);
538
539         if (depth_resolve_shader) {
540                 int depth_uniform;
541
542                 depth_uniform = GPU_shader_get_uniform(depth_resolve_shader, "depthbuffer");
543
544                 GPU_shader_bind(depth_resolve_shader);
545
546                 GPU_texture_bind(fx->depth_buffer_xray, 0);
547                 GPU_depth_texture_mode(fx->depth_buffer_xray, false, true);
548                 GPU_shader_uniform_texture(depth_resolve_shader, depth_uniform, fx->depth_buffer_xray);
549
550                 /* draw */
551                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
552
553                 /* disable bindings */
554                 GPU_depth_texture_mode(fx->depth_buffer_xray, true, false);
555                 GPU_texture_unbind(fx->depth_buffer_xray);
556
557                 GPU_shader_unbind();
558         }
559
560         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
561
562         glDisableClientState(GL_VERTEX_ARRAY);
563         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
564
565         glPopAttrib();
566 }
567
568
569 bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, struct Scene *scene, struct GPUOffScreen *ofs)
570 {
571         GPUTexture *src, *target;
572         int numslots = 0;
573         float invproj[4][4];
574         int i;
575         /* number of passes left. when there are no more passes, the result is passed to the frambuffer */
576         int passes_left = fx->num_passes;
577         /* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */
578         float viewvecs[3][4] = {
579             {-1.0f, -1.0f, -1.0f, 1.0f},
580             {1.0f, -1.0f, -1.0f, 1.0f},
581             {-1.0f, 1.0f, -1.0f, 1.0f}
582         };
583
584         if (fx->effects == 0)
585                 return false;
586
587         /* first, unbind the render-to-texture framebuffer */
588         GPU_framebuffer_texture_detach(fx->color_buffer);
589         GPU_framebuffer_texture_detach(fx->depth_buffer);
590
591         if (fx->restore_stencil)
592                 glPopAttrib();
593
594         src = fx->color_buffer;
595         target = fx->color_buffer_sec;
596
597         /* set up quad buffer */
598         glVertexPointer(2, GL_FLOAT, 0, fullscreencos);
599         glTexCoordPointer(2, GL_FLOAT, 0, fullscreenuvs);
600         glEnableClientState(GL_VERTEX_ARRAY);
601         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
602
603         /* full screen FX pass */
604
605         /* invert the view matrix */
606         invert_m4_m4(invproj, projmat);
607
608         /* convert the view vectors to view space */
609         for (i = 0; i < 3; i++) {
610                 mul_m4_v4(invproj, viewvecs[i]);
611                 /* normalized trick see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
612                 mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
613                 if (is_persp)
614                         mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
615                 viewvecs[i][3] = 1.0;
616         }
617
618         /* we need to store the differences */
619         viewvecs[1][0] -= viewvecs[0][0];
620         viewvecs[1][1] = viewvecs[2][1] - viewvecs[0][1];
621
622         /* calculate a depth offset as well */
623         if (!is_persp) {
624                 float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
625                 mul_m4_v4(invproj, vec_far);
626                 mul_v3_fl(vec_far, 1.0f / vec_far[3]);
627                 viewvecs[1][2] = vec_far[2] - viewvecs[0][2];
628         }
629
630         /* set invalid color in case shader fails */
631         glColor3f(1.0, 0.0, 1.0);
632         glDisable(GL_DEPTH_TEST);
633
634         /* ssao pass */
635         if (fx->effects & GPU_FX_FLAG_SSAO) {
636                 GPUShader *ssao_shader;
637                 ssao_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_SSAO, is_persp);
638                 if (ssao_shader) {
639                         const GPUSSAOSettings *fx_ssao = fx->settings.ssao;
640                         int color_uniform, depth_uniform;
641                         int ssao_uniform, ssao_color_uniform, viewvecs_uniform, ssao_sample_params_uniform;
642                         int ssao_jitter_uniform, ssao_concentric_tex;
643                         float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, fx_ssao->attenuation, 0.0f};
644                         float sample_params[4];
645
646                         sample_params[0] = fx->ssao_sample_count;
647                         /* multiplier so we tile the random texture on screen */
648                         sample_params[2] = fx->gbuffer_dim[0] / 64.0;
649                         sample_params[3] = fx->gbuffer_dim[1] / 64.0;
650
651                         ssao_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_params");
652                         ssao_color_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_color");
653                         color_uniform = GPU_shader_get_uniform(ssao_shader, "colorbuffer");
654                         depth_uniform = GPU_shader_get_uniform(ssao_shader, "depthbuffer");
655                         viewvecs_uniform = GPU_shader_get_uniform(ssao_shader, "viewvecs");
656                         ssao_sample_params_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_sample_params");
657                         ssao_concentric_tex = GPU_shader_get_uniform(ssao_shader, "ssao_concentric_tex");
658                         ssao_jitter_uniform = GPU_shader_get_uniform(ssao_shader, "jitter_tex");
659
660                         GPU_shader_bind(ssao_shader);
661
662                         GPU_shader_uniform_vector(ssao_shader, ssao_uniform, 4, 1, ssao_params);
663                         GPU_shader_uniform_vector(ssao_shader, ssao_color_uniform, 4, 1, fx_ssao->color);
664                         GPU_shader_uniform_vector(ssao_shader, viewvecs_uniform, 4, 3, viewvecs[0]);
665                         GPU_shader_uniform_vector(ssao_shader, ssao_sample_params_uniform, 4, 1, sample_params);
666
667                         GPU_texture_bind(src, numslots++);
668                         GPU_shader_uniform_texture(ssao_shader, color_uniform, src);
669
670                         GPU_texture_bind(fx->depth_buffer, numslots++);
671                         GPU_depth_texture_mode(fx->depth_buffer, false, true);
672                         GPU_shader_uniform_texture(ssao_shader, depth_uniform, fx->depth_buffer);
673
674                         GPU_texture_bind(fx->jitter_buffer, numslots++);
675                         GPU_shader_uniform_texture(ssao_shader, ssao_jitter_uniform, fx->jitter_buffer);
676
677                         GPU_texture_bind(fx->ssao_concentric_samples_tex, numslots++);
678                         GPU_shader_uniform_texture(ssao_shader, ssao_concentric_tex, fx->ssao_concentric_samples_tex);
679
680                         /* draw */
681                         gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
682
683                         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
684
685                         /* disable bindings */
686                         GPU_texture_unbind(src);
687                         GPU_depth_texture_mode(fx->depth_buffer, true, false);
688                         GPU_texture_unbind(fx->depth_buffer);
689                         GPU_texture_unbind(fx->jitter_buffer);
690                         GPU_texture_unbind(fx->ssao_concentric_samples_tex);
691
692                         /* may not be attached, in that case this just returns */
693                         if (target) {
694                                 GPU_framebuffer_texture_detach(target);
695                                 if (ofs) {
696                                         GPU_offscreen_bind(ofs, false);
697                                 }
698                                 else {
699                                         GPU_framebuffer_restore();
700                                 }
701                         }
702
703                         /* swap here, after src/target have been unbound */
704                         SWAP(GPUTexture *, target, src);
705                         numslots = 0;
706                 }
707         }
708
709         /* second pass, dof */
710         if (fx->effects & GPU_FX_FLAG_DOF) {
711                 const GPUDOFSettings *fx_dof = fx->settings.dof;
712                 GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3, *dof_shader_pass4, *dof_shader_pass5;
713                 float dof_params[4];
714                 float scale = scene->unit.system ? scene->unit.scale_length : 1.0f;
715                 /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm
716                  * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though
717                  * because the shader reads coordinates in world space, which is in blender units. */
718                 float scale_camera = 0.001f / scale;
719                 /* we want radius here for the aperture number  */
720                 float aperture = 0.5f * scale_camera * fx_dof->focal_length / fx_dof->fstop;
721
722                 dof_params[0] = aperture * fabsf(scale_camera * fx_dof->focal_length / ((fx_dof->focus_distance / scale) - scale_camera * fx_dof->focal_length));
723                 dof_params[1] = fx_dof->focus_distance / scale;
724                 dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
725                 dof_params[3] = 0.0f;
726
727                 /* DOF effect has many passes but most of them are performed on a texture whose dimensions are 4 times less than the original
728                  * (16 times lower than original screen resolution). Technique used is not very exact but should be fast enough and is based
729                  * on "Practical Post-Process Depth of Field" see http://http.developer.nvidia.com/GPUGems3/gpugems3_ch28.html */
730                 dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE, is_persp);
731                 dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO, is_persp);
732                 dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE, is_persp);
733                 dof_shader_pass4 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR, is_persp);
734                 dof_shader_pass5 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE, is_persp);
735
736                 /* error occured, restore framebuffers and return */
737                 if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3 && dof_shader_pass4 && dof_shader_pass5)) {
738                         GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
739                         GPU_framebuffer_restore();
740                         return false;
741                 }
742
743                 /* pass first, first level of blur in low res buffer */
744                 {
745                         int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform;
746                         int viewvecs_uniform;
747
748                         float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
749
750                         dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params");
751                         invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim");
752                         color_uniform = GPU_shader_get_uniform(dof_shader_pass1, "colorbuffer");
753                         depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer");
754                         viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs");
755
756                         GPU_shader_bind(dof_shader_pass1);
757
758                         GPU_shader_uniform_vector(dof_shader_pass1, dof_uniform, 4, 1, dof_params);
759                         GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
760                         GPU_shader_uniform_vector(dof_shader_pass1, viewvecs_uniform, 4, 3, viewvecs[0]);
761
762                         GPU_texture_bind(src, numslots++);
763                         GPU_shader_uniform_texture(dof_shader_pass1, color_uniform, src);
764
765                         GPU_texture_bind(fx->depth_buffer, numslots++);
766                         GPU_depth_texture_mode(fx->depth_buffer, false, true);
767                         GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer);
768
769                         /* target is the downsampled coc buffer */
770                         GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
771                         /* binding takes care of setting the viewport to the downsampled size */
772                         GPU_texture_bind_as_framebuffer(fx->dof_near_coc_buffer);
773
774                         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
775                         /* disable bindings */
776                         GPU_texture_unbind(src);
777                         GPU_depth_texture_mode(fx->depth_buffer, true, false);
778                         GPU_texture_unbind(fx->depth_buffer);
779
780                         GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
781                         numslots = 0;
782                 }
783
784                 /* second pass, gaussian blur the downsampled image */
785                 {
786                         int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform;
787                         int viewvecs_uniform;
788                         float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer),
789                                                        1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)};
790                         float tmp = invrendertargetdim[0];
791                         invrendertargetdim[0] = 0.0f;
792
793                         dof_params[2] = GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor);
794
795                         dof_uniform = GPU_shader_get_uniform(dof_shader_pass2, "dof_params");
796                         invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass2, "invrendertargetdim");
797                         color_uniform = GPU_shader_get_uniform(dof_shader_pass2, "colorbuffer");
798                         depth_uniform = GPU_shader_get_uniform(dof_shader_pass2, "depthbuffer");
799                         viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass2, "viewvecs");
800
801                         /* Blurring vertically */
802                         GPU_shader_bind(dof_shader_pass2);
803
804                         GPU_shader_uniform_vector(dof_shader_pass2, dof_uniform, 4, 1, dof_params);
805                         GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
806                         GPU_shader_uniform_vector(dof_shader_pass2, viewvecs_uniform, 4, 3, viewvecs[0]);
807
808                         GPU_texture_bind(fx->depth_buffer, numslots++);
809                         GPU_depth_texture_mode(fx->depth_buffer, false, true);
810                         GPU_shader_uniform_texture(dof_shader_pass2, depth_uniform, fx->depth_buffer);
811
812                         GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
813                         GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_buffer);
814
815                         /* use final buffer as a temp here */
816                         GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
817
818                         /* Drawing quad */
819                         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
820
821                         /* *unbind/detach */
822                         GPU_texture_unbind(fx->dof_near_coc_buffer);
823                         GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
824
825                         /* Blurring horizontally */
826                         invrendertargetdim[0] = tmp;
827                         invrendertargetdim[1] = 0.0f;
828                         GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
829
830                         GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
831                         GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_final_buffer);
832
833                         GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0, NULL);
834                         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
835
836                         /* *unbind/detach */
837                         GPU_depth_texture_mode(fx->depth_buffer, true, false);
838                         GPU_texture_unbind(fx->depth_buffer);
839
840                         GPU_texture_unbind(fx->dof_near_coc_final_buffer);
841                         GPU_framebuffer_texture_detach(fx->dof_near_coc_blurred_buffer);
842
843                         dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
844
845                         numslots = 0;
846                 }
847
848                 /* third pass, calculate near coc */
849                 {
850                         int near_coc_downsampled, near_coc_blurred;
851
852                         near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass3, "colorbuffer");
853                         near_coc_blurred = GPU_shader_get_uniform(dof_shader_pass3, "blurredcolorbuffer");
854
855                         GPU_shader_bind(dof_shader_pass3);
856
857                         GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
858                         GPU_shader_uniform_texture(dof_shader_pass3, near_coc_downsampled, fx->dof_near_coc_buffer);
859
860                         GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
861                         GPU_shader_uniform_texture(dof_shader_pass3, near_coc_blurred, fx->dof_near_coc_blurred_buffer);
862
863                         GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
864
865                         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
866                         /* disable bindings */
867                         GPU_texture_unbind(fx->dof_near_coc_buffer);
868                         GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
869
870                         /* unbinding here restores the size to the original */
871                         GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
872
873                         numslots = 0;
874                 }
875
876                 /* fourth pass blur final coc once to eliminate discontinuities */
877                 {
878                         int near_coc_downsampled;
879                         int invrendertargetdim_uniform;
880                         float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer),
881                                                        1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)};
882
883                         near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass4, "colorbuffer");
884                         invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass4, "invrendertargetdim");
885
886                         GPU_shader_bind(dof_shader_pass4);
887
888                         GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
889                         GPU_shader_uniform_texture(dof_shader_pass4, near_coc_downsampled, fx->dof_near_coc_final_buffer);
890                         GPU_shader_uniform_vector(dof_shader_pass4, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
891
892                         GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
893
894                         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
895                         /* disable bindings */
896                         GPU_texture_unbind(fx->dof_near_coc_final_buffer);
897
898                         /* unbinding here restores the size to the original */
899                         GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_near_coc_buffer);
900                         GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
901
902                         numslots = 0;
903                 }
904
905                 /* final pass, merge blurred layers according to final calculated coc */
906                 {
907                         int medium_blurred_uniform, high_blurred_uniform, original_uniform, depth_uniform, dof_uniform;
908                         int invrendertargetdim_uniform, viewvecs_uniform;
909                         float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
910
911                         medium_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "mblurredcolorbuffer");
912                         high_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "blurredcolorbuffer");
913                         dof_uniform = GPU_shader_get_uniform(dof_shader_pass5, "dof_params");
914                         invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass5, "invrendertargetdim");
915                         original_uniform = GPU_shader_get_uniform(dof_shader_pass5, "colorbuffer");
916                         depth_uniform = GPU_shader_get_uniform(dof_shader_pass5, "depthbuffer");
917                         viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass5, "viewvecs");
918
919                         GPU_shader_bind(dof_shader_pass5);
920
921                         GPU_shader_uniform_vector(dof_shader_pass5, dof_uniform, 4, 1, dof_params);
922                         GPU_shader_uniform_vector(dof_shader_pass5, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
923                         GPU_shader_uniform_vector(dof_shader_pass5, viewvecs_uniform, 4, 3, viewvecs[0]);
924
925                         GPU_texture_bind(src, numslots++);
926                         GPU_shader_uniform_texture(dof_shader_pass5, original_uniform, src);
927
928                         GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
929                         GPU_shader_uniform_texture(dof_shader_pass5, high_blurred_uniform, fx->dof_near_coc_blurred_buffer);
930
931                         GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
932                         GPU_shader_uniform_texture(dof_shader_pass5, medium_blurred_uniform, fx->dof_near_coc_buffer);
933
934                         GPU_texture_bind(fx->depth_buffer, numslots++);
935                         GPU_depth_texture_mode(fx->depth_buffer, false, true);
936                         GPU_shader_uniform_texture(dof_shader_pass5, depth_uniform, fx->depth_buffer);
937
938                         /* if this is the last pass, prepare for rendering on the frambuffer */
939                         gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
940
941                         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
942                         /* disable bindings */
943                         GPU_texture_unbind(fx->dof_near_coc_buffer);
944                         GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
945                         GPU_texture_unbind(src);
946                         GPU_depth_texture_mode(fx->depth_buffer, true, false);
947                         GPU_texture_unbind(fx->depth_buffer);
948
949                         /* may not be attached, in that case this just returns */
950                         if (target) {
951                                 GPU_framebuffer_texture_detach(target);
952                                 if (ofs) {
953                                         GPU_offscreen_bind(ofs, false);
954                                 }
955                                 else {
956                                         GPU_framebuffer_restore();
957                                 }
958                         }
959
960                         SWAP(GPUTexture *, target, src);
961                         numslots = 0;
962                 }
963         }
964
965         glDisableClientState(GL_VERTEX_ARRAY);
966         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
967
968         GPU_shader_unbind();
969
970         return true;
971 }
972
973 void GPU_fx_compositor_init_dof_settings(GPUDOFSettings *fx_dof)
974 {
975         fx_dof->fstop = 128.0f;
976         fx_dof->focal_length = 1.0f;
977         fx_dof->focus_distance = 1.0f;
978         fx_dof->sensor = 1.0f;
979 }
980
981 void GPU_fx_compositor_init_ssao_settings(GPUSSAOSettings *fx_ssao)
982 {
983         fx_ssao->factor = 1.0f;
984         fx_ssao->distance_max = 0.2f;
985         fx_ssao->attenuation = 1.0f;
986         fx_ssao->samples = 20;
987 }