DRW: Cleanup: Make DRW_shgroup_uniform_mat4 uniform expect float (*)[4]
[blender.git] / source / blender / draw / engines / eevee / eevee_volumes.c
1 /*
2  * Copyright 2016, Blender Foundation.
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  * Contributor(s): Blender Institute
19  *
20  */
21
22 /** \file eevee_volumes.c
23  *  \ingroup draw_engine
24  *
25  * Volumetric effects rendering using frostbite approach.
26  */
27
28 #include "DRW_render.h"
29
30 #include "BLI_rand.h"
31 #include "BLI_string_utils.h"
32
33 #include "DNA_object_force_types.h"
34 #include "DNA_smoke_types.h"
35 #include "DNA_world_types.h"
36
37 #include "BKE_global.h" /* for G.debug_value */
38 #include "BKE_modifier.h"
39 #include "BKE_mesh.h"
40 #include "BKE_object.h"
41
42 #include "ED_screen.h"
43
44 #include "eevee_private.h"
45 #include "GPU_draw.h"
46 #include "GPU_texture.h"
47
48 static struct {
49         char *volumetric_common_lib;
50         char *volumetric_common_lamps_lib;
51
52         struct GPUShader *volumetric_clear_sh;
53         struct GPUShader *volumetric_scatter_sh;
54         struct GPUShader *volumetric_scatter_with_lamps_sh;
55         struct GPUShader *volumetric_integration_sh;
56         struct GPUShader *volumetric_resolve_sh;
57
58         GPUTexture *color_src;
59         GPUTexture *depth_src;
60
61         /* List of all smoke domains rendered within this frame. */
62         ListBase smoke_domains;
63 } e_data = {NULL}; /* Engine data */
64
65 extern char datatoc_bsdf_common_lib_glsl[];
66 extern char datatoc_bsdf_direct_lib_glsl[];
67 extern char datatoc_common_uniforms_lib_glsl[];
68 extern char datatoc_common_view_lib_glsl[];
69 extern char datatoc_octahedron_lib_glsl[];
70 extern char datatoc_irradiance_lib_glsl[];
71 extern char datatoc_lamps_lib_glsl[];
72 extern char datatoc_volumetric_frag_glsl[];
73 extern char datatoc_volumetric_geom_glsl[];
74 extern char datatoc_volumetric_vert_glsl[];
75 extern char datatoc_volumetric_resolve_frag_glsl[];
76 extern char datatoc_volumetric_scatter_frag_glsl[];
77 extern char datatoc_volumetric_integration_frag_glsl[];
78 extern char datatoc_volumetric_lib_glsl[];
79 extern char datatoc_common_fullscreen_vert_glsl[];
80
81 static void eevee_create_shader_volumes(void)
82 {
83         e_data.volumetric_common_lib = BLI_string_joinN(
84                 datatoc_common_view_lib_glsl,
85                 datatoc_common_uniforms_lib_glsl,
86                 datatoc_bsdf_common_lib_glsl,
87                 datatoc_volumetric_lib_glsl);
88
89         e_data.volumetric_common_lamps_lib = BLI_string_joinN(
90                 datatoc_common_view_lib_glsl,
91                 datatoc_common_uniforms_lib_glsl,
92                 datatoc_bsdf_common_lib_glsl,
93                 datatoc_bsdf_direct_lib_glsl,
94                 datatoc_octahedron_lib_glsl,
95                 datatoc_irradiance_lib_glsl,
96                 datatoc_lamps_lib_glsl,
97                 datatoc_volumetric_lib_glsl);
98
99         e_data.volumetric_clear_sh = DRW_shader_create_with_lib(
100                 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.volumetric_scatter_sh = DRW_shader_create_with_lib(
107                 datatoc_volumetric_vert_glsl,
108                 datatoc_volumetric_geom_glsl,
109                 datatoc_volumetric_scatter_frag_glsl,
110                 e_data.volumetric_common_lamps_lib,
111                 SHADER_DEFINES
112                 "#define VOLUMETRICS\n"
113                 "#define VOLUME_SHADOW\n");
114         e_data.volumetric_scatter_with_lamps_sh = DRW_shader_create_with_lib(
115                 datatoc_volumetric_vert_glsl,
116                 datatoc_volumetric_geom_glsl,
117                 datatoc_volumetric_scatter_frag_glsl,
118                 e_data.volumetric_common_lamps_lib,
119                 SHADER_DEFINES
120                 "#define VOLUMETRICS\n"
121                 "#define VOLUME_LIGHTING\n"
122                 "#define VOLUME_SHADOW\n");
123         e_data.volumetric_integration_sh = DRW_shader_create_with_lib(
124                 datatoc_volumetric_vert_glsl,
125                 datatoc_volumetric_geom_glsl,
126                 datatoc_volumetric_integration_frag_glsl,
127                 e_data.volumetric_common_lib, NULL);
128         e_data.volumetric_resolve_sh = DRW_shader_create_with_lib(
129                 datatoc_common_fullscreen_vert_glsl, NULL,
130                 datatoc_volumetric_resolve_frag_glsl,
131                 e_data.volumetric_common_lib, NULL);
132 }
133
134 void EEVEE_volumes_set_jitter(EEVEE_ViewLayerData *sldata, unsigned int current_sample)
135 {
136         EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
137
138         double ht_point[3];
139         double ht_offset[3] = {0.0, 0.0};
140         unsigned int ht_primes[3] = {3, 7, 2};
141
142         BLI_halton_3D(ht_primes, ht_offset, current_sample, ht_point);
143
144         common_data->vol_jitter[0] = (float)ht_point[0];
145         common_data->vol_jitter[1] = (float)ht_point[1];
146         common_data->vol_jitter[2] = (float)ht_point[2];
147 }
148
149 int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
150 {
151         EEVEE_StorageList *stl = vedata->stl;
152         EEVEE_FramebufferList *fbl = vedata->fbl;
153         EEVEE_TextureList *txl = vedata->txl;
154         EEVEE_EffectsInfo *effects = stl->effects;
155         EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
156
157         const DRWContextState *draw_ctx = DRW_context_state_get();
158         ViewLayer *view_layer = draw_ctx->view_layer;
159         IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
160
161         const float *viewport_size = DRW_viewport_size_get();
162
163         BLI_listbase_clear(&e_data.smoke_domains);
164
165         if (BKE_collection_engine_property_value_get_bool(props, "volumetric_enable")) {
166
167                 /* Shaders */
168                 if (!e_data.volumetric_scatter_sh) {
169                         eevee_create_shader_volumes();
170                 }
171
172                 int tile_size = BKE_collection_engine_property_value_get_int(props, "volumetric_tile_size");
173
174                 /* Find Froxel Texture resolution. */
175                 int tex_size[3];
176
177                 tex_size[0] = (int)ceilf(fmaxf(1.0f, viewport_size[0] / (float)tile_size));
178                 tex_size[1] = (int)ceilf(fmaxf(1.0f, viewport_size[1] / (float)tile_size));
179                 tex_size[2] = max_ii(BKE_collection_engine_property_value_get_int(props, "volumetric_samples"), 1);
180
181                 common_data->vol_coord_scale[0] = viewport_size[0] / (float)(tile_size * tex_size[0]);
182                 common_data->vol_coord_scale[1] = viewport_size[1] / (float)(tile_size * tex_size[1]);
183
184                 /* TODO compute snap to maxZBuffer for clustered rendering */
185
186                 if ((common_data->vol_tex_size[0] != tex_size[0]) ||
187                     (common_data->vol_tex_size[1] != tex_size[1]) ||
188                     (common_data->vol_tex_size[2] != tex_size[2]))
189                 {
190                         DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering);
191                         DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction);
192                         DRW_TEXTURE_FREE_SAFE(txl->volume_prop_emission);
193                         DRW_TEXTURE_FREE_SAFE(txl->volume_prop_phase);
194                         DRW_TEXTURE_FREE_SAFE(txl->volume_scatter);
195                         DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance);
196                         DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
197                         DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance_history);
198                         GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
199                         GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
200                         GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
201                         common_data->vol_tex_size[0] = tex_size[0];
202                         common_data->vol_tex_size[1] = tex_size[1];
203                         common_data->vol_tex_size[2] = tex_size[2];
204
205                         common_data->vol_inv_tex_size[0] = 1.0f / (float)(tex_size[0]);
206                         common_data->vol_inv_tex_size[1] = 1.0f / (float)(tex_size[1]);
207                         common_data->vol_inv_tex_size[2] = 1.0f / (float)(tex_size[2]);
208                 }
209
210                 /* Like frostbite's paper, 5% blend of the new frame. */
211                 common_data->vol_history_alpha = (txl->volume_prop_scattering == NULL) ? 0.0f : 0.95f;
212
213                 if (txl->volume_prop_scattering == NULL) {
214                         /* Volume properties: We evaluate all volumetric objects
215                          * and store their final properties into each froxel */
216                         txl->volume_prop_scattering = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
217                                                                             DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
218                         txl->volume_prop_extinction = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
219                                                                             DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
220                         txl->volume_prop_emission = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
221                                                                           DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
222                         txl->volume_prop_phase = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
223                                                                        DRW_TEX_RG_16, DRW_TEX_FILTER, NULL);
224
225                         /* Volume scattering: We compute for each froxel the
226                          * Scattered light towards the view. We also resolve temporal
227                          * super sampling during this stage. */
228                         txl->volume_scatter = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
229                                                                     DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
230                         txl->volume_transmittance = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
231                                                                           DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
232
233                         /* Final integration: We compute for each froxel the
234                          * amount of scattered light and extinction coef at this
235                          * given depth. We use theses textures as double buffer
236                          * for the volumetric history. */
237                         txl->volume_scatter_history = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
238                                                                             DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
239                         txl->volume_transmittance_history = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
240                                                                                   DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
241                 }
242
243                 /* Temporal Super sampling jitter */
244                 unsigned int ht_primes[3] = {3, 7, 2};
245                 unsigned int current_sample = 0;
246
247                 /* If TAA is in use do not use the history buffer. */
248                 bool do_taa = ((effects->enabled_effects & EFFECT_TAA) != 0);
249
250                 if (draw_ctx->evil_C != NULL) {
251                         struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C);
252                         do_taa = do_taa && (ED_screen_animation_no_scrub(wm) == NULL);
253                 }
254
255                 if (do_taa) {
256                         common_data->vol_history_alpha = 0.0f;
257                         current_sample = effects->taa_current_sample - 1;
258                         effects->volume_current_sample = -1;
259                 }
260                 else {
261                         const unsigned int max_sample = (ht_primes[0] * ht_primes[1] * ht_primes[2]);
262                         current_sample = effects->volume_current_sample = (effects->volume_current_sample + 1) % max_sample;
263                         if (current_sample != max_sample - 1) {
264                                 DRW_viewport_request_redraw();
265                         }
266                 }
267
268                 EEVEE_volumes_set_jitter(sldata, current_sample);
269
270                 /* Framebuffer setup */
271                 GPU_framebuffer_ensure_config(&fbl->volumetric_fb, {
272                         GPU_ATTACHMENT_NONE,
273                         GPU_ATTACHMENT_TEXTURE(txl->volume_prop_scattering),
274                         GPU_ATTACHMENT_TEXTURE(txl->volume_prop_extinction),
275                         GPU_ATTACHMENT_TEXTURE(txl->volume_prop_emission),
276                         GPU_ATTACHMENT_TEXTURE(txl->volume_prop_phase)
277                 });
278                 GPU_framebuffer_ensure_config(&fbl->volumetric_scat_fb, {
279                         GPU_ATTACHMENT_NONE,
280                         GPU_ATTACHMENT_TEXTURE(txl->volume_scatter),
281                         GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance)
282                 });
283                 GPU_framebuffer_ensure_config(&fbl->volumetric_integ_fb, {
284                         GPU_ATTACHMENT_NONE,
285                         GPU_ATTACHMENT_TEXTURE(txl->volume_scatter_history),
286                         GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance_history)
287                 });
288
289                 float integration_start = BKE_collection_engine_property_value_get_float(props, "volumetric_start");
290                 float integration_end = BKE_collection_engine_property_value_get_float(props, "volumetric_end");
291                 common_data->vol_light_clamp = BKE_collection_engine_property_value_get_float(props, "volumetric_light_clamp");
292
293                 common_data->vol_shadow_steps = (float)BKE_collection_engine_property_value_get_int(props, "volumetric_shadow_samples");
294                 if (BKE_collection_engine_property_value_get_bool(props, "volumetric_shadows")) {
295                 }
296                 else {
297                         common_data->vol_shadow_steps = 0;
298                 }
299
300                 if (DRW_viewport_is_persp_get()) {
301                         float sample_distribution = BKE_collection_engine_property_value_get_float(props, "volumetric_sample_distribution");
302                         sample_distribution = 4.0f * (1.00001f - sample_distribution);
303
304                         const float clip_start = common_data->view_vecs[0][2];
305                         /* Negate */
306                         float near = integration_start = min_ff(-integration_start, clip_start - 1e-4f);
307                         float far = integration_end = min_ff(-integration_end, near - 1e-4f);
308
309                         common_data->vol_depth_param[0] = (far - near * exp2(1.0f / sample_distribution)) / (far - near);
310                         common_data->vol_depth_param[1] = (1.0f - common_data->vol_depth_param[0]) / near;
311                         common_data->vol_depth_param[2] = sample_distribution;
312                 }
313                 else {
314                         const float clip_start = common_data->view_vecs[0][2];
315                         const float clip_end = clip_start + common_data->view_vecs[1][2];
316                         integration_start = min_ff(integration_end, clip_start);
317                         integration_end = max_ff(-integration_end, clip_end);
318
319                         common_data->vol_depth_param[0] = integration_start;
320                         common_data->vol_depth_param[1] = integration_end;
321                         common_data->vol_depth_param[2] = 1.0f / (integration_end - integration_start);
322                 }
323
324                 /* Disable clamp if equal to 0. */
325                 if (common_data->vol_light_clamp == 0.0) {
326                         common_data->vol_light_clamp = FLT_MAX;
327                 }
328
329                 common_data->vol_use_lights = BKE_collection_engine_property_value_get_bool(props, "volumetric_lights");
330
331                 return EFFECT_VOLUMETRIC | EFFECT_POST_BUFFER;
332         }
333
334         /* Cleanup to release memory */
335         DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering);
336         DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction);
337         DRW_TEXTURE_FREE_SAFE(txl->volume_prop_emission);
338         DRW_TEXTURE_FREE_SAFE(txl->volume_prop_phase);
339         DRW_TEXTURE_FREE_SAFE(txl->volume_scatter);
340         DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance);
341         DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
342         DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance_history);
343         GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
344         GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
345         GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
346
347         return 0;
348 }
349
350 void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
351 {
352         EEVEE_PassList *psl = vedata->psl;
353         EEVEE_StorageList *stl = vedata->stl;
354         EEVEE_TextureList *txl = vedata->txl;
355         EEVEE_EffectsInfo *effects = stl->effects;
356         EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
357
358         if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
359                 const DRWContextState *draw_ctx = DRW_context_state_get();
360                 Scene *scene = draw_ctx->scene;
361                 DRWShadingGroup *grp = NULL;
362
363                 /* Quick breakdown of the Volumetric rendering:
364                  *
365                  * The rendering is separated in 4 stages:
366                  *
367                  * - Material Parameters : we collect volume properties of
368                  *   all participating media in the scene and store them in
369                  *   a 3D texture aligned with the 3D frustum.
370                  *   This is done in 2 passes, one that clear the texture
371                  *   and/or evaluate the world volumes, and the 2nd one that
372                  *   additively render object volumes.
373                  *
374                  * - Light Scattering : the volume properties then are sampled
375                  *   and light scattering is evaluated for each cell of the
376                  *   volume texture. Temporal supersampling (if enabled) occurs here.
377                  *
378                  * - Volume Integration : the scattered light and extinction is
379                  *   integrated (accumulated) along the viewrays. The result is stored
380                  *   for every cell in another texture.
381                  *
382                  * - Fullscreen Resolve : From the previous stage, we get two
383                  *   3D textures that contains integrated scatered light and extinction
384                  *   for "every" positions in the frustum. We only need to sample
385                  *   them and blend the scene color with thoses factors. This also
386                  *   work for alpha blended materials.
387                  **/
388
389                 /* World pass is not additive as it also clear the buffer. */
390                 psl->volumetric_world_ps = DRW_pass_create("Volumetric World", DRW_STATE_WRITE_COLOR);
391
392                 /* World Volumetric */
393                 struct World *wo = scene->world;
394                 if (wo != NULL && wo->use_nodes && wo->nodetree) {
395                         struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo);
396
397                         grp = DRW_shgroup_material_empty_tri_batch_create(mat,
398                                                                           psl->volumetric_world_ps,
399                                                                           common_data->vol_tex_size[2]);
400
401                         if (grp) {
402                                 DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
403                         }
404                 }
405
406                 if (grp == NULL) {
407                         /* If no world or volume material is present just clear the buffer with this drawcall */
408                         grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_clear_sh,
409                                                                      psl->volumetric_world_ps,
410                                                                      common_data->vol_tex_size[2]);
411
412                         DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
413                 }
414
415                 /* Volumetric Objects */
416                 psl->volumetric_objects_ps = DRW_pass_create("Volumetric Properties", DRW_STATE_WRITE_COLOR |
417                                                                                       DRW_STATE_ADDITIVE);
418
419                 struct GPUShader *scatter_sh = (common_data->vol_use_lights) ? e_data.volumetric_scatter_with_lamps_sh
420                                                                       : e_data.volumetric_scatter_sh;
421                 psl->volumetric_scatter_ps = DRW_pass_create("Volumetric Scattering", DRW_STATE_WRITE_COLOR);
422                 grp = DRW_shgroup_empty_tri_batch_create(scatter_sh, psl->volumetric_scatter_ps,
423                                                          common_data->vol_tex_size[2]);
424                 DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &sldata->irradiance_pool);
425                 DRW_shgroup_uniform_texture_ref(grp, "shadowTexture", &sldata->shadow_pool);
426                 DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_prop_scattering);
427                 DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_prop_extinction);
428                 DRW_shgroup_uniform_texture_ref(grp, "volumeEmission", &txl->volume_prop_emission);
429                 DRW_shgroup_uniform_texture_ref(grp, "volumePhase", &txl->volume_prop_phase);
430                 DRW_shgroup_uniform_texture_ref(grp, "historyScattering", &txl->volume_scatter_history);
431                 DRW_shgroup_uniform_texture_ref(grp, "historyTransmittance", &txl->volume_transmittance_history);
432                 DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
433                 DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
434                 DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
435
436                 psl->volumetric_integration_ps = DRW_pass_create("Volumetric Integration", DRW_STATE_WRITE_COLOR);
437                 grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_integration_sh,
438                                                          psl->volumetric_integration_ps,
439                                                          common_data->vol_tex_size[2]);
440                 DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_scatter);
441                 DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_transmittance);
442                 DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
443
444                 psl->volumetric_resolve_ps = DRW_pass_create("Volumetric Resolve", DRW_STATE_WRITE_COLOR);
445                 grp = DRW_shgroup_create(e_data.volumetric_resolve_sh, psl->volumetric_resolve_ps);
446                 DRW_shgroup_uniform_texture_ref(grp, "inScattering", &txl->volume_scatter);
447                 DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmittance);
448                 DRW_shgroup_uniform_texture_ref(grp, "inSceneColor", &e_data.color_src);
449                 DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
450                 DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
451                 DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
452         }
453 }
454
455 void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Scene *scene, Object *ob)
456 {
457         float *texcoloc = NULL;
458         float *texcosize = NULL;
459         struct ModifierData *md = NULL;
460         Material *ma = give_current_material(ob, 1);
461
462         if (ma == NULL) {
463                 return;
464         }
465
466         struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma);
467
468         DRWShadingGroup *grp = DRW_shgroup_material_empty_tri_batch_create(mat, vedata->psl->volumetric_objects_ps, sldata->common_data.vol_tex_size[2]);
469
470         /* If shader failed to compile or is currently compiling. */
471         if (grp == NULL) {
472                 return;
473         }
474
475         /* Making sure it's updated. */
476         invert_m4_m4(ob->imat, ob->obmat);
477
478         BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texcoloc, NULL, &texcosize);
479
480         DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
481         DRW_shgroup_uniform_mat4(grp, "volumeObjectMatrix", ob->imat);
482         DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1);
483         DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1);
484
485         /* Smoke Simulation */
486         if (((ob->base_flag & BASE_FROMDUPLI) == 0) &&
487             (md = modifiers_findByType(ob, eModifierType_Smoke)) &&
488             (modifier_isEnabled(scene, md, eModifierMode_Realtime)))
489         {
490                 SmokeModifierData *smd = (SmokeModifierData *)md;
491                 SmokeDomainSettings *sds = smd->domain;
492                 /* Don't show smoke before simulation starts, this could be made an option in the future. */
493                 const bool show_smoke = (CFRA >= sds->point_cache[0]->startframe);
494
495                 if (sds->fluid && show_smoke) {
496                         if (!sds->wt || !(sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
497                                 GPU_create_smoke(smd, 0);
498                         }
499                         else if (sds->wt && (sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
500                                 GPU_create_smoke(smd, 1);
501                         }
502                         BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(smd));
503                 }
504
505                 if (sds->tex != NULL) {
506                         DRW_shgroup_uniform_texture_ref(grp, "sampdensity", &sds->tex);
507                 }
508                 if (sds->tex_flame != NULL) {
509                         DRW_shgroup_uniform_texture_ref(grp, "sampflame", &sds->tex_flame);
510                 }
511
512                 /* Output is such that 0..1 maps to 0..1000K */
513                 DRW_shgroup_uniform_vec2(grp, "unftemperature", &sds->flame_ignition, 1);
514         }
515 }
516
517 void EEVEE_volumes_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
518 {
519         EEVEE_PassList *psl = vedata->psl;
520         EEVEE_TextureList *txl = vedata->txl;
521         EEVEE_FramebufferList *fbl = vedata->fbl;
522         EEVEE_StorageList *stl = vedata->stl;
523         EEVEE_EffectsInfo *effects = stl->effects;
524         if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
525                 DRW_stats_group_start("Volumetrics");
526
527                 /* Step 1: Participating Media Properties */
528                 GPU_framebuffer_bind(fbl->volumetric_fb);
529                 DRW_draw_pass(psl->volumetric_world_ps);
530                 DRW_draw_pass(psl->volumetric_objects_ps);
531
532                 /* Step 2: Scatter Light */
533                 GPU_framebuffer_bind(fbl->volumetric_scat_fb);
534                 DRW_draw_pass(psl->volumetric_scatter_ps);
535
536                 /* Step 3: Integration */
537                 GPU_framebuffer_bind(fbl->volumetric_integ_fb);
538                 DRW_draw_pass(psl->volumetric_integration_ps);
539
540                 /* Swap volume history buffers */
541                 SWAP(struct GPUFrameBuffer *, fbl->volumetric_scat_fb, fbl->volumetric_integ_fb);
542                 SWAP(GPUTexture *, txl->volume_scatter, txl->volume_scatter_history);
543                 SWAP(GPUTexture *, txl->volume_transmittance, txl->volume_transmittance_history);
544
545                 /* Restore */
546                 GPU_framebuffer_bind(fbl->main_fb);
547
548                 DRW_stats_group_end();
549         }
550 }
551
552 void EEVEE_volumes_resolve(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
553 {
554         EEVEE_PassList *psl = vedata->psl;
555         EEVEE_TextureList *txl = vedata->txl;
556         EEVEE_FramebufferList *fbl = vedata->fbl;
557         EEVEE_StorageList *stl = vedata->stl;
558         EEVEE_EffectsInfo *effects = stl->effects;
559
560         if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
561                 DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
562
563                 e_data.color_src = txl->color;
564                 e_data.depth_src = dtxl->depth;
565
566                 /* Step 4: Apply for opaque */
567                 GPU_framebuffer_bind(fbl->effect_color_fb);
568                 DRW_draw_pass(psl->volumetric_resolve_ps);
569
570                 /* Swap the buffers and rebind depth to the current buffer */
571                 SWAP(GPUFrameBuffer *, fbl->main_fb, fbl->effect_fb);
572                 SWAP(GPUFrameBuffer *, fbl->main_color_fb, fbl->effect_color_fb);
573                 SWAP(GPUTexture *, txl->color, txl->color_post);
574                 GPU_framebuffer_texture_attach(fbl->main_fb, dtxl->depth, 0, 0);
575         }
576 }
577
578 void EEVEE_volumes_free_smoke_textures(void)
579 {
580         /* Free Smoke Textures after rendering */
581         for (LinkData *link = e_data.smoke_domains.first; link; link = link->next) {
582                 SmokeModifierData *smd = (SmokeModifierData *)link->data;
583                 GPU_free_smoke(smd);
584         }
585         BLI_freelistN(&e_data.smoke_domains);
586 }
587
588 void EEVEE_volumes_free(void)
589 {
590         MEM_SAFE_FREE(e_data.volumetric_common_lib);
591         MEM_SAFE_FREE(e_data.volumetric_common_lamps_lib);
592
593         DRW_SHADER_FREE_SAFE(e_data.volumetric_clear_sh);
594         DRW_SHADER_FREE_SAFE(e_data.volumetric_scatter_sh);
595         DRW_SHADER_FREE_SAFE(e_data.volumetric_scatter_with_lamps_sh);
596         DRW_SHADER_FREE_SAFE(e_data.volumetric_integration_sh);
597         DRW_SHADER_FREE_SAFE(e_data.volumetric_resolve_sh);
598 }