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:
-rw-r--r--source/blender/draw/CMakeLists.txt1
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c1
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c139
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c1
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h8
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c2
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl72
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl14
-rw-r--r--source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl64
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl88
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_grid_fill_frag.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl14
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl4
14 files changed, 358 insertions, 56 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 9c806f26fda..8339b6b8720 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -137,6 +137,7 @@ data_to_c_simple(engines/eevee/shaders/lamps_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lightprobe_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lightprobe_geom.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lightprobe_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lightprobe_cube_display_frag.glsl SRC)
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index d1cd1b1440c..d5582a498a4 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -55,6 +55,7 @@ static void eevee_view_layer_data_free(void *storage)
DRW_FRAMEBUFFER_FREE_SAFE(sldata->probe_fb);
DRW_FRAMEBUFFER_FREE_SAFE(sldata->probe_filter_fb);
DRW_TEXTURE_FREE_SAFE(sldata->probe_rt);
+ DRW_TEXTURE_FREE_SAFE(sldata->probe_depth_rt);
DRW_TEXTURE_FREE_SAFE(sldata->probe_pool);
DRW_TEXTURE_FREE_SAFE(sldata->irradiance_pool);
DRW_TEXTURE_FREE_SAFE(sldata->irradiance_rt);
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 32b5023c65e..a83562e81ce 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -47,11 +47,13 @@
#include "ED_screen.h"
#define IRRADIANCE_POOL_SIZE 1024
+#define HAMMERSLEY_SIZE 1024
static struct {
struct GPUShader *probe_default_sh;
struct GPUShader *probe_filter_glossy_sh;
struct GPUShader *probe_filter_diffuse_sh;
+ struct GPUShader *probe_filter_visibility_sh;
struct GPUShader *probe_grid_fill_sh;
struct GPUShader *probe_grid_display_sh;
struct GPUShader *probe_planar_display_sh;
@@ -62,7 +64,6 @@ static struct {
struct GPUTexture *planar_pool_placeholder;
struct GPUTexture *depth_placeholder;
struct GPUTexture *depth_array_placeholder;
- struct GPUTexture *cube_face_depth;
struct GPUTexture *cube_face_minmaxz;
int update_world;
@@ -73,6 +74,7 @@ extern char datatoc_background_vert_glsl[];
extern char datatoc_default_world_frag_glsl[];
extern char datatoc_lightprobe_filter_glossy_frag_glsl[];
extern char datatoc_lightprobe_filter_diffuse_frag_glsl[];
+extern char datatoc_lightprobe_filter_visibility_frag_glsl[];
extern char datatoc_lightprobe_geom_glsl[];
extern char datatoc_lightprobe_vert_glsl[];
extern char datatoc_lightprobe_planar_display_frag_glsl[];
@@ -159,6 +161,7 @@ static void planar_pool_ensure_alloc(EEVEE_Data *vedata, int num_planar_ref)
void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(vedata))
{
+ bool update_all = false;
const DRWContextState *draw_ctx = DRW_context_state_get();
ViewLayer *view_layer = draw_ctx->view_layer;
IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
@@ -176,7 +179,7 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda
e_data.probe_filter_glossy_sh = DRW_shader_create(
datatoc_lightprobe_vert_glsl, datatoc_lightprobe_geom_glsl, shader_str,
- "#define HAMMERSLEY_SIZE 1024\n"
+ "#define HAMMERSLEY_SIZE " STRINGIFY(HAMMERSLEY_SIZE) "\n"
"#define NOISE_SIZE 64\n");
e_data.probe_default_sh = DRW_shader_create(
@@ -200,7 +203,21 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda
#elif defined(IRRADIANCE_HL2)
"#define IRRADIANCE_HL2\n"
#endif
- "#define HAMMERSLEY_SIZE 1024\n"
+ "#define HAMMERSLEY_SIZE " STRINGIFY(HAMMERSLEY_SIZE) "\n"
+ "#define NOISE_SIZE 64\n");
+
+ MEM_freeN(shader_str);
+
+ ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_lightprobe_filter_visibility_frag_glsl);
+ shader_str = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ e_data.probe_filter_visibility_sh = DRW_shader_create_fullscreen(
+ shader_str,
+ "#define HAMMERSLEY_SIZE " STRINGIFY(HAMMERSLEY_SIZE) "\n"
"#define NOISE_SIZE 64\n");
MEM_freeN(shader_str);
@@ -260,7 +277,7 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda
datatoc_lightprobe_planar_downsample_frag_glsl,
NULL);
- e_data.hammersley = create_hammersley_sample_texture(1024);
+ e_data.hammersley = create_hammersley_sample_texture(HAMMERSLEY_SIZE);
}
if (!sldata->probes) {
@@ -275,21 +292,15 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda
}
int prop_bounce_num = BKE_collection_engine_property_value_get_int(props, "gi_diffuse_bounces");
- /* Update all probes if number of bounces mismatch. */
if (sldata->probes->num_bounce != prop_bounce_num) {
- e_data.update_world |= PROBE_UPDATE_ALL;
- sldata->probes->updated_bounce = 0;
- sldata->probes->grid_initialized = false;
+ sldata->probes->num_bounce = prop_bounce_num;
+ update_all = true;
}
- sldata->probes->num_bounce = prop_bounce_num;
int prop_cubemap_res = BKE_collection_engine_property_value_get_int(props, "gi_cubemap_resolution");
if (sldata->probes->cubemap_res != prop_cubemap_res) {
sldata->probes->cubemap_res = prop_cubemap_res;
-
- e_data.update_world |= PROBE_UPDATE_ALL;
- sldata->probes->updated_bounce = 0;
- sldata->probes->grid_initialized = false;
+ update_all = true;
sldata->probes->target_size = prop_cubemap_res >> 1;
@@ -297,25 +308,27 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda
DRW_TEXTURE_FREE_SAFE(sldata->probe_pool);
}
- /* Setup Render Target Cubemap */
-
- /* We do this detach / attach dance to not generate an invalid framebuffer (mixed cubemap / 2D map) */
- if (sldata->probe_rt) {
- /* XXX Silly,TODO Cleanup this mess */
- DRW_framebuffer_texture_detach(sldata->probe_rt);
+ int visibility_res = BKE_collection_engine_property_value_get_int(props, "gi_visibility_resolution");
+ if (sldata->probes->irradiance_vis_size != visibility_res) {
+ sldata->probes->irradiance_vis_size = visibility_res;
+ update_all = true;
}
- DRWFboTexture tex_probe = {&e_data.cube_face_depth, DRW_TEX_DEPTH_24, DRW_TEX_TEMP};
- DRW_framebuffer_init(&sldata->probe_fb, &draw_engine_eevee_type, sldata->probes->target_size, sldata->probes->target_size, &tex_probe, 1);
+ if (update_all) {
+ e_data.update_world |= PROBE_UPDATE_ALL;
+ sldata->probes->updated_bounce = 0;
+ sldata->probes->grid_initialized = false;
+ }
+ /* Setup Render Target Cubemap */
if (!sldata->probe_rt) {
+ sldata->probe_depth_rt = DRW_texture_create_cube(sldata->probes->target_size, DRW_TEX_DEPTH_24, 0, NULL);
sldata->probe_rt = DRW_texture_create_cube(sldata->probes->target_size, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
}
- if (sldata->probe_rt) {
- /* XXX Silly,TODO Cleanup this mess */
- DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_rt, 0, 0);
- }
+ DRWFboTexture tex_probe[2] = {{&sldata->probe_depth_rt, DRW_TEX_DEPTH_24, 0},
+ {&sldata->probe_rt, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP}};
+ DRW_framebuffer_init(&sldata->probe_fb, &draw_engine_eevee_type, sldata->probes->target_size, sldata->probes->target_size, tex_probe, 2);
/* Minmaxz Pyramid */
// DRWFboTexture tex_minmaxz = {&e_data.cube_face_minmaxz, DRW_TEX_RG_32, DRW_TEX_MIPMAP | DRW_TEX_TEMP};
@@ -435,10 +448,29 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
}
{
+ psl->probe_visibility_compute = DRW_pass_create("LightProbe Visibility Compute", DRW_STATE_WRITE_COLOR);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_filter_visibility_sh, psl->probe_visibility_compute);
+ DRW_shgroup_uniform_int(grp, "outputSize", &sldata->probes->shres, 1);
+ DRW_shgroup_uniform_float(grp, "visibilityRange", &sldata->probes->visibility_range, 1);
+ DRW_shgroup_uniform_float(grp, "visibilityBlur", &sldata->probes->visibility_blur, 1);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &sldata->probes->samples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &sldata->probes->invsamples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "storedTexelSize", &sldata->probes->texel_size, 1);
+ DRW_shgroup_uniform_float(grp, "nearClip", &sldata->probes->near_clip, 1);
+ DRW_shgroup_uniform_float(grp, "farClip", &sldata->probes->far_clip, 1);
+ DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
+ DRW_shgroup_uniform_texture(grp, "probeDepth", sldata->probe_depth_rt);
+
+ struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+ DRW_shgroup_call_add(grp, geom, NULL);
+ }
+
+ {
psl->probe_grid_fill = DRW_pass_create("LightProbe Grid Floodfill", DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_grid_fill_sh, psl->probe_grid_fill);
- DRW_shgroup_uniform_buffer(grp, "gridTexture", &sldata->irradiance_pool);
+ DRW_shgroup_uniform_buffer(grp, "irradianceGrid", &sldata->irradiance_pool);
struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call_add(grp, geom, NULL);
@@ -751,6 +783,13 @@ static void EEVEE_lightprobes_updates(EEVEE_ViewLayerData *sldata, EEVEE_PassLis
copy_v3_v3_int(egrid->resolution, &probe->grid_resolution_x);
+ /* Visibility bias */
+ egrid->visibility_bias = 0.05f * probe->vis_bias;
+ egrid->visibility_bleed = probe->vis_bleedbias;
+ egrid->visibility_range = max_ff(max_ff(len_v3(egrid->increment_x),
+ len_v3(egrid->increment_y)),
+ len_v3(egrid->increment_z)) + 1.0f;
+
/* Debug Display */
if (BKE_object_is_visible(ob) &&
DRW_state_draw_support() &&
@@ -825,16 +864,18 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
/* we need a signed format for Spherical Harmonics */
int irradiance_format = DRW_TEX_RGBA_16;
#else
- int irradiance_format = DRW_TEX_RGB_11_11_10;
+ int irradiance_format = DRW_TEX_RGBA_8;
#endif
/* TODO Allocate bigger storage if needed. */
if (!sldata->irradiance_pool || !sldata->irradiance_rt) {
if (!sldata->irradiance_pool) {
- sldata->irradiance_pool = DRW_texture_create_2D(IRRADIANCE_POOL_SIZE, IRRADIANCE_POOL_SIZE, irradiance_format, DRW_TEX_FILTER, NULL);
+ sldata->irradiance_pool = DRW_texture_create_2D_array(IRRADIANCE_POOL_SIZE, IRRADIANCE_POOL_SIZE, 2,
+ irradiance_format, DRW_TEX_FILTER, NULL);
}
if (!sldata->irradiance_rt) {
- sldata->irradiance_rt = DRW_texture_create_2D(IRRADIANCE_POOL_SIZE, IRRADIANCE_POOL_SIZE, irradiance_format, DRW_TEX_FILTER, NULL);
+ sldata->irradiance_rt = DRW_texture_create_2D_array(IRRADIANCE_POOL_SIZE, IRRADIANCE_POOL_SIZE, 2,
+ irradiance_format, DRW_TEX_FILTER, NULL);
}
pinfo->num_render_grid = 0;
pinfo->updated_bounce = 0;
@@ -953,7 +994,9 @@ static void glossy_filter_probe(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
}
/* Diffuse filter probe_rt to irradiance_pool at index probe_idx */
-static void diffuse_filter_probe(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl, int offset)
+static void diffuse_filter_probe(
+ EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl, int offset,
+ float clipsta, float clipend, float vis_range, float vis_blur)
{
EEVEE_LightProbesInfo *pinfo = sldata->probes;
@@ -994,6 +1037,26 @@ static void diffuse_filter_probe(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata
DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, size[0], size[1]);
DRW_draw_pass(psl->probe_diffuse_compute);
+ /* Compute visibility */
+ pinfo->samples_ct = 512.0f; /* TODO refine */
+ pinfo->invsamples_ct = 1.0f / pinfo->samples_ct;
+ pinfo->shres = pinfo->irradiance_vis_size;
+ pinfo->visibility_range = vis_range;
+ pinfo->visibility_blur = vis_blur;
+ pinfo->near_clip = -clipsta;
+ pinfo->far_clip = -clipend;
+ pinfo->texel_size = 1.0f / (float)pinfo->irradiance_vis_size;
+
+ cell_per_row = IRRADIANCE_POOL_SIZE / pinfo->irradiance_vis_size;
+ x = pinfo->irradiance_vis_size * (offset % cell_per_row);
+ y = pinfo->irradiance_vis_size * (offset / cell_per_row);
+
+ DRW_framebuffer_texture_detach(sldata->irradiance_rt);
+ DRW_framebuffer_texture_layer_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 1, 0);
+
+ DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, pinfo->irradiance_vis_size, sldata->probes->irradiance_vis_size);
+ DRW_draw_pass(psl->probe_visibility_compute);
+
/* reattach to have a valid framebuffer. */
DRW_framebuffer_texture_detach(sldata->irradiance_rt);
DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
@@ -1044,8 +1107,8 @@ static void render_scene_to_probe(
/* Detach to rebind the right cubeface. */
DRW_framebuffer_bind(sldata->probe_fb);
- DRW_framebuffer_texture_attach(sldata->probe_fb, e_data.cube_face_depth, 0, 0);
DRW_framebuffer_texture_detach(sldata->probe_rt);
+ DRW_framebuffer_texture_detach(sldata->probe_depth_rt);
for (int i = 0; i < 6; ++i) {
float viewmat[4][4], persmat[4][4];
float viewinv[4][4], persinv[4][4];
@@ -1068,6 +1131,7 @@ static void render_scene_to_probe(
EEVEE_draw_shadows(sldata, psl);
DRW_framebuffer_cubeface_attach(sldata->probe_fb, sldata->probe_rt, 0, i, 0);
+ DRW_framebuffer_cubeface_attach(sldata->probe_fb, sldata->probe_depth_rt, 0, i, 0);
DRW_framebuffer_viewport_size(sldata->probe_fb, 0, 0, pinfo->target_size, pinfo->target_size);
DRW_framebuffer_clear(false, true, false, NULL, 1.0);
@@ -1078,7 +1142,7 @@ static void render_scene_to_probe(
DRW_draw_pass(psl->probe_background);
- // EEVEE_create_minmax_buffer(vedata, e_data.cube_face_depth);
+ // EEVEE_create_minmax_buffer(vedata, sldata->probe_depth_rt);
/* Rebind Planar FB */
DRW_framebuffer_bind(sldata->probe_fb);
@@ -1089,9 +1153,10 @@ static void render_scene_to_probe(
DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
DRW_framebuffer_texture_detach(sldata->probe_rt);
+ DRW_framebuffer_texture_detach(sldata->probe_depth_rt);
}
DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_rt, 0, 0);
- DRW_framebuffer_texture_detach(e_data.cube_face_depth);
+ DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_depth_rt, 0, 0);
DRW_viewport_matrix_override_unset(DRW_MAT_PERS);
DRW_viewport_matrix_override_unset(DRW_MAT_PERSINV);
@@ -1212,6 +1277,7 @@ static void render_world_to_probe(EEVEE_ViewLayerData *sldata, EEVEE_PassList *p
/* Detach to rebind the right cubeface. */
DRW_framebuffer_bind(sldata->probe_fb);
DRW_framebuffer_texture_detach(sldata->probe_rt);
+ DRW_framebuffer_texture_detach(sldata->probe_depth_rt);
for (int i = 0; i < 6; ++i) {
float viewmat[4][4], persmat[4][4];
float viewinv[4][4], persinv[4][4];
@@ -1237,6 +1303,7 @@ static void render_world_to_probe(EEVEE_ViewLayerData *sldata, EEVEE_PassList *p
DRW_framebuffer_texture_detach(sldata->probe_rt);
}
DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_rt, 0, 0);
+ DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_depth_rt, 0, 0);
DRW_viewport_matrix_override_unset(DRW_MAT_PERS);
DRW_viewport_matrix_override_unset(DRW_MAT_PERSINV);
@@ -1276,7 +1343,7 @@ static void lightprobes_refresh_world(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
glossy_filter_probe(sldata, vedata, psl, 0);
}
if (e_data.update_world & PROBE_UPDATE_GRID) {
- diffuse_filter_probe(sldata, vedata, psl, 0);
+ diffuse_filter_probe(sldata, vedata, psl, 0, 0.0, 0.0, 0.0, 0.0);
SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
DRW_framebuffer_texture_detach(sldata->probe_pool);
DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
@@ -1465,7 +1532,8 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_
DRW_uniformbuffer_update(sldata->grid_ubo, &sldata->probes->grid_data);
}
render_scene_to_probe(sldata, vedata, pos, prb->clipsta, prb->clipend);
- diffuse_filter_probe(sldata, vedata, psl, egrid->offset + cell_id);
+ diffuse_filter_probe(sldata, vedata, psl, egrid->offset + cell_id,
+ prb->clipsta, prb->clipend, egrid->visibility_range, prb->vis_blur);
/* To see what is going on. */
SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
/* Restore */
@@ -1543,6 +1611,7 @@ void EEVEE_lightprobes_free(void)
DRW_SHADER_FREE_SAFE(e_data.probe_default_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_filter_glossy_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_filter_diffuse_sh);
+ DRW_SHADER_FREE_SAFE(e_data.probe_filter_visibility_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_grid_fill_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_grid_display_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_planar_display_sh);
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 41564bb2703..c25ab1e7859 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -374,6 +374,7 @@ static void add_standard_uniforms(
DRW_shgroup_uniform_buffer(shgrp, "probeCubes", &sldata->probe_pool);
DRW_shgroup_uniform_buffer(shgrp, "probePlanars", &vedata->txl->planar_pool);
DRW_shgroup_uniform_buffer(shgrp, "irradianceGrid", &sldata->irradiance_pool);
+ DRW_shgroup_uniform_int(shgrp, "irradianceVisibilitySize", &sldata->probes->irradiance_vis_size, 1);
DRW_shgroup_uniform_buffer(shgrp, "shadowTexture", &sldata->shadow_pool);
DRW_shgroup_uniform_int(shgrp, "outputSsrId", ssr_id, 1);
DRW_shgroup_uniform_vec4(shgrp, "aoParameters[0]", &vedata->stl->effects->ao_dist, 2);
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index dc99d941db8..36a6d3fb1d0 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -141,6 +141,7 @@ typedef struct EEVEE_PassList {
struct DRWPass *probe_background;
struct DRWPass *probe_glossy_compute;
struct DRWPass *probe_diffuse_compute;
+ struct DRWPass *probe_visibility_compute;
struct DRWPass *probe_grid_fill;
struct DRWPass *probe_display;
struct DRWPass *probe_planar_downsample_ps;
@@ -369,6 +370,7 @@ typedef struct EEVEE_LightGrid {
float increment_x[3], attenuation_bias; /* world space vector between 2 opposite cells */
float increment_y[3], level_bias;
float increment_z[3], pad4;
+ float visibility_bias, visibility_bleed, visibility_range, pad5;
} EEVEE_LightGrid;
typedef struct EEVEE_PlanarReflection {
@@ -391,6 +393,7 @@ typedef struct EEVEE_LightProbesInfo {
int num_bounce;
int cubemap_res;
int target_size;
+ int irradiance_vis_size;
int grid_initialized;
/* Actual number of probes that have datas. */
int num_render_cube;
@@ -402,9 +405,13 @@ typedef struct EEVEE_LightProbesInfo {
float padding_size;
float samples_ct;
float invsamples_ct;
+ float near_clip;
+ float far_clip;
float roughness;
float lodfactor;
float lod_rt_max, lod_cube_max, lod_planar_max;
+ float visibility_range;
+ float visibility_blur;
int shres;
int shnbr;
bool specular_toggle;
@@ -550,6 +557,7 @@ typedef struct EEVEE_ViewLayerData {
struct GPUFrameBuffer *probe_filter_fb;
struct GPUTexture *probe_rt;
+ struct GPUTexture *probe_depth_rt;
struct GPUTexture *probe_pool;
struct GPUTexture *irradiance_pool;
struct GPUTexture *irradiance_rt;
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index dfb88572cf8..dae4503dc32 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -86,8 +86,8 @@ static void eevee_create_shader_volumes(void)
ds_frag = BLI_dynstr_new();
BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
BLI_dynstr_append(ds_frag, datatoc_bsdf_direct_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_irradiance_lib_glsl);
BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_irradiance_lib_glsl);
BLI_dynstr_append(ds_frag, datatoc_lamps_lib_glsl);
BLI_dynstr_append(ds_frag, datatoc_volumetric_lib_glsl);
e_data.volumetric_common_lamps_lib = BLI_dynstr_get_cstring(ds_frag);
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 aecb1e6dde4..37ed2235c6f 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -432,6 +432,78 @@ vec3 normal_decode(vec2 enc, vec3 view)
return n;
}
+/* ---- RGBM (shared multiplier) encoding ---- */
+/* From http://iwasbeingirony.blogspot.fr/2010/06/difference-between-rgbm-and-rgbd.html */
+
+/* Higher RGBM_MAX_RANGE gives imprecision issues in low intensity. */
+#define RGBM_MAX_RANGE 512.0
+
+vec4 rgbm_encode(vec3 rgb)
+{
+ float maxRGB = max_v3(rgb);
+ float M = maxRGB / RGBM_MAX_RANGE;
+ M = ceil(M * 255.0) / 255.0;
+ return vec4(rgb / (M * RGBM_MAX_RANGE), M);
+}
+
+vec3 rgbm_decode(vec4 data)
+{
+ return data.rgb * (data.a * RGBM_MAX_RANGE);
+}
+
+/* ---- RGBE (shared exponent) encoding ---- */
+vec4 rgbe_encode(vec3 rgb)
+{
+ float maxRGB = max_v3(rgb);
+ float fexp = ceil(log2(maxRGB));
+ return vec4(rgb / exp2(fexp), (fexp + 128.0) / 255.0);
+}
+
+vec3 rgbe_decode(vec4 data)
+{
+ float fexp = data.a * 255.0 - 128.0;
+ return data.rgb * exp2(fexp);
+}
+
+#if 1
+#define irradiance_encode rgbe_encode
+#define irradiance_decode rgbe_decode
+#else /* No ecoding (when using floating point format) */
+#define irradiance_encode(X) (X).rgbb
+#define irradiance_decode(X) (X).rgb
+#endif
+
+/* Irradiance Visibility Encoding */
+#if 1
+vec4 visibility_encode(vec2 accum, float range)
+{
+ accum /= range;
+
+ vec4 data;
+ data.x = fract(accum.x);
+ data.y = floor(accum.x) / 255.0;
+ data.z = fract(accum.y);
+ data.w = floor(accum.y) / 255.0;
+
+ return data;
+}
+
+vec2 visibility_decode(vec4 data, float range)
+{
+ return (data.xz + data.yw * 255.0) * range;
+}
+#else /* No ecoding (when using floating point format) */
+vec4 visibility_encode(vec2 accum, float range)
+{
+ return accum.xyxy;
+}
+
+vec2 visibility_decode(vec4 data, float range)
+{
+ return data.xy;
+}
+#endif
+
/* Fresnel monochromatic, perfect mirror */
float F_eta(float eta, float cos_theta)
{
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl
index f58dac6c0a0..8cb5a66290d 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl
@@ -90,4 +90,18 @@ vec3 sample_hemisphere(float nsample, vec3 N, vec3 T, vec3 B)
return tangent_to_world(Ht, N, T, B);
}
+
+vec3 sample_cone(float nsample, float angle, vec3 N, vec3 T, vec3 B)
+{
+ vec3 Xi = hammersley_3d(nsample);
+
+ float z = cos(angle * Xi.x); /* cos theta */
+ float r = sqrt( 1.0f - z*z ); /* sin theta */
+ float x = r * Xi.y;
+ float y = r * Xi.z;
+
+ vec3 Ht = vec3(x, y, z);
+
+ return tangent_to_world(Ht, N, T, B);
+}
#endif \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl b/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl
index 95e7af41398..2555d413da9 100644
--- a/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl
@@ -1,5 +1,6 @@
-uniform sampler2D irradianceGrid;
+uniform sampler2DArray irradianceGrid;
+uniform int irradianceVisibilitySize;
#define IRRADIANCE_LIB
@@ -36,7 +37,7 @@ IrradianceData load_irradiance_cell(int cell, vec3 N)
uvs += vec2(cell_co) / vec2(textureSize(irradianceGrid, 0));
IrradianceData ir;
- ir.color = texture(irradianceGrid, uvs).rgb;
+ ir.color = texture(irradianceGrid, vec3(uvs, 0.0)).rgb;
#elif defined(IRRADIANCE_SH_L2)
@@ -48,15 +49,15 @@ IrradianceData load_irradiance_cell(int cell, vec3 N)
ivec3 ofs = ivec3(0, 1, 2);
IrradianceData ir;
- ir.shcoefs[0] = texelFetch(irradianceGrid, cell_co + ofs.xx, 0).rgb;
- ir.shcoefs[1] = texelFetch(irradianceGrid, cell_co + ofs.yx, 0).rgb;
- ir.shcoefs[2] = texelFetch(irradianceGrid, cell_co + ofs.zx, 0).rgb;
- ir.shcoefs[3] = texelFetch(irradianceGrid, cell_co + ofs.xy, 0).rgb;
- ir.shcoefs[4] = texelFetch(irradianceGrid, cell_co + ofs.yy, 0).rgb;
- ir.shcoefs[5] = texelFetch(irradianceGrid, cell_co + ofs.zy, 0).rgb;
- ir.shcoefs[6] = texelFetch(irradianceGrid, cell_co + ofs.xz, 0).rgb;
- ir.shcoefs[7] = texelFetch(irradianceGrid, cell_co + ofs.yz, 0).rgb;
- ir.shcoefs[8] = texelFetch(irradianceGrid, cell_co + ofs.zz, 0).rgb;
+ ir.shcoefs[0] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.xx, 0), 0).rgb;
+ ir.shcoefs[1] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.yx, 0), 0).rgb;
+ ir.shcoefs[2] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.zx, 0), 0).rgb;
+ ir.shcoefs[3] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.xy, 0), 0).rgb;
+ ir.shcoefs[4] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.yy, 0), 0).rgb;
+ ir.shcoefs[5] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.zy, 0), 0).rgb;
+ ir.shcoefs[6] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.xz, 0), 0).rgb;
+ ir.shcoefs[7] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.yz, 0), 0).rgb;
+ ir.shcoefs[8] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.zz, 0), 0).rgb;
#else /* defined(IRRADIANCE_HL2) */
@@ -68,15 +69,50 @@ IrradianceData load_irradiance_cell(int cell, vec3 N)
ivec3 is_negative = ivec3(step(0.0, -N));
IrradianceData ir;
- ir.cubesides[0] = texelFetch(irradianceGrid, cell_co + ivec2(0, is_negative.x), 0).rgb;
- ir.cubesides[1] = texelFetch(irradianceGrid, cell_co + ivec2(1, is_negative.y), 0).rgb;
- ir.cubesides[2] = texelFetch(irradianceGrid, cell_co + ivec2(2, is_negative.z), 0).rgb;
+ ir.cubesides[0] = irradiance_decode(texelFetch(irradianceGrid, ivec3(cell_co + ivec2(0, is_negative.x), 0), 0));
+ ir.cubesides[1] = irradiance_decode(texelFetch(irradianceGrid, ivec3(cell_co + ivec2(1, is_negative.y), 0), 0));
+ ir.cubesides[2] = irradiance_decode(texelFetch(irradianceGrid, ivec3(cell_co + ivec2(2, is_negative.z), 0), 0));
#endif
return ir;
}
+float load_visibility_cell(int cell, vec3 L, float dist, float bias, float bleed_bias, float range)
+{
+ /* Keep in sync with diffuse_filter_probe() */
+ ivec2 cell_co = ivec2(irradianceVisibilitySize);
+ int cell_per_row = textureSize(irradianceGrid, 0).x / irradianceVisibilitySize;
+ cell_co.x *= (cell) % cell_per_row;
+ cell_co.y *= (cell) / cell_per_row;
+
+ vec2 texel_size = 1.0 / vec2(textureSize(irradianceGrid, 0).xy);
+ vec2 co = vec2(cell_co) * texel_size;
+
+ vec2 uv = mapping_octahedron(-L, vec2(1.0 / float(irradianceVisibilitySize)));
+ uv *= vec2(irradianceVisibilitySize) * texel_size;
+
+ vec4 data = texture(irradianceGrid, vec3(co + uv, 1.0));
+
+ /* Decoding compressed data */
+ vec2 moments = visibility_decode(data, range);
+
+ /* Doing chebishev test */
+ float variance = abs(moments.x * moments.x - moments.y);
+ variance = max(variance, bias / 10.0);
+
+ float d = dist - moments.x;
+ float p_max = variance / (variance + d * d);
+
+ /* Increase contrast in the weight by squaring it */
+ p_max *= p_max;
+
+ /* Now reduce light-bleeding by removing the [0, x] tail and linearly rescaling (x, 1] */
+ p_max = clamp((p_max - bleed_bias) / (1.0 - bleed_bias), 0.0, 1.0);
+
+ return (dist <= moments.x) ? 1.0 : p_max;
+}
+
/* http://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/ */
vec3 spherical_harmonics_L1(vec3 N, vec3 shcoefs[4])
{
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl
index 0b97548c8df..eb4315c93a3 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl
@@ -192,6 +192,6 @@ void main()
}
}
- FragColor = vec4(out_radiance / weight, 1.0);
+ FragColor = irradiance_encode(out_radiance / weight);
#endif
} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl
new file mode 100644
index 00000000000..0727e73f507
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl
@@ -0,0 +1,88 @@
+
+uniform samplerCube probeDepth;
+uniform int outputSize;
+uniform float lodFactor;
+uniform float storedTexelSize;
+uniform float lodMax;
+uniform float nearClip;
+uniform float farClip;
+uniform float visibilityRange;
+uniform float visibilityBlur;
+
+out vec4 FragColor;
+
+vec3 octahedral_to_cubemap_proj(vec2 co)
+{
+ co = co * 2.0 - 1.0;
+
+ vec2 abs_co = abs(co);
+ vec3 v = vec3(co, 1.0 - (abs_co.x + abs_co.y));
+
+ if ( abs_co.x + abs_co.y > 1.0 ) {
+ v.xy = (abs(co.yx) - 1.0) * -sign(co.xy);
+ }
+
+ return v;
+}
+
+float linear_depth(float z)
+{
+ return (nearClip * farClip) / (z * (nearClip - farClip) + farClip);
+}
+
+float get_world_distance(float depth, vec3 cos)
+{
+ float is_background = step(1.0, depth);
+ depth = linear_depth(depth);
+ depth += 1e1 * is_background;
+ cos = normalize(abs(cos));
+ float cos_vec = max(cos.x, max(cos.y, cos.z));
+ return depth / cos_vec;
+}
+
+void main()
+{
+ ivec2 texel = ivec2(gl_FragCoord.xy) % ivec2(outputSize);
+
+ vec3 cos;
+
+ cos.xy = (vec2(texel) + 0.5) * storedTexelSize;
+
+ /* add a 2 pixel border to ensure filtering is correct */
+ cos.xy *= 1.0 + storedTexelSize * 2.0;
+ cos.xy -= storedTexelSize;
+
+ float pattern = 1.0;
+
+ /* edge mirroring : only mirror if directly adjacent
+ * (not diagonally adjacent) */
+ vec2 m = abs(cos.xy - 0.5) + 0.5;
+ vec2 f = floor(m);
+ if (f.x - f.y != 0.0) {
+ cos.xy = 1.0 - cos.xy;
+ }
+
+ /* clamp to [0-1] */
+ cos.xy = fract(cos.xy);
+
+ /* get cubemap vector */
+ cos = normalize(octahedral_to_cubemap_proj(cos.xy));
+
+ vec3 T, B;
+ make_orthonormal_basis(cos, T, B); /* Generate tangent space */
+
+ vec2 accum = vec2(0.0);
+
+ for (float i = 0; i < sampleCount; i++) {
+ vec3 sample = sample_cone(i, M_PI_2 * visibilityBlur, cos, T, B);
+ float depth = texture(probeDepth, sample).r;
+ depth = get_world_distance(depth, sample);
+ accum += vec2(depth, depth * depth);
+ }
+
+ accum *= invSampleCount;
+ accum = abs(accum);
+
+ /* Encode to normalized RGBA 8 */
+ FragColor = visibility_encode(accum, visibilityRange);
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_fill_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_fill_frag.glsl
index cea1ca5e7b0..c9e66ceffb2 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_fill_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_fill_frag.glsl
@@ -1,4 +1,4 @@
-uniform sampler2D gridTexture;
+uniform sampler2DArray irradianceGrid;
out vec4 FragColor;
@@ -12,7 +12,7 @@ void main()
const ivec2 data_size = ivec2(3, 2);
#endif
ivec2 coord = ivec2(gl_FragCoord.xy) % data_size;
- FragColor = texelFetch(gridTexture, coord, 0);
+ FragColor = texelFetch(irradianceGrid, ivec3(coord, 0), 0);
if (any(greaterThanEqual(ivec2(gl_FragCoord.xy), data_size))) {
FragColor = vec4(0.0, 0.0, 0.0, 1.0);
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl
index 834bacc118b..e914228aded 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl
@@ -49,6 +49,7 @@ struct GridData {
vec4 ws_increment_x_atten_bias; /* world space vector between 2 opposite cells */
vec4 ws_increment_y_lvl_bias;
vec4 ws_increment_z;
+ vec4 vis_bias_bleed_range;
};
#define g_corner ws_corner_atten_scale.xyz
@@ -60,6 +61,9 @@ struct GridData {
#define g_increment_z ws_increment_z.xyz
#define g_resolution resolution_offset.xyz
#define g_offset resolution_offset.w
+#define g_vis_bias vis_bias_bleed_range.x
+#define g_vis_bleed vis_bias_bleed_range.y
+#define g_vis_range vis_bias_bleed_range.z
#ifndef MAX_PROBE
#define MAX_PROBE 1
@@ -227,14 +231,18 @@ vec3 probe_evaluate_grid(GridData gd, vec3 W, vec3 N, vec3 localpos)
gd.g_increment_y * cell_cos.y +
gd.g_increment_z * cell_cos.z);
- // vec3 ws_point_to_cell = ws_cell_location - W;
- // vec3 ws_light = normalize(ws_point_to_cell);
+ vec3 ws_point_to_cell = ws_cell_location - W;
+ float ws_dist_point_to_cell = length(ws_point_to_cell);
+ vec3 ws_light = ws_point_to_cell / ws_dist_point_to_cell;
vec3 trilinear = mix(1 - trilinear_weight, trilinear_weight, offset);
float weight = trilinear.x * trilinear.y * trilinear.z;
+ /* Precomputed visibility */
+ weight *= load_visibility_cell(cell, ws_light, ws_dist_point_to_cell, gd.g_vis_bias, gd.g_vis_bleed, gd.g_vis_range);
+
/* Smooth backface test */
- // weight *= sqrt(max(0.002, dot(ws_light, N)));
+ weight *= sqrt(max(0.002, dot(ws_light, N)));
/* Avoid zero weight */
weight = max(0.00001, weight);
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
index b3f5e8b60ad..1376c53d633 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
@@ -128,12 +128,16 @@ vec3 light_volume_shadow(LightData ld, vec3 ray_wpos, vec4 l_vector, sampler3D v
#ifdef IRRADIANCE_LIB
vec3 irradiance_volumetric(vec3 wpos)
{
+#ifdef IRRADIANCE_HL2
IrradianceData ir_data = load_irradiance_cell(0, vec3(1.0));
vec3 irradiance = ir_data.cubesides[0] + ir_data.cubesides[1] + ir_data.cubesides[2];
ir_data = load_irradiance_cell(0, vec3(-1.0));
irradiance += ir_data.cubesides[0] + ir_data.cubesides[1] + ir_data.cubesides[2];
irradiance *= 0.16666666; /* 1/6 */
return irradiance;
+#else
+ return vec3(0.0);
+#endif
}
#endif