Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2017-07-05 19:28:48 +0300
committerClément Foucault <foucault.clem@gmail.com>2017-07-05 19:28:48 +0300
commit291b365e26525493fa0be61c858440ce62868559 (patch)
tree7e8f916409e4f5e7bf6f5fb065eff25b2ad36917
parent8b78a8d9bcb4398873c83cd5f73a4a67f067395d (diff)
Eevee: Volumetrics: Add settings.
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py10
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c111
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c12
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c50
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h28
-rw-r--r--source/blender/draw/engines/eevee/shaders/lamps_lib.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl41
-rw-r--r--source/blender/makesrna/intern/rna_scene.c70
9 files changed, 265 insertions, 62 deletions
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 679a80aa6dc..40307a1d3bb 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -616,6 +616,7 @@ class RENDER_PT_clay_collection_settings(RenderButtonsPanel, Panel):
col.prop(props, "ssao_attenuation")
col.prop(props, "hair_brightness_randomness")
+
class RENDER_PT_eevee_poststack_settings(RenderButtonsPanel, Panel):
bl_label = "Post Process Stack"
COMPAT_ENGINES = {'BLENDER_EEVEE'}
@@ -698,7 +699,14 @@ class RENDER_PT_eevee_volumetric(RenderButtonsPanel, Panel):
layout.active = props.volumetric_enable
col = layout.column()
- # to be completed
+ col.prop(props, "volumetric_start")
+ col.prop(props, "volumetric_end")
+ col.prop(props, "volumetric_samples")
+ col.prop(props, "volumetric_sample_distribution")
+ col.prop(props, "volumetric_lights")
+ col.prop(props, "volumetric_shadows")
+ col.prop(props, "volumetric_shadow_samples")
+ col.prop(props, "volumetric_colored_transmittance")
classes = (
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index 8893a8c62e9..36d91c0cc28 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -61,6 +61,9 @@ static void eevee_scene_layer_data_free(void *storage)
DRW_TEXTURE_FREE_SAFE(sldata->probe_pool);
DRW_TEXTURE_FREE_SAFE(sldata->irradiance_pool);
DRW_TEXTURE_FREE_SAFE(sldata->irradiance_rt);
+
+ /* Volumetrics */
+ MEM_SAFE_FREE(sldata->volumetrics);
}
static void eevee_lamp_data_free(void *storage)
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index a816fe8332a..602d4f272b8 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -134,7 +134,7 @@ static void eevee_motion_blur_camera_get_matrix_at_time(
mul_m4_m4m4(r_mat, params.winmat, obmat);
}
-void EEVEE_effects_init(EEVEE_Data *vedata)
+void EEVEE_effects_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
@@ -403,29 +403,68 @@ void EEVEE_effects_init(EEVEE_Data *vedata)
&tex, 1);
if (BKE_collection_engine_property_value_get_bool(props, "volumetric_enable")) {
- /* Integration result buffer(s) */
- if (false) { /* TODO check and free the framebuffer if config changes */
- /* Monocromatic transmittance in alpha */
- DRWFboTexture tex_vol = {&stl->g_data->volumetric, DRW_TEX_RGBA_16, DRW_TEX_MIPMAP | DRW_TEX_FILTER | DRW_TEX_TEMP};
-
- DRW_framebuffer_init(&fbl->volumetric_fb, &draw_engine_eevee_type,
- (int)viewport_size[0] / 2, (int)viewport_size[1] / 2,
- &tex_vol, 1);
- }
- else {
- /* Transmittance is separated, No need for alpha and DRW_TEX_RGB_11_11_10 gives the same vram usage */
- /* Hint ! Could reuse this for transparency! */
- DRWFboTexture tex_vol[2] = {{&stl->g_data->volumetric, DRW_TEX_RGB_11_11_10, DRW_TEX_MIPMAP | DRW_TEX_FILTER | DRW_TEX_TEMP},
- {&stl->g_data->volumetric_transmit, DRW_TEX_RGB_11_11_10, DRW_TEX_MIPMAP | DRW_TEX_FILTER | DRW_TEX_TEMP}};
-
- DRW_framebuffer_init(&fbl->volumetric_fb, &draw_engine_eevee_type,
- (int)viewport_size[0] / 2, (int)viewport_size[1] / 2,
- tex_vol, 2);
- }
-
World *wo = scene->world;
+
+ /* TODO: this will not be the case if we support object volumetrics */
if ((wo != NULL) && (wo->use_nodes) && (wo->nodetree != NULL)) {
effects->enabled_effects |= EFFECT_VOLUMETRIC;
+
+ if (sldata->volumetrics == NULL) {
+ sldata->volumetrics = MEM_callocN(sizeof(EEVEE_VolumetricsInfo), "EEVEE_VolumetricsInfo");
+ }
+
+ EEVEE_VolumetricsInfo *volumetrics = sldata->volumetrics;
+ bool last_use_colored_transmit = volumetrics->use_colored_transmit; /* Save to compare */
+
+ volumetrics->integration_start = BKE_collection_engine_property_value_get_float(props, "volumetric_start");
+ volumetrics->integration_end = BKE_collection_engine_property_value_get_float(props, "volumetric_end");
+
+ if (DRW_viewport_is_persp_get()) {
+ /* Negate */
+ volumetrics->integration_start = -volumetrics->integration_start;
+ volumetrics->integration_end = -volumetrics->integration_end;
+ }
+ else {
+ const float clip_start = stl->g_data->viewvecs[0][2];
+ const float clip_end = stl->g_data->viewvecs[1][2];
+ volumetrics->integration_start = min_ff(volumetrics->integration_end, clip_start);
+ volumetrics->integration_end = max_ff(-volumetrics->integration_end, clip_end);
+ }
+
+ volumetrics->sample_distribution = BKE_collection_engine_property_value_get_float(props, "volumetric_sample_distribution");
+ volumetrics->integration_step_count = (float)BKE_collection_engine_property_value_get_int(props, "volumetric_samples");
+ volumetrics->shadow_step_count = (float)BKE_collection_engine_property_value_get_int(props, "volumetric_shadow_samples");
+
+ volumetrics->use_lights = BKE_collection_engine_property_value_get_bool(props, "volumetric_lights");
+ volumetrics->use_volume_shadows = BKE_collection_engine_property_value_get_bool(props, "volumetric_shadows");
+ volumetrics->use_colored_transmit = BKE_collection_engine_property_value_get_bool(props, "volumetric_colored_transmittance");
+
+ if (last_use_colored_transmit != volumetrics->use_colored_transmit) {
+ if (fbl->volumetric_fb != NULL) {
+ DRW_framebuffer_free(fbl->volumetric_fb);
+ fbl->volumetric_fb = NULL;
+ }
+ }
+
+ /* Integration result buffer(s) */
+ if (volumetrics->use_colored_transmit == false) {
+ /* Monocromatic transmittance in alpha */
+ DRWFboTexture tex_vol = {&stl->g_data->volumetric, DRW_TEX_RGBA_16, DRW_TEX_MIPMAP | DRW_TEX_FILTER | DRW_TEX_TEMP};
+
+ DRW_framebuffer_init(&fbl->volumetric_fb, &draw_engine_eevee_type,
+ (int)viewport_size[0] / 2, (int)viewport_size[1] / 2,
+ &tex_vol, 1);
+ }
+ else {
+ /* Transmittance is separated, No need for alpha and DRW_TEX_RGB_11_11_10 gives the same vram usage */
+ /* Hint ! Could reuse this for transparency! */
+ DRWFboTexture tex_vol[2] = {{&stl->g_data->volumetric, DRW_TEX_RGB_11_11_10, DRW_TEX_MIPMAP | DRW_TEX_FILTER | DRW_TEX_TEMP},
+ {&stl->g_data->volumetric_transmit, DRW_TEX_RGB_11_11_10, DRW_TEX_MIPMAP | DRW_TEX_FILTER | DRW_TEX_TEMP}};
+
+ DRW_framebuffer_init(&fbl->volumetric_fb, &draw_engine_eevee_type,
+ (int)viewport_size[0] / 2, (int)viewport_size[1] / 2,
+ tex_vol, 2);
+ }
}
}
}
@@ -462,8 +501,12 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
struct World *wo = scene->world; /* Already checked non NULL */
+ EEVEE_VolumetricsInfo *volumetrics = sldata->volumetrics;
+
+ struct GPUMaterial *mat = EEVEE_material_world_volume_get(
+ scene, wo, volumetrics->use_lights, volumetrics->use_volume_shadows,
+ false, volumetrics->use_colored_transmit);
- struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo);
psl->volumetric_integrate_ps = DRW_pass_create("Volumetric Integration", DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_material_create(mat, psl->volumetric_integrate_ps);
@@ -478,11 +521,14 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_int(grp, "grid_count", &sldata->probes->num_render_grid, 1);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
+ DRW_shgroup_uniform_vec2(grp, "volume_start_end", &sldata->volumetrics->integration_start, 1);
+ DRW_shgroup_uniform_vec3(grp, "volume_samples", &sldata->volumetrics->integration_step_count, 1);
DRW_shgroup_call_add(grp, quad, NULL);
- if (false) { /* Monochromatic transmittance */
+ if (volumetrics->use_colored_transmit == false) { /* Monochromatic transmittance */
psl->volumetric_resolve_ps = DRW_pass_create("Volumetric Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_TRANSMISSION);
grp = DRW_shgroup_create(e_data.volumetric_upsample_sh, psl->volumetric_resolve_ps);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
DRW_shgroup_uniform_buffer(grp, "depthFull", &e_data.depth_src);
DRW_shgroup_uniform_buffer(grp, "volumetricBuffer", &stl->g_data->volumetric);
DRW_shgroup_call_add(grp, quad, NULL);
@@ -490,12 +536,14 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
else {
psl->volumetric_resolve_transmit_ps = DRW_pass_create("Volumetric Transmittance Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_MULTIPLY);
grp = DRW_shgroup_create(e_data.volumetric_upsample_sh, psl->volumetric_resolve_transmit_ps);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
DRW_shgroup_uniform_buffer(grp, "depthFull", &e_data.depth_src);
DRW_shgroup_uniform_buffer(grp, "volumetricBuffer", &stl->g_data->volumetric_transmit);
DRW_shgroup_call_add(grp, quad, NULL);
psl->volumetric_resolve_ps = DRW_pass_create("Volumetric Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
grp = DRW_shgroup_create(e_data.volumetric_upsample_sh, psl->volumetric_resolve_ps);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
DRW_shgroup_uniform_buffer(grp, "depthFull", &e_data.depth_src);
DRW_shgroup_uniform_buffer(grp, "volumetricBuffer", &stl->g_data->volumetric);
DRW_shgroup_call_add(grp, quad, NULL);
@@ -659,7 +707,7 @@ void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, GPUTexture *depth_src)
DRW_framebuffer_recursive_downsample(fbl->minmaxz_fb, stl->g_data->minmaxz, 6, &minmax_downsample_cb, vedata);
}
-void EEVEE_effects_do_volumetrics(EEVEE_Data *vedata)
+void EEVEE_effects_do_volumetrics(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
EEVEE_FramebufferList *fbl = vedata->fbl;
@@ -673,25 +721,26 @@ void EEVEE_effects_do_volumetrics(EEVEE_Data *vedata)
/* Compute volumetric integration at halfres. */
DRW_framebuffer_texture_attach(fbl->volumetric_fb, stl->g_data->volumetric, 0, 0);
- DRW_framebuffer_texture_attach(fbl->volumetric_fb, stl->g_data->volumetric_transmit, 1, 0);
+ if (sldata->volumetrics->use_colored_transmit) {
+ DRW_framebuffer_texture_attach(fbl->volumetric_fb, stl->g_data->volumetric_transmit, 1, 0);
+ }
DRW_framebuffer_bind(fbl->volumetric_fb);
DRW_draw_pass(psl->volumetric_integrate_ps);
/* Resolve at fullres */
DRW_framebuffer_texture_detach(dtxl->depth);
DRW_framebuffer_bind(fbl->main);
- if (false) {
- DRW_draw_pass(psl->volumetric_resolve_ps);
- }
- else {
+ if (sldata->volumetrics->use_colored_transmit) {
DRW_draw_pass(psl->volumetric_resolve_transmit_ps);
- DRW_draw_pass(psl->volumetric_resolve_ps);
}
+ DRW_draw_pass(psl->volumetric_resolve_ps);
/* Restore */
DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
DRW_framebuffer_texture_detach(stl->g_data->volumetric);
- DRW_framebuffer_texture_detach(stl->g_data->volumetric_transmit);
+ if (sldata->volumetrics->use_colored_transmit) {
+ DRW_framebuffer_texture_detach(stl->g_data->volumetric_transmit);
+ }
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index c72e1f03f4d..feee13b06f8 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -65,7 +65,7 @@ static void EEVEE_engine_init(void *ved)
EEVEE_materials_init(stl);
EEVEE_lights_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
- EEVEE_effects_init(vedata);
+ EEVEE_effects_init(sldata, vedata);
}
static void EEVEE_cache_init(void *vedata)
@@ -161,7 +161,7 @@ static void EEVEE_draw_scene(void *vedata)
DRW_draw_pass(psl->material_pass);
/* Volumetrics */
- EEVEE_effects_do_volumetrics(vedata);
+ EEVEE_effects_do_volumetrics(sldata, vedata);
/* Post Process */
EEVEE_draw_effects(vedata);
@@ -191,6 +191,14 @@ static void EEVEE_scene_layer_settings_create(RenderEngine *UNUSED(engine), IDPr
props->subtype == IDP_GROUP_SUB_ENGINE_RENDER);
BKE_collection_engine_property_add_bool(props, "volumetric_enable", false);
+ BKE_collection_engine_property_add_float(props, "volumetric_start", 0.1);
+ BKE_collection_engine_property_add_float(props, "volumetric_end", 100.0);
+ BKE_collection_engine_property_add_int(props, "volumetric_samples", 64);
+ BKE_collection_engine_property_add_float(props, "volumetric_sample_distribution", 0.8);
+ BKE_collection_engine_property_add_bool(props, "volumetric_lights", true);
+ BKE_collection_engine_property_add_bool(props, "volumetric_shadows", false);
+ BKE_collection_engine_property_add_int(props, "volumetric_shadow_samples", 16);
+ BKE_collection_engine_property_add_bool(props, "volumetric_colored_transmittance", true);
BKE_collection_engine_property_add_bool(props, "gtao_enable", false);
BKE_collection_engine_property_add_bool(props, "gtao_use_bent_normals", true);
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index c0ddd977bbc..4cc8b5ed93c 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -209,6 +209,35 @@ static char *eevee_get_defines(int options)
return str;
}
+static char *eevee_get_volume_defines(int options)
+{
+ char *str = NULL;
+
+ BLI_assert(options < VAR_MAT_MAX);
+
+ DynStr *ds = BLI_dynstr_new();
+ BLI_dynstr_appendf(ds, SHADER_DEFINES);
+ BLI_dynstr_appendf(ds, "#define VOLUMETRICS\n");
+
+ if ((options & VAR_VOLUME_SHADOW) != 0) {
+ BLI_dynstr_appendf(ds, "#define VOLUME_SHADOW\n");
+ }
+ if ((options & VAR_VOLUME_HOMO) != 0) {
+ BLI_dynstr_appendf(ds, "#define VOLUME_HOMOGENEOUS\n");
+ }
+ if ((options & VAR_VOLUME_LIGHT) != 0) {
+ BLI_dynstr_appendf(ds, "#define VOLUME_LIGHTING\n");
+ }
+ if ((options & VAR_VOLUME_COLOR) != 0) {
+ BLI_dynstr_appendf(ds, "#define COLOR_TRANSMITTANCE\n");
+ }
+
+ str = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+
+ return str;
+}
+
static void add_standard_uniforms(DRWShadingGroup *shgrp, EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
{
DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
@@ -406,20 +435,33 @@ struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, Wor
SHADER_DEFINES "#define WORLD_BACKGROUND\n");
}
-struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, World *wo)
+struct GPUMaterial *EEVEE_material_world_volume_get(
+ struct Scene *scene, World *wo,
+ bool use_lights, bool use_volume_shadows, bool is_homogeneous, bool use_color_transmit)
{
const void *engine = &DRW_engine_viewport_eevee_type;
int options = VAR_WORLD_VOLUME;
+ if (use_lights) options |= VAR_VOLUME_LIGHT;
+ if (is_homogeneous) options |= VAR_VOLUME_HOMO;
+ if (use_volume_shadows) options |= VAR_VOLUME_SHADOW;
+ if (use_color_transmit) options |= VAR_VOLUME_COLOR;
+
GPUMaterial *mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine, options);
if (mat != NULL) {
return mat;
}
- return GPU_material_from_nodetree(
+
+ char *defines = eevee_get_volume_defines(options);
+
+ mat = GPU_material_from_nodetree(
scene, wo->nodetree, &wo->gpumaterial, engine, options,
datatoc_background_vert_glsl, NULL, e_data.volume_shader_lib,
- SHADER_DEFINES "#define VOLUMETRICS\n"
- "#define COLOR_TRANSMITTANCE\n");
+ defines);
+
+ MEM_freeN(defines);
+
+ return mat;
}
struct GPUMaterial *EEVEE_material_mesh_get(
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index b9cd3adfab2..286d833fca3 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -48,9 +48,14 @@ extern struct DrawEngineType draw_engine_eevee_type;
/* World shader variations */
enum {
- VAR_WORLD_BACKGROUND,
- VAR_WORLD_PROBE,
- VAR_WORLD_VOLUME,
+ VAR_VOLUME_SHADOW = (1 << 0),
+ VAR_VOLUME_HOMO = (1 << 1),
+ VAR_VOLUME_LIGHT = (1 << 2),
+ VAR_VOLUME_COLOR = (1 << 3),
+
+ VAR_WORLD_BACKGROUND = 16,
+ VAR_WORLD_PROBE = 17,
+ VAR_WORLD_VOLUME = 18,
};
/* Material shader variations */
@@ -181,6 +186,13 @@ typedef struct EEVEE_ShadowRender {
float exponent;
} EEVEE_ShadowRender;
+/* ************ VOLUME DATA ************ */
+typedef struct EEVEE_VolumetricsInfo {
+ float integration_step_count, shadow_step_count, sample_distribution;
+ float integration_start, integration_end;
+ bool use_lights, use_volume_shadows, use_colored_transmit;
+} EEVEE_VolumetricsInfo;
+
/* ************ LIGHT DATA ************* */
typedef struct EEVEE_LampsInfo {
int num_light, cache_num_light;
@@ -358,6 +370,9 @@ typedef struct EEVEE_SceneLayerData {
struct GPUTexture *irradiance_rt;
struct ListBase probe_queue; /* List of probes to update */
+
+ /* Volumetrics */
+ struct EEVEE_VolumetricsInfo *volumetrics;
} EEVEE_SceneLayerData;
/* ************ OBJECT DATA ************ */
@@ -427,7 +442,8 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl
void EEVEE_materials_cache_finish(EEVEE_Data *vedata);
struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, struct World *wo);
struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, struct World *wo);
-struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, struct World *wo);
+struct GPUMaterial *EEVEE_material_world_volume_get(
+ struct Scene *scene, struct World *wo, bool use_lights, bool use_volume_shadows, bool is_homogeneous, bool use_color_transmit);
struct GPUMaterial *EEVEE_material_mesh_lightprobe_get(struct Scene *scene, Material *ma);
struct GPUMaterial *EEVEE_material_mesh_get(struct Scene *scene, Material *ma, bool use_ao, bool use_bent_normals);
struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma, bool use_ao, bool use_bent_normals);
@@ -453,10 +469,10 @@ void EEVEE_lightprobes_refresh(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
void EEVEE_lightprobes_free(void);
/* eevee_effects.c */
-void EEVEE_effects_init(EEVEE_Data *vedata);
+void EEVEE_effects_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, struct GPUTexture *depth_src);
-void EEVEE_effects_do_volumetrics(EEVEE_Data *vedata);
+void EEVEE_effects_do_volumetrics(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_draw_effects(EEVEE_Data *vedata);
void EEVEE_effects_free(void);
diff --git a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
index ba1e0e89d28..061719b5685 100644
--- a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
@@ -107,7 +107,7 @@ float light_visibility(LightData ld, vec3 W, vec4 l_vector)
vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward));
}
-#if !defined(VOLUMETRICS) || defined(SHADOWS)
+#if !defined(VOLUMETRICS) || defined(VOLUME_SHADOW)
/* shadowing */
if (ld.l_shadowid >= (MAX_SHADOW_MAP + MAX_SHADOW_CUBE)) {
vis *= shadow_cascade(ld.l_shadowid, W);
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
index efc744f3ca4..916ff01b520 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
@@ -1,7 +1,19 @@
#ifdef VOLUMETRICS
+#define VOLUMETRIC_INTEGRATION_MAX_STEP 256
+#define VOLUMETRIC_SHADOW_MAX_STEP 128
+
uniform int light_count;
+uniform vec2 volume_start_end;
+uniform vec3 volume_samples;
+
+#define volume_start volume_start_end.x
+#define volume_end volume_start_end.y
+
+#define volume_integration_steps volume_samples.x
+#define volume_shadows_steps volume_samples.y
+#define volume_sample_distribution volume_samples.z
#ifdef COLOR_TRANSMITTANCE
layout(location = 0) out vec4 outScattering;
@@ -51,7 +63,7 @@ float phase_function_isotropic()
float phase_function(vec3 v, vec3 l, float g)
{
-#ifndef VOLUME_ISOTROPIC
+#ifndef VOLUME_ISOTROPIC /* TODO Use this flag when only isotropic closures are used */
/* Henyey-Greenstein */
float cos_theta = dot(v, l);
g = clamp(g, -1.0 + 1e-3, 1.0 - 1e-3);
@@ -97,12 +109,11 @@ vec3 light_volume_shadow(LightData ld, vec3 ray_wpos, vec4 l_vector, vec3 s_exti
return exp(-s_extinction * l_vector.w);
#else
/* Heterogeneous volume shadows */
- const float numStep = 16.0;
- float dd = l_vector.w / numStep;
+ float dd = l_vector.w / volume_shadows_steps;
vec3 L = l_vector.xyz * l_vector.w;
vec3 shadow = vec3(1.0);
- for (float s = 0.5; s < (numStep - 0.1); s += 1.0) {
- vec3 pos = ray_wpos + L * (s / numStep);
+ for (float s = 0.5; s < VOLUMETRIC_SHADOW_MAX_STEP && s < (volume_shadows_steps - 0.1); s += 1.0) {
+ vec3 pos = ray_wpos + L * (s / volume_shadows_steps);
vec3 s_extinction = participating_media_extinction(pos);
shadow *= exp(-s_extinction * dd);
}
@@ -114,17 +125,15 @@ vec3 light_volume_shadow(LightData ld, vec3 ray_wpos, vec4 l_vector, vec3 s_exti
#endif /* VOLUME_SHADOW */
}
-float find_next_step(float near, float far, float noise, int iter, int iter_count)
+float find_next_step(float iter, float noise)
{
- const float lambda = 0.8f; /* TODO : Parameter */
-
- float progress = (float(iter) + noise) / float(iter_count);
+ float progress = (iter + noise) / volume_integration_steps;
- float linear_split = mix(near, far, progress);
+ float linear_split = mix(volume_start, volume_end, progress);
if (ProjectionMatrix[3][3] == 0.0) {
- float exp_split = near * pow(far / near, progress);
- return mix(linear_split, exp_split, lambda);
+ float exp_split = volume_start * pow(volume_end / volume_start, progress);
+ return mix(linear_split, exp_split, volume_sample_distribution);
}
else {
return linear_split;
@@ -169,11 +178,9 @@ void main()
float rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).r;
/* Less noisy but noticeable patterns, could work better with temporal AA. */
// float rand = (1.0 / 16.0) * float(((int(gl_FragCoord.x + gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3));
- float near = get_view_z_from_depth(0.0);
- float far = get_view_z_from_depth(1.0);
- float dist = near;
- for (int i = 1; i < 64; ++i) {
- float new_dist = find_next_step(near, far, rand, i, 64);
+ float dist = volume_start;
+ for (float i = 0.5; i < VOLUMETRIC_INTEGRATION_MAX_STEP && i < (volume_integration_steps - 0.1); ++i) {
+ float new_dist = find_next_step(rand, i);
float step = dist - new_dist; /* Marching step */
dist = new_dist;
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 8ff88af2df4..09a075cb128 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -2613,6 +2613,14 @@ RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(motion_blur_enable)
RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(motion_blur_samples)
RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(motion_blur_shutter)
RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(volumetric_enable)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(volumetric_start)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(volumetric_end)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(volumetric_samples)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(volumetric_sample_distribution)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(volumetric_lights)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(volumetric_shadows)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(volumetric_shadow_samples)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(volumetric_colored_transmittance)
/* object engine */
RNA_LAYER_MODE_OBJECT_GET_SET_BOOL(show_wire)
@@ -6175,6 +6183,68 @@ static void rna_def_scene_layer_engine_settings_eevee(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_SceneLayerEngineSettings_update");
+ prop = RNA_def_property(srna, "volumetric_start", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_start_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_start_set", NULL);
+ RNA_def_property_ui_text(prop, "Start", "Start distance of the volumetric effect");
+ RNA_def_property_range(prop, 1e-6f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_SceneLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "volumetric_end", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_end_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_end_set", NULL);
+ RNA_def_property_ui_text(prop, "End", "End distance of the volumetric effect");
+ RNA_def_property_range(prop, 1e-6f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_SceneLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "volumetric_samples", PROP_INT, PROP_NONE);
+ RNA_def_property_int_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_samples_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_samples_set", NULL);
+ RNA_def_property_ui_text(prop, "Samples", "Number of samples to compute volumetric effects");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_range(prop, 1, 256);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_SceneLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "volumetric_sample_distribution", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_sample_distribution_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_sample_distribution_set", NULL);
+ RNA_def_property_ui_text(prop, "Exponential Sampling", "Distribute more samples closer to the camera");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_SceneLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "volumetric_lights", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_lights_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_lights_set");
+ RNA_def_property_ui_text(prop, "Volumetric Lighting", "Enable scene lamps interactions with volumetrics");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_SceneLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "volumetric_shadows", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_shadows_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_shadows_set");
+ RNA_def_property_ui_text(prop, "Volumetric Shadows", "Generate shadows from volumetric material (Very expensive)");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_SceneLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "volumetric_shadow_samples", PROP_INT, PROP_NONE);
+ RNA_def_property_int_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_shadow_samples_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_shadow_samples_set", NULL);
+ RNA_def_property_range(prop, 1, 128);
+ RNA_def_property_ui_text(prop, "Volumetric Shadow Samples", "Number of samples to compute volumetric shadowing");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_SceneLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "volumetric_colored_transmittance", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_colored_transmittance_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_colored_transmittance_set");
+ RNA_def_property_ui_text(prop, "Colored transmittance", "Enable wavelength dependant volumetric transmittance");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_SceneLayerEngineSettings_update");
+
/* Ambient Occlusion */
prop = RNA_def_property(srna, "gtao_enable", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_gtao_enable_get",