Eevee: Remove the Volumetric Render checkbox
authorClément Foucault <foucault.clem@gmail.com>
Thu, 16 May 2019 19:41:22 +0000 (21:41 +0200)
committerClément Foucault <foucault.clem@gmail.com>
Fri, 17 May 2019 11:38:42 +0000 (13:38 +0200)
This is to simplify the usage of Volumetrics.

Now it automatically detect if there is any Volumetric material in the
view and allocate the needed buffer if any.

14 files changed:
release/scripts/startup/bl_ui/properties_render.py
source/blender/blenloader/intern/versioning_280.c
source/blender/draw/engines/eevee/eevee_effects.c
source/blender/draw/engines/eevee/eevee_engine.c
source/blender/draw/engines/eevee/eevee_lightcache.c
source/blender/draw/engines/eevee/eevee_materials.c
source/blender/draw/engines/eevee/eevee_private.h
source/blender/draw/engines/eevee/eevee_render.c
source/blender/draw/engines/eevee/eevee_volumes.c
source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
source/blender/draw/intern/DRW_render.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/intern/rna_scene.c
tests/python/eevee_render_tests.py

index fbf247b..b99e2b9 100644 (file)
@@ -241,11 +241,6 @@ class RENDER_PT_eevee_volumetric(RenderButtonsPanel, Panel):
     def poll(cls, context):
         return (context.engine in cls.COMPAT_ENGINES)
 
-    def draw_header(self, context):
-        scene = context.scene
-        props = scene.eevee
-        self.layout.prop(props, "use_volumetric", text="")
-
     def draw(self, context):
         layout = self.layout
         layout.use_property_split = True
@@ -253,8 +248,6 @@ class RENDER_PT_eevee_volumetric(RenderButtonsPanel, Panel):
         scene = context.scene
         props = scene.eevee
 
-        layout.active = props.use_volumetric
-
         col = layout.column(align=True)
         col.prop(props, "volumetric_start")
         col.prop(props, "volumetric_end")
index 84c9aa0..d248933 100644 (file)
@@ -1673,7 +1673,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
 
         IDProperty *props = IDP_GetPropertyFromGroup(scene->layer_properties,
                                                      RE_engine_id_BLENDER_EEVEE);
-        EEVEE_GET_BOOL(props, volumetric_enable, SCE_EEVEE_VOLUMETRIC_ENABLED);
+        // EEVEE_GET_BOOL(props, volumetric_enable, SCE_EEVEE_VOLUMETRIC_ENABLED);
         EEVEE_GET_BOOL(props, volumetric_lights, SCE_EEVEE_VOLUMETRIC_LIGHTS);
         EEVEE_GET_BOOL(props, volumetric_shadows, SCE_EEVEE_VOLUMETRIC_SHADOWS);
         EEVEE_GET_BOOL(props, gtao_enable, SCE_EEVEE_GTAO_ENABLED);
index 91426b3..7956921 100644 (file)
@@ -160,8 +160,8 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
   effects->enabled_effects |= EEVEE_temporal_sampling_init(sldata, vedata);
   effects->enabled_effects |= EEVEE_occlusion_init(sldata, vedata);
   effects->enabled_effects |= EEVEE_screen_raytrace_init(sldata, vedata);
-  effects->enabled_effects |= EEVEE_volumes_init(sldata, vedata);
 
+  EEVEE_volumes_init(sldata, vedata);
   EEVEE_subsurface_init(sldata, vedata);
 
   /* Force normal buffer creation. */
@@ -263,16 +263,6 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
     GPU_FRAMEBUFFER_FREE_SAFE(fbl->double_buffer_depth_fb);
   }
 
-  /**
-   * Setup double buffer so we can access last frame as it was before post processes.
-   */
-  if ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0) {
-    SETUP_BUFFER(txl->color_double_buffer, fbl->double_buffer_fb, fbl->double_buffer_color_fb);
-  }
-  else {
-    CLEANUP_BUFFER(txl->color_double_buffer, fbl->double_buffer_fb, fbl->double_buffer_color_fb);
-  }
-
   if ((effects->enabled_effects & (EFFECT_TAA | EFFECT_TAA_REPROJECT)) != 0) {
     SETUP_BUFFER(txl->taa_history, fbl->taa_history_fb, fbl->taa_history_color_fb);
   }
@@ -384,6 +374,23 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
   }
 }
 
+void EEVEE_effects_draw_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+  EEVEE_FramebufferList *fbl = vedata->fbl;
+  EEVEE_TextureList *txl = vedata->txl;
+  EEVEE_EffectsInfo *effects = vedata->stl->effects;
+  DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+  /**
+   * Setup double buffer so we can access last frame as it was before post processes.
+   */
+  if ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0) {
+    SETUP_BUFFER(txl->color_double_buffer, fbl->double_buffer_fb, fbl->double_buffer_color_fb);
+  }
+  else {
+    CLEANUP_BUFFER(txl->color_double_buffer, fbl->double_buffer_fb, fbl->double_buffer_color_fb);
+  }
+}
+
 #if 0 /* Not required for now */
 static void min_downsample_cb(void *vedata, int UNUSED(level))
 {
index 9fc11d9..481b566 100644 (file)
@@ -154,9 +154,13 @@ static void eevee_cache_finish(void *vedata)
 {
   EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
 
+  EEVEE_volumes_cache_finish(sldata, vedata);
   EEVEE_materials_cache_finish(sldata, vedata);
   EEVEE_lights_cache_finish(sldata, vedata);
   EEVEE_lightprobes_cache_finish(sldata, vedata);
+
+  EEVEE_effects_draw_init(sldata, vedata);
+  EEVEE_volumes_draw_init(sldata, vedata);
 }
 
 /* As renders in an HDR offscreen buffer, we need draw everything once
index c639f4b..3e0e5f6 100644 (file)
@@ -757,10 +757,14 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb
   }
   DRW_render_object_iter(vedata, NULL, lbake->depsgraph, EEVEE_render_cache);
 
+  EEVEE_volumes_cache_finish(sldata, vedata);
   EEVEE_materials_cache_finish(sldata, vedata);
   EEVEE_lights_cache_finish(sldata, vedata);
   EEVEE_lightprobes_cache_finish(sldata, vedata);
 
+  EEVEE_effects_draw_init(sldata, vedata);
+  EEVEE_volumes_draw_init(sldata, vedata);
+
   txl->color = NULL;
 
   DRW_render_instance_buffer_finish();
index e6369af..7989d4d 100644 (file)
@@ -327,9 +327,6 @@ static char *eevee_get_defines(int options)
   if ((options & VAR_MAT_ESM) != 0) {
     BLI_dynstr_append(ds, "#define SHADOW_ESM\n");
   }
-  if (((options & VAR_MAT_VOLUME) != 0) && ((options & VAR_MAT_BLEND) != 0)) {
-    BLI_dynstr_append(ds, "#define USE_ALPHA_BLEND_VOLUMETRICS\n");
-  }
   if ((options & VAR_MAT_LOOKDEV) != 0) {
     /* Auto config shadow method. Avoid more permutation. */
     BLI_assert((options & (VAR_MAT_VSM | VAR_MAT_ESM)) == 0);
@@ -376,6 +373,7 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp,
                                   bool use_alpha_blend)
 {
   LightCache *lcache = vedata->stl->g_data->light_cache;
+  EEVEE_EffectsInfo *effects = vedata->stl->effects;
 
   if (ssr_id == NULL) {
     static int no_ssr = -1.0f;
@@ -397,9 +395,8 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp,
     DRW_shgroup_uniform_texture_ref(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer);
   }
   if ((use_diffuse || use_glossy) && !use_ssrefraction) {
-    if ((vedata->stl->effects->enabled_effects & EFFECT_GTAO) != 0) {
-      DRW_shgroup_uniform_texture_ref(
-          shgrp, "horizonBuffer", &vedata->stl->effects->gtao_horizons);
+    if ((effects->enabled_effects & EFFECT_GTAO) != 0) {
+      DRW_shgroup_uniform_texture_ref(shgrp, "horizonBuffer", &effects->gtao_horizons);
     }
     else {
       /* Use maxzbuffer as fallback to avoid sampling problem on certain platform, see: T52593 */
@@ -423,11 +420,9 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp,
       DRW_shgroup_uniform_texture_ref(shgrp, "colorBuffer", &vedata->txl->refract_color);
     }
   }
-
-  if ((vedata->stl->effects->enabled_effects & EFFECT_VOLUMETRIC) != 0 && use_alpha_blend) {
-    /* Do not use history buffers as they already have been swapped */
-    DRW_shgroup_uniform_texture_ref(shgrp, "inScattering", &vedata->txl->volume_scatter);
-    DRW_shgroup_uniform_texture_ref(shgrp, "inTransmittance", &vedata->txl->volume_transmittance);
+  if (use_alpha_blend) {
+    DRW_shgroup_uniform_texture_ref(shgrp, "inScattering", &effects->volume_scatter);
+    DRW_shgroup_uniform_texture_ref(shgrp, "inTransmittance", &effects->volume_transmit);
   }
 }
 
@@ -752,8 +747,6 @@ struct GPUMaterial *EEVEE_material_mesh_get(struct Scene *scene,
   SET_FLAG_FROM_TEST(options, use_refract, VAR_MAT_REFRACT);
   SET_FLAG_FROM_TEST(options, effects->sss_separate_albedo, VAR_MAT_SSSALBED);
   SET_FLAG_FROM_TEST(options, use_translucency, VAR_MAT_TRANSLUC);
-  SET_FLAG_FROM_TEST(
-      options, ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) && use_blend, VAR_MAT_VOLUME);
 
   options |= eevee_material_shadow_option(shadow_method);
 
@@ -884,15 +877,12 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create(EEVEE_ViewLaye
                                                                   bool use_ssr,
                                                                   int shadow_method)
 {
-  EEVEE_EffectsInfo *effects = vedata->stl->effects;
   static int ssr_id;
   ssr_id = (use_ssr) ? 1 : -1;
   int options = VAR_MAT_MESH;
 
   SET_FLAG_FROM_TEST(options, is_hair, VAR_MAT_HAIR);
   SET_FLAG_FROM_TEST(options, use_blend, VAR_MAT_BLEND);
-  SET_FLAG_FROM_TEST(
-      options, ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) && use_blend, VAR_MAT_VOLUME);
 
   options |= eevee_material_shadow_option(shadow_method);
 
@@ -1722,7 +1712,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
     }
 
     /* Volumetrics */
-    if (((stl->effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) && use_volume_material) {
+    if (use_volume_material) {
       EEVEE_volumes_cache_object_add(sldata, vedata, scene, ob);
     }
   }
index 2db36e4..e213061 100644 (file)
@@ -333,9 +333,9 @@ typedef struct EEVEE_TextureList {
   struct GPUTexture *volume_prop_emission;
   struct GPUTexture *volume_prop_phase;
   struct GPUTexture *volume_scatter;
-  struct GPUTexture *volume_transmittance;
+  struct GPUTexture *volume_transmit;
   struct GPUTexture *volume_scatter_history;
-  struct GPUTexture *volume_transmittance_history;
+  struct GPUTexture *volume_transmit_history;
 
   struct GPUTexture *lookdev_grid_tx;
   struct GPUTexture *lookdev_cube_tx;
@@ -552,6 +552,8 @@ typedef struct EEVEE_EffectsInfo {
   struct GPUTexture *sss_stencil;
   /* Volumetrics */
   int volume_current_sample;
+  struct GPUTexture *volume_scatter;
+  struct GPUTexture *volume_transmit;
   /* SSR */
   bool reflection_trace_full;
   bool ssr_was_persp;
@@ -1062,13 +1064,15 @@ void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data
 void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata);
 
 /* eevee_volumes.c */
-int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
 void EEVEE_volumes_set_jitter(EEVEE_ViewLayerData *sldata, uint current_sample);
 void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
 void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
                                     EEVEE_Data *vedata,
                                     struct Scene *scene,
                                     Object *ob);
+void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_volumes_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
 void EEVEE_volumes_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
 void EEVEE_volumes_resolve(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
 void EEVEE_volumes_free_smoke_textures(void);
@@ -1080,6 +1084,7 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
                         Object *camera,
                         const bool minimal);
 void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_effects_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
 void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer);
 void EEVEE_downsample_buffer(EEVEE_Data *vedata, struct GPUTexture *texture_src, int level);
 void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUTexture *texture_src, int level);
index 8a2f7bd..8e3857a 100644 (file)
@@ -486,10 +486,14 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
   EEVEE_PrivateData *g_data = stl->g_data;
 
   /* FINISH CACHE */
+  EEVEE_volumes_cache_finish(sldata, vedata);
   EEVEE_materials_cache_finish(sldata, vedata);
   EEVEE_lights_cache_finish(sldata, vedata);
   EEVEE_lightprobes_cache_finish(sldata, vedata);
 
+  EEVEE_effects_draw_init(sldata, vedata);
+  EEVEE_volumes_draw_init(sldata, vedata);
+
   /* Sort transparents before the loop. */
   DRW_pass_sort_shgroup_z(psl->transparent_pass);
 
index 8867bf1..3994261 100644 (file)
@@ -49,8 +49,8 @@ static struct {
   char *volumetric_common_lights_lib;
 
   struct GPUShader *volumetric_clear_sh;
-  struct GPUShader *volumetric_scatter_sh;
-  struct GPUShader *volumetric_scatter_with_lights_sh;
+  struct GPUShader *scatter_sh;
+  struct GPUShader *scatter_with_lights_sh;
   struct GPUShader *volumetric_integration_sh;
   struct GPUShader *volumetric_resolve_sh;
 
@@ -60,6 +60,9 @@ static struct {
   GPUTexture *dummy_density;
   GPUTexture *dummy_flame;
 
+  GPUTexture *dummy_scatter;
+  GPUTexture *dummy_transmit;
+
   /* List of all smoke domains rendered within this frame. */
   ListBase smoke_domains;
 } e_data = {NULL}; /* Engine data */
@@ -100,22 +103,21 @@ static void eevee_create_shader_volumes(void)
                                                           e_data.volumetric_common_lib,
                                                           "#define VOLUMETRICS\n"
                                                           "#define CLEAR\n");
-  e_data.volumetric_scatter_sh = DRW_shader_create_with_lib(datatoc_volumetric_vert_glsl,
-                                                            datatoc_volumetric_geom_glsl,
-                                                            datatoc_volumetric_scatter_frag_glsl,
-                                                            e_data.volumetric_common_lights_lib,
-                                                            SHADER_DEFINES
-                                                            "#define VOLUMETRICS\n"
-                                                            "#define VOLUME_SHADOW\n");
-  e_data.volumetric_scatter_with_lights_sh = DRW_shader_create_with_lib(
-      datatoc_volumetric_vert_glsl,
-      datatoc_volumetric_geom_glsl,
-      datatoc_volumetric_scatter_frag_glsl,
-      e_data.volumetric_common_lights_lib,
-      SHADER_DEFINES
-      "#define VOLUMETRICS\n"
-      "#define VOLUME_LIGHTING\n"
-      "#define VOLUME_SHADOW\n");
+  e_data.scatter_sh = DRW_shader_create_with_lib(datatoc_volumetric_vert_glsl,
+                                                 datatoc_volumetric_geom_glsl,
+                                                 datatoc_volumetric_scatter_frag_glsl,
+                                                 e_data.volumetric_common_lights_lib,
+                                                 SHADER_DEFINES
+                                                 "#define VOLUMETRICS\n"
+                                                 "#define VOLUME_SHADOW\n");
+  e_data.scatter_with_lights_sh = DRW_shader_create_with_lib(datatoc_volumetric_vert_glsl,
+                                                             datatoc_volumetric_geom_glsl,
+                                                             datatoc_volumetric_scatter_frag_glsl,
+                                                             e_data.volumetric_common_lights_lib,
+                                                             SHADER_DEFINES
+                                                             "#define VOLUMETRICS\n"
+                                                             "#define VOLUME_LIGHTING\n"
+                                                             "#define VOLUME_SHADOW\n");
   e_data.volumetric_integration_sh = DRW_shader_create_with_lib(
       datatoc_volumetric_vert_glsl,
       datatoc_volumetric_geom_glsl,
@@ -150,7 +152,7 @@ void EEVEE_volumes_set_jitter(EEVEE_ViewLayerData *sldata, uint current_sample)
   common_data->vol_jitter[2] = (float)ht_point[2];
 }
 
-int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
 {
   EEVEE_StorageList *stl = vedata->stl;
   EEVEE_FramebufferList *fbl = vedata->fbl;
@@ -165,312 +167,207 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
 
   BLI_listbase_clear(&e_data.smoke_domains);
 
-  if (scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_ENABLED) {
-
-    /* Shaders */
-    if (!e_data.volumetric_scatter_sh) {
-      eevee_create_shader_volumes();
-    }
-
-    const int tile_size = scene_eval->eevee.volumetric_tile_size;
-
-    /* Find Froxel Texture resolution. */
-    int tex_size[3];
-
-    tex_size[0] = (int)ceilf(fmaxf(1.0f, viewport_size[0] / (float)tile_size));
-    tex_size[1] = (int)ceilf(fmaxf(1.0f, viewport_size[1] / (float)tile_size));
-    tex_size[2] = max_ii(scene_eval->eevee.volumetric_samples, 1);
-
-    common_data->vol_coord_scale[0] = viewport_size[0] / (float)(tile_size * tex_size[0]);
-    common_data->vol_coord_scale[1] = viewport_size[1] / (float)(tile_size * tex_size[1]);
-
-    /* TODO compute snap to maxZBuffer for clustered rendering */
-
-    if ((common_data->vol_tex_size[0] != tex_size[0]) ||
-        (common_data->vol_tex_size[1] != tex_size[1]) ||
-        (common_data->vol_tex_size[2] != tex_size[2])) {
-      DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering);
-      DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction);
-      DRW_TEXTURE_FREE_SAFE(txl->volume_prop_emission);
-      DRW_TEXTURE_FREE_SAFE(txl->volume_prop_phase);
-      DRW_TEXTURE_FREE_SAFE(txl->volume_scatter);
-      DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance);
-      DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
-      DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance_history);
-      GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
-      GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
-      GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
-      common_data->vol_tex_size[0] = tex_size[0];
-      common_data->vol_tex_size[1] = tex_size[1];
-      common_data->vol_tex_size[2] = tex_size[2];
-
-      common_data->vol_inv_tex_size[0] = 1.0f / (float)(tex_size[0]);
-      common_data->vol_inv_tex_size[1] = 1.0f / (float)(tex_size[1]);
-      common_data->vol_inv_tex_size[2] = 1.0f / (float)(tex_size[2]);
-    }
-
-    /* Like frostbite's paper, 5% blend of the new frame. */
-    common_data->vol_history_alpha = (txl->volume_prop_scattering == NULL) ? 0.0f : 0.95f;
-
-    if (txl->volume_prop_scattering == NULL) {
-      /* Volume properties: We evaluate all volumetric objects
-       * and store their final properties into each froxel */
-      txl->volume_prop_scattering = DRW_texture_create_3d(
-          tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
-      txl->volume_prop_extinction = DRW_texture_create_3d(
-          tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
-      txl->volume_prop_emission = DRW_texture_create_3d(
-          tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
-      txl->volume_prop_phase = DRW_texture_create_3d(
-          tex_size[0], tex_size[1], tex_size[2], GPU_RG16F, DRW_TEX_FILTER, NULL);
-
-      /* Volume scattering: We compute for each froxel the
-       * Scattered light towards the view. We also resolve temporal
-       * super sampling during this stage. */
-      txl->volume_scatter = DRW_texture_create_3d(
-          tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
-      txl->volume_transmittance = DRW_texture_create_3d(
-          tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
+  const int tile_size = scene_eval->eevee.volumetric_tile_size;
+
+  /* Find Froxel Texture resolution. */
+  int tex_size[3];
+
+  tex_size[0] = (int)ceilf(fmaxf(1.0f, viewport_size[0] / (float)tile_size));
+  tex_size[1] = (int)ceilf(fmaxf(1.0f, viewport_size[1] / (float)tile_size));
+  tex_size[2] = max_ii(scene_eval->eevee.volumetric_samples, 1);
+
+  common_data->vol_coord_scale[0] = viewport_size[0] / (float)(tile_size * tex_size[0]);
+  common_data->vol_coord_scale[1] = viewport_size[1] / (float)(tile_size * tex_size[1]);
+
+  /* TODO compute snap to maxZBuffer for clustered rendering */
+  if ((common_data->vol_tex_size[0] != tex_size[0]) ||
+      (common_data->vol_tex_size[1] != tex_size[1]) ||
+      (common_data->vol_tex_size[2] != tex_size[2])) {
+    DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering);
+    DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction);
+    DRW_TEXTURE_FREE_SAFE(txl->volume_prop_emission);
+    DRW_TEXTURE_FREE_SAFE(txl->volume_prop_phase);
+    DRW_TEXTURE_FREE_SAFE(txl->volume_scatter);
+    DRW_TEXTURE_FREE_SAFE(txl->volume_transmit);
+    DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
+    DRW_TEXTURE_FREE_SAFE(txl->volume_transmit_history);
+    GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
+    GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
+    GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
+    copy_v3_v3_int(common_data->vol_tex_size, tex_size);
+
+    common_data->vol_inv_tex_size[0] = 1.0f / (float)(tex_size[0]);
+    common_data->vol_inv_tex_size[1] = 1.0f / (float)(tex_size[1]);
+    common_data->vol_inv_tex_size[2] = 1.0f / (float)(tex_size[2]);
+  }
 
-      /* Final integration: We compute for each froxel the
-       * amount of scattered light and extinction coef at this
-       * given depth. We use theses textures as double buffer
-       * for the volumetric history. */
-      txl->volume_scatter_history = DRW_texture_create_3d(
-          tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
-      txl->volume_transmittance_history = DRW_texture_create_3d(
-          tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
-    }
+  /* Like frostbite's paper, 5% blend of the new frame. */
+  common_data->vol_history_alpha = (txl->volume_prop_scattering == NULL) ? 0.0f : 0.95f;
 
-    /* Temporal Super sampling jitter */
-    uint ht_primes[3] = {3, 7, 2};
-    uint current_sample = 0;
+  /* Temporal Super sampling jitter */
+  uint ht_primes[3] = {3, 7, 2};
+  uint current_sample = 0;
 
-    /* If TAA is in use do not use the history buffer. */
-    bool do_taa = ((effects->enabled_effects & EFFECT_TAA) != 0);
+  /* If TAA is in use do not use the history buffer. */
+  bool do_taa = ((effects->enabled_effects & EFFECT_TAA) != 0);
 
-    if (draw_ctx->evil_C != NULL) {
-      struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C);
-      do_taa = do_taa && (ED_screen_animation_no_scrub(wm) == NULL);
-    }
+  if (draw_ctx->evil_C != NULL) {
+    struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C);
+    do_taa = do_taa && (ED_screen_animation_no_scrub(wm) == NULL);
+  }
 
-    if (do_taa) {
-      common_data->vol_history_alpha = 0.0f;
-      current_sample = effects->taa_current_sample - 1;
-      effects->volume_current_sample = -1;
-    }
-    else {
-      const uint max_sample = (ht_primes[0] * ht_primes[1] * ht_primes[2]);
-      current_sample = effects->volume_current_sample = (effects->volume_current_sample + 1) %
-                                                        max_sample;
-      if (current_sample != max_sample - 1) {
-        DRW_viewport_request_redraw();
-      }
+  if (do_taa) {
+    common_data->vol_history_alpha = 0.0f;
+    current_sample = effects->taa_current_sample - 1;
+    effects->volume_current_sample = -1;
+  }
+  else {
+    const uint max_sample = (ht_primes[0] * ht_primes[1] * ht_primes[2]);
+    current_sample = effects->volume_current_sample = (effects->volume_current_sample + 1) %
+                                                      max_sample;
+    if (current_sample != max_sample - 1) {
+      DRW_viewport_request_redraw();
     }
+  }
 
-    EEVEE_volumes_set_jitter(sldata, current_sample);
+  EEVEE_volumes_set_jitter(sldata, current_sample);
 
-    /* Framebuffer setup */
-    GPU_framebuffer_ensure_config(&fbl->volumetric_fb,
-                                  {GPU_ATTACHMENT_NONE,
-                                   GPU_ATTACHMENT_TEXTURE(txl->volume_prop_scattering),
-                                   GPU_ATTACHMENT_TEXTURE(txl->volume_prop_extinction),
-                                   GPU_ATTACHMENT_TEXTURE(txl->volume_prop_emission),
-                                   GPU_ATTACHMENT_TEXTURE(txl->volume_prop_phase)});
-    GPU_framebuffer_ensure_config(&fbl->volumetric_scat_fb,
-                                  {GPU_ATTACHMENT_NONE,
-                                   GPU_ATTACHMENT_TEXTURE(txl->volume_scatter),
-                                   GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance)});
-    GPU_framebuffer_ensure_config(&fbl->volumetric_integ_fb,
-                                  {GPU_ATTACHMENT_NONE,
-                                   GPU_ATTACHMENT_TEXTURE(txl->volume_scatter_history),
-                                   GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance_history)});
-
-    float integration_start = scene_eval->eevee.volumetric_start;
-    float integration_end = scene_eval->eevee.volumetric_end;
-    common_data->vol_light_clamp = scene_eval->eevee.volumetric_light_clamp;
-    common_data->vol_shadow_steps = (float)scene_eval->eevee.volumetric_shadow_samples;
-    if ((scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_SHADOWS) == 0) {
-      common_data->vol_shadow_steps = 0;
-    }
+  float integration_start = scene_eval->eevee.volumetric_start;
+  float integration_end = scene_eval->eevee.volumetric_end;
+  common_data->vol_light_clamp = scene_eval->eevee.volumetric_light_clamp;
+  common_data->vol_shadow_steps = (float)scene_eval->eevee.volumetric_shadow_samples;
+  if ((scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_SHADOWS) == 0) {
+    common_data->vol_shadow_steps = 0;
+  }
 
-    /* Update view_vecs */
-    float invproj[4][4], winmat[4][4];
-    DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
-    DRW_viewport_matrix_get(invproj, DRW_MAT_WININV);
-    EEVEE_update_viewvecs(invproj, winmat, sldata->common_data.view_vecs);
-
-    if (DRW_viewport_is_persp_get()) {
-      float sample_distribution = scene_eval->eevee.volumetric_sample_distribution;
-      sample_distribution = 4.0f * (1.00001f - sample_distribution);
-
-      const float clip_start = common_data->view_vecs[0][2];
-      /* Negate */
-      float near = integration_start = min_ff(-integration_start, clip_start - 1e-4f);
-      float far = integration_end = min_ff(-integration_end, near - 1e-4f);
-
-      common_data->vol_depth_param[0] = (far - near * exp2(1.0f / sample_distribution)) /
-                                        (far - near);
-      common_data->vol_depth_param[1] = (1.0f - common_data->vol_depth_param[0]) / near;
-      common_data->vol_depth_param[2] = sample_distribution;
-    }
-    else {
-      const float clip_start = common_data->view_vecs[0][2];
-      const float clip_end = clip_start + common_data->view_vecs[1][2];
-      integration_start = min_ff(integration_end, clip_start);
-      integration_end = max_ff(-integration_end, clip_end);
-
-      common_data->vol_depth_param[0] = integration_start;
-      common_data->vol_depth_param[1] = integration_end;
-      common_data->vol_depth_param[2] = 1.0f / (integration_end - integration_start);
-    }
+  /* Update view_vecs */
+  float invproj[4][4], winmat[4][4];
+  DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
+  DRW_viewport_matrix_get(invproj, DRW_MAT_WININV);
+  EEVEE_update_viewvecs(invproj, winmat, sldata->common_data.view_vecs);
+
+  if (DRW_viewport_is_persp_get()) {
+    float sample_distribution = scene_eval->eevee.volumetric_sample_distribution;
+    sample_distribution = 4.0f * (1.00001f - sample_distribution);
+
+    const float clip_start = common_data->view_vecs[0][2];
+    /* Negate */
+    float near = integration_start = min_ff(-integration_start, clip_start - 1e-4f);
+    float far = integration_end = min_ff(-integration_end, near - 1e-4f);
+
+    common_data->vol_depth_param[0] = (far - near * exp2(1.0f / sample_distribution)) /
+                                      (far - near);
+    common_data->vol_depth_param[1] = (1.0f - common_data->vol_depth_param[0]) / near;
+    common_data->vol_depth_param[2] = sample_distribution;
+  }
+  else {
+    const float clip_start = common_data->view_vecs[0][2];
+    const float clip_end = clip_start + common_data->view_vecs[1][2];
+    integration_start = min_ff(integration_end, clip_start);
+    integration_end = max_ff(-integration_end, clip_end);
+
+    common_data->vol_depth_param[0] = integration_start;
+    common_data->vol_depth_param[1] = integration_end;
+    common_data->vol_depth_param[2] = 1.0f / (integration_end - integration_start);
+  }
 
-    /* Disable clamp if equal to 0. */
-    if (common_data->vol_light_clamp == 0.0) {
-      common_data->vol_light_clamp = FLT_MAX;
-    }
+  /* Disable clamp if equal to 0. */
+  if (common_data->vol_light_clamp == 0.0) {
+    common_data->vol_light_clamp = FLT_MAX;
+  }
 
-    common_data->vol_use_lights = (scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_LIGHTS) != 0;
+  common_data->vol_use_lights = (scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_LIGHTS) != 0;
 
-    return EFFECT_VOLUMETRIC | EFFECT_POST_BUFFER;
+  if (!e_data.dummy_scatter) {
+    float scatter[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+    float transmit[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+    e_data.dummy_scatter = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, scatter);
+    e_data.dummy_transmit = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, transmit);
   }
-
-  /* Cleanup to release memory */
-  DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering);
-  DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction);
-  DRW_TEXTURE_FREE_SAFE(txl->volume_prop_emission);
-  DRW_TEXTURE_FREE_SAFE(txl->volume_prop_phase);
-  DRW_TEXTURE_FREE_SAFE(txl->volume_scatter);
-  DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance);
-  DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
-  DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance_history);
-  GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
-  GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
-  GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
-
-  return 0;
 }
 
 void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
 {
   EEVEE_PassList *psl = vedata->psl;
   EEVEE_StorageList *stl = vedata->stl;
-  EEVEE_TextureList *txl = vedata->txl;
   EEVEE_EffectsInfo *effects = stl->effects;
-  LightCache *lcache = stl->g_data->light_cache;
   EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
 
-  if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
-    const DRWContextState *draw_ctx = DRW_context_state_get();
-    Scene *scene = draw_ctx->scene;
-    DRWShadingGroup *grp = NULL;
-
-    /* Quick breakdown of the Volumetric rendering:
-     *
-     * The rendering is separated in 4 stages:
-     *
-     * - Material Parameters : we collect volume properties of
-     *   all participating media in the scene and store them in
-     *   a 3D texture aligned with the 3D frustum.
-     *   This is done in 2 passes, one that clear the texture
-     *   and/or evaluate the world volumes, and the 2nd one that
-     *   additively render object volumes.
-     *
-     * - Light Scattering : the volume properties then are sampled
-     *   and light scattering is evaluated for each cell of the
-     *   volume texture. Temporal super-sampling (if enabled) occurs here.
-     *
-     * - Volume Integration : the scattered light and extinction is
-     *   integrated (accumulated) along the view-rays. The result is stored
-     *   for every cell in another texture.
-     *
-     * - Full-screen Resolve : From the previous stage, we get two
-     *   3D textures that contains integrated scattered light and extinction
-     *   for "every" positions in the frustum. We only need to sample
-     *   them and blend the scene color with those factors. This also
-     *   work for alpha blended materials.
-     */
-
-    /* World pass is not additive as it also clear the buffer. */
-    psl->volumetric_world_ps = DRW_pass_create("Volumetric World", DRW_STATE_WRITE_COLOR);
-
-    /* World Volumetric */
-    struct World *wo = scene->world;
-    if (wo != NULL && wo->use_nodes && wo->nodetree &&
-        !LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) {
-      struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo);
+  const DRWContextState *draw_ctx = DRW_context_state_get();
+  Scene *scene = draw_ctx->scene;
+  DRWShadingGroup *grp = NULL;
 
-      grp = DRW_shgroup_material_create(mat, psl->volumetric_world_ps);
+  /* Shaders */
+  if (!e_data.scatter_sh) {
+    eevee_create_shader_volumes();
+  }
 
-      if (grp) {
-        DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
-        /* TODO (fclem): remove those (need to clean the GLSL files). */
-        DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
-        DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
-        DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
-        DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
-        DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
-
-        /* Fix principle volumetric not working with world materials. */
-        DRW_shgroup_uniform_texture(grp, "sampdensity", e_data.dummy_density);
-        DRW_shgroup_uniform_texture(grp, "sampflame", e_data.dummy_flame);
-        DRW_shgroup_uniform_vec2(grp, "unftemperature", (float[2]){0.0f, 1.0f}, 1);
-
-        DRW_shgroup_call_procedural_triangles(grp, common_data->vol_tex_size[2], NULL);
-      }
+  /* Quick breakdown of the Volumetric rendering:
+   *
+   * The rendering is separated in 4 stages:
+   *
+   * - Material Parameters : we collect volume properties of
+   *   all participating media in the scene and store them in
+   *   a 3D texture aligned with the 3D frustum.
+   *   This is done in 2 passes, one that clear the texture
+   *   and/or evaluate the world volumes, and the 2nd one that
+   *   additively render object volumes.
+   *
+   * - Light Scattering : the volume properties then are sampled
+   *   and light scattering is evaluated for each cell of the
+   *   volume texture. Temporal super-sampling (if enabled) occurs here.
+   *
+   * - Volume Integration : the scattered light and extinction is
+   *   integrated (accumulated) along the view-rays. The result is stored
+   *   for every cell in another texture.
+   *
+   * - Full-screen Resolve : From the previous stage, we get two
+   *   3D textures that contains integrated scattered light and extinction
+   *   for "every" positions in the frustum. We only need to sample
+   *   them and blend the scene color with those factors. This also
+   *   work for alpha blended materials.
+   */
+
+  /* World pass is not additive as it also clear the buffer. */
+  DRW_PASS_CREATE(psl->volumetric_world_ps, DRW_STATE_WRITE_COLOR);
+  DRW_PASS_CREATE(psl->volumetric_objects_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
+
+  /* World Volumetric */
+  struct World *wo = scene->world;
+  if (wo != NULL && wo->use_nodes && wo->nodetree &&
+      !LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) {
+    struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo);
+
+    if (GPU_material_use_domain_volume(mat)) {
+      grp = DRW_shgroup_material_create(mat, psl->volumetric_world_ps);
     }
 
-    if (grp == NULL) {
-      /* If no world or volume material is present just clear the buffer with this drawcall */
-      grp = DRW_shgroup_create(e_data.volumetric_clear_sh, psl->volumetric_world_ps);
-
+    if (grp) {
       DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+      /* TODO (fclem): remove those (need to clean the GLSL files). */
+      DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
+      DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+      DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+      DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+      DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+
+      /* Fix principle volumetric not working with world materials. */
+      DRW_shgroup_uniform_texture(grp, "sampdensity", e_data.dummy_density);
+      DRW_shgroup_uniform_texture(grp, "sampflame", e_data.dummy_flame);
+      DRW_shgroup_uniform_vec2_copy(grp, "unftemperature", (float[2]){0.0f, 1.0f});
 
       DRW_shgroup_call_procedural_triangles(grp, common_data->vol_tex_size[2], NULL);
-    }
-
-    /* Volumetric Objects */
-    psl->volumetric_objects_ps = DRW_pass_create("Volumetric Properties",
-                                                 DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
-
-    struct GPUShader *scatter_sh = (common_data->vol_use_lights) ?
-                                       e_data.volumetric_scatter_with_lights_sh :
-                                       e_data.volumetric_scatter_sh;
-    psl->volumetric_scatter_ps = DRW_pass_create("Volumetric Scattering", DRW_STATE_WRITE_COLOR);
-    grp = DRW_shgroup_create(scatter_sh, psl->volumetric_scatter_ps);
-    DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &lcache->grid_tx.tex);
-    DRW_shgroup_uniform_texture_ref(grp, "shadowCubeTexture", &sldata->shadow_cube_pool);
-    DRW_shgroup_uniform_texture_ref(grp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
-    DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_prop_scattering);
-    DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_prop_extinction);
-    DRW_shgroup_uniform_texture_ref(grp, "volumeEmission", &txl->volume_prop_emission);
-    DRW_shgroup_uniform_texture_ref(grp, "volumePhase", &txl->volume_prop_phase);
-    DRW_shgroup_uniform_texture_ref(grp, "historyScattering", &txl->volume_scatter_history);
-    DRW_shgroup_uniform_texture_ref(
-        grp, "historyTransmittance", &txl->volume_transmittance_history);
-    DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
-    DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
-    DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
 
-    DRW_shgroup_call_procedural_triangles(grp, common_data->vol_tex_size[2], NULL);
+      effects->enabled_effects |= (EFFECT_VOLUMETRIC | EFFECT_POST_BUFFER);
+    }
+  }
 
-    psl->volumetric_integration_ps = DRW_pass_create("Volumetric Integration",
-                                                     DRW_STATE_WRITE_COLOR);
-    grp = DRW_shgroup_create(e_data.volumetric_integration_sh, psl->volumetric_integration_ps);
-    DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_scatter);
-    DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_transmittance);
+  if (grp == NULL) {
+    /* If no world or volume material is present just clear the buffer with this drawcall */
+    grp = DRW_shgroup_create(e_data.volumetric_clear_sh, psl->volumetric_world_ps);
     DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
 
     DRW_shgroup_call_procedural_triangles(grp, common_data->vol_tex_size[2], NULL);
-
-    psl->volumetric_resolve_ps = DRW_pass_create("Volumetric Resolve", DRW_STATE_WRITE_COLOR);
-    grp = DRW_shgroup_create(e_data.volumetric_resolve_sh, psl->volumetric_resolve_ps);
-    DRW_shgroup_uniform_texture_ref(grp, "inScattering", &txl->volume_scatter);
-    DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmittance);
-    DRW_shgroup_uniform_texture_ref(grp, "inSceneColor", &e_data.color_src);
-    DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
-    DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
-    DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
   }
 }
 
@@ -581,6 +478,135 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
   /* TODO Reduce to number of slices intersecting. */
   /* TODO Preemptive culling. */
   DRW_shgroup_call_procedural_triangles(grp, sldata->common_data.vol_tex_size[2], NULL);
+
+  vedata->stl->effects->enabled_effects |= (EFFECT_VOLUMETRIC | EFFECT_POST_BUFFER);
+}
+
+void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+  EEVEE_PassList *psl = vedata->psl;
+  EEVEE_TextureList *txl = vedata->txl;
+  EEVEE_EffectsInfo *effects = vedata->stl->effects;
+  LightCache *lcache = vedata->stl->g_data->light_cache;
+  EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
+
+  if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
+    DRWShadingGroup *grp;
+    struct GPUShader *sh;
+
+    DRW_PASS_CREATE(psl->volumetric_scatter_ps, DRW_STATE_WRITE_COLOR);
+    sh = (common_data->vol_use_lights) ? e_data.scatter_with_lights_sh : e_data.scatter_sh;
+    grp = DRW_shgroup_create(sh, psl->volumetric_scatter_ps);
+    DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &lcache->grid_tx.tex);
+    DRW_shgroup_uniform_texture_ref(grp, "shadowCubeTexture", &sldata->shadow_cube_pool);
+    DRW_shgroup_uniform_texture_ref(grp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
+    DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_prop_scattering);
+    DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_prop_extinction);
+    DRW_shgroup_uniform_texture_ref(grp, "volumeEmission", &txl->volume_prop_emission);
+    DRW_shgroup_uniform_texture_ref(grp, "volumePhase", &txl->volume_prop_phase);
+    DRW_shgroup_uniform_texture_ref(grp, "historyScattering", &txl->volume_scatter_history);
+    DRW_shgroup_uniform_texture_ref(grp, "historyTransmittance", &txl->volume_transmit_history);
+    DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+    DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+    DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+
+    DRW_shgroup_call_procedural_triangles(grp, common_data->vol_tex_size[2], NULL);
+
+    DRW_PASS_CREATE(psl->volumetric_integration_ps, DRW_STATE_WRITE_COLOR);
+    grp = DRW_shgroup_create(e_data.volumetric_integration_sh, psl->volumetric_integration_ps);
+    DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_scatter);
+    DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_transmit);
+    DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+
+    DRW_shgroup_call_procedural_triangles(grp, common_data->vol_tex_size[2], NULL);
+
+    DRW_PASS_CREATE(psl->volumetric_resolve_ps, DRW_STATE_WRITE_COLOR);
+    grp = DRW_shgroup_create(e_data.volumetric_resolve_sh, psl->volumetric_resolve_ps);
+    DRW_shgroup_uniform_texture_ref(grp, "inScattering", &txl->volume_scatter);
+    DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit);
+    DRW_shgroup_uniform_texture_ref(grp, "inSceneColor", &e_data.color_src);
+    DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
+    DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+
+    DRW_shgroup_call_procedural_triangles(grp, 1, NULL);
+  }
+}
+
+void EEVEE_volumes_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+  EEVEE_FramebufferList *fbl = vedata->fbl;
+  EEVEE_TextureList *txl = vedata->txl;
+  EEVEE_EffectsInfo *effects = vedata->stl->effects;
+  EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
+
+  if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
+    int *tex_size = common_data->vol_tex_size;
+
+    if (txl->volume_prop_scattering == NULL) {
+      /* Volume properties: We evaluate all volumetric objects
+       * and store their final properties into each froxel */
+      txl->volume_prop_scattering = DRW_texture_create_3d(
+          tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
+      txl->volume_prop_extinction = DRW_texture_create_3d(
+          tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
+      txl->volume_prop_emission = DRW_texture_create_3d(
+          tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
+      txl->volume_prop_phase = DRW_texture_create_3d(
+          tex_size[0], tex_size[1], tex_size[2], GPU_RG16F, DRW_TEX_FILTER, NULL);
+
+      /* Volume scattering: We compute for each froxel the
+       * Scattered light towards the view. We also resolve temporal
+       * super sampling during this stage. */
+      txl->volume_scatter = DRW_texture_create_3d(
+          tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
+      txl->volume_transmit = DRW_texture_create_3d(
+          tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
+
+      /* Final integration: We compute for each froxel the
+       * amount of scattered light and extinction coef at this
+       * given depth. We use theses textures as double buffer
+       * for the volumetric history. */
+      txl->volume_scatter_history = DRW_texture_create_3d(
+          tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
+      txl->volume_transmit_history = DRW_texture_create_3d(
+          tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
+    }
+
+    GPU_framebuffer_ensure_config(&fbl->volumetric_fb,
+                                  {GPU_ATTACHMENT_NONE,
+                                   GPU_ATTACHMENT_TEXTURE(txl->volume_prop_scattering),
+                                   GPU_ATTACHMENT_TEXTURE(txl->volume_prop_extinction),
+                                   GPU_ATTACHMENT_TEXTURE(txl->volume_prop_emission),
+                                   GPU_ATTACHMENT_TEXTURE(txl->volume_prop_phase)});
+    GPU_framebuffer_ensure_config(&fbl->volumetric_scat_fb,
+                                  {GPU_ATTACHMENT_NONE,
+                                   GPU_ATTACHMENT_TEXTURE(txl->volume_scatter),
+                                   GPU_ATTACHMENT_TEXTURE(txl->volume_transmit)});
+    GPU_framebuffer_ensure_config(&fbl->volumetric_integ_fb,
+                                  {GPU_ATTACHMENT_NONE,
+                                   GPU_ATTACHMENT_TEXTURE(txl->volume_scatter_history),
+                                   GPU_ATTACHMENT_TEXTURE(txl->volume_transmit_history)});
+
+    /* Usage happens after buffer have been swapped. */
+    effects->volume_scatter = txl->volume_scatter_history;
+    effects->volume_transmit = txl->volume_transmit_history;
+  }
+  else {
+    DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering);
+    DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction);
+    DRW_TEXTURE_FREE_SAFE(txl->volume_prop_emission);
+    DRW_TEXTURE_FREE_SAFE(txl->volume_prop_phase);
+    DRW_TEXTURE_FREE_SAFE(txl->volume_scatter);
+    DRW_TEXTURE_FREE_SAFE(txl->volume_transmit);
+    DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
+    DRW_TEXTURE_FREE_SAFE(txl->volume_transmit_history);
+    GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
+    GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
+    GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
+
+    effects->volume_scatter = e_data.dummy_scatter;
+    effects->volume_transmit = e_data.dummy_transmit;
+  }
 }
 
 void EEVEE_volumes_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
@@ -593,23 +619,19 @@ void EEVEE_volumes_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda
   if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
     DRW_stats_group_start("Volumetrics");
 
-    /* Step 1: Participating Media Properties */
     GPU_framebuffer_bind(fbl->volumetric_fb);
     DRW_draw_pass(psl->volumetric_world_ps);
     DRW_draw_pass(psl->volumetric_objects_ps);
 
-    /* Step 2: Scatter Light */
     GPU_framebuffer_bind(fbl->volumetric_scat_fb);
     DRW_draw_pass(psl->volumetric_scatter_ps);
 
-    /* Step 3: Integration */
     GPU_framebuffer_bind(fbl->volumetric_integ_fb);
     DRW_draw_pass(psl->volumetric_integration_ps);
 
-    /* Swap volume history buffers */
     SWAP(struct GPUFrameBuffer *, fbl->volumetric_scat_fb, fbl->volumetric_integ_fb);
     SWAP(GPUTexture *, txl->volume_scatter, txl->volume_scatter_history);
-    SWAP(GPUTexture *, txl->volume_transmittance, txl->volume_transmittance_history);
+    SWAP(GPUTexture *, txl->volume_transmit, txl->volume_transmit_history);
 
     /* Restore */
     GPU_framebuffer_bind(fbl->main_fb);
@@ -663,12 +685,15 @@ void EEVEE_volumes_free(void)
   MEM_SAFE_FREE(e_data.volumetric_common_lib);
   MEM_SAFE_FREE(e_data.volumetric_common_lights_lib);
 
+  DRW_TEXTURE_FREE_SAFE(e_data.dummy_scatter);
+  DRW_TEXTURE_FREE_SAFE(e_data.dummy_transmit);
+
   DRW_TEXTURE_FREE_SAFE(e_data.dummy_density);
   DRW_TEXTURE_FREE_SAFE(e_data.dummy_flame);
 
   DRW_SHADER_FREE_SAFE(e_data.volumetric_clear_sh);
-  DRW_SHADER_FREE_SAFE(e_data.volumetric_scatter_sh);
-  DRW_SHADER_FREE_SAFE(e_data.volumetric_scatter_with_lights_sh);
+  DRW_SHADER_FREE_SAFE(e_data.scatter_sh);
+  DRW_SHADER_FREE_SAFE(e_data.scatter_with_lights_sh);
   DRW_SHADER_FREE_SAFE(e_data.volumetric_integration_sh);
   DRW_SHADER_FREE_SAFE(e_data.volumetric_resolve_sh);
 }
index 12e60f0..d7160ae 100644 (file)
@@ -898,7 +898,7 @@ layout(location = 4) out vec4 sssAlbedo;
 
 Closure nodetree_exec(void); /* Prototype */
 
-#    if defined(USE_ALPHA_BLEND_VOLUMETRICS)
+#    if defined(USE_ALPHA_BLEND)
 /* Prototype because this file is included before volumetric_lib.glsl */
 vec4 volumetric_resolve(vec4 scene_color, vec2 frag_uvs, float frag_depth);
 #    endif
@@ -912,7 +912,7 @@ void main()
   cl.opacity = 1.0;
 #    endif
 
-#    if defined(USE_ALPHA_BLEND_VOLUMETRICS)
+#    if defined(USE_ALPHA_BLEND)
   /* XXX fragile, better use real viewport resolution */
   vec2 uvs = gl_FragCoord.xy / vec2(2 * textureSize(maxzBuffer, 0).xy);
   fragColor.rgb = volumetric_resolve(vec4(cl.radiance, cl.opacity), uvs, gl_FragCoord.z).rgb;
index 8337255..8d4d66e 100644 (file)
@@ -525,6 +525,8 @@ void DRW_pass_sort_shgroup_z(DRWPass *pass);
 
 bool DRW_pass_is_empty(DRWPass *pass);
 
+#define DRW_PASS_CREATE(pass, state) (pass = DRW_pass_create(#pass, state))
+
 /* Viewport */
 typedef enum {
   /* keep in sync with the union struct DRWMatrixState. */
index a5af5be..c64a593 100644 (file)
@@ -2369,7 +2369,7 @@ typedef enum eGPencil_Guide_Reference {
 
 /* SceneEEVEE->flag */
 enum {
-  SCE_EEVEE_VOLUMETRIC_ENABLED = (1 << 0),
+  // SCE_EEVEE_VOLUMETRIC_ENABLED = (1 << 0), /* Unused */
   SCE_EEVEE_VOLUMETRIC_LIGHTS = (1 << 1),
   SCE_EEVEE_VOLUMETRIC_SHADOWS = (1 << 2),
   //  SCE_EEVEE_VOLUMETRIC_COLORED    = (1 << 3), /* Unused */
index ad814ff..5733b31 100644 (file)
@@ -6872,14 +6872,6 @@ static void rna_def_scene_eevee(BlenderRNA *brna)
   RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
 
   /* Volumetrics */
-  prop = RNA_def_property(srna, "use_volumetric", PROP_BOOLEAN, PROP_NONE);
-  RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_VOLUMETRIC_ENABLED);
-  RNA_def_property_boolean_default(prop, 0);
-  RNA_def_property_ui_text(
-      prop, "Volumetrics", "Enable scattering and absorbance of volumetric material");
-  RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
-  RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-
   prop = RNA_def_property(srna, "volumetric_start", PROP_FLOAT, PROP_DISTANCE);
   RNA_def_property_float_default(prop, 0.1f);
   RNA_def_property_ui_text(prop, "Start", "Start distance of the volumetric effect");
index 8eaf04f..5deb51f 100755 (executable)
@@ -25,7 +25,6 @@ def setup():
     eevee.use_gtao = True
     eevee.use_dof = False
 
-    eevee.use_volumetric = True
     eevee.use_volumetric_shadows = True
     eevee.volumetric_tile_size = '2'