Fix T58610: EEVEE: camera motion blur renders only one viewport sample
[blender.git] / source / blender / draw / engines / eevee / eevee_temporal_sampling.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2016, Blender Foundation.
17  */
18
19 /** \file
20  * \ingroup draw_engine
21  *
22  * Temporal super sampling technique
23  */
24
25 #include "DRW_render.h"
26
27 #include "ED_screen.h"
28
29 #include "BLI_rand.h"
30
31 #include "DEG_depsgraph_query.h"
32
33 #include "eevee_private.h"
34 #include "GPU_texture.h"
35
36 #define FILTER_CDF_TABLE_SIZE 512
37
38 static struct {
39         /* Pixel filter table: Only blackman-harris for now. */
40         bool inited;
41         float inverted_cdf[FILTER_CDF_TABLE_SIZE];
42 } e_data = {false}; /* Engine data */
43
44 extern char datatoc_common_uniforms_lib_glsl[];
45 extern char datatoc_common_view_lib_glsl[];
46 extern char datatoc_bsdf_common_lib_glsl[];
47
48 static float UNUSED_FUNCTION(filter_box)(float UNUSED(x))
49 {
50         return 1.0f;
51 }
52
53 static float filter_blackman_harris(float x)
54 {
55         /* Hardcoded 1px footprint [-0.5..0.5]. We resize later. */
56         const float width = 1.0f;
57         x = 2.0f * M_PI * (x / width + 0.5f);
58         return 0.35875f - 0.48829f * cosf(x) + 0.14128f * cosf(2.0f * x) - 0.01168f * cosf(3.0f * x);
59 }
60
61 /* Compute cumulative distribution function of a discrete function. */
62 static void compute_cdf(float (*func)(float x), float cdf[FILTER_CDF_TABLE_SIZE])
63 {
64         cdf[0] = 0.0f;
65         /* Actual CDF evaluation. */
66         for (int u = 0; u < FILTER_CDF_TABLE_SIZE - 1; ++u) {
67                 float x = (float)(u + 1) / (float)(FILTER_CDF_TABLE_SIZE - 1);
68                 cdf[u + 1] = cdf[u] + func(x - 0.5f); /* [-0.5..0.5]. We resize later. */
69         }
70         /* Normalize the CDF. */
71         for (int u = 0; u < FILTER_CDF_TABLE_SIZE - 1; u++) {
72                 cdf[u] /= cdf[FILTER_CDF_TABLE_SIZE - 1];
73         }
74         /* Just to make sure. */
75         cdf[FILTER_CDF_TABLE_SIZE - 1] = 1.0f;
76 }
77
78 static void invert_cdf(const float cdf[FILTER_CDF_TABLE_SIZE], float invert_cdf[FILTER_CDF_TABLE_SIZE])
79 {
80         for (int u = 0; u < FILTER_CDF_TABLE_SIZE; u++) {
81                 float x = (float)u / (float)(FILTER_CDF_TABLE_SIZE - 1);
82                 for (int i = 0; i < FILTER_CDF_TABLE_SIZE; ++i) {
83                         if (cdf[i] >= x) {
84                                 if (i == FILTER_CDF_TABLE_SIZE - 1) {
85                                         invert_cdf[u] = 1.0f;
86                                 }
87                                 else {
88                                         float t = (x - cdf[i]) / (cdf[i + 1] - cdf[i]);
89                                         invert_cdf[u] = ((float)i + t) / (float)(FILTER_CDF_TABLE_SIZE - 1);
90                                 }
91                                 break;
92                         }
93                 }
94         }
95 }
96
97 /* Evaluate a discrete function table with linear interpolation. */
98 static float eval_table(float *table, float x)
99 {
100         CLAMP(x, 0.0f, 1.0f);
101         x = x * (FILTER_CDF_TABLE_SIZE - 1);
102
103         int index = min_ii((int)(x), FILTER_CDF_TABLE_SIZE - 1);
104         int nindex = min_ii(index + 1, FILTER_CDF_TABLE_SIZE - 1);
105         float t = x - index;
106
107         return (1.0f - t) * table[index] + t * table[nindex];
108 }
109
110 static void eevee_create_cdf_table_temporal_sampling(void)
111 {
112         float *cdf_table = MEM_mallocN(sizeof(float) * FILTER_CDF_TABLE_SIZE, "Eevee Filter CDF table");
113
114         float filter_width = 2.0f; /* Use a 2 pixel footprint by default. */
115
116         {
117                 /* Use blackman-harris filter. */
118                 filter_width *= 2.0f;
119                 compute_cdf(filter_blackman_harris, cdf_table);
120         }
121
122         invert_cdf(cdf_table, e_data.inverted_cdf);
123
124         /* Scale and offset table. */
125         for (int i = 0; i < FILTER_CDF_TABLE_SIZE; ++i) {
126                 e_data.inverted_cdf[i] = (e_data.inverted_cdf[i] - 0.5f) * filter_width;
127         }
128
129         MEM_freeN(cdf_table);
130         e_data.inited = true;
131 }
132
133 void EEVEE_temporal_sampling_matrices_calc(
134         EEVEE_EffectsInfo *effects, float viewmat[4][4], float persmat[4][4], const double ht_point[2])
135 {
136         const float *viewport_size = DRW_viewport_size_get();
137         const DRWContextState *draw_ctx = DRW_context_state_get();
138         Scene *scene = draw_ctx->scene;
139         RenderData *rd = &scene->r;
140
141         float filter_size = rd->gauss; /* Sigh.. Stupid legacy naming. */
142
143         float ofs_x = eval_table(e_data.inverted_cdf, (float)(ht_point[0])) * filter_size;
144         float ofs_y = eval_table(e_data.inverted_cdf, (float)(ht_point[1])) * filter_size;
145
146         window_translate_m4(
147                 effects->overide_winmat, persmat,
148                 ofs_x / viewport_size[0],
149                 ofs_y / viewport_size[1]);
150
151         mul_m4_m4m4(effects->overide_persmat, effects->overide_winmat, viewmat);
152         invert_m4_m4(effects->overide_persinv, effects->overide_persmat);
153         invert_m4_m4(effects->overide_wininv, effects->overide_winmat);
154 }
155
156 void EEVEE_temporal_sampling_reset(EEVEE_Data *vedata)
157 {
158         vedata->stl->effects->taa_render_sample = 1;
159 }
160
161 int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
162 {
163         EEVEE_StorageList *stl = vedata->stl;
164         // EEVEE_FramebufferList *fbl = vedata->fbl;
165         // EEVEE_TextureList *txl = vedata->txl;
166         EEVEE_EffectsInfo *effects = stl->effects;
167         int repro_flag = 0;
168
169         if (!e_data.inited) {
170                 eevee_create_cdf_table_temporal_sampling();
171         }
172
173         /* Reset for each "redraw". When rendering using ogl render,
174          * we accumulate the redraw inside the drawing loop in eevee_draw_background().
175          * But we do NOT accumulate between "redraw" (as in full draw manager drawloop)
176          * because the opengl render already does that. */
177         effects->taa_render_sample = 1;
178
179         const DRWContextState *draw_ctx = DRW_context_state_get();
180         const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
181
182         if ((scene_eval->eevee.taa_samples != 1) ||
183             DRW_state_is_image_render())
184         {
185                 float persmat[4][4], viewmat[4][4];
186
187                 if (!DRW_state_is_image_render() &&
188                     (scene_eval->eevee.flag & SCE_EEVEE_TAA_REPROJECTION))
189                 {
190                         repro_flag = EFFECT_TAA_REPROJECT | EFFECT_VELOCITY_BUFFER | EFFECT_DEPTH_DOUBLE_BUFFER | EFFECT_DOUBLE_BUFFER | EFFECT_POST_BUFFER;
191                         effects->taa_reproject_sample = ((effects->taa_reproject_sample + 1) % 16);
192                 }
193
194                 /* Until we support reprojection, we need to make sure
195                  * that the history buffer contains correct information. */
196                 bool view_is_valid = stl->g_data->valid_double_buffer;
197
198                 view_is_valid = view_is_valid && (stl->g_data->view_updated == false);
199
200                 if (draw_ctx->evil_C != NULL) {
201                         struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C);
202                         view_is_valid = view_is_valid && (ED_screen_animation_no_scrub(wm) == NULL);
203                 }
204
205                 effects->taa_total_sample = scene_eval->eevee.taa_samples;
206                 MAX2(effects->taa_total_sample, 0);
207
208                 DRW_viewport_matrix_get(persmat, DRW_MAT_PERS);
209                 DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW);
210                 DRW_viewport_matrix_get(effects->overide_winmat, DRW_MAT_WIN);
211                 /* The view is jittered by the oglrenderer. So avoid testing in this case. */
212                 if (!DRW_state_is_image_render()) {
213                         view_is_valid = view_is_valid && compare_m4m4(persmat, effects->prev_drw_persmat, FLT_MIN);
214                         copy_m4_m4(effects->prev_drw_persmat, persmat);
215                 }
216
217                 /* Prevent ghosting from probe data. */
218                 view_is_valid = view_is_valid && (effects->prev_drw_support == DRW_state_draw_support());
219                 effects->prev_drw_support = DRW_state_draw_support();
220
221                 if (((effects->taa_total_sample == 0) || (effects->taa_current_sample < effects->taa_total_sample)) ||
222                     DRW_state_is_image_render())
223                 {
224                         if (view_is_valid) {
225                                 /* OGL render already jitter the camera. */
226                                 if (!DRW_state_is_image_render()) {
227                                         effects->taa_current_sample += 1;
228                                         repro_flag = 0;
229
230                                         double ht_point[2];
231                                         double ht_offset[2] = {0.0, 0.0};
232                                         uint ht_primes[2] = {2, 3};
233
234                                         BLI_halton_2D(ht_primes, ht_offset, effects->taa_current_sample - 1, ht_point);
235
236                                         EEVEE_temporal_sampling_matrices_calc(effects, viewmat, persmat, ht_point);
237
238                                         DRW_viewport_matrix_override_set(effects->overide_persmat, DRW_MAT_PERS);
239                                         DRW_viewport_matrix_override_set(effects->overide_persinv, DRW_MAT_PERSINV);
240                                         DRW_viewport_matrix_override_set(effects->overide_winmat, DRW_MAT_WIN);
241                                         DRW_viewport_matrix_override_set(effects->overide_wininv, DRW_MAT_WININV);
242                                 }
243                         }
244                         else {
245                                 effects->taa_current_sample = 1;
246                         }
247                 }
248                 else {
249                         effects->taa_current_sample = 1;
250                 }
251
252                 return repro_flag | EFFECT_TAA | EFFECT_DOUBLE_BUFFER | EFFECT_DEPTH_DOUBLE_BUFFER | EFFECT_POST_BUFFER;
253         }
254
255         effects->taa_current_sample = 1;
256
257         return repro_flag;
258 }
259
260 void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
261 {
262         EEVEE_PassList *psl = vedata->psl;
263         EEVEE_StorageList *stl = vedata->stl;
264         EEVEE_TextureList *txl = vedata->txl;
265         EEVEE_EffectsInfo *effects = stl->effects;
266
267         if ((effects->enabled_effects & (EFFECT_TAA | EFFECT_TAA_REPROJECT)) != 0) {
268                 struct GPUShader *sh = EEVEE_shaders_taa_resolve_sh_get(effects->enabled_effects);
269
270                 psl->taa_resolve = DRW_pass_create("Temporal AA Resolve", DRW_STATE_WRITE_COLOR);
271                 DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->taa_resolve);
272
273                 DRW_shgroup_uniform_texture_ref(grp, "colorHistoryBuffer", &txl->taa_history);
274                 DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer);
275                 DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
276
277                 if (effects->enabled_effects & EFFECT_TAA_REPROJECT) {
278                         // DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
279                         DRW_shgroup_uniform_texture_ref(grp, "velocityBuffer", &effects->velocity_tx);
280                 }
281                 else {
282                         DRW_shgroup_uniform_float(grp, "alpha", &effects->taa_alpha, 1);
283                 }
284                 DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
285         }
286 }
287
288 void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata)
289 {
290         EEVEE_PassList *psl = vedata->psl;
291         EEVEE_TextureList *txl = vedata->txl;
292         EEVEE_FramebufferList *fbl = vedata->fbl;
293         EEVEE_StorageList *stl = vedata->stl;
294         EEVEE_EffectsInfo *effects = stl->effects;
295
296         if ((effects->enabled_effects & (EFFECT_TAA | EFFECT_TAA_REPROJECT)) != 0) {
297                 if ((effects->enabled_effects & EFFECT_TAA) != 0 && effects->taa_current_sample != 1) {
298                         if (DRW_state_is_image_render()) {
299                                 /* See EEVEE_temporal_sampling_init() for more details. */
300                                 effects->taa_alpha = 1.0f / (float)(effects->taa_render_sample);
301                         }
302                         else {
303                                 effects->taa_alpha = 1.0f / (float)(effects->taa_current_sample);
304                         }
305
306                         GPU_framebuffer_bind(effects->target_buffer);
307                         DRW_draw_pass(psl->taa_resolve);
308
309                         /* Restore the depth from sample 1. */
310                         if (!DRW_state_is_image_render()) {
311                                 GPU_framebuffer_blit(fbl->double_buffer_depth_fb, 0, fbl->main_fb, 0, GPU_DEPTH_BIT);
312                         }
313
314                         SWAP_BUFFERS_TAA();
315                 }
316                 else {
317                         if (!DRW_state_is_image_render()) {
318                                 /* Save the depth buffer for the next frame.
319                                  * This saves us from doing anything special
320                                  * in the other mode engines. */
321                                 GPU_framebuffer_blit(fbl->main_fb, 0, fbl->double_buffer_depth_fb, 0, GPU_DEPTH_BIT);
322                         }
323
324                         /* Do reprojection for noise reduction */
325                         /* TODO : do AA jitter if in only render view. */
326                         if (!DRW_state_is_image_render() &&
327                             (effects->enabled_effects & EFFECT_TAA_REPROJECT) != 0 &&
328                             stl->g_data->valid_taa_history)
329                         {
330                                 GPU_framebuffer_bind(effects->target_buffer);
331                                 DRW_draw_pass(psl->taa_resolve);
332                                 SWAP_BUFFERS_TAA();
333                         }
334                         else {
335                                 struct GPUFrameBuffer *source_fb = (effects->target_buffer == fbl->main_color_fb) ? fbl->effect_color_fb : fbl->main_color_fb;
336                                 GPU_framebuffer_blit(source_fb, 0, fbl->taa_history_color_fb, 0, GPU_COLOR_BIT);
337                         }
338                 }
339
340                 /* Make each loop count when doing a render. */
341                 if (DRW_state_is_image_render()) {
342                         effects->taa_render_sample += 1;
343                         effects->taa_current_sample += 1;
344                 }
345                 else {
346                         if ((effects->taa_total_sample == 0) ||
347                             (effects->taa_current_sample < effects->taa_total_sample))
348                         {
349                                 DRW_viewport_request_redraw();
350                         }
351                 }
352         }
353 }