e3afa91a5a9b3414014a8c069a4888f8b899eba1
[blender.git] / source / blender / draw / engines / eevee / eevee_volumes.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  * Volumetric effects rendering using frostbite approach.
23  */
24
25 #include "DRW_render.h"
26
27 #include "BLI_rand.h"
28 #include "BLI_string_utils.h"
29
30 #include "DNA_object_force_types.h"
31 #include "DNA_smoke_types.h"
32 #include "DNA_world_types.h"
33
34 #include "BKE_modifier.h"
35 #include "BKE_mesh.h"
36 #include "BKE_smoke.h"
37
38 #include "ED_screen.h"
39
40 #include "DEG_depsgraph_query.h"
41
42 #include "eevee_private.h"
43 #include "GPU_draw.h"
44 #include "GPU_texture.h"
45 #include "GPU_material.h"
46
47 static struct {
48   char *volumetric_common_lib;
49   char *volumetric_common_lights_lib;
50
51   struct GPUShader *volumetric_clear_sh;
52   struct GPUShader *scatter_sh;
53   struct GPUShader *scatter_with_lights_sh;
54   struct GPUShader *volumetric_integration_sh;
55   struct GPUShader *volumetric_resolve_sh;
56
57   GPUTexture *color_src;
58   GPUTexture *depth_src;
59
60   GPUTexture *dummy_density;
61   GPUTexture *dummy_flame;
62
63   GPUTexture *dummy_scatter;
64   GPUTexture *dummy_transmit;
65
66   /* List of all smoke domains rendered within this frame. */
67   ListBase smoke_domains;
68 } e_data = {NULL}; /* Engine data */
69
70 extern char datatoc_bsdf_common_lib_glsl[];
71 extern char datatoc_common_uniforms_lib_glsl[];
72 extern char datatoc_common_view_lib_glsl[];
73 extern char datatoc_octahedron_lib_glsl[];
74 extern char datatoc_irradiance_lib_glsl[];
75 extern char datatoc_lights_lib_glsl[];
76 extern char datatoc_volumetric_frag_glsl[];
77 extern char datatoc_volumetric_geom_glsl[];
78 extern char datatoc_volumetric_vert_glsl[];
79 extern char datatoc_volumetric_resolve_frag_glsl[];
80 extern char datatoc_volumetric_scatter_frag_glsl[];
81 extern char datatoc_volumetric_integration_frag_glsl[];
82 extern char datatoc_volumetric_lib_glsl[];
83 extern char datatoc_common_fullscreen_vert_glsl[];
84
85 static void eevee_create_shader_volumes(void)
86 {
87   e_data.volumetric_common_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
88                                                   datatoc_common_uniforms_lib_glsl,
89                                                   datatoc_bsdf_common_lib_glsl,
90                                                   datatoc_volumetric_lib_glsl);
91
92   e_data.volumetric_common_lights_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
93                                                          datatoc_common_uniforms_lib_glsl,
94                                                          datatoc_bsdf_common_lib_glsl,
95                                                          datatoc_octahedron_lib_glsl,
96                                                          datatoc_irradiance_lib_glsl,
97                                                          datatoc_lights_lib_glsl,
98                                                          datatoc_volumetric_lib_glsl);
99
100   e_data.volumetric_clear_sh = DRW_shader_create_with_lib(datatoc_volumetric_vert_glsl,
101                                                           datatoc_volumetric_geom_glsl,
102                                                           datatoc_volumetric_frag_glsl,
103                                                           e_data.volumetric_common_lib,
104                                                           "#define VOLUMETRICS\n"
105                                                           "#define CLEAR\n");
106   e_data.scatter_sh = DRW_shader_create_with_lib(datatoc_volumetric_vert_glsl,
107                                                  datatoc_volumetric_geom_glsl,
108                                                  datatoc_volumetric_scatter_frag_glsl,
109                                                  e_data.volumetric_common_lights_lib,
110                                                  SHADER_DEFINES
111                                                  "#define VOLUMETRICS\n"
112                                                  "#define VOLUME_SHADOW\n");
113   e_data.scatter_with_lights_sh = DRW_shader_create_with_lib(datatoc_volumetric_vert_glsl,
114                                                              datatoc_volumetric_geom_glsl,
115                                                              datatoc_volumetric_scatter_frag_glsl,
116                                                              e_data.volumetric_common_lights_lib,
117                                                              SHADER_DEFINES
118                                                              "#define VOLUMETRICS\n"
119                                                              "#define VOLUME_LIGHTING\n"
120                                                              "#define VOLUME_SHADOW\n");
121   e_data.volumetric_integration_sh = DRW_shader_create_with_lib(
122       datatoc_volumetric_vert_glsl,
123       datatoc_volumetric_geom_glsl,
124       datatoc_volumetric_integration_frag_glsl,
125       e_data.volumetric_common_lib,
126       NULL);
127   e_data.volumetric_resolve_sh = DRW_shader_create_with_lib(datatoc_common_fullscreen_vert_glsl,
128                                                             NULL,
129                                                             datatoc_volumetric_resolve_frag_glsl,
130                                                             e_data.volumetric_common_lib,
131                                                             NULL);
132
133   float color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
134   e_data.dummy_density = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, color);
135
136   float flame = 0.0f;
137   e_data.dummy_flame = DRW_texture_create_3d(1, 1, 1, GPU_R8, DRW_TEX_WRAP, &flame);
138 }
139
140 void EEVEE_volumes_set_jitter(EEVEE_ViewLayerData *sldata, uint current_sample)
141 {
142   EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
143
144   double ht_point[3];
145   double ht_offset[3] = {0.0, 0.0};
146   uint ht_primes[3] = {3, 7, 2};
147
148   BLI_halton_3d(ht_primes, ht_offset, current_sample, ht_point);
149
150   common_data->vol_jitter[0] = (float)ht_point[0];
151   common_data->vol_jitter[1] = (float)ht_point[1];
152   common_data->vol_jitter[2] = (float)ht_point[2];
153 }
154
155 void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
156 {
157   EEVEE_StorageList *stl = vedata->stl;
158   EEVEE_FramebufferList *fbl = vedata->fbl;
159   EEVEE_TextureList *txl = vedata->txl;
160   EEVEE_EffectsInfo *effects = stl->effects;
161   EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
162
163   const DRWContextState *draw_ctx = DRW_context_state_get();
164   const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
165
166   const float *viewport_size = DRW_viewport_size_get();
167
168   BLI_listbase_clear(&e_data.smoke_domains);
169
170   const int tile_size = scene_eval->eevee.volumetric_tile_size;
171
172   /* Find Froxel Texture resolution. */
173   int tex_size[3];
174
175   tex_size[0] = (int)ceilf(fmaxf(1.0f, viewport_size[0] / (float)tile_size));
176   tex_size[1] = (int)ceilf(fmaxf(1.0f, viewport_size[1] / (float)tile_size));
177   tex_size[2] = max_ii(scene_eval->eevee.volumetric_samples, 1);
178
179   common_data->vol_coord_scale[0] = viewport_size[0] / (float)(tile_size * tex_size[0]);
180   common_data->vol_coord_scale[1] = viewport_size[1] / (float)(tile_size * tex_size[1]);
181
182   /* TODO compute snap to maxZBuffer for clustered rendering */
183   if ((common_data->vol_tex_size[0] != tex_size[0]) ||
184       (common_data->vol_tex_size[1] != tex_size[1]) ||
185       (common_data->vol_tex_size[2] != tex_size[2])) {
186     DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering);
187     DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction);
188     DRW_TEXTURE_FREE_SAFE(txl->volume_prop_emission);
189     DRW_TEXTURE_FREE_SAFE(txl->volume_prop_phase);
190     DRW_TEXTURE_FREE_SAFE(txl->volume_scatter);
191     DRW_TEXTURE_FREE_SAFE(txl->volume_transmit);
192     DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
193     DRW_TEXTURE_FREE_SAFE(txl->volume_transmit_history);
194     GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
195     GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
196     GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
197     copy_v3_v3_int(common_data->vol_tex_size, tex_size);
198
199     common_data->vol_inv_tex_size[0] = 1.0f / (float)(tex_size[0]);
200     common_data->vol_inv_tex_size[1] = 1.0f / (float)(tex_size[1]);
201     common_data->vol_inv_tex_size[2] = 1.0f / (float)(tex_size[2]);
202   }
203
204   /* Like frostbite's paper, 5% blend of the new frame. */
205   common_data->vol_history_alpha = (txl->volume_prop_scattering == NULL) ? 0.0f : 0.95f;
206
207   /* Temporal Super sampling jitter */
208   uint ht_primes[3] = {3, 7, 2};
209   uint current_sample = 0;
210
211   /* If TAA is in use do not use the history buffer. */
212   bool do_taa = ((effects->enabled_effects & EFFECT_TAA) != 0);
213
214   if (draw_ctx->evil_C != NULL) {
215     struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C);
216     do_taa = do_taa && (ED_screen_animation_no_scrub(wm) == NULL);
217   }
218
219   if (do_taa) {
220     common_data->vol_history_alpha = 0.0f;
221     current_sample = effects->taa_current_sample - 1;
222     effects->volume_current_sample = -1;
223   }
224   else if (DRW_state_is_image_render()) {
225     const uint max_sample = (ht_primes[0] * ht_primes[1] * ht_primes[2]);
226     current_sample = effects->volume_current_sample = (effects->volume_current_sample + 1) %
227                                                       max_sample;
228     if (current_sample != max_sample - 1) {
229       DRW_viewport_request_redraw();
230     }
231   }
232
233   EEVEE_volumes_set_jitter(sldata, current_sample);
234
235   float integration_start = scene_eval->eevee.volumetric_start;
236   float integration_end = scene_eval->eevee.volumetric_end;
237   common_data->vol_light_clamp = scene_eval->eevee.volumetric_light_clamp;
238   common_data->vol_shadow_steps = (float)scene_eval->eevee.volumetric_shadow_samples;
239   if ((scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_SHADOWS) == 0) {
240     common_data->vol_shadow_steps = 0;
241   }
242
243   /* Update view_vecs */
244   float invproj[4][4], winmat[4][4];
245   DRW_view_winmat_get(NULL, winmat, false);
246   DRW_view_winmat_get(NULL, invproj, true);
247   EEVEE_update_viewvecs(invproj, winmat, sldata->common_data.view_vecs);
248
249   if (DRW_view_is_persp_get(NULL)) {
250     float sample_distribution = scene_eval->eevee.volumetric_sample_distribution;
251     sample_distribution = 4.0f * (1.00001f - sample_distribution);
252
253     const float clip_start = common_data->view_vecs[0][2];
254     /* Negate */
255     float near = integration_start = min_ff(-integration_start, clip_start - 1e-4f);
256     float far = integration_end = min_ff(-integration_end, near - 1e-4f);
257
258     common_data->vol_depth_param[0] = (far - near * exp2(1.0f / sample_distribution)) /
259                                       (far - near);
260     common_data->vol_depth_param[1] = (1.0f - common_data->vol_depth_param[0]) / near;
261     common_data->vol_depth_param[2] = sample_distribution;
262   }
263   else {
264     const float clip_start = common_data->view_vecs[0][2];
265     const float clip_end = clip_start + common_data->view_vecs[1][2];
266     integration_start = min_ff(integration_end, clip_start);
267     integration_end = max_ff(-integration_end, clip_end);
268
269     common_data->vol_depth_param[0] = integration_start;
270     common_data->vol_depth_param[1] = integration_end;
271     common_data->vol_depth_param[2] = 1.0f / (integration_end - integration_start);
272   }
273
274   /* Disable clamp if equal to 0. */
275   if (common_data->vol_light_clamp == 0.0) {
276     common_data->vol_light_clamp = FLT_MAX;
277   }
278
279   common_data->vol_use_lights = (scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_LIGHTS) != 0;
280
281   if (!e_data.dummy_scatter) {
282     float scatter[4] = {0.0f, 0.0f, 0.0f, 0.0f};
283     float transmit[4] = {1.0f, 1.0f, 1.0f, 1.0f};
284     e_data.dummy_scatter = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, scatter);
285     e_data.dummy_transmit = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, transmit);
286   }
287 }
288
289 void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
290 {
291   EEVEE_PassList *psl = vedata->psl;
292   EEVEE_StorageList *stl = vedata->stl;
293   EEVEE_EffectsInfo *effects = stl->effects;
294   EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
295
296   const DRWContextState *draw_ctx = DRW_context_state_get();
297   Scene *scene = draw_ctx->scene;
298   DRWShadingGroup *grp = NULL;
299
300   /* Shaders */
301   if (!e_data.scatter_sh) {
302     eevee_create_shader_volumes();
303   }
304
305   /* Quick breakdown of the Volumetric rendering:
306    *
307    * The rendering is separated in 4 stages:
308    *
309    * - Material Parameters : we collect volume properties of
310    *   all participating media in the scene and store them in
311    *   a 3D texture aligned with the 3D frustum.
312    *   This is done in 2 passes, one that clear the texture
313    *   and/or evaluate the world volumes, and the 2nd one that
314    *   additively render object volumes.
315    *
316    * - Light Scattering : the volume properties then are sampled
317    *   and light scattering is evaluated for each cell of the
318    *   volume texture. Temporal super-sampling (if enabled) occurs here.
319    *
320    * - Volume Integration : the scattered light and extinction is
321    *   integrated (accumulated) along the view-rays. The result is stored
322    *   for every cell in another texture.
323    *
324    * - Full-screen Resolve : From the previous stage, we get two
325    *   3D textures that contains integrated scattered light and extinction
326    *   for "every" positions in the frustum. We only need to sample
327    *   them and blend the scene color with those factors. This also
328    *   work for alpha blended materials.
329    */
330
331   /* World pass is not additive as it also clear the buffer. */
332   DRW_PASS_CREATE(psl->volumetric_world_ps, DRW_STATE_WRITE_COLOR);
333   DRW_PASS_CREATE(psl->volumetric_objects_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD);
334
335   /* World Volumetric */
336   struct World *wo = scene->world;
337   if (wo != NULL && wo->use_nodes && wo->nodetree &&
338       !LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) {
339     struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo);
340
341     if (GPU_material_use_domain_volume(mat)) {
342       grp = DRW_shgroup_material_create(mat, psl->volumetric_world_ps);
343     }
344
345     if (grp) {
346       DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
347       /* TODO (fclem): remove those (need to clean the GLSL files). */
348       DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
349       DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
350       DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
351       DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
352       DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
353
354       /* Fix principle volumetric not working with world materials. */
355       DRW_shgroup_uniform_texture(grp, "sampdensity", e_data.dummy_density);
356       DRW_shgroup_uniform_texture(grp, "sampflame", e_data.dummy_flame);
357       DRW_shgroup_uniform_vec2_copy(grp, "unftemperature", (float[2]){0.0f, 1.0f});
358
359       DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
360
361       effects->enabled_effects |= (EFFECT_VOLUMETRIC | EFFECT_POST_BUFFER);
362     }
363   }
364
365   if (grp == NULL) {
366     /* If no world or volume material is present just clear the buffer with this drawcall */
367     grp = DRW_shgroup_create(e_data.volumetric_clear_sh, psl->volumetric_world_ps);
368     DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
369
370     DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
371   }
372 }
373
374 typedef struct EEVEE_InstanceVolumeMatrix {
375   DrawData dd;
376   float volume_mat[4][4];
377 } EEVEE_InstanceVolumeMatrix;
378
379 void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
380                                     EEVEE_Data *vedata,
381                                     Scene *scene,
382                                     Object *ob)
383 {
384   const DRWContextState *draw_ctx = DRW_context_state_get();
385   static float white[3] = {1.0f, 1.0f, 1.0f};
386
387   float *texcoloc = NULL;
388   float *texcosize = NULL;
389   struct ModifierData *md = NULL;
390   Material *ma = give_current_material(ob, 1);
391
392   if (ma == NULL) {
393     return;
394   }
395
396   struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma);
397
398   /* If shader failed to compile or is currently compiling. */
399   if (GPU_material_status(mat) != GPU_MAT_SUCCESS) {
400     return;
401   }
402
403   DRWShadingGroup *grp = DRW_shgroup_material_create(mat, vedata->psl->volumetric_objects_ps);
404
405   BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texcoloc, NULL, &texcosize);
406
407   /* TODO(fclem) remove those "unnecessary" UBOs */
408   DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
409   DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
410   DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
411   DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
412   DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
413
414   DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
415   DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1);
416   DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1);
417
418   /* Smoke Simulation */
419   if (((ob->base_flag & BASE_FROM_DUPLI) == 0) &&
420       (md = modifiers_findByType(ob, eModifierType_Smoke)) &&
421       (modifier_isEnabled(scene, md, eModifierMode_Realtime)) &&
422       ((SmokeModifierData *)md)->domain != NULL) {
423     SmokeModifierData *smd = (SmokeModifierData *)md;
424     SmokeDomainSettings *sds = smd->domain;
425
426     /* Don't show smoke before simulation starts, this could be made an option in the future. */
427     const bool show_smoke = ((int)DEG_get_ctime(draw_ctx->depsgraph) >=
428                              sds->point_cache[0]->startframe);
429
430     if (sds->fluid && show_smoke) {
431       const bool show_highres = BKE_smoke_show_highres(scene, sds);
432       if (!sds->wt || !show_highres) {
433         GPU_create_smoke(smd, 0);
434       }
435       else if (sds->wt && show_highres) {
436         GPU_create_smoke(smd, 1);
437       }
438       BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(smd));
439     }
440
441     DRW_shgroup_uniform_texture_ref(
442         grp, "sampdensity", sds->tex ? &sds->tex : &e_data.dummy_density);
443     DRW_shgroup_uniform_texture_ref(
444         grp, "sampflame", sds->tex_flame ? &sds->tex_flame : &e_data.dummy_flame);
445
446     /* Constant Volume color. */
447     bool use_constant_color = ((sds->active_fields & SM_ACTIVE_COLORS) == 0 &&
448                                (sds->active_fields & SM_ACTIVE_COLOR_SET) != 0);
449
450     DRW_shgroup_uniform_vec3(
451         grp, "volumeColor", (use_constant_color) ? sds->active_color : white, 1);
452
453     /* Output is such that 0..1 maps to 0..1000K */
454     DRW_shgroup_uniform_vec2(grp, "unftemperature", &sds->flame_ignition, 1);
455   }
456   else {
457     DRW_shgroup_uniform_texture(grp, "sampdensity", e_data.dummy_density);
458     DRW_shgroup_uniform_texture(grp, "sampflame", e_data.dummy_flame);
459     DRW_shgroup_uniform_vec3(grp, "volumeColor", white, 1);
460     DRW_shgroup_uniform_vec2(grp, "unftemperature", (float[2]){0.0f, 1.0f}, 1);
461   }
462
463   /* TODO Reduce to number of slices intersecting. */
464   /* TODO Preemptive culling. */
465   DRW_shgroup_call_procedural_triangles(grp, ob, sldata->common_data.vol_tex_size[2]);
466
467   vedata->stl->effects->enabled_effects |= (EFFECT_VOLUMETRIC | EFFECT_POST_BUFFER);
468 }
469
470 void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
471 {
472   EEVEE_PassList *psl = vedata->psl;
473   EEVEE_TextureList *txl = vedata->txl;
474   EEVEE_EffectsInfo *effects = vedata->stl->effects;
475   LightCache *lcache = vedata->stl->g_data->light_cache;
476   EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
477
478   if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
479     DRWShadingGroup *grp;
480     struct GPUShader *sh;
481
482     DRW_PASS_CREATE(psl->volumetric_scatter_ps, DRW_STATE_WRITE_COLOR);
483     sh = (common_data->vol_use_lights) ? e_data.scatter_with_lights_sh : e_data.scatter_sh;
484     grp = DRW_shgroup_create(sh, psl->volumetric_scatter_ps);
485     DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &lcache->grid_tx.tex);
486     DRW_shgroup_uniform_texture_ref(grp, "shadowCubeTexture", &sldata->shadow_cube_pool);
487     DRW_shgroup_uniform_texture_ref(grp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
488     DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_prop_scattering);
489     DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_prop_extinction);
490     DRW_shgroup_uniform_texture_ref(grp, "volumeEmission", &txl->volume_prop_emission);
491     DRW_shgroup_uniform_texture_ref(grp, "volumePhase", &txl->volume_prop_phase);
492     DRW_shgroup_uniform_texture_ref(grp, "historyScattering", &txl->volume_scatter_history);
493     DRW_shgroup_uniform_texture_ref(grp, "historyTransmittance", &txl->volume_transmit_history);
494     DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
495     DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
496     DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
497
498     DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
499
500     DRW_PASS_CREATE(psl->volumetric_integration_ps, DRW_STATE_WRITE_COLOR);
501     grp = DRW_shgroup_create(e_data.volumetric_integration_sh, psl->volumetric_integration_ps);
502     DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_scatter);
503     DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_transmit);
504     DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
505
506     DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
507
508     DRW_PASS_CREATE(psl->volumetric_resolve_ps, DRW_STATE_WRITE_COLOR);
509     grp = DRW_shgroup_create(e_data.volumetric_resolve_sh, psl->volumetric_resolve_ps);
510     DRW_shgroup_uniform_texture_ref(grp, "inScattering", &txl->volume_scatter);
511     DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit);
512     DRW_shgroup_uniform_texture_ref(grp, "inSceneColor", &e_data.color_src);
513     DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
514     DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
515
516     DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
517   }
518 }
519
520 void EEVEE_volumes_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
521 {
522   EEVEE_FramebufferList *fbl = vedata->fbl;
523   EEVEE_TextureList *txl = vedata->txl;
524   EEVEE_EffectsInfo *effects = vedata->stl->effects;
525   EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
526
527   if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
528     int *tex_size = common_data->vol_tex_size;
529
530     if (txl->volume_prop_scattering == NULL) {
531       /* Volume properties: We evaluate all volumetric objects
532        * and store their final properties into each froxel */
533       txl->volume_prop_scattering = DRW_texture_create_3d(
534           tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
535       txl->volume_prop_extinction = DRW_texture_create_3d(
536           tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
537       txl->volume_prop_emission = DRW_texture_create_3d(
538           tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
539       txl->volume_prop_phase = DRW_texture_create_3d(
540           tex_size[0], tex_size[1], tex_size[2], GPU_RG16F, DRW_TEX_FILTER, NULL);
541
542       /* Volume scattering: We compute for each froxel the
543        * Scattered light towards the view. We also resolve temporal
544        * super sampling during this stage. */
545       txl->volume_scatter = DRW_texture_create_3d(
546           tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
547       txl->volume_transmit = DRW_texture_create_3d(
548           tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
549
550       /* Final integration: We compute for each froxel the
551        * amount of scattered light and extinction coef at this
552        * given depth. We use theses textures as double buffer
553        * for the volumetric history. */
554       txl->volume_scatter_history = DRW_texture_create_3d(
555           tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
556       txl->volume_transmit_history = DRW_texture_create_3d(
557           tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
558     }
559
560     GPU_framebuffer_ensure_config(&fbl->volumetric_fb,
561                                   {GPU_ATTACHMENT_NONE,
562                                    GPU_ATTACHMENT_TEXTURE(txl->volume_prop_scattering),
563                                    GPU_ATTACHMENT_TEXTURE(txl->volume_prop_extinction),
564                                    GPU_ATTACHMENT_TEXTURE(txl->volume_prop_emission),
565                                    GPU_ATTACHMENT_TEXTURE(txl->volume_prop_phase)});
566     GPU_framebuffer_ensure_config(&fbl->volumetric_scat_fb,
567                                   {GPU_ATTACHMENT_NONE,
568                                    GPU_ATTACHMENT_TEXTURE(txl->volume_scatter),
569                                    GPU_ATTACHMENT_TEXTURE(txl->volume_transmit)});
570     GPU_framebuffer_ensure_config(&fbl->volumetric_integ_fb,
571                                   {GPU_ATTACHMENT_NONE,
572                                    GPU_ATTACHMENT_TEXTURE(txl->volume_scatter_history),
573                                    GPU_ATTACHMENT_TEXTURE(txl->volume_transmit_history)});
574
575     /* Usage happens after buffer have been swapped. */
576     effects->volume_scatter = txl->volume_scatter_history;
577     effects->volume_transmit = txl->volume_transmit_history;
578   }
579   else {
580     DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering);
581     DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction);
582     DRW_TEXTURE_FREE_SAFE(txl->volume_prop_emission);
583     DRW_TEXTURE_FREE_SAFE(txl->volume_prop_phase);
584     DRW_TEXTURE_FREE_SAFE(txl->volume_scatter);
585     DRW_TEXTURE_FREE_SAFE(txl->volume_transmit);
586     DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
587     DRW_TEXTURE_FREE_SAFE(txl->volume_transmit_history);
588     GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
589     GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
590     GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
591
592     effects->volume_scatter = e_data.dummy_scatter;
593     effects->volume_transmit = e_data.dummy_transmit;
594   }
595 }
596
597 void EEVEE_volumes_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
598 {
599   EEVEE_PassList *psl = vedata->psl;
600   EEVEE_TextureList *txl = vedata->txl;
601   EEVEE_FramebufferList *fbl = vedata->fbl;
602   EEVEE_StorageList *stl = vedata->stl;
603   EEVEE_EffectsInfo *effects = stl->effects;
604   if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
605     DRW_stats_group_start("Volumetrics");
606
607     GPU_framebuffer_bind(fbl->volumetric_fb);
608     DRW_draw_pass(psl->volumetric_world_ps);
609     DRW_draw_pass(psl->volumetric_objects_ps);
610
611     GPU_framebuffer_bind(fbl->volumetric_scat_fb);
612     DRW_draw_pass(psl->volumetric_scatter_ps);
613
614     GPU_framebuffer_bind(fbl->volumetric_integ_fb);
615     DRW_draw_pass(psl->volumetric_integration_ps);
616
617     SWAP(struct GPUFrameBuffer *, fbl->volumetric_scat_fb, fbl->volumetric_integ_fb);
618     SWAP(GPUTexture *, txl->volume_scatter, txl->volume_scatter_history);
619     SWAP(GPUTexture *, txl->volume_transmit, txl->volume_transmit_history);
620
621     /* Restore */
622     GPU_framebuffer_bind(fbl->main_fb);
623
624     DRW_stats_group_end();
625   }
626 }
627
628 void EEVEE_volumes_resolve(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
629 {
630   EEVEE_PassList *psl = vedata->psl;
631   EEVEE_TextureList *txl = vedata->txl;
632   EEVEE_FramebufferList *fbl = vedata->fbl;
633   EEVEE_StorageList *stl = vedata->stl;
634   EEVEE_EffectsInfo *effects = stl->effects;
635
636   if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
637     DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
638
639     e_data.color_src = txl->color;
640     e_data.depth_src = dtxl->depth;
641
642     /* Step 4: Apply for opaque */
643     GPU_framebuffer_bind(fbl->effect_color_fb);
644     DRW_draw_pass(psl->volumetric_resolve_ps);
645
646     /* Swap the buffers and rebind depth to the current buffer */
647     SWAP(GPUFrameBuffer *, fbl->main_fb, fbl->effect_fb);
648     SWAP(GPUFrameBuffer *, fbl->main_color_fb, fbl->effect_color_fb);
649     SWAP(GPUTexture *, txl->color, txl->color_post);
650
651     /* Restore */
652     GPU_framebuffer_texture_detach(fbl->effect_fb, dtxl->depth);
653     GPU_framebuffer_texture_attach(fbl->main_fb, dtxl->depth, 0, 0);
654     GPU_framebuffer_bind(fbl->main_fb);
655   }
656 }
657
658 void EEVEE_volumes_free_smoke_textures(void)
659 {
660   /* Free Smoke Textures after rendering */
661   for (LinkData *link = e_data.smoke_domains.first; link; link = link->next) {
662     SmokeModifierData *smd = (SmokeModifierData *)link->data;
663     GPU_free_smoke(smd);
664   }
665   BLI_freelistN(&e_data.smoke_domains);
666 }
667
668 void EEVEE_volumes_free(void)
669 {
670   MEM_SAFE_FREE(e_data.volumetric_common_lib);
671   MEM_SAFE_FREE(e_data.volumetric_common_lights_lib);
672
673   DRW_TEXTURE_FREE_SAFE(e_data.dummy_scatter);
674   DRW_TEXTURE_FREE_SAFE(e_data.dummy_transmit);
675
676   DRW_TEXTURE_FREE_SAFE(e_data.dummy_density);
677   DRW_TEXTURE_FREE_SAFE(e_data.dummy_flame);
678
679   DRW_SHADER_FREE_SAFE(e_data.volumetric_clear_sh);
680   DRW_SHADER_FREE_SAFE(e_data.scatter_sh);
681   DRW_SHADER_FREE_SAFE(e_data.scatter_with_lights_sh);
682   DRW_SHADER_FREE_SAFE(e_data.volumetric_integration_sh);
683   DRW_SHADER_FREE_SAFE(e_data.volumetric_resolve_sh);
684 }