doxygen: add newline after \file
[blender.git] / source / blender / draw / engines / eevee / eevee_bloom.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  * Eevee's bloom shader.
23  */
24
25 #include "DRW_render.h"
26
27 #include "GPU_texture.h"
28
29 #include "DEG_depsgraph_query.h"
30
31 #include "eevee_private.h"
32
33 static struct {
34         /* Bloom */
35         struct GPUShader *bloom_blit_sh[2];
36         struct GPUShader *bloom_downsample_sh[2];
37         struct GPUShader *bloom_upsample_sh[2];
38         struct GPUShader *bloom_resolve_sh[2];
39 } e_data = {{NULL}}; /* Engine data */
40
41 extern char datatoc_effect_bloom_frag_glsl[];
42
43 static void eevee_create_shader_bloom(void)
44 {
45         e_data.bloom_blit_sh[0] = DRW_shader_create_fullscreen(
46                 datatoc_effect_bloom_frag_glsl,
47                 "#define STEP_BLIT\n");
48         e_data.bloom_blit_sh[1] = DRW_shader_create_fullscreen(
49                 datatoc_effect_bloom_frag_glsl,
50                 "#define STEP_BLIT\n"
51                 "#define HIGH_QUALITY\n");
52
53         e_data.bloom_downsample_sh[0] = DRW_shader_create_fullscreen(
54                 datatoc_effect_bloom_frag_glsl,
55                 "#define STEP_DOWNSAMPLE\n");
56         e_data.bloom_downsample_sh[1] = DRW_shader_create_fullscreen(
57                 datatoc_effect_bloom_frag_glsl,
58                 "#define STEP_DOWNSAMPLE\n"
59                 "#define HIGH_QUALITY\n");
60
61         e_data.bloom_upsample_sh[0] = DRW_shader_create_fullscreen(
62                 datatoc_effect_bloom_frag_glsl,
63                 "#define STEP_UPSAMPLE\n");
64         e_data.bloom_upsample_sh[1] = DRW_shader_create_fullscreen(
65                 datatoc_effect_bloom_frag_glsl,
66                 "#define STEP_UPSAMPLE\n"
67                 "#define HIGH_QUALITY\n");
68
69         e_data.bloom_resolve_sh[0] = DRW_shader_create_fullscreen(
70                 datatoc_effect_bloom_frag_glsl,
71                 "#define STEP_RESOLVE\n");
72         e_data.bloom_resolve_sh[1] = DRW_shader_create_fullscreen(
73                 datatoc_effect_bloom_frag_glsl,
74                 "#define STEP_RESOLVE\n"
75                 "#define HIGH_QUALITY\n");
76 }
77
78 int EEVEE_bloom_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
79 {
80         EEVEE_StorageList *stl = vedata->stl;
81         EEVEE_FramebufferList *fbl = vedata->fbl;
82         EEVEE_EffectsInfo *effects = stl->effects;
83
84         const DRWContextState *draw_ctx = DRW_context_state_get();
85         const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
86
87         if (scene_eval->eevee.flag & SCE_EEVEE_BLOOM_ENABLED) {
88                 const float *viewport_size = DRW_viewport_size_get();
89
90                 /* Shaders */
91                 if (!e_data.bloom_blit_sh[0]) {
92                         eevee_create_shader_bloom();
93                 }
94
95                 /* Bloom */
96                 int blitsize[2], texsize[2];
97
98                 /* Blit Buffer */
99                 effects->source_texel_size[0] = 1.0f / viewport_size[0];
100                 effects->source_texel_size[1] = 1.0f / viewport_size[1];
101
102                 blitsize[0] = (int)viewport_size[0];
103                 blitsize[1] = (int)viewport_size[1];
104
105                 effects->blit_texel_size[0] = 1.0f / (float)blitsize[0];
106                 effects->blit_texel_size[1] = 1.0f / (float)blitsize[1];
107
108                 effects->bloom_blit = DRW_texture_pool_query_2D(blitsize[0], blitsize[1], GPU_R11F_G11F_B10F,
109                                                                 &draw_engine_eevee_type);
110
111                 GPU_framebuffer_ensure_config(&fbl->bloom_blit_fb, {
112                         GPU_ATTACHMENT_NONE,
113                         GPU_ATTACHMENT_TEXTURE(effects->bloom_blit)
114                 });
115
116                 /* Parameters */
117                 const float threshold = scene_eval->eevee.bloom_threshold;
118                 const float knee = scene_eval->eevee.bloom_knee;
119                 const float intensity = scene_eval->eevee.bloom_intensity;
120                 const float *color = scene_eval->eevee.bloom_color;
121                 const float radius = scene_eval->eevee.bloom_radius;
122                 effects->bloom_clamp = scene_eval->eevee.bloom_clamp;
123
124                 /* determine the iteration count */
125                 const float minDim = (float)MIN2(blitsize[0], blitsize[1]);
126                 const float maxIter = (radius - 8.0f) + log(minDim) / log(2);
127                 const int maxIterInt = effects->bloom_iteration_len = (int)maxIter;
128
129                 CLAMP(effects->bloom_iteration_len, 1, MAX_BLOOM_STEP);
130
131                 effects->bloom_sample_scale = 0.5f + maxIter - (float)maxIterInt;
132                 effects->bloom_curve_threshold[0] = threshold - knee;
133                 effects->bloom_curve_threshold[1] = knee * 2.0f;
134                 effects->bloom_curve_threshold[2] = 0.25f / max_ff(1e-5f, knee);
135                 effects->bloom_curve_threshold[3] = threshold;
136
137                 mul_v3_v3fl(effects->bloom_color, color, intensity);
138
139                 /* Downsample buffers */
140                 copy_v2_v2_int(texsize, blitsize);
141                 for (int i = 0; i < effects->bloom_iteration_len; ++i) {
142                         texsize[0] /= 2; texsize[1] /= 2;
143
144                         texsize[0] = MAX2(texsize[0], 2);
145                         texsize[1] = MAX2(texsize[1], 2);
146
147                         effects->downsamp_texel_size[i][0] = 1.0f / (float)texsize[0];
148                         effects->downsamp_texel_size[i][1] = 1.0f / (float)texsize[1];
149
150                         effects->bloom_downsample[i] = DRW_texture_pool_query_2D(texsize[0], texsize[1], GPU_R11F_G11F_B10F,
151                                                                                  &draw_engine_eevee_type);
152                         GPU_framebuffer_ensure_config(&fbl->bloom_down_fb[i], {
153                                 GPU_ATTACHMENT_NONE,
154                                 GPU_ATTACHMENT_TEXTURE(effects->bloom_downsample[i])
155                         });
156                 }
157
158                 /* Upsample buffers */
159                 copy_v2_v2_int(texsize, blitsize);
160                 for (int i = 0; i < effects->bloom_iteration_len - 1; ++i) {
161                         texsize[0] /= 2; texsize[1] /= 2;
162
163                         texsize[0] = MAX2(texsize[0], 2);
164                         texsize[1] = MAX2(texsize[1], 2);
165
166                         effects->bloom_upsample[i] = DRW_texture_pool_query_2D(texsize[0], texsize[1], GPU_R11F_G11F_B10F,
167                                                                                &draw_engine_eevee_type);
168                         GPU_framebuffer_ensure_config(&fbl->bloom_accum_fb[i], {
169                                 GPU_ATTACHMENT_NONE,
170                                 GPU_ATTACHMENT_TEXTURE(effects->bloom_upsample[i])
171                         });
172                 }
173
174                 return EFFECT_BLOOM | EFFECT_POST_BUFFER;
175         }
176
177         /* Cleanup to release memory */
178         GPU_FRAMEBUFFER_FREE_SAFE(fbl->bloom_blit_fb);
179
180         for (int i = 0; i < MAX_BLOOM_STEP - 1; ++i) {
181                 GPU_FRAMEBUFFER_FREE_SAFE(fbl->bloom_down_fb[i]);
182                 GPU_FRAMEBUFFER_FREE_SAFE(fbl->bloom_accum_fb[i]);
183         }
184
185         return 0;
186 }
187
188 static DRWShadingGroup *eevee_create_bloom_pass(
189         const char *name, EEVEE_EffectsInfo *effects, struct GPUShader *sh, DRWPass **pass, bool upsample)
190 {
191         struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
192
193         *pass = DRW_pass_create(name, DRW_STATE_WRITE_COLOR);
194
195         DRWShadingGroup *grp = DRW_shgroup_create(sh, *pass);
196         DRW_shgroup_call_add(grp, quad, NULL);
197         DRW_shgroup_uniform_texture_ref(grp, "sourceBuffer", &effects->unf_source_buffer);
198         DRW_shgroup_uniform_vec2(grp, "sourceBufferTexelSize", effects->unf_source_texel_size, 1);
199         if (upsample) {
200                 DRW_shgroup_uniform_texture_ref(grp, "baseBuffer", &effects->unf_base_buffer);
201                 DRW_shgroup_uniform_float(grp, "sampleScale", &effects->bloom_sample_scale, 1);
202         }
203
204         return grp;
205 }
206
207 void EEVEE_bloom_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
208 {
209         EEVEE_PassList *psl = vedata->psl;
210         EEVEE_StorageList *stl = vedata->stl;
211         EEVEE_EffectsInfo *effects = stl->effects;
212
213         if ((effects->enabled_effects & EFFECT_BLOOM) != 0) {
214                 /**  Bloom algorithm
215                  *
216                  * Overview :
217                  * - Downsample the color buffer doing a small blur during each step.
218                  * - Accumulate bloom color using previously downsampled color buffers
219                  *   and do an upsample blur for each new accumulated layer.
220                  * - Finally add accumulation buffer onto the source color buffer.
221                  *
222                  *  [1/1] is original copy resolution (can be half or quarter res for performance)
223                  *
224                  *                                [DOWNSAMPLE CHAIN]                      [UPSAMPLE CHAIN]
225                  *
226                  *  Source Color ── [Blit] ──>  Bright Color Extract [1/1]                  Final Color
227                  *                                        |                                      Λ
228                  *                                [Downsample First]       Source Color ─> + [Resolve]
229                  *                                        v                                      |
230                  *                              Color Downsampled [1/2] ────────────> + Accumulation Buffer [1/2]
231                  *                                        |                                      Λ
232                  *                                       ───                                    ───
233                  *                                      Repeat                                 Repeat
234                  *                                       ───                                    ───
235                  *                                        v                                      |
236                  *                              Color Downsampled [1/N-1] ──────────> + Accumulation Buffer [1/N-1]
237                  *                                        |                                      Λ
238                  *                                   [Downsample]                            [Upsample]
239                  *                                        v                                      |
240                  *                              Color Downsampled [1/N] ─────────────────────────┘
241                  **/
242                 DRWShadingGroup *grp;
243                 const bool use_highres = true;
244                 const bool use_antiflicker = true;
245                 eevee_create_bloom_pass("Bloom Downsample First", effects, e_data.bloom_downsample_sh[use_antiflicker], &psl->bloom_downsample_first, false);
246                 eevee_create_bloom_pass("Bloom Downsample", effects, e_data.bloom_downsample_sh[0], &psl->bloom_downsample, false);
247                 eevee_create_bloom_pass("Bloom Upsample", effects, e_data.bloom_upsample_sh[use_highres], &psl->bloom_upsample, true);
248
249                 grp = eevee_create_bloom_pass("Bloom Blit", effects, e_data.bloom_blit_sh[use_antiflicker], &psl->bloom_blit, false);
250                 DRW_shgroup_uniform_vec4(grp, "curveThreshold", effects->bloom_curve_threshold, 1);
251                 DRW_shgroup_uniform_float(grp, "clampIntensity", &effects->bloom_clamp, 1);
252
253                 grp = eevee_create_bloom_pass("Bloom Resolve", effects, e_data.bloom_resolve_sh[use_highres], &psl->bloom_resolve, true);
254                 DRW_shgroup_uniform_vec3(grp, "bloomColor", effects->bloom_color, 1);
255         }
256 }
257
258 void EEVEE_bloom_draw(EEVEE_Data *vedata)
259 {
260         EEVEE_PassList *psl = vedata->psl;
261         EEVEE_TextureList *txl = vedata->txl;
262         EEVEE_FramebufferList *fbl = vedata->fbl;
263         EEVEE_StorageList *stl = vedata->stl;
264         EEVEE_EffectsInfo *effects = stl->effects;
265
266         /* Bloom */
267         if ((effects->enabled_effects & EFFECT_BLOOM) != 0) {
268                 struct GPUTexture *last;
269
270                 /* Extract bright pixels */
271                 copy_v2_v2(effects->unf_source_texel_size, effects->source_texel_size);
272                 effects->unf_source_buffer = effects->source_buffer;
273
274                 GPU_framebuffer_bind(fbl->bloom_blit_fb);
275                 DRW_draw_pass(psl->bloom_blit);
276
277                 /* Downsample */
278                 copy_v2_v2(effects->unf_source_texel_size, effects->blit_texel_size);
279                 effects->unf_source_buffer = effects->bloom_blit;
280
281                 GPU_framebuffer_bind(fbl->bloom_down_fb[0]);
282                 DRW_draw_pass(psl->bloom_downsample_first);
283
284                 last = effects->bloom_downsample[0];
285
286                 for (int i = 1; i < effects->bloom_iteration_len; ++i) {
287                         copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[i - 1]);
288                         effects->unf_source_buffer = last;
289
290                         GPU_framebuffer_bind(fbl->bloom_down_fb[i]);
291                         DRW_draw_pass(psl->bloom_downsample);
292
293                         /* Used in next loop */
294                         last = effects->bloom_downsample[i];
295                 }
296
297                 /* Upsample and accumulate */
298                 for (int i = effects->bloom_iteration_len - 2; i >= 0; --i) {
299                         copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[i]);
300                         effects->unf_source_buffer = effects->bloom_downsample[i];
301                         effects->unf_base_buffer = last;
302
303                         GPU_framebuffer_bind(fbl->bloom_accum_fb[i]);
304                         DRW_draw_pass(psl->bloom_upsample);
305
306                         last = effects->bloom_upsample[i];
307                 }
308
309                 /* Resolve */
310                 copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[0]);
311                 effects->unf_source_buffer = last;
312                 effects->unf_base_buffer = effects->source_buffer;
313
314                 GPU_framebuffer_bind(effects->target_buffer);
315                 DRW_draw_pass(psl->bloom_resolve);
316                 SWAP_BUFFERS();
317         }
318 }
319
320 void EEVEE_bloom_free(void)
321 {
322         for (int i = 0; i < 2; ++i) {
323                 DRW_SHADER_FREE_SAFE(e_data.bloom_blit_sh[i]);
324                 DRW_SHADER_FREE_SAFE(e_data.bloom_downsample_sh[i]);
325                 DRW_SHADER_FREE_SAFE(e_data.bloom_upsample_sh[i]);
326                 DRW_SHADER_FREE_SAFE(e_data.bloom_resolve_sh[i]);
327         }
328 }