Blender  V2.93
eevee_bloom.c
Go to the documentation of this file.
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 
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 const bool use_highres = true;
34 
36 {
37  EEVEE_StorageList *stl = vedata->stl;
38  EEVEE_FramebufferList *fbl = vedata->fbl;
39  EEVEE_EffectsInfo *effects = stl->effects;
40 
41  const DRWContextState *draw_ctx = DRW_context_state_get();
42  const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
43 
44  if (scene_eval->eevee.flag & SCE_EEVEE_BLOOM_ENABLED) {
45  const float *viewport_size = DRW_viewport_size_get();
46 
47  /* Bloom */
48  int blitsize[2], texsize[2];
49 
50  /* Blit Buffer */
51  effects->source_texel_size[0] = 1.0f / viewport_size[0];
52  effects->source_texel_size[1] = 1.0f / viewport_size[1];
53 
54  blitsize[0] = (int)viewport_size[0];
55  blitsize[1] = (int)viewport_size[1];
56 
57  effects->blit_texel_size[0] = 1.0f / (float)blitsize[0];
58  effects->blit_texel_size[1] = 1.0f / (float)blitsize[1];
59 
61  blitsize[0], blitsize[1], GPU_R11F_G11F_B10F, &draw_engine_eevee_type);
62 
63  GPU_framebuffer_ensure_config(
64  &fbl->bloom_blit_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(effects->bloom_blit)});
65 
66  /* Parameters */
67  const float threshold = scene_eval->eevee.bloom_threshold;
68  const float knee = scene_eval->eevee.bloom_knee;
69  const float intensity = scene_eval->eevee.bloom_intensity;
70  const float *color = scene_eval->eevee.bloom_color;
71  const float radius = scene_eval->eevee.bloom_radius;
72  effects->bloom_clamp = scene_eval->eevee.bloom_clamp;
73 
74  /* determine the iteration count */
75  const float minDim = (float)MIN2(blitsize[0], blitsize[1]);
76  const float maxIter = (radius - 8.0f) + log(minDim) / log(2);
77  const int maxIterInt = effects->bloom_iteration_len = (int)maxIter;
78 
80 
81  effects->bloom_sample_scale = 0.5f + maxIter - (float)maxIterInt;
82  effects->bloom_curve_threshold[0] = threshold - knee;
83  effects->bloom_curve_threshold[1] = knee * 2.0f;
84  effects->bloom_curve_threshold[2] = 0.25f / max_ff(1e-5f, knee);
85  effects->bloom_curve_threshold[3] = threshold;
86 
87  mul_v3_v3fl(effects->bloom_color, color, intensity);
88 
89  /* Downsample buffers */
90  copy_v2_v2_int(texsize, blitsize);
91  for (int i = 0; i < effects->bloom_iteration_len; i++) {
92  texsize[0] /= 2;
93  texsize[1] /= 2;
94 
95  texsize[0] = MAX2(texsize[0], 2);
96  texsize[1] = MAX2(texsize[1], 2);
97 
98  effects->downsamp_texel_size[i][0] = 1.0f / (float)texsize[0];
99  effects->downsamp_texel_size[i][1] = 1.0f / (float)texsize[1];
100 
102  texsize[0], texsize[1], GPU_R11F_G11F_B10F, &draw_engine_eevee_type);
103  GPU_framebuffer_ensure_config(
104  &fbl->bloom_down_fb[i],
105  {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(effects->bloom_downsample[i])});
106  }
107 
108  /* Upsample buffers */
109  copy_v2_v2_int(texsize, blitsize);
110  for (int i = 0; i < effects->bloom_iteration_len - 1; i++) {
111  texsize[0] /= 2;
112  texsize[1] /= 2;
113 
114  texsize[0] = MAX2(texsize[0], 2);
115  texsize[1] = MAX2(texsize[1], 2);
116 
118  texsize[0], texsize[1], GPU_R11F_G11F_B10F, &draw_engine_eevee_type);
119  GPU_framebuffer_ensure_config(
120  &fbl->bloom_accum_fb[i],
121  {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(effects->bloom_upsample[i])});
122  }
123 
125  }
126 
127  /* Cleanup to release memory */
129 
130  for (int i = 0; i < MAX_BLOOM_STEP - 1; i++) {
133  }
134 
135  return 0;
136 }
137 
138 static DRWShadingGroup *eevee_create_bloom_pass(const char *name,
139  EEVEE_EffectsInfo *effects,
140  struct GPUShader *sh,
141  DRWPass **pass,
142  bool upsample,
143  bool resolve)
144 {
146 
147  *pass = DRW_pass_create(name, DRW_STATE_WRITE_COLOR);
148 
149  DRWShadingGroup *grp = DRW_shgroup_create(sh, *pass);
150  DRW_shgroup_call(grp, quad, NULL);
151  DRW_shgroup_uniform_texture_ref(grp, "sourceBuffer", &effects->unf_source_buffer);
152  DRW_shgroup_uniform_vec2(grp, "sourceBufferTexelSize", effects->unf_source_texel_size, 1);
153  if (upsample) {
154  DRW_shgroup_uniform_texture_ref(grp, "baseBuffer", &effects->unf_base_buffer);
155  DRW_shgroup_uniform_float(grp, "sampleScale", &effects->bloom_sample_scale, 1);
156  }
157  if (resolve) {
158  DRW_shgroup_uniform_vec3(grp, "bloomColor", effects->bloom_color, 1);
159  DRW_shgroup_uniform_bool_copy(grp, "bloomAddBase", true);
160  }
161 
162  return grp;
163 }
164 
166 {
167  EEVEE_PassList *psl = vedata->psl;
168  EEVEE_StorageList *stl = vedata->stl;
169  EEVEE_EffectsInfo *effects = stl->effects;
170 
171  psl->bloom_accum_ps = NULL;
172 
173  if ((effects->enabled_effects & EFFECT_BLOOM) != 0) {
204  DRWShadingGroup *grp;
205  const bool use_antiflicker = true;
206  eevee_create_bloom_pass("Bloom Downsample First",
207  effects,
208  EEVEE_shaders_bloom_downsample_get(use_antiflicker),
210  false,
211  false);
212  eevee_create_bloom_pass("Bloom Downsample",
213  effects,
215  &psl->bloom_downsample,
216  false,
217  false);
218  eevee_create_bloom_pass("Bloom Upsample",
219  effects,
221  &psl->bloom_upsample,
222  true,
223  false);
224 
225  grp = eevee_create_bloom_pass("Bloom Blit",
226  effects,
227  EEVEE_shaders_bloom_blit_get(use_antiflicker),
228  &psl->bloom_blit,
229  false,
230  false);
231  DRW_shgroup_uniform_vec4(grp, "curveThreshold", effects->bloom_curve_threshold, 1);
232  DRW_shgroup_uniform_float(grp, "clampIntensity", &effects->bloom_clamp, 1);
233 
234  grp = eevee_create_bloom_pass("Bloom Resolve",
235  effects,
237  &psl->bloom_resolve,
238  true,
239  true);
240  }
241 }
242 
244 {
245  EEVEE_PassList *psl = vedata->psl;
246  EEVEE_TextureList *txl = vedata->txl;
247  EEVEE_FramebufferList *fbl = vedata->fbl;
248  EEVEE_StorageList *stl = vedata->stl;
249  EEVEE_EffectsInfo *effects = stl->effects;
250 
251  /* Bloom */
252  if ((effects->enabled_effects & EFFECT_BLOOM) != 0) {
253  struct GPUTexture *last;
254 
255  /* Extract bright pixels */
257  effects->unf_source_buffer = effects->source_buffer;
258 
261 
262  /* Downsample */
264  effects->unf_source_buffer = effects->bloom_blit;
265 
268 
269  last = effects->bloom_downsample[0];
270 
271  for (int i = 1; i < effects->bloom_iteration_len; i++) {
272  copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[i - 1]);
273  effects->unf_source_buffer = last;
274 
277 
278  /* Used in next loop */
279  last = effects->bloom_downsample[i];
280  }
281 
282  /* Upsample and accumulate */
283  for (int i = effects->bloom_iteration_len - 2; i >= 0; i--) {
285  effects->unf_source_buffer = last;
286  effects->unf_base_buffer = effects->bloom_downsample[i];
287 
290 
291  last = effects->bloom_upsample[i];
292  }
293 
294  /* Resolve */
296  effects->unf_source_buffer = last;
297  effects->unf_base_buffer = effects->source_buffer;
298 
301  SWAP_BUFFERS();
302  }
303 }
304 
306  EEVEE_Data *vedata,
307  uint UNUSED(tot_samples))
308 {
309  EEVEE_FramebufferList *fbl = vedata->fbl;
310  EEVEE_TextureList *txl = vedata->txl;
311  EEVEE_PassList *psl = vedata->psl;
312  EEVEE_StorageList *stl = vedata->stl;
313  EEVEE_EffectsInfo *effects = stl->effects;
314 
315  /* Create FrameBuffer. */
317 
318  GPU_framebuffer_ensure_config(&fbl->bloom_pass_accum_fb,
319  {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->bloom_accum)});
320 
321  /* Create Pass and shgroup. */
322  DRWShadingGroup *grp = eevee_create_bloom_pass("Bloom Accumulate",
323  effects,
325  &psl->bloom_accum_ps,
326  true,
327  true);
328  DRW_shgroup_uniform_bool_copy(grp, "bloomAddBase", false);
329 }
330 
332 {
333  EEVEE_FramebufferList *fbl = vedata->fbl;
334  EEVEE_PassList *psl = vedata->psl;
335  EEVEE_StorageList *stl = vedata->stl;
336 
340 
341  /* Restore */
343  }
344 }
typedef float(TangentPoint)[2]
MINLINE float max_ff(float a, float b)
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v2_v2_int(int r[2], const int a[2])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNUSED(x)
#define MAX2(a, b)
#define MIN2(a, b)
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
@ EEVEE_RENDER_PASS_BLOOM
@ SCE_EEVEE_BLOOM_ENABLED
@ DRW_STATE_WRITE_COLOR
Definition: DRW_render.h:315
#define DRW_shgroup_call(shgroup, geom, ob)
Definition: DRW_render.h:420
GPUBatch
Definition: GPU_batch.h:93
#define GPU_FRAMEBUFFER_FREE_SAFE(fb)
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
struct GPUShader GPUShader
Definition: GPU_shader.h:33
struct GPUTexture GPUTexture
Definition: GPU_texture.h:33
@ GPU_R11F_G11F_B10F
Definition: GPU_texture.h:119
Group RGB to Bright Vector Camera CLAMP
GPUBatch * DRW_cache_fullscreen_quad_get(void)
Definition: draw_cache.c:358
const DRWContextState * DRW_context_state_get(void)
const float * DRW_viewport_size_get(void)
Definition: draw_manager.c:439
void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
void DRW_shgroup_uniform_vec3(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
DRWShadingGroup * DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
DRWPass * DRW_pass_create(const char *name, DRWState state)
void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value)
void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
void DRW_shgroup_uniform_vec2(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
void DRW_draw_pass(DRWPass *pass)
void DRW_texture_ensure_fullscreen_2d(GPUTexture **tex, eGPUTextureFormat format, DRWTextureFlag flags)
GPUTexture * DRW_texture_pool_query_2d(int w, int h, eGPUTextureFormat format, DrawEngineType *engine_type)
void EEVEE_bloom_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
Definition: eevee_bloom.c:331
void EEVEE_bloom_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, uint UNUSED(tot_samples))
Definition: eevee_bloom.c:305
void EEVEE_bloom_draw(EEVEE_Data *vedata)
Definition: eevee_bloom.c:243
int EEVEE_bloom_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
Definition: eevee_bloom.c:35
static const bool use_highres
Definition: eevee_bloom.c:33
static DRWShadingGroup * eevee_create_bloom_pass(const char *name, EEVEE_EffectsInfo *effects, struct GPUShader *sh, DRWPass **pass, bool upsample, bool resolve)
Definition: eevee_bloom.c:138
void EEVEE_bloom_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
Definition: eevee_bloom.c:165
DrawEngineType draw_engine_eevee_type
Definition: eevee_engine.c:622
#define SWAP_BUFFERS()
#define MAX_BLOOM_STEP
Definition: eevee_private.h:55
struct GPUShader * EEVEE_shaders_bloom_blit_get(bool high_quality)
@ EFFECT_BLOOM
@ EFFECT_POST_BUFFER
struct GPUShader * EEVEE_shaders_bloom_upsample_get(bool high_quality)
struct GPUShader * EEVEE_shaders_bloom_resolve_get(bool high_quality)
struct GPUShader * EEVEE_shaders_bloom_downsample_get(bool high_quality)
GPUBatch * quad
INLINE Rall1d< T, V, S > log(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:303
struct Depsgraph * depsgraph
Definition: DRW_render.h:753
EEVEE_TextureList * txl
EEVEE_StorageList * stl
EEVEE_PassList * psl
EEVEE_FramebufferList * fbl
float blit_texel_size[2]
float downsamp_texel_size[MAX_BLOOM_STEP][2]
struct GPUTexture * source_buffer
float bloom_curve_threshold[4]
float unf_source_texel_size[2]
struct GPUTexture * bloom_blit
struct GPUFrameBuffer * target_buffer
struct GPUTexture * bloom_upsample[MAX_BLOOM_STEP - 1]
struct GPUTexture * bloom_downsample[MAX_BLOOM_STEP]
float source_texel_size[2]
EEVEE_EffectsFlag enabled_effects
struct GPUTexture * unf_base_buffer
struct GPUTexture * unf_source_buffer
struct GPUFrameBuffer * main_fb
struct GPUFrameBuffer * bloom_blit_fb
struct GPUFrameBuffer * bloom_pass_accum_fb
struct GPUFrameBuffer * bloom_accum_fb[MAX_BLOOM_STEP - 1]
struct GPUFrameBuffer * bloom_down_fb[MAX_BLOOM_STEP]
struct DRWPass * bloom_resolve
struct DRWPass * bloom_upsample
struct DRWPass * bloom_downsample_first
struct DRWPass * bloom_blit
struct DRWPass * bloom_accum_ps
struct DRWPass * bloom_downsample
eViewLayerEEVEEPassType render_passes
struct EEVEE_PrivateData * g_data
struct EEVEE_EffectsInfo * effects
struct GPUTexture * bloom_accum
float bloom_intensity
float bloom_color[3]
float bloom_threshold
struct SceneEEVEE eevee