diff options
-rw-r--r-- | release/scripts/startup/bl_ui/properties_render.py | 7 | ||||
-rw-r--r-- | source/blender/blenloader/intern/versioning_280.c | 2 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_effects.c | 29 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_engine.c | 4 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_lightcache.c | 4 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_materials.c | 24 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_private.h | 11 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_render.c | 4 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_volumes.c | 621 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl | 4 | ||||
-rw-r--r-- | source/blender/draw/intern/DRW_render.h | 2 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 2 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_scene.c | 8 | ||||
-rwxr-xr-x | tests/python/eevee_render_tests.py | 1 |
14 files changed, 374 insertions, 349 deletions
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index fbf247b2858..b99e2b9d731 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -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") diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 84c9aa01db3..d2489334c90 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -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); diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index 91426b36415..79569216399 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -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)) { diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 9fc11d989ce..481b566eff0 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -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 diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c index c639f4bdfcb..3e0e5f6d00f 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.c +++ b/source/blender/draw/engines/eevee/eevee_lightcache.c @@ -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(); diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index e6369af5e0f..7989d4d7ec2 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -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); } } diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 2db36e492f2..e2130615b1d 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -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); diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index 8a2f7bdd1e0..8e3857ae8a8 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -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); diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 8867bf107ec..39942617d2b 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -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); } diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl index 12e60f0250f..d7160aee340 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -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; diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 8337255464a..8d4d66e5853 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -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. */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index a5af5be4b57..c64a593c9e2 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -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 */ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index ad814ff0021..5733b31e02c 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -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"); diff --git a/tests/python/eevee_render_tests.py b/tests/python/eevee_render_tests.py index 8eaf04f8bea..5deb51fea4d 100755 --- a/tests/python/eevee_render_tests.py +++ b/tests/python/eevee_render_tests.py @@ -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' |