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