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
path: root/source
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2019-08-22 17:04:25 +0300
committerClément Foucault <foucault.clem@gmail.com>2019-09-05 18:37:50 +0300
commitd8aaf25c23fa10ee121dc4fdd1cafe544bcca355 (patch)
treeb5a16157beac22e4b474c699c1ce25f3d8c5be51 /source
parentca58936f2ff2b14a649722be20d98f8fa35831ff (diff)
Eevee: Shadow map refactor
Reviewed By: brecht Differential Revision: http://developer.blender.org/D5659
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/intern/scene.c3
-rw-r--r--source/blender/blenloader/intern/versioning_280.c2
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c3
-rw-r--r--source/blender/draw/CMakeLists.txt9
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c21
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c26
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c12
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c1438
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c128
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h245
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c15
-rw-r--r--source/blender/draw/engines/eevee/eevee_sampling.c111
-rw-r--r--source/blender/draw/engines/eevee/eevee_shadows.c412
-rw-r--r--source/blender/draw/engines/eevee/eevee_shadows_cascade.c439
-rw-r--r--source/blender/draw/engines/eevee/eevee_shadows_cube.c223
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c136
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c11
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl102
-rw-r--r--source/blender/draw/engines/eevee/shaders/default_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl43
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl165
-rw-r--r--source/blender/draw/engines/eevee/shaders/lights_lib.glsl407
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl46
-rw-r--r--source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl199
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_process_geom.glsl36
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_process_vert.glsl32
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl322
-rw-r--r--source/blender/draw/intern/DRW_render.h1
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c17
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c4
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl2
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl1
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl13
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl3
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl67
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl2
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_shader_to_rgba.glsl6
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl23
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl6
-rw-r--r--source/blender/makesdna/DNA_light_types.h10
-rw-r--r--source/blender/makesdna/DNA_scene_types.h4
-rw-r--r--source/blender/makesrna/intern/rna_light.c40
-rw-r--r--source/blender/makesrna/intern/rna_scene.c23
45 files changed, 1974 insertions, 2841 deletions
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 6f8d14252f0..b36e5a276e2 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -961,7 +961,6 @@ void BKE_scene_init(Scene *sce)
sce->eevee.motion_blur_samples = 8;
sce->eevee.motion_blur_shutter = 0.5f;
- sce->eevee.shadow_method = SHADOW_ESM;
sce->eevee.shadow_cube_size = 512;
sce->eevee.shadow_cascade_size = 1024;
@@ -972,7 +971,7 @@ void BKE_scene_init(Scene *sce)
sce->eevee.flag = SCE_EEVEE_VOLUMETRIC_LIGHTS | SCE_EEVEE_GTAO_BENT_NORMALS |
SCE_EEVEE_GTAO_BOUNCE | SCE_EEVEE_TAA_REPROJECTION |
- SCE_EEVEE_SSR_HALF_RESOLUTION;
+ SCE_EEVEE_SSR_HALF_RESOLUTION | SCE_EEVEE_SHADOW_SOFT;
}
Scene *BKE_scene_add(Main *bmain, const char *name)
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index a735b399ce3..54d2bd8499f 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -1854,7 +1854,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
EEVEE_GET_BOOL(props, shadow_high_bitdepth, SCE_EEVEE_SHADOW_HIGH_BITDEPTH);
EEVEE_GET_BOOL(props, taa_reprojection, SCE_EEVEE_TAA_REPROJECTION);
// EEVEE_GET_BOOL(props, sss_enable, SCE_EEVEE_SSS_ENABLED);
- EEVEE_GET_BOOL(props, sss_separate_albedo, SCE_EEVEE_SSS_SEPARATE_ALBEDO);
+ // EEVEE_GET_BOOL(props, sss_separate_albedo, SCE_EEVEE_SSS_SEPARATE_ALBEDO);
EEVEE_GET_BOOL(props, ssr_enable, SCE_EEVEE_SSR_ENABLED);
EEVEE_GET_BOOL(props, ssr_refraction, SCE_EEVEE_SSR_REFRACTION);
EEVEE_GET_BOOL(props, ssr_halfres, SCE_EEVEE_SSR_HALF_RESOLUTION);
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index fa22fd46068..657e79f718a 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -265,6 +265,9 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene)
/* Change default cubemap quality. */
scene->eevee.gi_filter_quality = 3.0f;
+ /* Enable Soft Shadows by default. */
+ scene->eevee.flag |= SCE_EEVEE_SHADOW_SOFT;
+
/* Be sure curfalloff and primitive are initializated */
ToolSettings *ts = scene->toolsettings;
if (ts->gp_sculpt.cur_falloff == NULL) {
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 19ab96868ef..50851c41770 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -103,7 +103,11 @@ set(SRC
engines/eevee/eevee_occlusion.c
engines/eevee/eevee_render.c
engines/eevee/eevee_screen_raytrace.c
+ engines/eevee/eevee_sampling.c
engines/eevee/eevee_shaders.c
+ engines/eevee/eevee_shadows.c
+ engines/eevee/eevee_shadows_cube.c
+ engines/eevee/eevee_shadows_cascade.c
engines/eevee/eevee_subsurface.c
engines/eevee/eevee_temporal_sampling.c
engines/eevee/eevee_volumes.c
@@ -201,6 +205,7 @@ data_to_c_simple(engines/eevee/shaders/effect_mist_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_motion_blur_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_ssr_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_subsurface_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/effect_translucency_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_temporal_aa.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lightprobe_planar_downsample_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl SRC)
@@ -209,10 +214,6 @@ data_to_c_simple(engines/eevee/shaders/prepass_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/prepass_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/shadow_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/shadow_vert.glsl SRC)
-data_to_c_simple(engines/eevee/shaders/shadow_process_vert.glsl SRC)
-data_to_c_simple(engines/eevee/shaders/shadow_process_geom.glsl SRC)
-data_to_c_simple(engines/eevee/shaders/shadow_store_frag.glsl SRC)
-data_to_c_simple(engines/eevee/shaders/shadow_copy_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/bsdf_lut_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/btdf_lut_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/bsdf_common_lib.glsl SRC)
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index b792f93ced2..dd70ee1bd4b 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -35,23 +35,13 @@ void EEVEE_view_layer_data_free(void *storage)
MEM_SAFE_FREE(sldata->lights);
DRW_UBO_FREE_SAFE(sldata->light_ubo);
DRW_UBO_FREE_SAFE(sldata->shadow_ubo);
- DRW_UBO_FREE_SAFE(sldata->shadow_render_ubo);
- GPU_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cube_target_fb);
- GPU_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cube_store_fb);
- GPU_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cube_copy_fb);
- GPU_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cascade_target_fb);
- GPU_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cascade_store_fb);
- GPU_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cascade_copy_fb);
- DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_target);
- DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_blur);
+ GPU_FRAMEBUFFER_FREE_SAFE(sldata->shadow_fb);
DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_pool);
- DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_target);
- DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_blur);
DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_pool);
- MEM_SAFE_FREE(sldata->shcasters_buffers[0].shadow_casters);
- MEM_SAFE_FREE(sldata->shcasters_buffers[0].flags);
- MEM_SAFE_FREE(sldata->shcasters_buffers[1].shadow_casters);
- MEM_SAFE_FREE(sldata->shcasters_buffers[1].flags);
+ for (int i = 0; i < 2; i++) {
+ MEM_SAFE_FREE(sldata->shcasters_buffers[i].bbox);
+ MEM_SAFE_FREE(sldata->shcasters_buffers[i].update);
+ }
if (sldata->fallback_lightcache) {
EEVEE_lightcache_free(sldata->fallback_lightcache);
@@ -153,7 +143,6 @@ static void eevee_light_data_init(DrawData *dd)
{
EEVEE_LightEngineData *led = (EEVEE_LightEngineData *)dd;
led->need_update = true;
- led->prev_cube_shadow_id = -1;
}
EEVEE_LightEngineData *EEVEE_light_data_get(Object *ob)
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index ab4eb7b8532..a1096390bce 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -84,7 +84,7 @@ static void eevee_engine_init(void *ved)
/* EEVEE_effects_init needs to go first for TAA */
EEVEE_effects_init(sldata, vedata, camera, false);
EEVEE_materials_init(sldata, stl, fbl);
- EEVEE_lights_init(sldata);
+ EEVEE_shadows_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
}
@@ -139,7 +139,7 @@ void EEVEE_cache_populate(void *vedata, Object *ob)
}
if (cast_shadow) {
- EEVEE_lights_cache_shcaster_object_add(sldata, ob);
+ EEVEE_shadows_caster_register(sldata, ob);
}
}
@@ -223,7 +223,7 @@ static void eevee_draw_background(void *vedata)
/* Refresh shadows */
DRW_stats_group_start("Shadows");
- EEVEE_draw_shadows(sldata, vedata, stl->effects->taa_view);
+ EEVEE_shadows_draw(sldata, vedata, stl->effects->taa_view);
DRW_stats_group_end();
if (((stl->effects->enabled_effects & EFFECT_TAA) != 0) &&
@@ -269,9 +269,7 @@ static void eevee_draw_background(void *vedata)
if (DRW_state_draw_background()) {
DRW_draw_pass(psl->background_pass);
}
- EEVEE_draw_default_passes(psl);
- DRW_draw_pass(psl->material_pass);
- DRW_draw_pass(psl->material_pass_cull);
+ EEVEE_materials_draw_opaque(sldata, psl);
EEVEE_subsurface_data_render(sldata, vedata);
DRW_stats_group_end();
@@ -368,11 +366,21 @@ static void eevee_draw_background(void *vedata)
}
break;
case 8:
- if (effects->sss_data) {
- DRW_transform_to_display(effects->sss_data, false, false);
+ if (effects->sss_irradiance) {
+ DRW_transform_to_display(effects->sss_irradiance, false, false);
}
break;
case 9:
+ if (effects->sss_radius) {
+ DRW_transform_to_display(effects->sss_radius, false, false);
+ }
+ break;
+ case 10:
+ if (effects->sss_albedo) {
+ DRW_transform_to_display(effects->sss_albedo, false, false);
+ }
+ break;
+ case 11:
if (effects->velocity_tx) {
DRW_transform_to_display(effects->velocity_tx, false, false);
}
@@ -467,7 +475,7 @@ static void eevee_engine_free(void)
EEVEE_depth_of_field_free();
EEVEE_effects_free();
EEVEE_lightprobes_free();
- EEVEE_lights_free();
+ EEVEE_shadows_free();
EEVEE_materials_free();
EEVEE_mist_free();
EEVEE_motion_blur_free();
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index 05aea652591..e32194a11de 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -743,7 +743,7 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb
EEVEE_effects_init(sldata, vedata, NULL, true);
EEVEE_materials_init(sldata, stl, fbl);
- EEVEE_lights_init(sldata);
+ EEVEE_shadows_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
EEVEE_effects_cache_init(sldata, vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 8b1309e8537..2d23359a175 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -904,7 +904,7 @@ static void lightbake_render_scene_face(int face, EEVEE_BakeRenderData *user_dat
struct GPUFrameBuffer **face_fb = user_data->face_fb;
/* Be sure that cascaded shadow maps are updated. */
- EEVEE_draw_shadows(sldata, user_data->vedata, views[face]);
+ EEVEE_shadows_draw(sldata, user_data->vedata, views[face]);
GPU_framebuffer_bind(face_fb[face]);
GPU_framebuffer_clear_depth(face_fb[face], 1.0f);
@@ -912,11 +912,9 @@ static void lightbake_render_scene_face(int face, EEVEE_BakeRenderData *user_dat
DRW_draw_pass(psl->depth_pass);
DRW_draw_pass(psl->depth_pass_cull);
DRW_draw_pass(psl->probe_background);
- DRW_draw_pass(psl->material_pass);
- DRW_draw_pass(psl->material_pass_cull);
+ EEVEE_materials_draw_opaque(sldata, psl);
DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
DRW_draw_pass(psl->sss_pass_cull);
- EEVEE_draw_default_passes(psl);
DRW_draw_pass(psl->transparent_pass);
}
@@ -964,7 +962,7 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us
DRW_stats_group_start("Planar Reflection");
/* Be sure that cascaded shadow maps are updated. */
- EEVEE_draw_shadows(sldata, vedata, stl->g_data->planar_views[layer]);
+ EEVEE_shadows_draw(sldata, vedata, stl->g_data->planar_views[layer]);
GPU_framebuffer_bind(fbl->planarref_fb);
GPU_framebuffer_clear_depth(fbl->planarref_fb, 1.0);
@@ -987,9 +985,7 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us
GPU_framebuffer_bind(fbl->planarref_fb);
/* Shading pass */
- EEVEE_draw_default_passes(psl);
- DRW_draw_pass(psl->material_pass);
- DRW_draw_pass(psl->material_pass_cull);
+ EEVEE_materials_draw_opaque(sldata, psl);
DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
DRW_draw_pass(psl->sss_pass_cull);
DRW_draw_pass(psl->refract_pass);
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index 0bfc23b8354..126ec8d81c4 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -20,11 +20,7 @@
* \ingroup DNA
*/
-#include "DRW_render.h"
-
-#include "BLI_dynstr.h"
-#include "BLI_rand.h"
-#include "BLI_rect.h"
+#include "BLI_sys_types.h" /* bool */
#include "BKE_object.h"
@@ -32,623 +28,20 @@
#include "eevee_private.h"
-#define SHADOW_CASTER_ALLOC_CHUNK 16
-
-// #define DEBUG_CSM
-// #define DEBUG_SHADOW_DISTRIBUTION
-
-static struct {
- struct GPUShader *shadow_sh;
- struct GPUShader *shadow_store_cube_sh[SHADOW_METHOD_MAX];
- struct GPUShader *shadow_store_cube_high_sh[SHADOW_METHOD_MAX];
- struct GPUShader *shadow_store_cascade_sh[SHADOW_METHOD_MAX];
- struct GPUShader *shadow_store_cascade_high_sh[SHADOW_METHOD_MAX];
- struct GPUShader *shadow_copy_cube_sh[SHADOW_METHOD_MAX];
- struct GPUShader *shadow_copy_cascade_sh[SHADOW_METHOD_MAX];
-} e_data = {NULL}; /* Engine data */
-
-extern char datatoc_shadow_vert_glsl[];
-extern char datatoc_shadow_frag_glsl[];
-extern char datatoc_shadow_process_vert_glsl[];
-extern char datatoc_shadow_process_geom_glsl[];
-extern char datatoc_shadow_store_frag_glsl[];
-extern char datatoc_shadow_copy_frag_glsl[];
-extern char datatoc_concentric_samples_lib_glsl[];
-
-extern char datatoc_common_view_lib_glsl[];
-
-/* Prototypes */
-static void eevee_light_setup(Object *ob, EEVEE_Light *evli);
-static float light_attenuation_radius_get(Light *la, float light_threshold);
-
-/* *********** LIGHT BITS *********** */
-static void lightbits_set_single(EEVEE_LightBits *bitf, uint idx, bool val)
-{
- if (val) {
- bitf->fields[idx / 8] |= (1 << (idx % 8));
- }
- else {
- bitf->fields[idx / 8] &= ~(1 << (idx % 8));
- }
-}
-
-static void lightbits_set_all(EEVEE_LightBits *bitf, bool val)
-{
- memset(bitf, (val) ? 0xFF : 0x00, sizeof(EEVEE_LightBits));
-}
-
-static void lightbits_or(EEVEE_LightBits *r, const EEVEE_LightBits *v)
-{
- for (int i = 0; i < MAX_LIGHTBITS_FIELDS; ++i) {
- r->fields[i] |= v->fields[i];
- }
-}
-
-static bool lightbits_get(const EEVEE_LightBits *r, uint idx)
-{
- return r->fields[idx / 8] & (1 << (idx % 8));
-}
-
-static void lightbits_convert(EEVEE_LightBits *r,
- const EEVEE_LightBits *bitf,
- const int *light_bit_conv_table,
- uint table_length)
-{
- for (int i = 0; i < table_length; ++i) {
- if (lightbits_get(bitf, i) != 0) {
- if (light_bit_conv_table[i] >= 0) {
- r->fields[i / 8] |= (1 << (i % 8));
- }
- }
- }
-}
-
-/* *********** FUNCTIONS *********** */
-
-void EEVEE_lights_init(EEVEE_ViewLayerData *sldata)
-{
- const uint shadow_ubo_size = sizeof(EEVEE_Shadow) * MAX_SHADOW +
- sizeof(EEVEE_ShadowCube) * MAX_SHADOW_CUBE +
- sizeof(EEVEE_ShadowCascade) * MAX_SHADOW_CASCADE;
-
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
-
- if (!e_data.shadow_sh) {
- e_data.shadow_sh = DRW_shader_create_with_lib(datatoc_shadow_vert_glsl,
- NULL,
- datatoc_shadow_frag_glsl,
- datatoc_common_view_lib_glsl,
- NULL);
- }
-
- if (!sldata->lights) {
- sldata->lights = MEM_callocN(sizeof(EEVEE_LightsInfo), "EEVEE_LightsInfo");
- sldata->light_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_Light) * MAX_LIGHT, NULL);
- sldata->shadow_ubo = DRW_uniformbuffer_create(shadow_ubo_size, NULL);
- sldata->shadow_render_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_ShadowRender), NULL);
-
- for (int i = 0; i < 2; ++i) {
- sldata->shcasters_buffers[i].shadow_casters = MEM_callocN(
- sizeof(EEVEE_ShadowCaster) * SHADOW_CASTER_ALLOC_CHUNK, "EEVEE_ShadowCaster buf");
- sldata->shcasters_buffers[i].flags = MEM_callocN(sizeof(sldata->shcasters_buffers[0].flags) *
- SHADOW_CASTER_ALLOC_CHUNK,
- "EEVEE_shcast_buffer flags buf");
- sldata->shcasters_buffers[i].alloc_count = SHADOW_CASTER_ALLOC_CHUNK;
- sldata->shcasters_buffers[i].count = 0;
- }
-
- sldata->lights->shcaster_frontbuffer = &sldata->shcasters_buffers[0];
- sldata->lights->shcaster_backbuffer = &sldata->shcasters_buffers[1];
- }
-
- /* Flip buffers */
- SWAP(EEVEE_ShadowCasterBuffer *,
- sldata->lights->shcaster_frontbuffer,
- sldata->lights->shcaster_backbuffer);
-
- const int sh_method = scene_eval->eevee.shadow_method;
- int sh_cube_size = scene_eval->eevee.shadow_cube_size;
- int sh_cascade_size = scene_eval->eevee.shadow_cascade_size;
- const bool sh_high_bitdepth = (scene_eval->eevee.flag & SCE_EEVEE_SHADOW_HIGH_BITDEPTH) != 0;
- sldata->lights->soft_shadows = (scene_eval->eevee.flag & SCE_EEVEE_SHADOW_SOFT) != 0;
-
- EEVEE_LightsInfo *linfo = sldata->lights;
- if ((linfo->shadow_cube_size != sh_cube_size) || (linfo->shadow_method != sh_method) ||
- (linfo->shadow_high_bitdepth != sh_high_bitdepth)) {
- BLI_assert((sh_cube_size > 0) && (sh_cube_size <= 4096));
- DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_pool);
- DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_target);
- DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_blur);
-
- /* Compute adequate size for the octahedral map. */
- linfo->shadow_cube_store_size = OCTAHEDRAL_SIZE_FROM_CUBESIZE(sh_cube_size);
-
- CLAMP(linfo->shadow_cube_store_size, 1, 4096);
- CLAMP(sh_cube_size, 1, 4096);
-
- linfo->shadow_render_data.cube_texel_size = 1.0f / sh_cube_size;
- }
-
- if ((linfo->shadow_cascade_size != sh_cascade_size) || (linfo->shadow_method != sh_method) ||
- (linfo->shadow_high_bitdepth != sh_high_bitdepth)) {
- BLI_assert((sh_cascade_size > 0) && (sh_cascade_size <= 4096));
- DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_pool);
- DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_target);
- DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_blur);
-
- CLAMP(sh_cascade_size, 1, 4096);
- }
-
- linfo->shadow_high_bitdepth = sh_high_bitdepth;
- linfo->shadow_method = sh_method;
- linfo->shadow_cube_size = sh_cube_size;
- linfo->shadow_cascade_size = sh_cascade_size;
-
- /* only compile the ones needed. reduce startup time. */
- if ((sh_method == SHADOW_ESM) && !e_data.shadow_copy_cube_sh[SHADOW_ESM]) {
- e_data.shadow_copy_cube_sh[SHADOW_ESM] = DRW_shader_create(datatoc_shadow_process_vert_glsl,
- datatoc_shadow_process_geom_glsl,
- datatoc_shadow_copy_frag_glsl,
- "#define ESM\n"
- "#define COPY\n");
- e_data.shadow_copy_cascade_sh[SHADOW_ESM] = DRW_shader_create(datatoc_shadow_process_vert_glsl,
- datatoc_shadow_process_geom_glsl,
- datatoc_shadow_copy_frag_glsl,
- "#define ESM\n"
- "#define COPY\n"
- "#define CSM\n");
- }
- else if ((sh_method == SHADOW_VSM) && !e_data.shadow_copy_cube_sh[SHADOW_VSM]) {
- e_data.shadow_copy_cube_sh[SHADOW_VSM] = DRW_shader_create(datatoc_shadow_process_vert_glsl,
- datatoc_shadow_process_geom_glsl,
- datatoc_shadow_copy_frag_glsl,
- "#define VSM\n"
- "#define COPY\n");
- e_data.shadow_copy_cascade_sh[SHADOW_VSM] = DRW_shader_create(datatoc_shadow_process_vert_glsl,
- datatoc_shadow_process_geom_glsl,
- datatoc_shadow_copy_frag_glsl,
- "#define VSM\n"
- "#define COPY\n"
- "#define CSM\n");
- }
-}
-
-static GPUShader *eevee_lights_get_store_sh(int shadow_method, bool high_blur, bool cascade)
-{
- GPUShader **shader;
-
- if (cascade) {
- shader = (high_blur) ? &e_data.shadow_store_cascade_high_sh[shadow_method] :
- &e_data.shadow_store_cascade_sh[shadow_method];
- }
- else {
- shader = (high_blur) ? &e_data.shadow_store_cube_high_sh[shadow_method] :
- &e_data.shadow_store_cube_sh[shadow_method];
- }
-
- if (*shader == NULL) {
- DynStr *ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, datatoc_concentric_samples_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_shadow_store_frag_glsl);
- char *store_shadow_shader_str = BLI_dynstr_get_cstring(ds_frag);
- BLI_dynstr_free(ds_frag);
-
- ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, (shadow_method == SHADOW_VSM) ? "#define VSM\n" : "#define ESM\n");
- if (high_blur) {
- BLI_dynstr_append(ds_frag, "#define HIGH_BLUR\n");
- }
- if (cascade) {
- BLI_dynstr_append(ds_frag, "#define CSM\n");
- }
- char *define_str = BLI_dynstr_get_cstring(ds_frag);
- BLI_dynstr_free(ds_frag);
-
- *shader = DRW_shader_create(datatoc_shadow_process_vert_glsl,
- datatoc_shadow_process_geom_glsl,
- store_shadow_shader_str,
- define_str);
-
- MEM_freeN(store_shadow_shader_str);
- MEM_freeN(define_str);
- }
-
- return *shader;
-}
-
-static DRWPass *eevee_lights_cube_store_pass_get(EEVEE_PassList *psl,
- EEVEE_ViewLayerData *sldata,
- int shadow_method,
- int shadow_samples_len)
-{
- bool high_blur = shadow_samples_len > 16;
- DRWPass **pass = (high_blur) ? &psl->shadow_cube_store_pass : &psl->shadow_cube_store_high_pass;
- if (*pass == NULL) {
- *pass = DRW_pass_create("Shadow Cube Storage Pass", DRW_STATE_WRITE_COLOR);
- GPUShader *shader = eevee_lights_get_store_sh(shadow_method, high_blur, false);
- DRWShadingGroup *grp = DRW_shgroup_create(shader, *pass);
- DRW_shgroup_uniform_texture_ref(grp, "shadowTexture", &sldata->shadow_cube_blur);
- DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
-
- DRW_shgroup_call_procedural_triangles(grp, NULL, 6);
- }
- return *pass;
-}
-
-static DRWPass *eevee_lights_cascade_store_pass_get(EEVEE_PassList *psl,
- EEVEE_ViewLayerData *sldata,
- int shadow_method,
- int shadow_samples_len)
-{
- bool high_blur = shadow_samples_len > 16;
- DRWPass **pass = (high_blur) ? &psl->shadow_cascade_store_pass :
- &psl->shadow_cascade_store_high_pass;
- if (*pass == NULL) {
- *pass = DRW_pass_create("Shadow Cascade Storage Pass", DRW_STATE_WRITE_COLOR);
- GPUShader *shader = eevee_lights_get_store_sh(shadow_method, high_blur, true);
- DRWShadingGroup *grp = DRW_shgroup_create(shader, *pass);
- DRW_shgroup_uniform_texture_ref(grp, "shadowTexture", &sldata->shadow_cascade_blur);
- DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
-
- DRW_shgroup_call_procedural_triangles(grp, NULL, MAX_CASCADE_NUM);
- }
- return *pass;
-}
-
-void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
-{
- EEVEE_LightsInfo *linfo = sldata->lights;
- EEVEE_StorageList *stl = vedata->stl;
- EEVEE_PassList *psl = vedata->psl;
-
- linfo->shcaster_frontbuffer->count = 0;
- linfo->num_light = 0;
- linfo->num_cube_layer = 0;
- linfo->num_cascade_layer = 0;
- linfo->gpu_cube_len = linfo->gpu_cascade_len = linfo->gpu_shadow_len = 0;
- linfo->cpu_cube_len = linfo->cpu_cascade_len = 0;
- memset(linfo->light_ref, 0, sizeof(linfo->light_ref));
- memset(linfo->shadow_cube_ref, 0, sizeof(linfo->shadow_cube_ref));
- memset(linfo->shadow_cascade_ref, 0, sizeof(linfo->shadow_cascade_ref));
- memset(linfo->new_shadow_id, -1, sizeof(linfo->new_shadow_id));
-
- /* Shadow Casters: Reset flags. */
- memset(linfo->shcaster_backbuffer->flags,
- (char)SHADOW_CASTER_PRUNED,
- linfo->shcaster_backbuffer->alloc_count);
- memset(linfo->shcaster_frontbuffer->flags, 0x00, linfo->shcaster_frontbuffer->alloc_count);
-
- psl->shadow_cube_store_pass = NULL;
- psl->shadow_cube_store_high_pass = NULL;
- psl->shadow_cascade_store_pass = NULL;
- psl->shadow_cascade_store_high_pass = NULL;
-
- {
- DRW_PASS_CREATE(psl->shadow_cube_copy_pass, DRW_STATE_WRITE_COLOR);
-
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.shadow_copy_cube_sh[linfo->shadow_method],
- psl->shadow_cube_copy_pass);
- DRW_shgroup_uniform_texture_ref(grp, "shadowTexture", &sldata->shadow_cube_target);
- DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
-
- DRW_shgroup_call_procedural_triangles(grp, NULL, 6);
- }
-
- {
- DRW_PASS_CREATE(psl->shadow_cascade_copy_pass, DRW_STATE_WRITE_COLOR);
-
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.shadow_copy_cascade_sh[linfo->shadow_method],
- psl->shadow_cascade_copy_pass);
- DRW_shgroup_uniform_texture_ref(grp, "shadowTexture", &sldata->shadow_cascade_target);
- DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
-
- DRW_shgroup_call_procedural_triangles(grp, NULL, MAX_CASCADE_NUM);
- }
-
- {
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
- DRW_PASS_CREATE(psl->shadow_pass, state);
-
- stl->g_data->shadow_shgrp = DRW_shgroup_create(e_data.shadow_sh, psl->shadow_pass);
- }
-}
-
-void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
+/* Reconstruct local obmat from EEVEE_light. (normalized) */
+void eevee_light_matrix_get(const EEVEE_Light *evli, float r_mat[4][4])
{
- EEVEE_LightsInfo *linfo = sldata->lights;
-
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const float threshold = draw_ctx->scene->eevee.light_threshold;
- /* Step 1 find all lights in the scene and setup them */
- if (linfo->num_light >= MAX_LIGHT) {
- printf("Too many lights in the scene !!!\n");
- }
- else {
- Light *la = (Light *)ob->data;
-
- /* Early out if light has no power. */
- if (la->energy == 0.0f || is_zero_v3(&la->r)) {
- return;
- }
-
- EEVEE_Light *evli = linfo->light_data + linfo->num_light;
- eevee_light_setup(ob, evli);
-
- /* We do not support shadowmaps for dupli lights. */
- if ((ob->base_flag & BASE_FROM_DUPLI) != 0) {
- linfo->num_light++;
- return;
- }
-
- EEVEE_LightEngineData *led = EEVEE_light_data_ensure(ob);
-
- /* Save previous shadow id. */
- int prev_cube_sh_id = led->prev_cube_shadow_id;
-
- /* Default light without shadows */
- led->data.ld.shadow_id = -1;
- led->prev_cube_shadow_id = -1;
-
- if (la->mode & LA_SHADOW) {
- if (la->type == LA_SUN) {
- int cascade_nbr = la->cascade_count;
-
- if ((linfo->gpu_cascade_len + 1) <= MAX_SHADOW_CASCADE) {
- /* Save Light object. */
- linfo->shadow_cascade_ref[linfo->cpu_cascade_len] = ob;
-
- /* Store indices. */
- EEVEE_ShadowCascadeData *data = &led->data.scad;
- data->shadow_id = linfo->gpu_shadow_len;
- data->cascade_id = linfo->gpu_cascade_len;
- data->layer_id = linfo->num_cascade_layer;
-
- /* Increment indices. */
- linfo->gpu_shadow_len += 1;
- linfo->gpu_cascade_len += 1;
- linfo->num_cascade_layer += cascade_nbr;
-
- linfo->cpu_cascade_len += 1;
- }
- }
- else if (la->type == LA_SPOT || la->type == LA_LOCAL || la->type == LA_AREA) {
- if ((linfo->gpu_cube_len + 1) <= MAX_SHADOW_CUBE) {
- /* Save Light object. */
- linfo->shadow_cube_ref[linfo->cpu_cube_len] = ob;
-
- /* For light update tracking. */
- if ((prev_cube_sh_id >= 0) && (prev_cube_sh_id < linfo->shcaster_backbuffer->count)) {
- linfo->new_shadow_id[prev_cube_sh_id] = linfo->cpu_cube_len;
- }
- led->prev_cube_shadow_id = linfo->cpu_cube_len;
-
- /* Saving light bounds for later. */
- BLI_assert(linfo->cpu_cube_len >= 0 && linfo->cpu_cube_len < MAX_LIGHT);
- copy_v3_v3(linfo->shadow_bounds[linfo->cpu_cube_len].center, ob->obmat[3]);
- linfo->shadow_bounds[linfo->cpu_cube_len].radius = light_attenuation_radius_get(
- la, threshold);
-
- EEVEE_ShadowCubeData *data = &led->data.scd;
- /* Store indices. */
- data->shadow_id = linfo->gpu_shadow_len;
- data->cube_id = linfo->gpu_cube_len;
- data->layer_id = linfo->num_cube_layer;
-
- /* Increment indices. */
- linfo->gpu_shadow_len += 1;
- linfo->gpu_cube_len += 1;
- linfo->num_cube_layer += 1;
-
- linfo->cpu_cube_len += 1;
- }
- }
- }
-
- led->data.ld.light_id = linfo->num_light;
- linfo->light_ref[linfo->num_light] = ob;
- linfo->num_light++;
- }
-}
-
-/* Add a shadow caster to the shadowpasses */
-void EEVEE_lights_cache_shcaster_add(EEVEE_ViewLayerData *UNUSED(sldata),
- EEVEE_StorageList *stl,
- struct GPUBatch *geom,
- Object *ob)
-{
- DRW_shgroup_call(stl->g_data->shadow_shgrp, geom, ob);
-}
-
-void EEVEE_lights_cache_shcaster_material_add(EEVEE_ViewLayerData *sldata,
- EEVEE_PassList *psl,
- struct GPUMaterial *gpumat,
- struct GPUBatch *geom,
- struct Object *ob,
- const float *alpha_threshold)
-{
- /* TODO / PERF : reuse the same shading group for objects with the same material */
- DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, psl->shadow_pass);
-
- if (grp == NULL) {
- return;
- }
-
- /* Grrr needed for correctness but not 99% of the time not needed.
- * TODO detect when needed? */
- DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_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);
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
-
- if (alpha_threshold != NULL) {
- DRW_shgroup_uniform_float(grp, "alphaThreshold", alpha_threshold, 1);
- }
-
- DRW_shgroup_call(grp, geom, ob);
+ copy_v3_v3(r_mat[0], evli->rightvec);
+ copy_v3_v3(r_mat[1], evli->upvec);
+ negate_v3_v3(r_mat[2], evli->forwardvec);
+ copy_v3_v3(r_mat[3], evli->position);
+ r_mat[0][3] = 0.0f;
+ r_mat[1][3] = 0.0f;
+ r_mat[2][3] = 0.0f;
+ r_mat[3][3] = 1.0f;
}
-/* Make that object update shadow casting lights inside its influence bounding box. */
-void EEVEE_lights_cache_shcaster_object_add(EEVEE_ViewLayerData *sldata, Object *ob)
-{
- if ((ob->base_flag & BASE_FROM_DUPLI) != 0) {
- /* TODO: Special case for dupli objects because we cannot save the object pointer. */
- return;
- }
-
- EEVEE_ObjectEngineData *oedata = EEVEE_object_data_ensure(ob);
- EEVEE_LightsInfo *linfo = sldata->lights;
- EEVEE_ShadowCasterBuffer *backbuffer = linfo->shcaster_backbuffer;
- EEVEE_ShadowCasterBuffer *frontbuffer = linfo->shcaster_frontbuffer;
- int past_id = oedata->shadow_caster_id;
-
- /* Update flags in backbuffer. */
- if (past_id > -1 && past_id < backbuffer->count) {
- backbuffer->flags[past_id] &= ~SHADOW_CASTER_PRUNED;
-
- if (oedata->need_update) {
- backbuffer->flags[past_id] |= SHADOW_CASTER_UPDATED;
- }
- }
-
- /* Update id. */
- oedata->shadow_caster_id = frontbuffer->count++;
-
- /* Make sure shadow_casters is big enough. */
- if (oedata->shadow_caster_id >= frontbuffer->alloc_count) {
- frontbuffer->alloc_count += SHADOW_CASTER_ALLOC_CHUNK;
- frontbuffer->shadow_casters = MEM_reallocN(
- frontbuffer->shadow_casters, sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count);
- frontbuffer->flags = MEM_reallocN(frontbuffer->flags,
- sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count);
- }
-
- EEVEE_ShadowCaster *shcaster = frontbuffer->shadow_casters + oedata->shadow_caster_id;
-
- if (oedata->need_update) {
- frontbuffer->flags[oedata->shadow_caster_id] = SHADOW_CASTER_UPDATED;
- }
-
- /* Update World AABB in frontbuffer. */
- BoundBox *bb = BKE_object_boundbox_get(ob);
- float min[3], max[3];
- INIT_MINMAX(min, max);
- for (int i = 0; i < 8; ++i) {
- float vec[3];
- copy_v3_v3(vec, bb->vec[i]);
- mul_m4_v3(ob->obmat, vec);
- minmax_v3v3_v3(min, max, vec);
- }
-
- EEVEE_BoundBox *aabb = &shcaster->bbox;
- add_v3_v3v3(aabb->center, min, max);
- mul_v3_fl(aabb->center, 0.5f);
- sub_v3_v3v3(aabb->halfdim, aabb->center, max);
-
- aabb->halfdim[0] = fabsf(aabb->halfdim[0]);
- aabb->halfdim[1] = fabsf(aabb->halfdim[1]);
- aabb->halfdim[2] = fabsf(aabb->halfdim[2]);
-
- oedata->need_update = false;
-}
-
-void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
-{
- EEVEE_LightsInfo *linfo = sldata->lights;
- eGPUTextureFormat shadow_pool_format = GPU_R32F;
-
- sldata->common_data.la_num_light = linfo->num_light;
-
- /* Setup enough layers. */
- /* Free textures if number mismatch. */
- if (linfo->num_cube_layer != linfo->cache_num_cube_layer) {
- DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_pool);
- linfo->cache_num_cube_layer = linfo->num_cube_layer;
- linfo->update_flag |= LIGHT_UPDATE_SHADOW_CUBE;
- }
-
- if (linfo->num_cascade_layer != linfo->cache_num_cascade_layer) {
- DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_pool);
- linfo->cache_num_cascade_layer = linfo->num_cascade_layer;
- }
-
- switch (linfo->shadow_method) {
- case SHADOW_ESM:
- shadow_pool_format = ((linfo->shadow_high_bitdepth) ? GPU_R32F : GPU_R16F);
- break;
- case SHADOW_VSM:
- shadow_pool_format = ((linfo->shadow_high_bitdepth) ? GPU_RG32F : GPU_RG16F);
- break;
- default:
- BLI_assert(!"Incorrect Shadow Method");
- break;
- }
-
- /* Cubemaps */
- if (!sldata->shadow_cube_target) {
- sldata->shadow_cube_target = DRW_texture_create_cube(
- linfo->shadow_cube_size, GPU_DEPTH_COMPONENT24, 0, NULL);
- sldata->shadow_cube_blur = DRW_texture_create_cube(
- linfo->shadow_cube_size, shadow_pool_format, DRW_TEX_FILTER, NULL);
- }
- GPU_framebuffer_ensure_config(
- &sldata->shadow_cube_copy_fb,
- {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(sldata->shadow_cube_blur)});
-
- if (!sldata->shadow_cube_pool) {
- sldata->shadow_cube_pool = DRW_texture_create_2d_array(linfo->shadow_cube_store_size,
- linfo->shadow_cube_store_size,
- max_ii(1, linfo->num_cube_layer),
- shadow_pool_format,
- DRW_TEX_FILTER,
- NULL);
- }
- GPU_framebuffer_ensure_config(&sldata->shadow_cube_target_fb,
- {GPU_ATTACHMENT_TEXTURE(sldata->shadow_cube_target)});
- GPU_framebuffer_ensure_config(
- &sldata->shadow_cube_store_fb,
- {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(sldata->shadow_cube_pool)});
-
- /* CSM */
- if (!sldata->shadow_cascade_target) {
- sldata->shadow_cascade_target = DRW_texture_create_2d_array(linfo->shadow_cascade_size,
- linfo->shadow_cascade_size,
- MAX_CASCADE_NUM,
- GPU_DEPTH_COMPONENT24,
- 0,
- NULL);
- sldata->shadow_cascade_blur = DRW_texture_create_2d_array(linfo->shadow_cascade_size,
- linfo->shadow_cascade_size,
- MAX_CASCADE_NUM,
- shadow_pool_format,
- DRW_TEX_FILTER,
- NULL);
- }
- GPU_framebuffer_ensure_config(
- &sldata->shadow_cascade_copy_fb,
- {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(sldata->shadow_cascade_blur)});
-
- if (!sldata->shadow_cascade_pool) {
- sldata->shadow_cascade_pool = DRW_texture_create_2d_array(linfo->shadow_cascade_size,
- linfo->shadow_cascade_size,
- max_ii(1, linfo->num_cascade_layer),
- shadow_pool_format,
- DRW_TEX_FILTER,
- NULL);
- }
- GPU_framebuffer_ensure_config(&sldata->shadow_cascade_target_fb,
- {GPU_ATTACHMENT_TEXTURE(sldata->shadow_cascade_target)});
- GPU_framebuffer_ensure_config(
- &sldata->shadow_cascade_store_fb,
- {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(sldata->shadow_cascade_pool)});
-
- /* Update Lights UBOs. */
- EEVEE_lights_update(sldata, vedata);
-}
-
-float light_attenuation_radius_get(Light *la, float light_threshold)
+static float light_attenuation_radius_get(const Light *la, float light_threshold)
{
if (la->mode & LA_CUSTOM_ATTENUATION) {
return la->att_dist;
@@ -664,7 +57,7 @@ float light_attenuation_radius_get(Light *la, float light_threshold)
return distance;
}
-static void light_shape_parameters_set(EEVEE_Light *evli, const Light *la, float scale[3])
+static void light_shape_parameters_set(EEVEE_Light *evli, const Light *la, const float scale[3])
{
if (la->type == LA_SPOT) {
/* Spot size & blend */
@@ -684,7 +77,7 @@ static void light_shape_parameters_set(EEVEE_Light *evli, const Light *la, float
}
}
else if (la->type == LA_SUN) {
- evli->radius = max_ff(0.001f, tanf(la->sun_angle / 2.0f));
+ evli->radius = max_ff(0.001f, tanf(min_ff(la->sun_angle, DEG2RADF(179.9f)) / 2.0f));
}
else {
evli->radius = max_ff(0.001f, la->area_size);
@@ -774,809 +167,54 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli)
mul_v3_fl(evli->color, power * la->energy);
/* No shadow by default */
- evli->shadowid = -1.0f;
-}
-
-/**
- * Special ball distribution:
- * Point are distributed in a way that when they are orthogonally
- * projected into any plane, the resulting distribution is (close to)
- * a uniform disc distribution.
- */
-static void sample_ball(int sample_ofs, float radius, float rsample[3])
-{
- double ht_point[3];
- double ht_offset[3] = {0.0, 0.0, 0.0};
- uint ht_primes[3] = {2, 3, 7};
-
- BLI_halton_3d(ht_primes, ht_offset, sample_ofs, ht_point);
-
- float omega = ht_point[1] * 2.0f * M_PI;
-
- rsample[2] = ht_point[0] * 2.0f - 1.0f; /* cos theta */
-
- float r = sqrtf(fmaxf(0.0f, 1.0f - rsample[2] * rsample[2])); /* sin theta */
-
- rsample[0] = r * cosf(omega);
- rsample[1] = r * sinf(omega);
-
- radius *= sqrt(sqrt(ht_point[2]));
- mul_v3_fl(rsample, radius);
-}
-
-static void sample_rectangle(
- int sample_ofs, float x_axis[3], float y_axis[3], float size_x, float size_y, float rsample[3])
-{
- double ht_point[2];
- double ht_offset[2] = {0.0, 0.0};
- uint ht_primes[2] = {2, 3};
-
- BLI_halton_2d(ht_primes, ht_offset, sample_ofs, ht_point);
-
- /* Change ditribution center to be 0,0 */
- ht_point[0] = (ht_point[0] > 0.5f) ? ht_point[0] - 1.0f : ht_point[0];
- ht_point[1] = (ht_point[1] > 0.5f) ? ht_point[1] - 1.0f : ht_point[1];
-
- zero_v3(rsample);
- madd_v3_v3fl(rsample, x_axis, (ht_point[0] * 2.0f) * size_x);
- madd_v3_v3fl(rsample, y_axis, (ht_point[1] * 2.0f) * size_y);
-}
-
-static void sample_ellipse(
- int sample_ofs, float x_axis[3], float y_axis[3], float size_x, float size_y, float rsample[3])
-{
- double ht_point[2];
- double ht_offset[2] = {0.0, 0.0};
- uint ht_primes[2] = {2, 3};
-
- BLI_halton_2d(ht_primes, ht_offset, sample_ofs, ht_point);
-
- /* Uniform disc sampling. */
- float omega = ht_point[1] * 2.0f * M_PI;
- float r = sqrtf(ht_point[0]);
- ht_point[0] = r * cosf(omega) * size_x;
- ht_point[1] = r * sinf(omega) * size_y;
-
- zero_v3(rsample);
- madd_v3_v3fl(rsample, x_axis, ht_point[0]);
- madd_v3_v3fl(rsample, y_axis, ht_point[1]);
-}
-
-static void shadow_cube_random_position_set(EEVEE_Light *evli,
- Light *la,
- int sample_ofs,
- float ws_sample_pos[3])
-{
- float jitter[3];
-
-#ifndef DEBUG_SHADOW_DISTRIBUTION
- int i = sample_ofs;
-#else
- for (int i = 0; i <= sample_ofs; ++i) {
-#endif
- switch (la->type) {
- case LA_AREA:
- if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_SQUARE)) {
- sample_rectangle(i, evli->rightvec, evli->upvec, evli->sizex, evli->sizey, jitter);
- }
- else {
- sample_ellipse(i, evli->rightvec, evli->upvec, evli->sizex, evli->sizey, jitter);
- }
- break;
- default:
- sample_ball(i, evli->radius, jitter);
- }
-#ifdef DEBUG_SHADOW_DISTRIBUTION
- float p[3];
- add_v3_v3v3(p, jitter, ws_sample_pos);
- DRW_debug_sphere(p, 0.01f, (float[4]){1.0f, (sample_ofs == i) ? 1.0f : 0.0f, 0.0f, 1.0f});
-}
-#endif
-add_v3_v3(ws_sample_pos, jitter);
-}
-
-static void eevee_shadow_cube_setup(Object *ob,
- EEVEE_LightsInfo *linfo,
- EEVEE_LightEngineData *led,
- int sample_ofs)
-{
- EEVEE_ShadowCubeData *sh_data = &led->data.scd;
- EEVEE_Light *evli = linfo->light_data + sh_data->light_id;
- EEVEE_Shadow *ubo_data = linfo->shadow_data + sh_data->shadow_id;
- EEVEE_ShadowCube *cube_data = linfo->shadow_cube_data + sh_data->cube_id;
- Light *la = (Light *)ob->data;
-
- copy_v3_v3(cube_data->position, ob->obmat[3]);
-
- if (linfo->soft_shadows) {
- shadow_cube_random_position_set(evli, la, sample_ofs, cube_data->position);
- }
-
- ubo_data->bias = 0.05f * la->bias;
- ubo_data->near = la->clipsta;
- ubo_data->far = 1.0f / (evli->invsqrdist * evli->invsqrdist);
- ubo_data->exp = (linfo->shadow_method == SHADOW_VSM) ? la->bleedbias : la->bleedexp;
-
- evli->shadowid = (float)(sh_data->shadow_id);
- ubo_data->shadow_start = (float)(sh_data->layer_id);
- ubo_data->data_start = (float)(sh_data->cube_id);
- ubo_data->shadow_blur = la->soft * 0.02f; /* Used by translucence shadowmap blur */
-
- ubo_data->contact_dist = (la->mode & LA_SHAD_CONTACT) ? la->contact_dist : 0.0f;
- ubo_data->contact_bias = 0.05f * la->contact_bias;
- ubo_data->contact_spread = la->contact_spread;
- ubo_data->contact_thickness = la->contact_thickness;
-}
-
-static void shadow_cascade_random_matrix_set(float mat[4][4], float radius, int sample_ofs)
-{
- float jitter[3];
-
-#ifndef DEBUG_SHADOW_DISTRIBUTION
- int i = sample_ofs;
-#else
- for (int i = 0; i <= sample_ofs; ++i) {
-#endif
- sample_ellipse(i, mat[0], mat[1], radius, radius, jitter);
-#ifdef DEBUG_SHADOW_DISTRIBUTION
- float p[3];
- add_v3_v3v3(p, jitter, mat[2]);
- DRW_debug_sphere(p, 0.01f, (float[4]){1.0f, (sample_ofs == i) ? 1.0f : 0.0f, 0.0f, 1.0f});
-}
-#endif
-
-add_v3_v3(mat[2], jitter);
-orthogonalize_m4(mat, 2);
-}
-
-#define LERP(t, a, b) ((a) + (t) * ((b) - (a)))
-
-static double round_to_digits(double value, int digits)
-{
- double factor = pow(10.0, digits - ceil(log10(fabs(value))));
- return round(value * factor) / factor;
-}
-
-static void frustum_min_bounding_sphere(const float corners[8][3],
- float r_center[3],
- float *r_radius)
-{
-#if 0 /* Simple solution but waste too much space. */
- float minvec[3], maxvec[3];
-
- /* compute the bounding box */
- INIT_MINMAX(minvec, maxvec);
- for (int i = 0; i < 8; ++i) {
- minmax_v3v3_v3(minvec, maxvec, corners[i]);
- }
-
- /* compute the bounding sphere of this box */
- r_radius = len_v3v3(minvec, maxvec) * 0.5f;
- add_v3_v3v3(r_center, minvec, maxvec);
- mul_v3_fl(r_center, 0.5f);
-#else
- /* Find averaged center. */
- zero_v3(r_center);
- for (int i = 0; i < 8; ++i) {
- add_v3_v3(r_center, corners[i]);
- }
- mul_v3_fl(r_center, 1.0f / 8.0f);
-
- /* Search the largest distance from the sphere center. */
- *r_radius = 0.0f;
- for (int i = 0; i < 8; ++i) {
- float rad = len_squared_v3v3(corners[i], r_center);
- if (rad > *r_radius) {
- *r_radius = rad;
- }
- }
-
- /* TODO try to reduce the radius further by moving the center.
- * Remember we need a __stable__ solution! */
-
- /* Try to reduce float imprecision leading to shimmering. */
- *r_radius = (float)round_to_digits(sqrtf(*r_radius), 3);
-#endif
-}
-
-static void eevee_shadow_cascade_setup(Object *ob,
- EEVEE_LightsInfo *linfo,
- EEVEE_LightEngineData *led,
- DRWView *view,
- float view_near,
- float view_far,
- int sample_ofs)
-{
- Light *la = (Light *)ob->data;
-
- /* Camera Matrices */
- float persinv[4][4], vp_projmat[4][4];
- DRW_view_persmat_get(view, persinv, true);
- DRW_view_winmat_get(view, vp_projmat, false);
- bool is_persp = DRW_view_is_persp_get(view);
-
- /* Lights Matrices */
- int cascade_nbr = la->cascade_count;
-
- EEVEE_ShadowCascadeData *sh_data = &led->data.scad;
- EEVEE_Light *evli = linfo->light_data + sh_data->light_id;
- EEVEE_Shadow *ubo_data = linfo->shadow_data + sh_data->shadow_id;
- EEVEE_ShadowCascade *cascade_data = linfo->shadow_cascade_data + sh_data->cascade_id;
-
- /* obmat = Object Space > World Space */
- /* viewmat = World Space > View Space */
- float(*viewmat)[4] = sh_data->viewmat;
-#if 0 /* done at culling time */
- normalize_m4_m4(viewmat, ob->obmat);
-#endif
-
- if (linfo->soft_shadows) {
- shadow_cascade_random_matrix_set(viewmat, evli->radius, sample_ofs);
- }
-
- copy_m4_m4(sh_data->viewinv, viewmat);
- invert_m4(viewmat);
-
- /* The technique consists into splitting
- * the view frustum into several sub-frustum
- * that are individually receiving one shadow map */
-
- float csm_start, csm_end;
-
- if (is_persp) {
- csm_start = view_near;
- csm_end = max_ff(view_far, -la->cascade_max_dist);
- /* Avoid artifacts */
- csm_end = min_ff(view_near, csm_end);
- }
- else {
- csm_start = -view_far;
- csm_end = view_far;
- }
-
- /* init near/far */
- for (int c = 0; c < MAX_CASCADE_NUM; ++c) {
- cascade_data->split_start[c] = csm_end;
- cascade_data->split_end[c] = csm_end;
- }
-
- /* Compute split planes */
- float splits_start_ndc[MAX_CASCADE_NUM];
- float splits_end_ndc[MAX_CASCADE_NUM];
-
- {
- /* Nearest plane */
- float p[4] = {1.0f, 1.0f, csm_start, 1.0f};
- /* TODO: we don't need full m4 multiply here */
- mul_m4_v4(vp_projmat, p);
- splits_start_ndc[0] = p[2];
- if (is_persp) {
- splits_start_ndc[0] /= p[3];
- }
- }
-
- {
- /* Farthest plane */
- float p[4] = {1.0f, 1.0f, csm_end, 1.0f};
- /* TODO: we don't need full m4 multiply here */
- mul_m4_v4(vp_projmat, p);
- splits_end_ndc[cascade_nbr - 1] = p[2];
- if (is_persp) {
- splits_end_ndc[cascade_nbr - 1] /= p[3];
- }
- }
-
- cascade_data->split_start[0] = csm_start;
- cascade_data->split_end[cascade_nbr - 1] = csm_end;
-
- for (int c = 1; c < cascade_nbr; ++c) {
- /* View Space */
- float linear_split = LERP(((float)(c) / (float)cascade_nbr), csm_start, csm_end);
- float exp_split = csm_start * powf(csm_end / csm_start, (float)(c) / (float)cascade_nbr);
-
- if (is_persp) {
- cascade_data->split_start[c] = LERP(la->cascade_exponent, linear_split, exp_split);
- }
- else {
- cascade_data->split_start[c] = linear_split;
- }
- cascade_data->split_end[c - 1] = cascade_data->split_start[c];
-
- /* Add some overlap for smooth transition */
- cascade_data->split_start[c] = LERP(la->cascade_fade,
- cascade_data->split_end[c - 1],
- (c > 1) ? cascade_data->split_end[c - 2] :
- cascade_data->split_start[0]);
-
- /* NDC Space */
- {
- float p[4] = {1.0f, 1.0f, cascade_data->split_start[c], 1.0f};
- /* TODO: we don't need full m4 multiply here */
- mul_m4_v4(vp_projmat, p);
- splits_start_ndc[c] = p[2];
-
- if (is_persp) {
- splits_start_ndc[c] /= p[3];
- }
- }
-
- {
- float p[4] = {1.0f, 1.0f, cascade_data->split_end[c - 1], 1.0f};
- /* TODO: we don't need full m4 multiply here */
- mul_m4_v4(vp_projmat, p);
- splits_end_ndc[c - 1] = p[2];
-
- if (is_persp) {
- splits_end_ndc[c - 1] /= p[3];
- }
- }
- }
-
- /* Set last cascade split fade distance into the first split_start. */
- float prev_split = (cascade_nbr > 1) ? cascade_data->split_end[cascade_nbr - 2] :
- cascade_data->split_start[0];
- cascade_data->split_start[0] = LERP(
- la->cascade_fade, cascade_data->split_end[cascade_nbr - 1], prev_split);
-
- /* For each cascade */
- for (int c = 0; c < cascade_nbr; ++c) {
- float(*projmat)[4] = sh_data->projmat[c];
- /* Given 8 frustum corners */
- float corners[8][3] = {
- /* Near Cap */
- {1.0f, -1.0f, splits_start_ndc[c]},
- {-1.0f, -1.0f, splits_start_ndc[c]},
- {-1.0f, 1.0f, splits_start_ndc[c]},
- {1.0f, 1.0f, splits_start_ndc[c]},
- /* Far Cap */
- {1.0f, -1.0f, splits_end_ndc[c]},
- {-1.0f, -1.0f, splits_end_ndc[c]},
- {-1.0f, 1.0f, splits_end_ndc[c]},
- {1.0f, 1.0f, splits_end_ndc[c]},
- };
-
- /* Transform them into world space */
- for (int i = 0; i < 8; ++i) {
- mul_project_m4_v3(persinv, corners[i]);
- }
-
- float center[3];
- frustum_min_bounding_sphere(corners, center, &(sh_data->radius[c]));
-
-#ifdef DEBUG_CSM
- float dbg_col[4] = {0.0f, 0.0f, 0.0f, 1.0f};
- if (c < 3) {
- dbg_col[c] = 1.0f;
- }
- DRW_debug_bbox((BoundBox *)&corners, dbg_col);
- DRW_debug_sphere(center, sh_data->radius[c], dbg_col);
-#endif
-
- /* Project into lightspace */
- mul_m4_v3(viewmat, center);
-
- /* Snap projection center to nearest texel to cancel shimmering. */
- float shadow_origin[2], shadow_texco[2];
- /* Light to texture space. */
- mul_v2_v2fl(shadow_origin, center, linfo->shadow_cascade_size / (2.0f * sh_data->radius[c]));
-
- /* Find the nearest texel. */
- shadow_texco[0] = roundf(shadow_origin[0]);
- shadow_texco[1] = roundf(shadow_origin[1]);
-
- /* Compute offset. */
- sub_v2_v2(shadow_texco, shadow_origin);
- /* Texture to light space. */
- mul_v2_fl(shadow_texco, (2.0f * sh_data->radius[c]) / linfo->shadow_cascade_size);
-
- /* Apply offset. */
- add_v2_v2(center, shadow_texco);
-
- /* Expand the projection to cover frustum range */
- rctf rect_cascade;
- BLI_rctf_init_pt_radius(&rect_cascade, center, sh_data->radius[c]);
- orthographic_m4(projmat,
- rect_cascade.xmin,
- rect_cascade.xmax,
- rect_cascade.ymin,
- rect_cascade.ymax,
- la->clipsta,
- la->clipend);
-
- mul_m4_m4m4(sh_data->viewprojmat[c], projmat, viewmat);
- mul_m4_m4m4(cascade_data->shadowmat[c], texcomat, sh_data->viewprojmat[c]);
-
-#ifdef DEBUG_CSM
- DRW_debug_m4_as_bbox(sh_data->viewprojmat[c], dbg_col, true);
-#endif
- }
-
- ubo_data->bias = 0.05f * la->bias;
- ubo_data->near = la->clipsta;
- ubo_data->far = la->clipend;
- ubo_data->exp = (linfo->shadow_method == SHADOW_VSM) ? la->bleedbias : la->bleedexp;
-
- evli->shadowid = (float)(sh_data->shadow_id);
- ubo_data->shadow_start = (float)(sh_data->layer_id);
- ubo_data->data_start = (float)(sh_data->cascade_id);
- ubo_data->shadow_blur = la->soft * 0.02f; /* Used by translucence shadowmap blur */
-
- ubo_data->contact_dist = (la->mode & LA_SHAD_CONTACT) ? la->contact_dist : 0.0f;
- ubo_data->contact_bias = 0.05f * la->contact_bias;
- ubo_data->contact_spread = la->contact_spread;
- ubo_data->contact_thickness = la->contact_thickness;
+ evli->shadow_id = -1.0f;
}
-/* Used for checking if object is inside the shadow volume. */
-static bool sphere_bbox_intersect(const EEVEE_BoundSphere *bs, const EEVEE_BoundBox *bb)
+void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
- /* We are testing using a rougher AABB vs AABB test instead of full AABB vs Sphere. */
- /* TODO test speed with AABB vs Sphere. */
- bool x = fabsf(bb->center[0] - bs->center[0]) <= (bb->halfdim[0] + bs->radius);
- bool y = fabsf(bb->center[1] - bs->center[1]) <= (bb->halfdim[1] + bs->radius);
- bool z = fabsf(bb->center[2] - bs->center[2]) <= (bb->halfdim[2] + bs->radius);
+ EEVEE_LightsInfo *linfo = sldata->lights;
+ linfo->num_light = 0;
- return x && y && z;
+ EEVEE_shadows_cache_init(sldata, vedata);
}
-void EEVEE_lights_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
{
- EEVEE_StorageList *stl = vedata->stl;
- EEVEE_EffectsInfo *effects = stl->effects;
EEVEE_LightsInfo *linfo = sldata->lights;
- Object *ob;
- int i;
- char *flag;
- EEVEE_ShadowCaster *shcaster;
- EEVEE_BoundSphere *bsphere;
- EEVEE_ShadowCasterBuffer *frontbuffer = linfo->shcaster_frontbuffer;
- EEVEE_ShadowCasterBuffer *backbuffer = linfo->shcaster_backbuffer;
-
- EEVEE_LightBits update_bits = {{0}};
- if ((linfo->update_flag & LIGHT_UPDATE_SHADOW_CUBE) != 0) {
- /* Update all lights. */
- lightbits_set_all(&update_bits, true);
- }
- else {
- /* Search for deleted shadow casters and if shcaster WAS in shadow radius. */
- /* No need to run this if we already update all lights. */
- EEVEE_LightBits past_bits = {{0}};
- EEVEE_LightBits curr_bits = {{0}};
- shcaster = backbuffer->shadow_casters;
- flag = backbuffer->flags;
- for (i = 0; i < backbuffer->count; ++i, ++flag, ++shcaster) {
- /* If the shadowcaster has been deleted or updated. */
- if (*flag != 0) {
- /* Add the lights that were intersecting with its BBox. */
- lightbits_or(&past_bits, &shcaster->bits);
- }
- }
- /* Convert old bits to new bits and add result to final update bits. */
- /* NOTE: This might be overkill since all lights are tagged to refresh if
- * the light count changes. */
- lightbits_convert(&curr_bits, &past_bits, linfo->new_shadow_id, MAX_LIGHT);
- lightbits_or(&update_bits, &curr_bits);
- }
-
- /* Search for updates in current shadow casters. */
- shcaster = frontbuffer->shadow_casters;
- flag = frontbuffer->flags;
- for (i = 0; i < frontbuffer->count; i++, flag++, shcaster++) {
- /* Run intersection checks to fill the bitfields. */
- bsphere = linfo->shadow_bounds;
- for (int j = 0; j < linfo->cpu_cube_len; j++, bsphere++) {
- bool iter = sphere_bbox_intersect(bsphere, &shcaster->bbox);
- lightbits_set_single(&shcaster->bits, j, iter);
- }
- /* Only add to final bits if objects has been updated. */
- if (*flag != 0) {
- lightbits_or(&update_bits, &shcaster->bits);
- }
- }
+ const Light *la = (Light *)ob->data;
- /* Setup shadow cube in UBO and tag for update if necessary. */
- for (i = 0; (i < MAX_SHADOW_CUBE) && (ob = linfo->shadow_cube_ref[i]); i++) {
- EEVEE_LightEngineData *led = EEVEE_light_data_ensure(ob);
-
- eevee_shadow_cube_setup(ob, linfo, led, effects->taa_current_sample - 1);
- if (lightbits_get(&update_bits, i) != 0 || linfo->soft_shadows) {
- led->need_update = true;
- }
+ if (linfo->num_light >= MAX_LIGHT) {
+ printf("Too many lights in the scene !!!\n");
+ return;
}
- /* Resize shcasters buffers if too big. */
- if (frontbuffer->alloc_count - frontbuffer->count > SHADOW_CASTER_ALLOC_CHUNK) {
- frontbuffer->alloc_count = (frontbuffer->count / SHADOW_CASTER_ALLOC_CHUNK) *
- SHADOW_CASTER_ALLOC_CHUNK;
- frontbuffer->alloc_count += (frontbuffer->count % SHADOW_CASTER_ALLOC_CHUNK != 0) ?
- SHADOW_CASTER_ALLOC_CHUNK :
- 0;
- frontbuffer->shadow_casters = MEM_reallocN(
- frontbuffer->shadow_casters, sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count);
- frontbuffer->flags = MEM_reallocN(frontbuffer->flags,
- sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count);
+ /* Early out if light has no power. */
+ if (la->energy == 0.0f || is_zero_v3(&la->r)) {
+ return;
}
-}
-
-static void eevee_ensure_cube_views(float near, float far, const float pos[3], DRWView *view[6])
-{
- float winmat[4][4], viewmat[4][4];
- perspective_m4(winmat, -near, near, -near, near, near, far);
- for (int i = 0; i < 6; i++) {
- unit_m4(viewmat);
- negate_v3_v3(viewmat[3], pos);
- mul_m4_m4m4(viewmat, cubefacemat[i], viewmat);
+ EEVEE_Light *evli = linfo->light_data + linfo->num_light;
+ eevee_light_setup(ob, evli);
- if (view[i] == NULL) {
- view[i] = DRW_view_create(viewmat, winmat, NULL, NULL, NULL);
+ if (la->mode & LA_SHADOW) {
+ if (la->type == LA_SUN) {
+ EEVEE_shadows_cascade_add(linfo, evli, ob);
}
- else {
- DRW_view_update(view[i], viewmat, winmat, NULL, NULL);
+ else if (ELEM(la->type, LA_SPOT, LA_LOCAL, LA_AREA)) {
+ EEVEE_shadows_cube_add(linfo, evli, ob);
}
}
-}
-static void eevee_ensure_cascade_views(EEVEE_ShadowCascadeData *cascade_data,
- int cascade_count,
- DRWView *view[4])
-{
- for (int i = 0; i < cascade_count; i++) {
- if (view[i] == NULL) {
- view[i] = DRW_view_create(cascade_data->viewmat, cascade_data->projmat[i], NULL, NULL, NULL);
- }
- else {
- DRW_view_update(view[i], cascade_data->viewmat, cascade_data->projmat[i], NULL, NULL);
- }
- }
+ linfo->num_light++;
}
-/* this refresh lights shadow buffers */
-void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, DRWView *view)
+void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
- EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
- EEVEE_EffectsInfo *effects = stl->effects;
- EEVEE_PrivateData *g_data = stl->g_data;
EEVEE_LightsInfo *linfo = sldata->lights;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const float light_threshold = draw_ctx->scene->eevee.light_threshold;
- Object *ob;
- int i;
-
- int saved_ray_type = sldata->common_data.ray_type;
-
- /* TODO: make it optional if we don't draw shadows. */
- sldata->common_data.ray_type = EEVEE_RAY_SHADOW;
- DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
-
- /* Precompute all shadow/view test before rendering and trashing the culling cache. */
- bool cube_visible[MAX_SHADOW_CUBE];
- for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
- Light *la = (Light *)ob->data;
- BoundSphere bsphere = {
- .center = {ob->obmat[3][0], ob->obmat[3][1], ob->obmat[3][2]},
- .radius = light_attenuation_radius_get(la, light_threshold),
- };
- cube_visible[i] = DRW_culling_sphere_test(view, &bsphere);
- }
-
- bool cascade_visible[MAX_SHADOW_CASCADE];
- for (i = 0; (ob = linfo->shadow_cascade_ref[i]) && (i < MAX_SHADOW_CASCADE); i++) {
- EEVEE_LightEngineData *led = EEVEE_light_data_get(ob);
- EEVEE_ShadowCascadeData *sh_data = &led->data.scad;
- float plane[4];
- normalize_m4_m4(sh_data->viewmat, ob->obmat);
- plane_from_point_normal_v3(plane, sh_data->viewmat[3], sh_data->viewmat[2]);
- /* TODO: check against near/far instead of "local Z = 0" plane.
- * Or even the cascades AABB. */
- cascade_visible[i] = DRW_culling_plane_test(view, plane);
- }
-
- /* Cube Shadow Maps */
- DRW_stats_group_start("Cube Shadow Maps");
- /* Render each shadow to one layer of the array */
- for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
- EEVEE_LightEngineData *led = EEVEE_light_data_ensure(ob);
- Light *la = (Light *)ob->data;
-
- if (!led->need_update || !cube_visible[i]) {
- continue;
- }
-
- EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
- EEVEE_ShadowCubeData *evscd = &led->data.scd;
- EEVEE_ShadowCube *cube_data = linfo->shadow_cube_data + evscd->cube_id;
-
- srd->clip_near = la->clipsta;
- srd->clip_far = light_attenuation_radius_get(la, light_threshold);
- srd->stored_texel_size = 1.0 / (float)linfo->shadow_cube_store_size;
- srd->exponent = la->bleedexp;
-
- eevee_ensure_cube_views(
- srd->clip_near, srd->clip_far, cube_data->position, g_data->cube_views);
-
- /* Render shadow cube */
- /* Render 6 faces separately: seems to be faster for the general case.
- * The only time it's more beneficial is when the CPU culling overhead
- * outweigh the instancing overhead. which is rarely the case. */
- for (int j = 0; j < 6; j++) {
- DRW_view_set_active(g_data->cube_views[j]);
-
- GPU_framebuffer_texture_cubeface_attach(
- sldata->shadow_cube_target_fb, sldata->shadow_cube_target, 0, j, 0);
- GPU_framebuffer_bind(sldata->shadow_cube_target_fb);
- GPU_framebuffer_clear_depth(sldata->shadow_cube_target_fb, 1.0f);
- DRW_draw_pass(psl->shadow_pass);
- }
-
- /* 0.001f is arbitrary, but it should be relatively small so that filter size is not too big.
- */
- float filter_texture_size = la->soft * 0.001f;
- float filter_pixel_size = ceil(filter_texture_size / srd->cube_texel_size);
-
- /* TODO: OPTI: Don't do this intermediate step if no filter is needed. */
- {
- srd->filter_size[0] = srd->cube_texel_size * ((filter_pixel_size > 1.0f) ? 1.5f : 0.0f);
- srd->view_count = 6;
- srd->base_id = 0;
- DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd);
-
- /* Copy using a small 3x3 box filter */
- GPU_framebuffer_bind(sldata->shadow_cube_copy_fb);
- DRW_draw_pass(psl->shadow_cube_copy_pass);
- }
- /* Push it to shadowmap array */
- {
- /* Adjust constants if concentric samples change. */
- const float max_filter_size = 7.5f;
- const float magic = 4.5f; /* Dunno why but that works. */
- const int max_sample = 256;
-
- if (filter_pixel_size > 2.0f) {
- srd->filter_size[0] = srd->cube_texel_size * max_filter_size * magic;
- filter_pixel_size = max_ff(0.0f, filter_pixel_size - 3.0f);
- /* Compute number of concentric samples. Depends directly on filter size. */
- float pix_size_sqr = filter_pixel_size * filter_pixel_size;
- srd->shadow_samples_len[0] = min_ii(
- max_sample, 4 + 8 * (int)filter_pixel_size + 4 * (int)(pix_size_sqr));
- }
- else {
- srd->filter_size[0] = 0.0f;
- srd->shadow_samples_len[0] = 4;
- }
- srd->view_count = 1;
- srd->base_id = evscd->layer_id;
- srd->shadow_samples_len_inv[0] = 1.0f / (float)srd->shadow_samples_len[0];
- DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd);
-
- DRWPass *store_pass = eevee_lights_cube_store_pass_get(
- psl, sldata, linfo->shadow_method, srd->shadow_samples_len[0]);
-
- GPU_framebuffer_bind(sldata->shadow_cube_store_fb);
- DRW_draw_pass(store_pass);
- }
-
- if (linfo->soft_shadows == false) {
- led->need_update = false;
- }
- }
- linfo->update_flag &= ~LIGHT_UPDATE_SHADOW_CUBE;
- DRW_stats_group_end();
-
- float near = DRW_view_near_distance_get(view);
- float far = DRW_view_far_distance_get(view);
-
- /* Cascaded Shadow Maps */
- DRW_stats_group_start("Cascaded Shadow Maps");
- for (i = 0; (ob = linfo->shadow_cascade_ref[i]) && (i < MAX_SHADOW_CASCADE); i++) {
- if (!cascade_visible[i]) {
- continue;
- }
-
- EEVEE_LightEngineData *led = EEVEE_light_data_ensure(ob);
- Light *la = (Light *)ob->data;
-
- EEVEE_ShadowCascadeData *evscd = &led->data.scad;
- EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
-
- srd->clip_near = la->clipsta;
- srd->clip_far = la->clipend;
- srd->view_count = la->cascade_count;
- srd->stored_texel_size = 1.0 / (float)linfo->shadow_cascade_size;
-
- DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data);
-
- eevee_shadow_cascade_setup(ob, linfo, led, view, near, far, effects->taa_current_sample - 1);
-
- /* Meh, Reusing the cube views. */
- BLI_assert(MAX_CASCADE_NUM <= 6);
- eevee_ensure_cascade_views(evscd, la->cascade_count, g_data->cube_views);
-
- /* Render shadow cascades */
- /* Render cascade separately: seems to be faster for the general case.
- * The only time it's more beneficial is when the CPU culling overhead
- * outweigh the instancing overhead. which is rarely the case. */
- for (int j = 0; j < la->cascade_count; j++) {
- DRW_view_set_active(g_data->cube_views[j]);
-
- GPU_framebuffer_texture_layer_attach(
- sldata->shadow_cascade_target_fb, sldata->shadow_cascade_target, 0, j, 0);
- GPU_framebuffer_bind(sldata->shadow_cascade_target_fb);
- GPU_framebuffer_clear_depth(sldata->shadow_cascade_target_fb, 1.0f);
- DRW_draw_pass(psl->shadow_pass);
- }
- /* Copy using a small 3x3 box filter */
- {
- /* NOTE: We always do it in the case of CSM because of artifacts in the farthest cascade. */
- copy_v4_fl(srd->filter_size, srd->stored_texel_size);
- srd->base_id = 0;
- DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd);
-
- GPU_framebuffer_bind(sldata->shadow_cascade_copy_fb);
- DRW_draw_pass(psl->shadow_cascade_copy_pass);
- }
- /* Push it to shadowmap array and blur more */
- {
- int max_pass_sample = 0;
-
- for (int j = 0; j < la->cascade_count; j++) {
- /* 0.01f factor to convert to percentage */
- float filter_texture_size = la->soft * 0.01f / evscd->radius[j];
- float filter_pixel_size = ceil(linfo->shadow_cascade_size * filter_texture_size);
- /* Adjust constants if concentric samples change. */
- const float max_filter_size = 7.5f;
- const float magic = 3.2f; /* Arbitrary: less banding */
- const int max_sample = 256;
-
- if (filter_pixel_size > 2.0f) {
- srd->filter_size[j] = srd->stored_texel_size * max_filter_size * magic;
- filter_pixel_size = max_ff(0.0f, filter_pixel_size - 3.0f);
- /* Compute number of concentric samples. Depends directly on filter size. */
- float pix_size_sqr = filter_pixel_size * filter_pixel_size;
- srd->shadow_samples_len[j] = min_ii(
- max_sample, 4 + 8 * (int)filter_pixel_size + 4 * (int)(pix_size_sqr));
- }
- else {
- srd->filter_size[j] = 0.0f;
- srd->shadow_samples_len[j] = 4;
- }
- srd->shadow_samples_len_inv[j] = 1.0f / (float)srd->shadow_samples_len[j];
- max_pass_sample = max_ii(max_pass_sample, srd->shadow_samples_len[j]);
- }
- srd->base_id = evscd->layer_id;
- DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd);
-
- /* XXX(fclem) this create drawcalls outside of cache generation. */
- DRWPass *store_pass = eevee_lights_cascade_store_pass_get(
- psl, sldata, linfo->shadow_method, max_pass_sample);
-
- GPU_framebuffer_bind(sldata->shadow_cascade_store_fb);
- DRW_draw_pass(store_pass);
- }
- }
-
- DRW_stats_group_end();
-
- DRW_view_set_active(view);
+ sldata->common_data.la_num_light = linfo->num_light;
DRW_uniformbuffer_update(sldata->light_ubo, &linfo->light_data);
- DRW_uniformbuffer_update(sldata->shadow_ubo, &linfo->shadow_data); /* Update all data at once */
-
- sldata->common_data.ray_type = saved_ray_type;
- DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
-}
-void EEVEE_lights_free(void)
-{
- DRW_SHADER_FREE_SAFE(e_data.shadow_sh);
- for (int i = 0; i < SHADOW_METHOD_MAX; ++i) {
- DRW_SHADER_FREE_SAFE(e_data.shadow_store_cube_sh[i]);
- DRW_SHADER_FREE_SAFE(e_data.shadow_store_cube_high_sh[i]);
- DRW_SHADER_FREE_SAFE(e_data.shadow_store_cascade_sh[i]);
- DRW_SHADER_FREE_SAFE(e_data.shadow_store_cascade_high_sh[i]);
- DRW_SHADER_FREE_SAFE(e_data.shadow_copy_cube_sh[i]);
- DRW_SHADER_FREE_SAFE(e_data.shadow_copy_cascade_sh[i]);
- }
+ EEVEE_shadows_update(sldata, vedata);
}
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 738745f3072..99bfba0d203 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -63,8 +63,6 @@ static struct {
struct GPUTexture *util_tex;
struct GPUTexture *noise_tex;
- struct GPUUniformBuffer *dummy_sss_profile;
-
uint sss_count;
float alpha_hash_offset;
@@ -273,21 +271,6 @@ struct GPUTexture *EEVEE_materials_get_util_tex(void)
return e_data.util_tex;
}
-static int eevee_material_shadow_option(int shadow_method)
-{
- switch (shadow_method) {
- case SHADOW_ESM:
- return VAR_MAT_ESM;
- case SHADOW_VSM:
- return VAR_MAT_VSM;
- default:
- BLI_assert(!"Incorrect Shadow Method");
- break;
- }
-
- return 0;
-}
-
static char *eevee_get_defines(int options)
{
char *str = NULL;
@@ -322,23 +305,8 @@ static char *eevee_get_defines(int options)
if ((options & VAR_MAT_REFRACT) != 0) {
BLI_dynstr_append(ds, "#define USE_REFRACTION\n");
}
- if ((options & VAR_MAT_SSSALBED) != 0) {
- BLI_dynstr_append(ds, "#define USE_SSS_ALBEDO\n");
- }
- if ((options & VAR_MAT_TRANSLUC) != 0) {
- BLI_dynstr_append(ds, "#define USE_TRANSLUCENCY\n");
- }
- if ((options & VAR_MAT_VSM) != 0) {
- BLI_dynstr_append(ds, "#define SHADOW_VSM\n");
- }
- if ((options & VAR_MAT_ESM) != 0) {
- BLI_dynstr_append(ds, "#define SHADOW_ESM\n");
- }
if ((options & VAR_MAT_LOOKDEV) != 0) {
- /* Auto config shadow method. Avoid more permutation. */
- BLI_assert((options & (VAR_MAT_VSM | VAR_MAT_ESM)) == 0);
BLI_dynstr_append(ds, "#define LOOKDEV\n");
- BLI_dynstr_append(ds, "#define SHADOW_ESM\n");
}
str = BLI_dynstr_get_cstring(ds);
@@ -435,11 +403,6 @@ static void create_default_shader(int options)
MEM_freeN(frag_str);
}
-static void eevee_init_dummys(void)
-{
- e_data.dummy_sss_profile = GPU_material_create_sss_profile_ubo();
-}
-
static void eevee_init_noise_texture(void)
{
e_data.noise_tex = DRW_texture_create_2d(64, 64, GPU_RGBA16F, 0, (float *)blue_noise);
@@ -631,7 +594,6 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
eevee_init_util_texture();
eevee_init_noise_texture();
- eevee_init_dummys();
}
if (!DRW_state_is_image_render() && ((stl->effects->enabled_effects & EFFECT_TAA) == 0)) {
@@ -731,22 +693,15 @@ struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, World *
struct GPUMaterial *EEVEE_material_mesh_get(struct Scene *scene,
Material *ma,
- EEVEE_Data *vedata,
+ EEVEE_Data *UNUSED(vedata),
bool use_blend,
- bool use_refract,
- bool use_translucency,
- int shadow_method)
+ bool use_refract)
{
- EEVEE_EffectsInfo *effects = vedata->stl->effects;
const void *engine = &DRW_engine_viewport_eevee_type;
int options = VAR_MAT_MESH;
SET_FLAG_FROM_TEST(options, use_blend, VAR_MAT_BLEND);
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);
-
- options |= eevee_material_shadow_option(shadow_method);
GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
if (mat) {
@@ -835,13 +790,11 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene,
return mat;
}
-struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma, int shadow_method)
+struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma)
{
const void *engine = &DRW_engine_viewport_eevee_type;
int options = VAR_MAT_MESH | VAR_MAT_HAIR;
- options |= eevee_material_shadow_option(shadow_method);
-
GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
if (mat) {
return mat;
@@ -872,8 +825,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create(EEVEE_ViewLaye
DRWPass *pass,
bool is_hair,
bool use_blend,
- bool use_ssr,
- int shadow_method)
+ bool use_ssr)
{
static int ssr_id;
ssr_id = (use_ssr) ? 1 : -1;
@@ -882,8 +834,6 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create(EEVEE_ViewLaye
SET_FLAG_FROM_TEST(options, is_hair, VAR_MAT_HAIR);
SET_FLAG_FROM_TEST(options, use_blend, VAR_MAT_BLEND);
- options |= eevee_material_shadow_option(shadow_method);
-
if (e_data.default_lit[options] == NULL) {
create_default_shader(options);
}
@@ -903,8 +853,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(EEVEE_ViewLayerDa
ParticleSystem *psys,
ModifierData *md,
bool is_hair,
- bool use_ssr,
- int shadow_method)
+ bool use_ssr)
{
static int ssr_id;
ssr_id = (use_ssr) ? 1 : -1;
@@ -916,8 +865,6 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(EEVEE_ViewLayerDa
SET_FLAG_FROM_TEST(options, is_hair, VAR_MAT_HAIR);
- options |= eevee_material_shadow_option(shadow_method);
-
if (e_data.default_lit[options] == NULL) {
create_default_shader(options);
}
@@ -1164,7 +1111,6 @@ static void material_opaque(Material *ma,
Scene *scene = draw_ctx->scene;
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
- EEVEE_LightsInfo *linfo = sldata->lights;
bool use_diffuse, use_glossy, use_refract;
float *color_p = &ma->r;
@@ -1186,11 +1132,8 @@ static void material_opaque(Material *ma,
*shgrp_depth_clip = emsg->depth_clip_grp;
/* This will have been created already, just perform a lookup. */
- *gpumat =
- (use_gpumat) ?
- EEVEE_material_mesh_get(
- scene, ma, vedata, false, use_ssrefract, use_translucency, linfo->shadow_method) :
- NULL;
+ *gpumat = (use_gpumat) ? EEVEE_material_mesh_get(scene, ma, vedata, false, use_ssrefract) :
+ NULL;
*gpumat_depth = (use_gpumat) ? EEVEE_material_mesh_depth_get(
scene, ma, (ma->blend_method == MA_BM_HASHED), false) :
NULL;
@@ -1203,8 +1146,7 @@ static void material_opaque(Material *ma,
static float half = 0.5f;
/* Shading */
- *gpumat = EEVEE_material_mesh_get(
- scene, ma, vedata, false, use_ssrefract, use_translucency, linfo->shadow_method);
+ *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, false, use_ssrefract);
eGPUMaterialStatus status_mat_surface = GPU_material_status(*gpumat);
@@ -1311,15 +1253,15 @@ static void material_opaque(Material *ma,
*gpumat, stl->effects->sss_sample_count, &sss_tex_profile);
if (sss_profile) {
- if (use_translucency) {
- DRW_shgroup_uniform_block(*shgrp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_texture(*shgrp, "sssTexProfile", sss_tex_profile);
- }
-
/* Limit of 8 bit stencil buffer. ID 255 is refraction. */
if (e_data.sss_count < 254) {
- DRW_shgroup_stencil_mask(*shgrp, e_data.sss_count + 1);
- EEVEE_subsurface_add_pass(sldata, vedata, e_data.sss_count + 1, sss_profile);
+ int sss_id = e_data.sss_count + 1;
+ DRW_shgroup_stencil_mask(*shgrp, sss_id);
+ EEVEE_subsurface_add_pass(sldata, vedata, sss_id, sss_profile);
+ if (use_translucency) {
+ EEVEE_subsurface_translucency_add_pass(
+ sldata, vedata, sss_id, sss_profile, sss_tex_profile);
+ }
e_data.sss_count++;
}
else {
@@ -1327,19 +1269,6 @@ static void material_opaque(Material *ma,
printf("Error: Too many different Subsurface shader in the scene.\n");
}
}
- else {
- if (use_translucency) {
- /* NOTE: This is a nasty workaround, because the sss profile might not have been
- * generated but the UBO is still declared in this case even if not used.
- * But rendering without a bound UBO might result in crashes on certain platform. */
- DRW_shgroup_uniform_block(*shgrp, "sssProfile", e_data.dummy_sss_profile);
- }
- }
- }
- else {
- if (use_translucency) {
- DRW_shgroup_uniform_block(*shgrp, "sssProfile", e_data.dummy_sss_profile);
- }
}
break;
}
@@ -1360,8 +1289,7 @@ static void material_opaque(Material *ma,
/* Fallback to default shader */
if (*shgrp == NULL) {
bool use_ssr = ((effects->enabled_effects & EFFECT_SSR) != 0);
- *shgrp = EEVEE_default_shading_group_get(
- sldata, vedata, NULL, NULL, NULL, false, use_ssr, linfo->shadow_method);
+ *shgrp = EEVEE_default_shading_group_get(sldata, vedata, NULL, NULL, NULL, false, use_ssr);
DRW_shgroup_uniform_vec3(*shgrp, "basecol", color_p, 1);
DRW_shgroup_uniform_float(*shgrp, "metallic", metal_p, 1);
DRW_shgroup_uniform_float(*shgrp, "specular", spec_p, 1);
@@ -1401,7 +1329,6 @@ static void material_transparent(Material *ma,
Scene *scene = draw_ctx->scene;
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
- EEVEE_LightsInfo *linfo = sldata->lights;
const bool do_cull = (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0;
const bool use_ssrefract = (((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) &&
@@ -1417,8 +1344,7 @@ static void material_transparent(Material *ma,
static float half = 0.5f;
/* Shading */
- *gpumat = EEVEE_material_mesh_get(
- scene, ma, vedata, true, use_ssrefract, false, linfo->shadow_method);
+ *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, true, use_ssrefract);
switch (GPU_material_status(*gpumat)) {
case GPU_MAT_SUCCESS: {
@@ -1461,7 +1387,7 @@ static void material_transparent(Material *ma,
/* Fallback to default shader */
if (*shgrp == NULL) {
*shgrp = EEVEE_default_shading_group_create(
- sldata, vedata, psl->transparent_pass, false, true, false, linfo->shadow_method);
+ sldata, vedata, psl->transparent_pass, false, true, false);
DRW_shgroup_uniform_vec3(*shgrp, "basecol", color_p, 1);
DRW_shgroup_uniform_float(*shgrp, "metallic", metal_p, 1);
DRW_shgroup_uniform_float(*shgrp, "specular", spec_p, 1);
@@ -1650,18 +1576,18 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
struct GPUMaterial *gpumat;
switch (ma_array[i]->blend_shadow) {
case MA_BS_SOLID:
- EEVEE_lights_cache_shcaster_add(sldata, stl, mat_geom[i], ob);
+ EEVEE_shadows_caster_add(sldata, stl, mat_geom[i], ob);
*cast_shadow = true;
break;
case MA_BS_CLIP:
gpumat = EEVEE_material_mesh_depth_get(scene, ma_array[i], false, true);
- EEVEE_lights_cache_shcaster_material_add(
+ EEVEE_shadows_caster_material_add(
sldata, psl, gpumat, mat_geom[i], ob, &ma_array[i]->alpha_threshold);
*cast_shadow = true;
break;
case MA_BS_HASHED:
gpumat = EEVEE_material_mesh_depth_get(scene, ma_array[i], true, true);
- EEVEE_lights_cache_shcaster_material_add(sldata, psl, gpumat, mat_geom[i], ob, NULL);
+ EEVEE_shadows_caster_material_add(sldata, psl, gpumat, mat_geom[i], ob, NULL);
*cast_shadow = true;
break;
case MA_BS_NONE:
@@ -1728,8 +1654,7 @@ void EEVEE_hair_cache_populate(EEVEE_Data *vedata,
static float half = 0.5f;
static float error_col[3] = {1.0f, 0.0f, 1.0f};
static float compile_col[3] = {0.5f, 0.5f, 0.5f};
- struct GPUMaterial *gpumat = EEVEE_material_hair_get(
- scene, ma, sldata->lights->shadow_method);
+ struct GPUMaterial *gpumat = EEVEE_material_hair_get(scene, ma);
switch (GPU_material_status(gpumat)) {
case GPU_MAT_SUCCESS: {
@@ -1774,8 +1699,7 @@ void EEVEE_hair_cache_populate(EEVEE_Data *vedata,
/* Fallback to default shader */
if (shgrp == NULL) {
- shgrp = EEVEE_default_shading_group_get(
- sldata, vedata, ob, psys, md, true, use_ssr, sldata->lights->shadow_method);
+ shgrp = EEVEE_default_shading_group_get(sldata, vedata, ob, psys, md, true, use_ssr);
DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1);
DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1);
DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1);
@@ -1819,14 +1743,16 @@ void EEVEE_materials_free(void)
DRW_SHADER_FREE_SAFE(e_data.update_noise_sh);
DRW_TEXTURE_FREE_SAFE(e_data.util_tex);
DRW_TEXTURE_FREE_SAFE(e_data.noise_tex);
- DRW_UBO_FREE_SAFE(e_data.dummy_sss_profile);
}
-void EEVEE_draw_default_passes(EEVEE_PassList *psl)
+void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_PassList *psl)
{
for (int i = 0; i < VAR_MAT_MAX; ++i) {
if (psl->default_pass[i]) {
DRW_draw_pass(psl->default_pass[i]);
}
}
+
+ DRW_draw_pass(psl->material_pass);
+ DRW_draw_pass(psl->material_pass_cull);
}
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index fefdaef970a..28a8983cfee 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -23,9 +23,12 @@
#ifndef __EEVEE_PRIVATE_H__
#define __EEVEE_PRIVATE_H__
+#include "DRW_render.h"
+
+#include "BLI_bitmap.h"
+
#include "DNA_lightprobe_types.h"
-struct EEVEE_BoundSphere;
struct EEVEE_ShadowCasterBuffer;
struct GPUFrameBuffer;
struct Object;
@@ -39,11 +42,13 @@ extern struct DrawEngineType draw_engine_eevee_type;
#define MAX_PLANAR 16 /* TODO : find size by dividing UBO max size by grid data size */
#define MAX_LIGHT 128 /* TODO : find size by dividing UBO max size by light data size */
#define MAX_CASCADE_NUM 4
-#define MAX_SHADOW 256 /* TODO : Make this depends on GL_MAX_ARRAY_TEXTURE_LAYERS */
+#define MAX_SHADOW 128 /* TODO : Make this depends on GL_MAX_ARRAY_TEXTURE_LAYERS */
#define MAX_SHADOW_CASCADE 8
#define MAX_SHADOW_CUBE (MAX_SHADOW - MAX_CASCADE_NUM * MAX_SHADOW_CASCADE)
#define MAX_BLOOM_STEP 16
+// #define DEBUG_SHADOW_DISTRIBUTION
+
/* Only define one of these. */
// #define IRRADIANCE_SH_L2
// #define IRRADIANCE_CUBEMAP
@@ -150,14 +155,12 @@ enum {
VAR_MAT_PROBE = (1 << 1),
VAR_MAT_HAIR = (1 << 2),
VAR_MAT_BLEND = (1 << 3),
- VAR_MAT_VSM = (1 << 4),
- VAR_MAT_ESM = (1 << 5),
- VAR_MAT_VOLUME = (1 << 6),
- VAR_MAT_LOOKDEV = (1 << 7),
+ VAR_MAT_VOLUME = (1 << 4),
+ VAR_MAT_LOOKDEV = (1 << 5),
/* Max number of variation */
/* IMPORTANT : Leave it last and set
* it's value accordingly. */
- VAR_MAT_MAX = (1 << 8),
+ VAR_MAT_MAX = (1 << 6),
/* These are options that are not counted in VAR_MAT_MAX
* because they are not cumulative with the others above. */
VAR_MAT_CLIP = (1 << 9),
@@ -165,8 +168,6 @@ enum {
VAR_MAT_MULT = (1 << 11),
VAR_MAT_SHADOW = (1 << 12),
VAR_MAT_REFRACT = (1 << 13),
- VAR_MAT_TRANSLUC = (1 << 15),
- VAR_MAT_SSSALBED = (1 << 16),
};
/* ************ PROBE UBO ************* */
@@ -190,10 +191,6 @@ typedef struct EEVEE_PlanarReflection {
/* --------------------------------------- */
-typedef struct EEVEE_BoundSphere {
- float center[3], radius;
-} EEVEE_BoundSphere;
-
typedef struct EEVEE_BoundBox {
float center[3], halfdim[3];
} EEVEE_BoundBox;
@@ -201,12 +198,6 @@ typedef struct EEVEE_BoundBox {
typedef struct EEVEE_PassList {
/* Shadows */
struct DRWPass *shadow_pass;
- struct DRWPass *shadow_cube_copy_pass;
- struct DRWPass *shadow_cube_store_pass;
- struct DRWPass *shadow_cube_store_high_pass;
- struct DRWPass *shadow_cascade_copy_pass;
- struct DRWPass *shadow_cascade_store_pass;
- struct DRWPass *shadow_cascade_store_high_pass;
/* Probes */
struct DRWPass *probe_background;
@@ -242,6 +233,7 @@ typedef struct EEVEE_PassList {
struct DRWPass *sss_blur_ps;
struct DRWPass *sss_resolve_ps;
struct DRWPass *sss_accum_ps;
+ struct DRWPass *sss_translucency_ps;
struct DRWPass *color_downsample_ps;
struct DRWPass *color_downsample_cube_ps;
struct DRWPass *velocity_resolve;
@@ -292,6 +284,7 @@ typedef struct EEVEE_FramebufferList {
struct GPUFrameBuffer *sss_blit_fb;
struct GPUFrameBuffer *sss_resolve_fb;
struct GPUFrameBuffer *sss_clear_fb;
+ struct GPUFrameBuffer *sss_translucency_fb;
struct GPUFrameBuffer *sss_accum_fb;
struct GPUFrameBuffer *dof_down_fb;
struct GPUFrameBuffer *dof_scatter_fb;
@@ -368,7 +361,7 @@ typedef struct EEVEE_StorageList {
typedef struct EEVEE_Light {
float position[3], invsqrdist;
float color[3], spec;
- float spotsize, spotblend, radius, shadowid;
+ float spotsize, spotblend, radius, shadow_id;
float rightvec[3], sizex;
float upvec[3], sizey;
float forwardvec[3], light_type;
@@ -378,13 +371,13 @@ typedef struct EEVEE_Light {
#define LAMPTYPE_AREA_ELLIPSE 100.0f
typedef struct EEVEE_Shadow {
- float near, far, bias, exp;
- float shadow_start, data_start, multi_shadow_count, shadow_blur;
+ float near, far, bias, type_data_id;
float contact_dist, contact_bias, contact_spread, contact_thickness;
} EEVEE_Shadow;
typedef struct EEVEE_ShadowCube {
- float position[3], pad;
+ float shadowmat[4][4];
+ float position[3], _pad0[1];
} EEVEE_ShadowCube;
typedef struct EEVEE_ShadowCascade {
@@ -392,42 +385,34 @@ typedef struct EEVEE_ShadowCascade {
float shadowmat[MAX_CASCADE_NUM][4][4];
float split_start[4];
float split_end[4];
+ float shadow_vec[3], tex_id;
} EEVEE_ShadowCascade;
-typedef struct EEVEE_ShadowRender {
- int shadow_samples_len[MAX_CASCADE_NUM];
- float shadow_samples_len_inv[MAX_CASCADE_NUM];
- float filter_size[MAX_CASCADE_NUM];
- int view_count;
- int base_id;
- float cube_texel_size;
- float stored_texel_size;
- float clip_near;
- float clip_far;
- float exponent;
- float pad;
-} EEVEE_ShadowRender;
+typedef struct EEVEE_ShadowCascadeRender {
+ /* World->Light->NDC : used for rendering the shadow map. */
+ float projmat[MAX_CASCADE_NUM][4][4];
+ float viewmat[4][4], viewinv[4][4];
+ float radius[MAX_CASCADE_NUM];
+ float cascade_max_dist;
+ float cascade_exponent;
+ float cascade_fade;
+ int cascade_count;
+} EEVEE_ShadowCascadeRender;
BLI_STATIC_ASSERT_ALIGN(EEVEE_Light, 16)
BLI_STATIC_ASSERT_ALIGN(EEVEE_Shadow, 16)
BLI_STATIC_ASSERT_ALIGN(EEVEE_ShadowCube, 16)
BLI_STATIC_ASSERT_ALIGN(EEVEE_ShadowCascade, 16)
-BLI_STATIC_ASSERT_ALIGN(EEVEE_ShadowRender, 16)
-
-/* This is just a really long bitflag with special function to access it. */
-#define MAX_LIGHTBITS_FIELDS (MAX_LIGHT / 8)
-typedef struct EEVEE_LightBits {
- uchar fields[MAX_LIGHTBITS_FIELDS];
-} EEVEE_LightBits;
-typedef struct EEVEE_ShadowCaster {
- struct EEVEE_LightBits bits;
- struct EEVEE_BoundBox bbox;
-} EEVEE_ShadowCaster;
+BLI_STATIC_ASSERT(sizeof(EEVEE_Shadow) * MAX_SHADOW +
+ sizeof(EEVEE_ShadowCascade) * MAX_SHADOW_CASCADE +
+ sizeof(EEVEE_ShadowCube) * MAX_SHADOW_CUBE <
+ 16384,
+ "Shadow UBO is too big!!!")
typedef struct EEVEE_ShadowCasterBuffer {
- struct EEVEE_ShadowCaster *shadow_casters;
- char *flags;
+ struct EEVEE_BoundBox *bbox;
+ BLI_bitmap *update;
uint alloc_count;
uint count;
} EEVEE_ShadowCasterBuffer;
@@ -437,42 +422,31 @@ typedef struct EEVEE_LightsInfo {
int num_light, cache_num_light;
int num_cube_layer, cache_num_cube_layer;
int num_cascade_layer, cache_num_cascade_layer;
- int gpu_cube_len, gpu_cascade_len, gpu_shadow_len;
- int cpu_cube_len, cpu_cascade_len;
- int update_flag;
- int shadow_cube_size, shadow_cascade_size, shadow_method;
+ int cube_len, cascade_len, shadow_len;
+ int shadow_cube_size, shadow_cascade_size;
bool shadow_high_bitdepth, soft_shadows;
- int shadow_cube_store_size;
- /* List of lights in the scene. */
- /* XXX This is fragile, can get out of sync quickly. */
- struct Object *light_ref[MAX_LIGHT];
- struct Object *shadow_cube_ref[MAX_SHADOW_CUBE];
- struct Object *shadow_cascade_ref[MAX_SHADOW_CASCADE];
/* UBO Storage : data used by UBO */
struct EEVEE_Light light_data[MAX_LIGHT];
- struct EEVEE_ShadowRender shadow_render_data;
struct EEVEE_Shadow shadow_data[MAX_SHADOW];
struct EEVEE_ShadowCube shadow_cube_data[MAX_SHADOW_CUBE];
struct EEVEE_ShadowCascade shadow_cascade_data[MAX_SHADOW_CASCADE];
+ /* Additionnal rendering info for cascade. */
+ struct EEVEE_ShadowCascadeRender shadow_cascade_render[MAX_SHADOW_CASCADE];
+ /* Back index in light_data. */
+ uchar shadow_cube_light_indices[MAX_SHADOW_CUBE];
+ uchar shadow_cascade_light_indices[MAX_SHADOW_CASCADE];
+ /* Update bitmap. */
+ BLI_bitmap sh_cube_update[BLI_BITMAP_SIZE(MAX_SHADOW_CUBE)];
/* Lights tracking */
- int new_shadow_id[MAX_LIGHT]; /* To be able to convert old bitfield to new bitfield */
- struct EEVEE_BoundSphere shadow_bounds[MAX_LIGHT]; /* Tightly packed light bounds */
- /* Pointers only. */
- struct EEVEE_ShadowCasterBuffer *shcaster_frontbuffer;
- struct EEVEE_ShadowCasterBuffer *shcaster_backbuffer;
+ struct BoundSphere shadow_bounds[MAX_LIGHT]; /* Tightly packed light bounds */
+ /* List of bbox and update bitmap. Double buffered. */
+ struct EEVEE_ShadowCasterBuffer *shcaster_frontbuffer, *shcaster_backbuffer;
+ /* AABB of all shadow casters combined. */
+ struct {
+ float min[3], max[3];
+ } shcaster_aabb;
} EEVEE_LightsInfo;
-/* EEVEE_LightsInfo->shadow_casters_flag */
-enum {
- SHADOW_CASTER_PRUNED = (1 << 0),
- SHADOW_CASTER_UPDATED = (1 << 1),
-};
-
-/* EEVEE_LightsInfo->update_flag */
-enum {
- LIGHT_UPDATE_SHADOW_CUBE = (1 << 0),
-};
-
/* ************ PROBE DATA ************* */
typedef struct EEVEE_LightProbeVisTest {
struct Collection *collection; /* Skip test if NULL */
@@ -552,8 +526,8 @@ typedef struct EEVEE_EffectsInfo {
bool swap_double_buffer;
/* SSSS */
int sss_sample_count;
- bool sss_separate_albedo;
- struct GPUTexture *sss_data; /* Textures from pool */
+ struct GPUTexture *sss_irradiance; /* Textures from pool */
+ struct GPUTexture *sss_radius;
struct GPUTexture *sss_albedo;
struct GPUTexture *sss_blur;
struct GPUTexture *sss_stencil;
@@ -711,20 +685,10 @@ typedef struct EEVEE_ViewLayerData {
struct GPUUniformBuffer *light_ubo;
struct GPUUniformBuffer *shadow_ubo;
- struct GPUUniformBuffer *shadow_render_ubo;
struct GPUUniformBuffer *shadow_samples_ubo;
- struct GPUFrameBuffer *shadow_cube_target_fb;
- struct GPUFrameBuffer *shadow_cube_store_fb;
- struct GPUFrameBuffer *shadow_cube_copy_fb;
- struct GPUFrameBuffer *shadow_cascade_target_fb;
- struct GPUFrameBuffer *shadow_cascade_store_fb;
- struct GPUFrameBuffer *shadow_cascade_copy_fb;
-
- struct GPUTexture *shadow_cube_target;
- struct GPUTexture *shadow_cube_blur;
- struct GPUTexture *shadow_cascade_target;
- struct GPUTexture *shadow_cascade_blur;
+ struct GPUFrameBuffer *shadow_fb;
+
struct GPUTexture *shadow_cube_pool;
struct GPUTexture *shadow_cascade_pool;
@@ -746,23 +710,6 @@ typedef struct EEVEE_ViewLayerData {
/* ************ OBJECT DATA ************ */
-typedef struct EEVEE_LightData {
- short light_id, shadow_id;
-} EEVEE_LightData;
-
-typedef struct EEVEE_ShadowCubeData {
- short light_id, shadow_id, cube_id, layer_id;
-} EEVEE_ShadowCubeData;
-
-typedef struct EEVEE_ShadowCascadeData {
- short light_id, shadow_id, cascade_id, layer_id;
- /* World->Light->NDC : used for rendering the shadow map. */
- float viewprojmat[MAX_CASCADE_NUM][4][4]; /* Could be removed. */
- float projmat[MAX_CASCADE_NUM][4][4];
- float viewmat[4][4], viewinv[4][4];
- float radius[MAX_CASCADE_NUM];
-} EEVEE_ShadowCascadeData;
-
/* These are the structs stored inside Objects.
* It works even if the object is in multiple layers
* because we don't get the same "Object *" for each layer. */
@@ -770,13 +717,6 @@ typedef struct EEVEE_LightEngineData {
DrawData dd;
bool need_update;
- /* This needs to be out of the union to avoid undefined behavior. */
- short prev_cube_shadow_id;
- union {
- struct EEVEE_LightData ld;
- struct EEVEE_ShadowCubeData scd;
- struct EEVEE_ShadowCascadeData scad;
- } data;
} EEVEE_LightEngineData;
typedef struct EEVEE_LightProbeEngineData {
@@ -895,43 +835,67 @@ void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
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_mesh_get(struct Scene *scene,
- Material *ma,
- EEVEE_Data *vedata,
- bool use_blend,
- bool use_refract,
- bool use_translucency,
- int shadow_method);
+struct GPUMaterial *EEVEE_material_mesh_get(
+ struct Scene *scene, Material *ma, EEVEE_Data *vedata, bool use_blend, bool use_refract);
struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material *ma);
struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene,
Material *ma,
bool use_hashed_alpha,
bool is_shadow);
-struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma, int shadow_method);
+struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma);
void EEVEE_materials_free(void);
-void EEVEE_draw_default_passes(EEVEE_PassList *psl);
+void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl);
void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const double offsets[3]);
void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_viewvecs)[4]);
/* eevee_lights.c */
-void EEVEE_lights_init(EEVEE_ViewLayerData *sldata);
+void eevee_light_matrix_get(const EEVEE_Light *evli, float r_mat[4][4]);
void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, struct Object *ob);
-void EEVEE_lights_cache_shcaster_add(EEVEE_ViewLayerData *sldata,
- EEVEE_StorageList *stl,
- struct GPUBatch *geom,
- Object *ob);
-void EEVEE_lights_cache_shcaster_material_add(EEVEE_ViewLayerData *sldata,
- EEVEE_PassList *psl,
- struct GPUMaterial *gpumat,
- struct GPUBatch *geom,
- struct Object *ob,
- const float *alpha_threshold);
-void EEVEE_lights_cache_shcaster_object_add(EEVEE_ViewLayerData *sldata, struct Object *ob);
void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-void EEVEE_lights_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, struct DRWView *view);
-void EEVEE_lights_free(void);
+
+/* eevee_shadows.c */
+void eevee_contact_shadow_setup(const Light *la, EEVEE_Shadow *evsh);
+void EEVEE_shadows_init(EEVEE_ViewLayerData *sldata);
+void EEVEE_shadows_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_shadows_caster_add(EEVEE_ViewLayerData *sldata,
+ EEVEE_StorageList *stl,
+ struct GPUBatch *geom,
+ Object *ob);
+void EEVEE_shadows_caster_material_add(EEVEE_ViewLayerData *sldata,
+ EEVEE_PassList *psl,
+ struct GPUMaterial *gpumat,
+ struct GPUBatch *geom,
+ struct Object *ob,
+ const float *alpha_threshold);
+void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, struct Object *ob);
+void EEVEE_shadows_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_shadows_cube_add(EEVEE_LightsInfo *linfo, EEVEE_Light *evli, struct Object *ob);
+bool EEVEE_shadows_cube_setup(EEVEE_LightsInfo *linfo, const EEVEE_Light *evli, int sample_ofs);
+void EEVEE_shadows_cascade_add(EEVEE_LightsInfo *linfo, EEVEE_Light *evli, struct Object *ob);
+void EEVEE_shadows_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, struct DRWView *view);
+void EEVEE_shadows_draw_cubemap(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, int cube_index);
+void EEVEE_shadows_draw_cascades(EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
+ DRWView *view,
+ int cascade_index);
+void EEVEE_shadows_free(void);
+
+/* eevee_sampling.c */
+void EEVEE_sample_ball(int sample_ofs, float radius, float rsample[3]);
+void EEVEE_sample_rectangle(int sample_ofs,
+ const float x_axis[3],
+ const float y_axis[3],
+ float size_x,
+ float size_y,
+ float rsample[3]);
+void EEVEE_sample_ellipse(int sample_ofs,
+ const float x_axis[3],
+ const float y_axis[3],
+ float size_x,
+ float size_y,
+ float rsample[3]);
+void EEVEE_random_rotation_m4(int sample_ofs, float scale, float r_mat[4][4]);
/* eevee_shaders.c */
void EEVEE_shaders_lightprobe_shaders_init(void);
@@ -1044,6 +1008,11 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
EEVEE_Data *vedata,
uint sss_id,
struct GPUUniformBuffer *sss_profile);
+void EEVEE_subsurface_translucency_add_pass(EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
+ uint sss_id,
+ struct GPUUniformBuffer *sss_profile,
+ struct GPUTexture *sss_tex_profile);
void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index f840fa23bd2..da957239f42 100644
--- a/source/blender/draw/engines/eevee/eevee_render.c
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -133,7 +133,7 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
/* EEVEE_effects_init needs to go first for TAA */
EEVEE_effects_init(sldata, vedata, ob_camera_eval, false);
EEVEE_materials_init(sldata, stl, fbl);
- EEVEE_lights_init(sldata);
+ EEVEE_shadows_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
/* INIT CACHE */
@@ -198,7 +198,7 @@ void EEVEE_render_cache(void *vedata,
}
if (cast_shadow) {
- EEVEE_lights_cache_shcaster_object_add(sldata, ob);
+ EEVEE_shadows_caster_register(sldata, ob);
}
}
@@ -478,7 +478,8 @@ static void eevee_render_draw_background(EEVEE_Data *vedata)
GPU_ATTACHMENT_LEAVE,
GPU_ATTACHMENT_TEXTURE(stl->effects->ssr_normal_input),
GPU_ATTACHMENT_TEXTURE(stl->effects->ssr_specrough_input),
- GPU_ATTACHMENT_TEXTURE(stl->effects->sss_data),
+ GPU_ATTACHMENT_TEXTURE(stl->effects->sss_irradiance),
+ GPU_ATTACHMENT_TEXTURE(stl->effects->sss_radius),
GPU_ATTACHMENT_TEXTURE(stl->effects->sss_albedo)});
GPU_framebuffer_bind(fbl->main_fb);
}
@@ -582,8 +583,8 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
EEVEE_lightprobes_refresh_planar(sldata, vedata);
/* Refresh Shadows */
- EEVEE_lights_update(sldata, vedata);
- EEVEE_draw_shadows(sldata, vedata, stl->effects->taa_view);
+ EEVEE_shadows_update(sldata, vedata);
+ EEVEE_shadows_draw(sldata, vedata, stl->effects->taa_view);
/* Set matrices. */
DRW_view_set_active(stl->effects->taa_view);
@@ -605,9 +606,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
/* Shading pass */
eevee_render_draw_background(vedata);
GPU_framebuffer_bind(fbl->main_fb);
- EEVEE_draw_default_passes(psl);
- DRW_draw_pass(psl->material_pass);
- DRW_draw_pass(psl->material_pass_cull);
+ EEVEE_materials_draw_opaque(sldata, psl);
EEVEE_subsurface_data_render(sldata, vedata);
/* Effects pre-transparency */
EEVEE_subsurface_compute(sldata, vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_sampling.c b/source/blender/draw/engines/eevee/eevee_sampling.c
new file mode 100644
index 00000000000..9d91e000562
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_sampling.c
@@ -0,0 +1,111 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2019, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup EEVEE
+ */
+
+#include "eevee_private.h"
+
+#include "BLI_rand.h"
+
+/**
+ * Special ball distribution:
+ * Point are distributed in a way that when they are orthogonally
+ * projected into any plane, the resulting distribution is (close to)
+ * a uniform disc distribution.
+ */
+void EEVEE_sample_ball(int sample_ofs, float radius, float rsample[3])
+{
+ double ht_point[3];
+ double ht_offset[3] = {0.0, 0.0, 0.0};
+ uint ht_primes[3] = {2, 3, 7};
+
+ BLI_halton_3d(ht_primes, ht_offset, sample_ofs, ht_point);
+
+ float omega = ht_point[1] * 2.0f * M_PI;
+
+ rsample[2] = ht_point[0] * 2.0f - 1.0f; /* cos theta */
+
+ float r = sqrtf(fmaxf(0.0f, 1.0f - rsample[2] * rsample[2])); /* sin theta */
+
+ rsample[0] = r * cosf(omega);
+ rsample[1] = r * sinf(omega);
+
+ radius *= sqrt(sqrt(ht_point[2]));
+ mul_v3_fl(rsample, radius);
+}
+
+void EEVEE_sample_rectangle(int sample_ofs,
+ const float x_axis[3],
+ const float y_axis[3],
+ float size_x,
+ float size_y,
+ float rsample[3])
+{
+ double ht_point[2];
+ double ht_offset[2] = {0.0, 0.0};
+ uint ht_primes[2] = {2, 3};
+
+ BLI_halton_2d(ht_primes, ht_offset, sample_ofs, ht_point);
+
+ /* Change ditribution center to be 0,0 */
+ ht_point[0] = (ht_point[0] > 0.5f) ? ht_point[0] - 1.0f : ht_point[0];
+ ht_point[1] = (ht_point[1] > 0.5f) ? ht_point[1] - 1.0f : ht_point[1];
+
+ zero_v3(rsample);
+ madd_v3_v3fl(rsample, x_axis, (ht_point[0] * 2.0f) * size_x);
+ madd_v3_v3fl(rsample, y_axis, (ht_point[1] * 2.0f) * size_y);
+}
+
+void EEVEE_sample_ellipse(int sample_ofs,
+ const float x_axis[3],
+ const float y_axis[3],
+ float size_x,
+ float size_y,
+ float rsample[3])
+{
+ double ht_point[2];
+ double ht_offset[2] = {0.0, 0.0};
+ uint ht_primes[2] = {2, 3};
+
+ BLI_halton_2d(ht_primes, ht_offset, sample_ofs, ht_point);
+
+ /* Uniform disc sampling. */
+ float omega = ht_point[1] * 2.0f * M_PI;
+ float r = sqrtf(ht_point[0]);
+ ht_point[0] = r * cosf(omega) * size_x;
+ ht_point[1] = r * sinf(omega) * size_y;
+
+ zero_v3(rsample);
+ madd_v3_v3fl(rsample, x_axis, ht_point[0]);
+ madd_v3_v3fl(rsample, y_axis, ht_point[1]);
+}
+
+void EEVEE_random_rotation_m4(int sample_ofs, float scale, float r_mat[4][4])
+{
+ double ht_point[3];
+ double ht_offset[3] = {0.0, 0.0, 0.0};
+ uint ht_primes[3] = {2, 3, 5};
+
+ BLI_halton_3d(ht_primes, ht_offset, sample_ofs, ht_point);
+
+ rotate_m4(r_mat, 'X', ht_point[0] * scale);
+ rotate_m4(r_mat, 'Y', ht_point[1] * scale);
+ rotate_m4(r_mat, 'Z', ht_point[2] * scale);
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c
new file mode 100644
index 00000000000..a709e668f34
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_shadows.c
@@ -0,0 +1,412 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2019, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup EEVEE
+ */
+
+#include "BLI_sys_types.h" /* bool */
+
+// #include "BLI_dynstr.h"
+// #include "BLI_rand.h"
+
+#include "BKE_object.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "eevee_private.h"
+
+#define SH_CASTER_ALLOC_CHUNK 32
+
+static struct {
+ struct GPUShader *shadow_sh;
+} e_data = {NULL}; /* Engine data */
+
+extern char datatoc_shadow_vert_glsl[];
+extern char datatoc_shadow_frag_glsl[];
+extern char datatoc_common_view_lib_glsl[];
+
+void eevee_contact_shadow_setup(const Light *la, EEVEE_Shadow *evsh)
+{
+ evsh->contact_dist = (la->mode & LA_SHAD_CONTACT) ? la->contact_dist : 0.0f;
+ evsh->contact_bias = 0.05f * la->contact_bias;
+ evsh->contact_thickness = la->contact_thickness;
+}
+
+void EEVEE_shadows_init(EEVEE_ViewLayerData *sldata)
+{
+ const uint shadow_ubo_size = sizeof(EEVEE_Shadow) * MAX_SHADOW +
+ sizeof(EEVEE_ShadowCube) * MAX_SHADOW_CUBE +
+ sizeof(EEVEE_ShadowCascade) * MAX_SHADOW_CASCADE;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
+
+ if (!e_data.shadow_sh) {
+ e_data.shadow_sh = DRW_shader_create_with_lib(datatoc_shadow_vert_glsl,
+ NULL,
+ datatoc_shadow_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ NULL);
+ }
+
+ if (!sldata->lights) {
+ sldata->lights = MEM_callocN(sizeof(EEVEE_LightsInfo), "EEVEE_LightsInfo");
+ sldata->light_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_Light) * MAX_LIGHT, NULL);
+ sldata->shadow_ubo = DRW_uniformbuffer_create(shadow_ubo_size, NULL);
+
+ for (int i = 0; i < 2; ++i) {
+ sldata->shcasters_buffers[i].bbox = MEM_callocN(
+ sizeof(EEVEE_BoundBox) * SH_CASTER_ALLOC_CHUNK, __func__);
+ sldata->shcasters_buffers[i].update = BLI_BITMAP_NEW(SH_CASTER_ALLOC_CHUNK, __func__);
+ sldata->shcasters_buffers[i].alloc_count = SH_CASTER_ALLOC_CHUNK;
+ sldata->shcasters_buffers[i].count = 0;
+ }
+ sldata->lights->shcaster_frontbuffer = &sldata->shcasters_buffers[0];
+ sldata->lights->shcaster_backbuffer = &sldata->shcasters_buffers[1];
+ }
+
+ /* Flip buffers */
+ SWAP(EEVEE_ShadowCasterBuffer *,
+ sldata->lights->shcaster_frontbuffer,
+ sldata->lights->shcaster_backbuffer);
+
+ int sh_cube_size = scene_eval->eevee.shadow_cube_size;
+ int sh_cascade_size = scene_eval->eevee.shadow_cascade_size;
+ const bool sh_high_bitdepth = (scene_eval->eevee.flag & SCE_EEVEE_SHADOW_HIGH_BITDEPTH) != 0;
+ sldata->lights->soft_shadows = (scene_eval->eevee.flag & SCE_EEVEE_SHADOW_SOFT) != 0;
+
+ EEVEE_LightsInfo *linfo = sldata->lights;
+ if ((linfo->shadow_cube_size != sh_cube_size) ||
+ (linfo->shadow_high_bitdepth != sh_high_bitdepth)) {
+ BLI_assert((sh_cube_size > 0) && (sh_cube_size <= 4096));
+ DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_pool);
+ CLAMP(sh_cube_size, 1, 4096);
+ }
+
+ if ((linfo->shadow_cascade_size != sh_cascade_size) ||
+ (linfo->shadow_high_bitdepth != sh_high_bitdepth)) {
+ BLI_assert((sh_cascade_size > 0) && (sh_cascade_size <= 4096));
+ DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_pool);
+ CLAMP(sh_cascade_size, 1, 4096);
+ }
+
+ linfo->shadow_high_bitdepth = sh_high_bitdepth;
+ linfo->shadow_cube_size = sh_cube_size;
+ linfo->shadow_cascade_size = sh_cascade_size;
+}
+
+void EEVEE_shadows_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_LightsInfo *linfo = sldata->lights;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_PassList *psl = vedata->psl;
+
+ EEVEE_ShadowCasterBuffer *backbuffer = linfo->shcaster_backbuffer;
+ EEVEE_ShadowCasterBuffer *frontbuffer = linfo->shcaster_frontbuffer;
+
+ frontbuffer->count = 0;
+ linfo->num_cube_layer = 0;
+ linfo->num_cascade_layer = 0;
+ linfo->cube_len = linfo->cascade_len = linfo->shadow_len = 0;
+
+ /* Shadow Casters: Reset flags. */
+ BLI_bitmap_set_all(backbuffer->update, true, backbuffer->alloc_count);
+ /* Is this one needed? */
+ BLI_bitmap_set_all(frontbuffer->update, false, frontbuffer->alloc_count);
+
+ INIT_MINMAX(linfo->shcaster_aabb.min, linfo->shcaster_aabb.max);
+
+ {
+ DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_SHADOW_OFFSET;
+ DRW_PASS_CREATE(psl->shadow_pass, state);
+
+ stl->g_data->shadow_shgrp = DRW_shgroup_create(e_data.shadow_sh, psl->shadow_pass);
+ }
+}
+
+/* Add a shadow caster to the shadowpasses */
+void EEVEE_shadows_caster_add(EEVEE_ViewLayerData *UNUSED(sldata),
+ EEVEE_StorageList *stl,
+ struct GPUBatch *geom,
+ Object *ob)
+{
+ DRW_shgroup_call(stl->g_data->shadow_shgrp, geom, ob);
+}
+
+void EEVEE_shadows_caster_material_add(EEVEE_ViewLayerData *sldata,
+ EEVEE_PassList *psl,
+ struct GPUMaterial *gpumat,
+ struct GPUBatch *geom,
+ struct Object *ob,
+ const float *alpha_threshold)
+{
+ /* TODO / PERF : reuse the same shading group for objects with the same material */
+ DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, psl->shadow_pass);
+
+ if (grp == NULL) {
+ return;
+ }
+
+ /* Grrr needed for correctness but not 99% of the time not needed.
+ * TODO detect when needed? */
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_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);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+
+ if (alpha_threshold != NULL) {
+ DRW_shgroup_uniform_float(grp, "alphaThreshold", alpha_threshold, 1);
+ }
+
+ DRW_shgroup_call(grp, geom, ob);
+}
+
+/* Make that object update shadow casting lights inside its influence bounding box. */
+void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, Object *ob)
+{
+ EEVEE_LightsInfo *linfo = sldata->lights;
+ EEVEE_ShadowCasterBuffer *backbuffer = linfo->shcaster_backbuffer;
+ EEVEE_ShadowCasterBuffer *frontbuffer = linfo->shcaster_frontbuffer;
+ bool update = true;
+ int id = frontbuffer->count;
+
+ /* Make sure shadow_casters is big enough. */
+ if (id + 1 >= frontbuffer->alloc_count) {
+ frontbuffer->alloc_count += SH_CASTER_ALLOC_CHUNK;
+ frontbuffer->bbox = MEM_reallocN(frontbuffer->bbox,
+ sizeof(EEVEE_BoundBox) * frontbuffer->alloc_count);
+ BLI_BITMAP_RESIZE(frontbuffer->update, frontbuffer->alloc_count);
+ }
+
+ if (ob->base_flag & BASE_FROM_DUPLI) {
+ /* Duplis will always refresh the shadowmaps as if they were deleted each frame. */
+ /* TODO(fclem) fix this. */
+ update = true;
+ }
+ else {
+ EEVEE_ObjectEngineData *oedata = EEVEE_object_data_ensure(ob);
+ int past_id = oedata->shadow_caster_id;
+ oedata->shadow_caster_id = id;
+ /* Update flags in backbuffer. */
+ if (past_id > -1 && past_id < backbuffer->count) {
+ BLI_BITMAP_SET(backbuffer->update, past_id, oedata->need_update);
+ }
+ update = oedata->need_update;
+ oedata->need_update = false;
+ }
+
+ if (update) {
+ BLI_BITMAP_ENABLE(frontbuffer->update, id);
+ }
+
+ /* Update World AABB in frontbuffer. */
+ BoundBox *bb = BKE_object_boundbox_get(ob);
+ float min[3], max[3];
+ INIT_MINMAX(min, max);
+ for (int i = 0; i < 8; ++i) {
+ float vec[3];
+ copy_v3_v3(vec, bb->vec[i]);
+ mul_m4_v3(ob->obmat, vec);
+ minmax_v3v3_v3(min, max, vec);
+ }
+
+ EEVEE_BoundBox *aabb = &frontbuffer->bbox[id];
+ add_v3_v3v3(aabb->center, min, max);
+ mul_v3_fl(aabb->center, 0.5f);
+ sub_v3_v3v3(aabb->halfdim, aabb->center, max);
+
+ aabb->halfdim[0] = fabsf(aabb->halfdim[0]);
+ aabb->halfdim[1] = fabsf(aabb->halfdim[1]);
+ aabb->halfdim[2] = fabsf(aabb->halfdim[2]);
+
+ minmax_v3v3_v3(linfo->shcaster_aabb.min, linfo->shcaster_aabb.max, min);
+ minmax_v3v3_v3(linfo->shcaster_aabb.min, linfo->shcaster_aabb.max, max);
+
+ frontbuffer->count++;
+}
+
+/* Used for checking if object is inside the shadow volume. */
+static bool sphere_bbox_intersect(const BoundSphere *bs, const EEVEE_BoundBox *bb)
+{
+ /* We are testing using a rougher AABB vs AABB test instead of full AABB vs Sphere. */
+ /* TODO test speed with AABB vs Sphere. */
+ bool x = fabsf(bb->center[0] - bs->center[0]) <= (bb->halfdim[0] + bs->radius);
+ bool y = fabsf(bb->center[1] - bs->center[1]) <= (bb->halfdim[1] + bs->radius);
+ bool z = fabsf(bb->center[2] - bs->center[2]) <= (bb->halfdim[2] + bs->radius);
+
+ return x && y && z;
+}
+
+void EEVEE_shadows_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+ EEVEE_LightsInfo *linfo = sldata->lights;
+ EEVEE_ShadowCasterBuffer *backbuffer = linfo->shcaster_backbuffer;
+ EEVEE_ShadowCasterBuffer *frontbuffer = linfo->shcaster_frontbuffer;
+
+ eGPUTextureFormat shadow_pool_format = (linfo->shadow_high_bitdepth) ? GPU_DEPTH_COMPONENT24 :
+ GPU_DEPTH_COMPONENT16;
+ /* Setup enough layers. */
+ /* Free textures if number mismatch. */
+ if (linfo->num_cube_layer != linfo->cache_num_cube_layer) {
+ DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_pool);
+ linfo->cache_num_cube_layer = linfo->num_cube_layer;
+ /* Update all lights. */
+ BLI_bitmap_set_all(&linfo->sh_cube_update[0], true, MAX_LIGHT);
+ }
+
+ if (linfo->num_cascade_layer != linfo->cache_num_cascade_layer) {
+ DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_pool);
+ linfo->cache_num_cascade_layer = linfo->num_cascade_layer;
+ }
+
+ if (!sldata->shadow_cube_pool) {
+ /* TODO shadowcube array. */
+ int cube_size = linfo->shadow_cube_size + ((true) ? 2 : 0);
+ sldata->shadow_cube_pool = DRW_texture_create_2d_array(cube_size,
+ cube_size,
+ max_ii(1, linfo->num_cube_layer * 6),
+ shadow_pool_format,
+ DRW_TEX_FILTER | DRW_TEX_COMPARE,
+ NULL);
+ }
+
+ if (!sldata->shadow_cascade_pool) {
+ sldata->shadow_cascade_pool = DRW_texture_create_2d_array(linfo->shadow_cascade_size,
+ linfo->shadow_cascade_size,
+ max_ii(1, linfo->num_cascade_layer),
+ shadow_pool_format,
+ DRW_TEX_FILTER | DRW_TEX_COMPARE,
+ NULL);
+ }
+
+ if (sldata->shadow_fb == NULL) {
+ sldata->shadow_fb = GPU_framebuffer_create();
+ }
+
+ /* Gather all light own update bits. to avoid costly intersection check. */
+ for (int j = 0; j < linfo->cube_len; j++) {
+ const EEVEE_Light *evli = linfo->light_data + linfo->shadow_cube_light_indices[j];
+ /* Setup shadow cube in UBO and tag for update if necessary. */
+ if (EEVEE_shadows_cube_setup(linfo, evli, effects->taa_current_sample - 1)) {
+ BLI_BITMAP_ENABLE(&linfo->sh_cube_update[0], j);
+ }
+ }
+
+ /* TODO(fclem) This part can be slow, optimize it. */
+ EEVEE_BoundBox *bbox = backbuffer->bbox;
+ BoundSphere *bsphere = linfo->shadow_bounds;
+ /* Search for deleted shadow casters or if shcaster WAS in shadow radius. */
+ for (int i = 0; i < backbuffer->count; ++i) {
+ /* If the shadowcaster has been deleted or updated. */
+ if (BLI_BITMAP_TEST(backbuffer->update, i)) {
+ for (int j = 0; j < linfo->cube_len; j++) {
+ if (!BLI_BITMAP_TEST(&linfo->sh_cube_update[0], j)) {
+ if (sphere_bbox_intersect(&bsphere[j], &bbox[i])) {
+ BLI_BITMAP_ENABLE(&linfo->sh_cube_update[0], j);
+ }
+ }
+ }
+ }
+ }
+ /* Search for updates in current shadow casters. */
+ bbox = frontbuffer->bbox;
+ for (int i = 0; i < frontbuffer->count; i++) {
+ /* If the shadowcaster has been updated. */
+ if (BLI_BITMAP_TEST(frontbuffer->update, i)) {
+ for (int j = 0; j < linfo->cube_len; j++) {
+ if (!BLI_BITMAP_TEST(&linfo->sh_cube_update[0], j)) {
+ if (sphere_bbox_intersect(&bsphere[j], &bbox[i])) {
+ BLI_BITMAP_ENABLE(&linfo->sh_cube_update[0], j);
+ }
+ }
+ }
+ }
+ }
+
+ /* Resize shcasters buffers if too big. */
+ if (frontbuffer->alloc_count - frontbuffer->count > SH_CASTER_ALLOC_CHUNK) {
+ frontbuffer->alloc_count = (frontbuffer->count / SH_CASTER_ALLOC_CHUNK) *
+ SH_CASTER_ALLOC_CHUNK;
+ frontbuffer->alloc_count += (frontbuffer->count % SH_CASTER_ALLOC_CHUNK != 0) ?
+ SH_CASTER_ALLOC_CHUNK :
+ 0;
+ frontbuffer->bbox = MEM_reallocN(frontbuffer->bbox,
+ sizeof(EEVEE_BoundBox) * frontbuffer->alloc_count);
+ BLI_BITMAP_RESIZE(frontbuffer->update, frontbuffer->alloc_count);
+ }
+}
+
+/* this refresh lights shadow buffers */
+void EEVEE_shadows_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, DRWView *view)
+{
+ EEVEE_LightsInfo *linfo = sldata->lights;
+
+ int saved_ray_type = sldata->common_data.ray_type;
+
+ /* Precompute all shadow/view test before rendering and trashing the culling cache. */
+ BLI_bitmap *cube_visible = BLI_BITMAP_NEW_ALLOCA(MAX_SHADOW_CUBE);
+ bool any_visible = false;
+ for (int cube = 0; cube < linfo->cube_len; cube++) {
+ if (DRW_culling_sphere_test(view, linfo->shadow_bounds + cube)) {
+ BLI_BITMAP_ENABLE(cube_visible, cube);
+ any_visible = true;
+ }
+ }
+
+ if (!any_visible && linfo->cascade_len == 0) {
+ sldata->common_data.ray_type = EEVEE_RAY_SHADOW;
+ DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
+ }
+
+ DRW_stats_group_start("Cube Shadow Maps");
+ {
+ for (int cube = 0; cube < linfo->cube_len; cube++) {
+ if (BLI_BITMAP_TEST(cube_visible, cube) && BLI_BITMAP_TEST(linfo->sh_cube_update, cube)) {
+ EEVEE_shadows_draw_cubemap(sldata, vedata, cube);
+ }
+ }
+ }
+ DRW_stats_group_end();
+
+ DRW_stats_group_start("Cascaded Shadow Maps");
+ {
+ for (int cascade = 0; cascade < linfo->cascade_len; cascade++) {
+ EEVEE_shadows_draw_cascades(sldata, vedata, view, cascade);
+ }
+ }
+ DRW_stats_group_end();
+
+ DRW_view_set_active(view);
+
+ DRW_uniformbuffer_update(sldata->shadow_ubo, &linfo->shadow_data); /* Update all data at once */
+
+ if (!any_visible && linfo->cascade_len == 0) {
+ sldata->common_data.ray_type = saved_ray_type;
+ DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
+ }
+}
+
+void EEVEE_shadows_free(void)
+{
+ DRW_SHADER_FREE_SAFE(e_data.shadow_sh);
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/eevee_shadows_cascade.c b/source/blender/draw/engines/eevee/eevee_shadows_cascade.c
new file mode 100644
index 00000000000..d5e038f716c
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_shadows_cascade.c
@@ -0,0 +1,439 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2019, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup EEVEE
+ */
+
+#include "BLI_rect.h"
+#include "BLI_sys_types.h" /* bool */
+
+#include "BKE_object.h"
+
+#include "eevee_private.h"
+
+#include "BLI_rand.h" /* needs to be after for some reason. */
+
+void EEVEE_shadows_cascade_add(EEVEE_LightsInfo *linfo, EEVEE_Light *evli, Object *ob)
+{
+ if (linfo->cascade_len >= MAX_SHADOW_CASCADE) {
+ return;
+ }
+
+ const Light *la = (Light *)ob->data;
+ EEVEE_Shadow *sh_data = linfo->shadow_data + linfo->shadow_len;
+ EEVEE_ShadowCascade *csm_data = linfo->shadow_cascade_data + linfo->cascade_len;
+ EEVEE_ShadowCascadeRender *csm_render = linfo->shadow_cascade_render + linfo->cascade_len;
+
+ sh_data->bias = max_ff(la->bias * 0.00002f, 0.0f);
+ eevee_contact_shadow_setup(la, sh_data);
+
+ linfo->shadow_cascade_light_indices[linfo->cascade_len] = linfo->num_light;
+ evli->shadow_id = linfo->shadow_len++;
+ sh_data->type_data_id = linfo->cascade_len++;
+ csm_data->tex_id = linfo->num_cascade_layer;
+ csm_render->cascade_fade = la->cascade_fade;
+ csm_render->cascade_count = la->cascade_count;
+ csm_render->cascade_exponent = la->cascade_exponent;
+ csm_render->cascade_max_dist = la->cascade_max_dist;
+
+ linfo->num_cascade_layer += la->cascade_count;
+}
+
+static void shadow_cascade_random_matrix_set(float mat[4][4], float radius, int sample_ofs)
+{
+ float jitter[3];
+#ifndef DEBUG_SHADOW_DISTRIBUTION
+ EEVEE_sample_ellipse(sample_ofs, mat[0], mat[1], radius, radius, jitter);
+#else
+ for (int i = 0; i <= sample_ofs; ++i) {
+ EEVEE_sample_ellipse(i, mat[0], mat[1], radius, radius, jitter);
+ float p[3];
+ add_v3_v3v3(p, jitter, mat[2]);
+ DRW_debug_sphere(p, 0.01f, (float[4]){1.0f, (sample_ofs == i) ? 1.0f : 0.0f, 0.0f, 1.0f});
+ }
+#endif
+ add_v3_v3(mat[2], jitter);
+ orthogonalize_m4(mat, 2);
+}
+
+static double round_to_digits(double value, int digits)
+{
+ double factor = pow(10.0, digits - ceil(log10(fabs(value))));
+ return round(value * factor) / factor;
+}
+
+static void frustum_min_bounding_sphere(const float corners[8][3],
+ float r_center[3],
+ float *r_radius)
+{
+#if 0 /* Simple solution but waste too much space. */
+ float minvec[3], maxvec[3];
+
+ /* compute the bounding box */
+ INIT_MINMAX(minvec, maxvec);
+ for (int i = 0; i < 8; ++i) {
+ minmax_v3v3_v3(minvec, maxvec, corners[i]);
+ }
+
+ /* compute the bounding sphere of this box */
+ r_radius = len_v3v3(minvec, maxvec) * 0.5f;
+ add_v3_v3v3(r_center, minvec, maxvec);
+ mul_v3_fl(r_center, 0.5f);
+#else
+ /* Find averaged center. */
+ zero_v3(r_center);
+ for (int i = 0; i < 8; ++i) {
+ add_v3_v3(r_center, corners[i]);
+ }
+ mul_v3_fl(r_center, 1.0f / 8.0f);
+
+ /* Search the largest distance from the sphere center. */
+ *r_radius = 0.0f;
+ for (int i = 0; i < 8; ++i) {
+ float rad = len_squared_v3v3(corners[i], r_center);
+ if (rad > *r_radius) {
+ *r_radius = rad;
+ }
+ }
+
+ /* TODO try to reduce the radius further by moving the center.
+ * Remember we need a __stable__ solution! */
+
+ /* Try to reduce float imprecision leading to shimmering. */
+ *r_radius = (float)round_to_digits(sqrtf(*r_radius), 3);
+#endif
+}
+
+BLI_INLINE float lerp(float t, float a, float b)
+{
+ return ((a) + (t) * ((b) - (a)));
+}
+
+static void eevee_shadow_cascade_setup(EEVEE_LightsInfo *linfo,
+ EEVEE_Light *evli,
+ DRWView *view,
+ float view_near,
+ float view_far,
+ int sample_ofs)
+{
+ EEVEE_Shadow *shdw_data = linfo->shadow_data + (int)evli->shadow_id;
+ EEVEE_ShadowCascade *csm_data = linfo->shadow_cascade_data + (int)shdw_data->type_data_id;
+ EEVEE_ShadowCascadeRender *csm_render = linfo->shadow_cascade_render +
+ (int)shdw_data->type_data_id;
+ int cascade_nbr = csm_render->cascade_count;
+ float cascade_fade = csm_render->cascade_fade;
+ float cascade_max_dist = csm_render->cascade_max_dist;
+ float cascade_exponent = csm_render->cascade_exponent;
+
+ float jitter_ofs[2];
+ double ht_point[2];
+ double ht_offset[2] = {0.0, 0.0};
+ uint ht_primes[2] = {2, 3};
+
+ BLI_halton_2d(ht_primes, ht_offset, sample_ofs, ht_point);
+
+ /* Not really sure why we need 4.0 factor here. */
+ jitter_ofs[0] = (ht_point[0] * 2.0 - 1.0) * 4.0 / linfo->shadow_cascade_size;
+ jitter_ofs[1] = (ht_point[1] * 2.0 - 1.0) * 4.0 / linfo->shadow_cascade_size;
+
+ /* Camera Matrices */
+ float persinv[4][4], vp_projmat[4][4];
+ DRW_view_persmat_get(view, persinv, true);
+ DRW_view_winmat_get(view, vp_projmat, false);
+ bool is_persp = DRW_view_is_persp_get(view);
+
+ /* obmat = Object Space > World Space */
+ /* viewmat = World Space > View Space */
+ float(*viewmat)[4] = csm_render->viewmat;
+ eevee_light_matrix_get(evli, viewmat);
+ /* At this point, viewmat == normalize_m4(obmat) */
+
+ if (linfo->soft_shadows) {
+ shadow_cascade_random_matrix_set(viewmat, evli->radius, sample_ofs);
+ }
+
+ copy_m4_m4(csm_render->viewinv, viewmat);
+ invert_m4(viewmat);
+
+ copy_v3_v3(csm_data->shadow_vec, csm_render->viewinv[2]);
+
+ /* Compute near and far value based on all shadow casters cumulated AABBs. */
+ float sh_near = -1.0e30f, sh_far = 1.0e30f;
+ BoundBox shcaster_bounds;
+ BKE_boundbox_init_from_minmax(
+ &shcaster_bounds, linfo->shcaster_aabb.min, linfo->shcaster_aabb.max);
+#ifdef DEBUG_CSM
+ float dbg_col1[4] = {1.0f, 0.5f, 0.6f, 1.0f};
+ DRW_debug_bbox(&shcaster_bounds, dbg_col1);
+#endif
+ for (int i = 0; i < 8; i++) {
+ mul_m4_v3(viewmat, shcaster_bounds.vec[i]);
+ sh_near = max_ff(sh_near, shcaster_bounds.vec[i][2]);
+ sh_far = min_ff(sh_far, shcaster_bounds.vec[i][2]);
+ }
+#ifdef DEBUG_CSM
+ float dbg_col2[4] = {0.5f, 1.0f, 0.6f, 1.0f};
+ float pts[2][3] = {{0.0, 0.0, sh_near}, {0.0, 0.0, sh_far}};
+ mul_m4_v3(csm_render->viewinv, pts[0]);
+ mul_m4_v3(csm_render->viewinv, pts[1]);
+ DRW_debug_sphere(pts[0], 1.0f, dbg_col1);
+ DRW_debug_sphere(pts[1], 1.0f, dbg_col2);
+#endif
+ /* The rest of the function is assuming inverted Z. */
+ /* Add a little bias to avoid invalid matrices. */
+ sh_far = -(sh_far - 1e-3);
+ sh_near = -sh_near;
+
+ /* The technique consists into splitting
+ * the view frustum into several sub-frustum
+ * that are individually receiving one shadow map */
+
+ float csm_start, csm_end;
+
+ if (is_persp) {
+ csm_start = view_near;
+ csm_end = max_ff(view_far, -cascade_max_dist);
+ /* Avoid artifacts */
+ csm_end = min_ff(view_near, csm_end);
+ }
+ else {
+ csm_start = -view_far;
+ csm_end = view_far;
+ }
+
+ /* init near/far */
+ for (int c = 0; c < MAX_CASCADE_NUM; ++c) {
+ csm_data->split_start[c] = csm_end;
+ csm_data->split_end[c] = csm_end;
+ }
+
+ /* Compute split planes */
+ float splits_start_ndc[MAX_CASCADE_NUM];
+ float splits_end_ndc[MAX_CASCADE_NUM];
+
+ {
+ /* Nearest plane */
+ float p[4] = {1.0f, 1.0f, csm_start, 1.0f};
+ /* TODO: we don't need full m4 multiply here */
+ mul_m4_v4(vp_projmat, p);
+ splits_start_ndc[0] = p[2];
+ if (is_persp) {
+ splits_start_ndc[0] /= p[3];
+ }
+ }
+
+ {
+ /* Farthest plane */
+ float p[4] = {1.0f, 1.0f, csm_end, 1.0f};
+ /* TODO: we don't need full m4 multiply here */
+ mul_m4_v4(vp_projmat, p);
+ splits_end_ndc[cascade_nbr - 1] = p[2];
+ if (is_persp) {
+ splits_end_ndc[cascade_nbr - 1] /= p[3];
+ }
+ }
+
+ csm_data->split_start[0] = csm_start;
+ csm_data->split_end[cascade_nbr - 1] = csm_end;
+
+ for (int c = 1; c < cascade_nbr; ++c) {
+ /* View Space */
+ float linear_split = lerp(((float)(c) / (float)cascade_nbr), csm_start, csm_end);
+ float exp_split = csm_start * powf(csm_end / csm_start, (float)(c) / (float)cascade_nbr);
+
+ if (is_persp) {
+ csm_data->split_start[c] = lerp(cascade_exponent, linear_split, exp_split);
+ }
+ else {
+ csm_data->split_start[c] = linear_split;
+ }
+ csm_data->split_end[c - 1] = csm_data->split_start[c];
+
+ /* Add some overlap for smooth transition */
+ csm_data->split_start[c] = lerp(cascade_fade,
+ csm_data->split_end[c - 1],
+ (c > 1) ? csm_data->split_end[c - 2] :
+ csm_data->split_start[0]);
+
+ /* NDC Space */
+ {
+ float p[4] = {1.0f, 1.0f, csm_data->split_start[c], 1.0f};
+ /* TODO: we don't need full m4 multiply here */
+ mul_m4_v4(vp_projmat, p);
+ splits_start_ndc[c] = p[2];
+
+ if (is_persp) {
+ splits_start_ndc[c] /= p[3];
+ }
+ }
+
+ {
+ float p[4] = {1.0f, 1.0f, csm_data->split_end[c - 1], 1.0f};
+ /* TODO: we don't need full m4 multiply here */
+ mul_m4_v4(vp_projmat, p);
+ splits_end_ndc[c - 1] = p[2];
+
+ if (is_persp) {
+ splits_end_ndc[c - 1] /= p[3];
+ }
+ }
+ }
+
+ /* Set last cascade split fade distance into the first split_start. */
+ float prev_split = (cascade_nbr > 1) ? csm_data->split_end[cascade_nbr - 2] :
+ csm_data->split_start[0];
+ csm_data->split_start[0] = lerp(cascade_fade, csm_data->split_end[cascade_nbr - 1], prev_split);
+
+ /* For each cascade */
+ for (int c = 0; c < cascade_nbr; ++c) {
+ float(*projmat)[4] = csm_render->projmat[c];
+ /* Given 8 frustum corners */
+ float corners[8][3] = {
+ /* Near Cap */
+ {1.0f, -1.0f, splits_start_ndc[c]},
+ {-1.0f, -1.0f, splits_start_ndc[c]},
+ {-1.0f, 1.0f, splits_start_ndc[c]},
+ {1.0f, 1.0f, splits_start_ndc[c]},
+ /* Far Cap */
+ {1.0f, -1.0f, splits_end_ndc[c]},
+ {-1.0f, -1.0f, splits_end_ndc[c]},
+ {-1.0f, 1.0f, splits_end_ndc[c]},
+ {1.0f, 1.0f, splits_end_ndc[c]},
+ };
+
+ /* Transform them into world space */
+ for (int i = 0; i < 8; ++i) {
+ mul_project_m4_v3(persinv, corners[i]);
+ }
+
+ float center[3];
+ frustum_min_bounding_sphere(corners, center, &(csm_render->radius[c]));
+
+#ifdef DEBUG_CSM
+ float dbg_col[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ if (c < 3) {
+ dbg_col[c] = 1.0f;
+ }
+ DRW_debug_bbox((BoundBox *)&corners, dbg_col);
+ DRW_debug_sphere(center, csm_render->radius[c], dbg_col);
+#endif
+
+ /* Project into lightspace */
+ mul_m4_v3(viewmat, center);
+
+ /* Snap projection center to nearest texel to cancel shimmering. */
+ float shadow_origin[2], shadow_texco[2];
+ /* Light to texture space. */
+ mul_v2_v2fl(
+ shadow_origin, center, linfo->shadow_cascade_size / (2.0f * csm_render->radius[c]));
+
+ /* Find the nearest texel. */
+ shadow_texco[0] = roundf(shadow_origin[0]);
+ shadow_texco[1] = roundf(shadow_origin[1]);
+
+ /* Compute offset. */
+ sub_v2_v2(shadow_texco, shadow_origin);
+ /* Texture to light space. */
+ mul_v2_fl(shadow_texco, (2.0f * csm_render->radius[c]) / linfo->shadow_cascade_size);
+
+ /* Apply offset. */
+ add_v2_v2(center, shadow_texco);
+
+ /* Expand the projection to cover frustum range */
+ rctf rect_cascade;
+ BLI_rctf_init_pt_radius(&rect_cascade, center, csm_render->radius[c]);
+ orthographic_m4(projmat,
+ rect_cascade.xmin,
+ rect_cascade.xmax,
+ rect_cascade.ymin,
+ rect_cascade.ymax,
+ sh_near,
+ sh_far);
+
+ /* Anti-Aliasing */
+ if (linfo->soft_shadows) {
+ add_v2_v2(projmat[3], jitter_ofs);
+ }
+
+ float viewprojmat[4][4];
+ mul_m4_m4m4(viewprojmat, projmat, viewmat);
+ mul_m4_m4m4(csm_data->shadowmat[c], texcomat, viewprojmat);
+
+#ifdef DEBUG_CSM
+ DRW_debug_m4_as_bbox(viewprojmat, dbg_col, true);
+#endif
+ }
+
+ shdw_data->near = sh_near;
+ shdw_data->far = sh_far;
+}
+
+static void eevee_ensure_cascade_views(EEVEE_ShadowCascadeRender *csm_render,
+ DRWView *view[MAX_CASCADE_NUM])
+{
+ for (int i = 0; i < csm_render->cascade_count; i++) {
+ if (view[i] == NULL) {
+ view[i] = DRW_view_create(csm_render->viewmat, csm_render->projmat[i], NULL, NULL, NULL);
+ }
+ else {
+ DRW_view_update(view[i], csm_render->viewmat, csm_render->projmat[i], NULL, NULL);
+ }
+ }
+}
+
+void EEVEE_shadows_draw_cascades(EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
+ DRWView *view,
+ int cascade_index)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+ EEVEE_PrivateData *g_data = stl->g_data;
+ EEVEE_LightsInfo *linfo = sldata->lights;
+
+ EEVEE_Light *evli = linfo->light_data + linfo->shadow_cascade_light_indices[cascade_index];
+ EEVEE_Shadow *shdw_data = linfo->shadow_data + (int)evli->shadow_id;
+ EEVEE_ShadowCascade *csm_data = linfo->shadow_cascade_data + (int)shdw_data->type_data_id;
+ EEVEE_ShadowCascadeRender *csm_render = linfo->shadow_cascade_render +
+ (int)shdw_data->type_data_id;
+
+ float near = DRW_view_near_distance_get(view);
+ float far = DRW_view_far_distance_get(view);
+
+ eevee_shadow_cascade_setup(linfo, evli, view, near, far, effects->taa_current_sample - 1);
+
+ /* Meh, Reusing the cube views. */
+ BLI_assert(MAX_CASCADE_NUM <= 6);
+ eevee_ensure_cascade_views(csm_render, g_data->cube_views);
+
+ /* Render shadow cascades */
+ /* Render cascade separately: seems to be faster for the general case.
+ * The only time it's more beneficial is when the CPU culling overhead
+ * outweigh the instancing overhead. which is rarely the case. */
+ for (int j = 0; j < csm_render->cascade_count; j++) {
+ DRW_view_set_active(g_data->cube_views[j]);
+ int layer = csm_data->tex_id + j;
+ GPU_framebuffer_texture_layer_attach(
+ sldata->shadow_fb, sldata->shadow_cascade_pool, 0, layer, 0);
+ GPU_framebuffer_bind(sldata->shadow_fb);
+ GPU_framebuffer_clear_depth(sldata->shadow_fb, 1.0f);
+ DRW_draw_pass(psl->shadow_pass);
+ }
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/eevee_shadows_cube.c b/source/blender/draw/engines/eevee/eevee_shadows_cube.c
new file mode 100644
index 00000000000..b10c206703a
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_shadows_cube.c
@@ -0,0 +1,223 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2019, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup EEVEE
+ */
+
+#include "eevee_private.h"
+
+void EEVEE_shadows_cube_add(EEVEE_LightsInfo *linfo, EEVEE_Light *evli, Object *ob)
+{
+ if (linfo->cube_len >= MAX_SHADOW_CUBE) {
+ return;
+ }
+
+ const Light *la = (Light *)ob->data;
+ EEVEE_Shadow *sh_data = linfo->shadow_data + linfo->shadow_len;
+
+ /* Always update dupli lights as EEVEE_LightEngineData is not saved.
+ * Same issue with dupli shadow casters. */
+ bool update = (ob->base_flag & BASE_FROM_DUPLI) != 0;
+ if (!update) {
+ EEVEE_LightEngineData *led = EEVEE_light_data_ensure(ob);
+ if (led->need_update) {
+ update = true;
+ led->need_update = false;
+ }
+ }
+
+ if (update) {
+ BLI_BITMAP_ENABLE(&linfo->sh_cube_update[0], linfo->cube_len);
+ }
+
+ sh_data->near = max_ff(la->clipsta, 1e-8f);
+ sh_data->bias = max_ff(la->bias * 0.05f, 0.0f);
+ eevee_contact_shadow_setup(la, sh_data);
+
+ /* Saving light bounds for later. */
+ BoundSphere *cube_bound = linfo->shadow_bounds + linfo->cube_len;
+ copy_v3_v3(cube_bound->center, evli->position);
+ cube_bound->radius = sqrt(1.0f / evli->invsqrdist);
+
+ linfo->shadow_cube_light_indices[linfo->cube_len] = linfo->num_light;
+ evli->shadow_id = linfo->shadow_len++;
+ sh_data->type_data_id = linfo->cube_len++;
+
+ /* Same as linfo->cube_len, no need to save. */
+ linfo->num_cube_layer++;
+}
+
+static void shadow_cube_random_position_set(const EEVEE_Light *evli,
+ int sample_ofs,
+ float ws_sample_pos[3])
+{
+ float jitter[3];
+#ifdef DEBUG_SHADOW_DISTRIBUTION
+ int i = 0;
+start:
+#else
+ int i = sample_ofs;
+#endif
+ switch ((int)evli->light_type) {
+ case LA_AREA:
+ EEVEE_sample_rectangle(i, evli->rightvec, evli->upvec, evli->sizex, evli->sizey, jitter);
+ break;
+ case (int)LAMPTYPE_AREA_ELLIPSE:
+ EEVEE_sample_ellipse(i, evli->rightvec, evli->upvec, evli->sizex, evli->sizey, jitter);
+ break;
+ default:
+ EEVEE_sample_ball(i, evli->radius, jitter);
+ }
+#ifdef DEBUG_SHADOW_DISTRIBUTION
+ float p[3];
+ add_v3_v3v3(p, jitter, ws_sample_pos);
+ DRW_debug_sphere(p, 0.01f, (float[4]){1.0f, (sample_ofs == i) ? 1.0f : 0.0f, 0.0f, 1.0f});
+ if (i++ < sample_ofs) {
+ goto start;
+ }
+#endif
+ add_v3_v3(ws_sample_pos, jitter);
+}
+
+/* Return true if sample has changed and light needs to be updated. */
+bool EEVEE_shadows_cube_setup(EEVEE_LightsInfo *linfo, const EEVEE_Light *evli, int sample_ofs)
+{
+ EEVEE_Shadow *shdw_data = linfo->shadow_data + (int)evli->shadow_id;
+ EEVEE_ShadowCube *cube_data = linfo->shadow_cube_data + (int)shdw_data->type_data_id;
+
+ eevee_light_matrix_get(evli, cube_data->shadowmat);
+
+ shdw_data->far = max_ff(sqrt(1.0f / evli->invsqrdist), 3e-4);
+ shdw_data->near = min_ff(shdw_data->near, shdw_data->far - 1e-4);
+
+ bool update = false;
+
+ if (linfo->soft_shadows) {
+ shadow_cube_random_position_set(evli, sample_ofs, cube_data->shadowmat[3]);
+ /* Update if position changes (avoid infinite update if soft shadows does not move).
+ * Other changes are caught by depsgraph tagging. This one is for update between samples. */
+ update = !compare_v3v3(cube_data->shadowmat[3], cube_data->position, 1e-10f);
+ /**
+ * Anti-Aliasing jitter: Add random rotation.
+ *
+ * The 2.0 factor is because texel angular size is not even across the cubemap,
+ * so we make the rotation range a bit bigger.
+ * This will not blur the shadow even if the spread is too big since we are just
+ * rotating the shadow cubemap.
+ * Note that this may be a rough approximation an may not converge to a perfectly
+ * smooth shadow (because sample distribution is quite non-uniform) but is enought
+ * in practice.
+ **/
+ /* NOTE: this has implication for spotlight rendering optimization
+ * (see EEVEE_shadows_draw_cubemap). */
+ float angular_texel_size = 2.0f * DEG2RADF(90) / (float)linfo->shadow_cube_size;
+ EEVEE_random_rotation_m4(sample_ofs, angular_texel_size, cube_data->shadowmat);
+ }
+
+ copy_v3_v3(cube_data->position, cube_data->shadowmat[3]);
+ invert_m4(cube_data->shadowmat);
+
+ return update;
+}
+
+static void eevee_ensure_cube_views(
+ float near, float far, int cube_res, const float viewmat[4][4], DRWView *view[6])
+{
+ float winmat[4][4];
+ float side = near;
+
+ /* TODO shadowcube array. */
+ if (true) {
+ /* This half texel offset is used to ensure correct filtering between faces. */
+ /* FIXME: This exhibit float precision issue with lower cube_res.
+ * But it seems to be caused by the perspective_m4. */
+ side *= ((float)cube_res + 1.0f) / (float)(cube_res);
+ }
+
+ perspective_m4(winmat, -side, side, -side, side, near, far);
+
+ for (int i = 0; i < 6; i++) {
+ float tmp[4][4];
+ mul_m4_m4m4(tmp, cubefacemat[i], viewmat);
+
+ if (view[i] == NULL) {
+ view[i] = DRW_view_create(tmp, winmat, NULL, NULL, NULL);
+ }
+ else {
+ DRW_view_update(view[i], tmp, winmat, NULL, NULL);
+ }
+ }
+}
+
+/* Does a spot angle fits a single cubeface. */
+static bool spot_angle_fit_single_face(const EEVEE_Light *evli)
+{
+ /* alpha = spot/cone half angle. */
+ /* beta = scaled spot/cone half angle. */
+ float cos_alpha = evli->spotsize;
+ float sin_alpha = sqrtf(max_ff(0.0f, 1.0f - cos_alpha * cos_alpha));
+ float cos_beta = min_ff(cos_alpha / hypotf(cos_alpha, sin_alpha * evli->sizex),
+ cos_alpha / hypotf(cos_alpha, sin_alpha * evli->sizey));
+ /* Don't use 45 degrees because AA jitter can offset the face. */
+ return cos_beta > cosf(DEG2RADF(42.0f));
+}
+
+void EEVEE_shadows_draw_cubemap(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, int cube_index)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_PrivateData *g_data = stl->g_data;
+ EEVEE_LightsInfo *linfo = sldata->lights;
+
+ EEVEE_Light *evli = linfo->light_data + linfo->shadow_cube_light_indices[cube_index];
+ EEVEE_Shadow *shdw_data = linfo->shadow_data + (int)evli->shadow_id;
+ EEVEE_ShadowCube *cube_data = linfo->shadow_cube_data + (int)shdw_data->type_data_id;
+
+ eevee_ensure_cube_views(shdw_data->near,
+ shdw_data->far,
+ linfo->shadow_cube_size,
+ cube_data->shadowmat,
+ g_data->cube_views);
+
+ /* Render shadow cube */
+ /* Render 6 faces separately: seems to be faster for the general case.
+ * The only time it's more beneficial is when the CPU culling overhead
+ * outweigh the instancing overhead. which is rarely the case. */
+ for (int j = 0; j < 6; j++) {
+ /* Optimization: Only render the needed faces. */
+ /* Skip all but -Z face. */
+ if (evli->light_type == LA_SPOT && j != 5 && spot_angle_fit_single_face(evli))
+ continue;
+ /* Skip +Z face. */
+ if (evli->light_type != LA_LOCAL && j == 4)
+ continue;
+ /* TODO(fclem) some cube sides can be invisible in the main views. Cull them. */
+ // if (frustum_intersect(g_data->cube_views[j], main_view))
+ // continue;
+
+ DRW_view_set_active(g_data->cube_views[j]);
+ int layer = cube_index * 6 + j;
+ GPU_framebuffer_texture_layer_attach(sldata->shadow_fb, sldata->shadow_cube_pool, 0, layer, 0);
+ GPU_framebuffer_bind(sldata->shadow_fb);
+ GPU_framebuffer_clear_depth(sldata->shadow_fb, 1.0f);
+ DRW_draw_pass(psl->shadow_pass);
+ }
+
+ BLI_BITMAP_SET(&linfo->sh_cube_update[0], cube_index, false);
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
index 24956239508..30ad8482f76 100644
--- a/source/blender/draw/engines/eevee/eevee_subsurface.c
+++ b/source/blender/draw/engines/eevee/eevee_subsurface.c
@@ -38,7 +38,13 @@ static struct {
extern char datatoc_common_view_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
+extern char datatoc_lights_lib_glsl[];
+extern char datatoc_raytrace_lib_glsl[];
+extern char datatoc_octahedron_lib_glsl[];
+extern char datatoc_bsdf_sampling_lib_glsl[];
+extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_effect_subsurface_frag_glsl[];
+extern char datatoc_effect_translucency_frag_glsl[];
static void eevee_create_shader_subsurface(void)
{
@@ -46,16 +52,23 @@ static void eevee_create_shader_subsurface(void)
datatoc_common_uniforms_lib_glsl,
datatoc_effect_subsurface_frag_glsl);
+ /* TODO(fclem) remove some of these dependencies. */
+ char *frag_translucent_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_bsdf_common_lib_glsl,
+ datatoc_bsdf_sampling_lib_glsl,
+ datatoc_raytrace_lib_glsl,
+ datatoc_octahedron_lib_glsl,
+ datatoc_lights_lib_glsl,
+ datatoc_effect_translucency_frag_glsl);
+
e_data.sss_sh[0] = DRW_shader_create_fullscreen(frag_str, "#define FIRST_PASS\n");
e_data.sss_sh[1] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n");
- e_data.sss_sh[2] = DRW_shader_create_fullscreen(frag_str,
- "#define SECOND_PASS\n"
- "#define USE_SEP_ALBEDO\n");
- e_data.sss_sh[3] = DRW_shader_create_fullscreen(frag_str,
- "#define SECOND_PASS\n"
- "#define USE_SEP_ALBEDO\n"
- "#define RESULT_ACCUM\n");
+ e_data.sss_sh[2] = DRW_shader_create_fullscreen(frag_str, "#define RESULT_ACCUM\n");
+ e_data.sss_sh[3] = DRW_shader_create_fullscreen(frag_translucent_str,
+ "#define EEVEE_TRANSLUCENCY\n" SHADER_DEFINES);
+ MEM_freeN(frag_translucent_str);
MEM_freeN(frag_str);
}
@@ -69,7 +82,6 @@ void EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
effects->sss_sample_count = 1 + scene_eval->eevee.sss_samples * 2;
- effects->sss_separate_albedo = (scene_eval->eevee.flag & SCE_EEVEE_SSS_SEPARATE_ALBEDO) != 0;
common_data->sss_jitter_threshold = scene_eval->eevee.sss_jitter_threshold;
}
@@ -90,9 +102,13 @@ void EEVEE_subsurface_draw_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
effects->sss_stencil = DRW_texture_pool_query_2d(
fs_size[0], fs_size[1], GPU_DEPTH24_STENCIL8, &draw_engine_eevee_type);
effects->sss_blur = DRW_texture_pool_query_2d(
- fs_size[0], fs_size[1], GPU_RGBA16F, &draw_engine_eevee_type);
- effects->sss_data = DRW_texture_pool_query_2d(
- fs_size[0], fs_size[1], GPU_RGBA16F, &draw_engine_eevee_type);
+ fs_size[0], fs_size[1], GPU_R11F_G11F_B10F, &draw_engine_eevee_type);
+ effects->sss_irradiance = DRW_texture_pool_query_2d(
+ fs_size[0], fs_size[1], GPU_R11F_G11F_B10F, &draw_engine_eevee_type);
+ effects->sss_radius = DRW_texture_pool_query_2d(
+ fs_size[0], fs_size[1], GPU_R16F, &draw_engine_eevee_type);
+ effects->sss_albedo = DRW_texture_pool_query_2d(
+ fs_size[0], fs_size[1], GPU_R11F_G11F_B10F, &draw_engine_eevee_type);
GPUTexture *stencil_tex = effects->sss_stencil;
@@ -115,15 +131,13 @@ void EEVEE_subsurface_draw_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
{GPU_ATTACHMENT_TEXTURE(stencil_tex), GPU_ATTACHMENT_TEXTURE(txl->color)});
GPU_framebuffer_ensure_config(
- &fbl->sss_clear_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(effects->sss_data)});
+ &fbl->sss_translucency_fb,
+ {GPU_ATTACHMENT_TEXTURE(stencil_tex), GPU_ATTACHMENT_TEXTURE(effects->sss_irradiance)});
- if (effects->sss_separate_albedo) {
- effects->sss_albedo = DRW_texture_pool_query_2d(
- fs_size[0], fs_size[1], GPU_R11F_G11F_B10F, &draw_engine_eevee_type);
- }
- else {
- effects->sss_albedo = NULL;
- }
+ GPU_framebuffer_ensure_config(&fbl->sss_clear_fb,
+ {GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->sss_irradiance),
+ GPU_ATTACHMENT_TEXTURE(effects->sss_radius)});
}
else {
/* Cleanup to release memory */
@@ -132,7 +146,8 @@ void EEVEE_subsurface_draw_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_clear_fb);
effects->sss_stencil = NULL;
effects->sss_blur = NULL;
- effects->sss_data = NULL;
+ effects->sss_irradiance = NULL;
+ effects->sss_radius = NULL;
}
}
@@ -202,6 +217,7 @@ void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
DRW_PASS_CREATE(psl->sss_blur_ps, state);
DRW_PASS_CREATE(psl->sss_resolve_ps, state | DRW_STATE_BLEND_ADD);
DRW_PASS_CREATE(psl->sss_accum_ps, state | DRW_STATE_BLEND_ADD);
+ DRW_PASS_CREATE(psl->sss_translucency_ps, state | DRW_STATE_BLEND_ADD);
}
void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
@@ -219,42 +235,66 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
- DRW_shgroup_uniform_texture_ref(grp, "sssData", &effects->sss_data);
+ DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_irradiance);
+ DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_stencil_mask(grp, sss_id);
DRW_shgroup_call(grp, quad, NULL);
- struct GPUShader *sh = (effects->sss_separate_albedo) ? e_data.sss_sh[2] : e_data.sss_sh[1];
- grp = DRW_shgroup_create(sh, psl->sss_resolve_ps);
+ grp = DRW_shgroup_create(e_data.sss_sh[1], psl->sss_resolve_ps);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
- DRW_shgroup_uniform_texture_ref(grp, "sssData", &effects->sss_blur);
+ DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_blur);
+ DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
+ DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_stencil_mask(grp, sss_id);
DRW_shgroup_call(grp, quad, NULL);
- if (effects->sss_separate_albedo) {
- DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
- }
-
if (DRW_state_is_image_render()) {
- grp = DRW_shgroup_create(e_data.sss_sh[3], psl->sss_accum_ps);
+ grp = DRW_shgroup_create(e_data.sss_sh[2], psl->sss_accum_ps);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
- DRW_shgroup_uniform_texture_ref(grp, "sssData", &effects->sss_blur);
+ DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_blur);
+ DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
+ DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_stencil_mask(grp, sss_id);
DRW_shgroup_call(grp, quad, NULL);
-
- if (effects->sss_separate_albedo) {
- DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
- }
}
}
+void EEVEE_subsurface_translucency_add_pass(EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
+ uint sss_id,
+ struct GPUUniformBuffer *sss_profile,
+ GPUTexture *sss_tex_profile)
+{
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+ struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
+ GPUTexture **depth_src = GPU_depth_blitting_workaround() ? &effects->sss_stencil : &dtxl->depth;
+
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[3], psl->sss_translucency_ps);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_texture(grp, "sssTexProfile", sss_tex_profile);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
+ DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
+ DRW_shgroup_uniform_texture_ref(grp, "sssShadowCubes", &sldata->shadow_cube_pool);
+ DRW_shgroup_uniform_texture_ref(grp, "sssShadowCascades", &sldata->shadow_cascade_pool);
+ DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
+ 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_stencil_mask(grp, sss_id);
+ DRW_shgroup_call(grp, quad, NULL);
+}
+
void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
@@ -273,7 +313,8 @@ void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
GPU_ATTACHMENT_LEAVE,
GPU_ATTACHMENT_LEAVE,
GPU_ATTACHMENT_LEAVE,
- GPU_ATTACHMENT_TEXTURE(effects->sss_data),
+ GPU_ATTACHMENT_TEXTURE(effects->sss_irradiance),
+ GPU_ATTACHMENT_TEXTURE(effects->sss_radius),
GPU_ATTACHMENT_TEXTURE(effects->sss_albedo)});
GPU_framebuffer_bind(fbl->main_fb);
@@ -287,11 +328,12 @@ void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
GPU_ATTACHMENT_LEAVE,
GPU_ATTACHMENT_LEAVE,
GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_NONE});
}
}
-void EEVEE_subsurface_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
@@ -313,6 +355,28 @@ void EEVEE_subsurface_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
GPU_framebuffer_blit(fbl->main_fb, 0, fbl->sss_blur_fb, 0, GPU_STENCIL_BIT);
}
+ if (!DRW_pass_is_empty(psl->sss_translucency_ps)) {
+ /* We sample the shadowmaps using normal sampler. We need to disable Comparison mode.
+ * TODO(fclem) avoid this by using sampler objects.*/
+ GPU_texture_bind(sldata->shadow_cube_pool, 0);
+ GPU_texture_compare_mode(sldata->shadow_cube_pool, false);
+ GPU_texture_unbind(sldata->shadow_cube_pool);
+ GPU_texture_bind(sldata->shadow_cascade_pool, 0);
+ GPU_texture_compare_mode(sldata->shadow_cascade_pool, false);
+ GPU_texture_unbind(sldata->shadow_cascade_pool);
+
+ GPU_framebuffer_bind(fbl->sss_translucency_fb);
+ DRW_draw_pass(psl->sss_translucency_ps);
+
+ /* Reset original state. */
+ GPU_texture_bind(sldata->shadow_cube_pool, 0);
+ GPU_texture_compare_mode(sldata->shadow_cube_pool, true);
+ GPU_texture_unbind(sldata->shadow_cube_pool);
+ GPU_texture_bind(sldata->shadow_cascade_pool, 0);
+ GPU_texture_compare_mode(sldata->shadow_cascade_pool, true);
+ GPU_texture_unbind(sldata->shadow_cascade_pool);
+ }
+
/* 1. horizontal pass */
GPU_framebuffer_bind(fbl->sss_blur_fb);
GPU_framebuffer_clear_color(fbl->sss_blur_fb, clear);
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 7fb5c25ffc6..8a2576e174d 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -595,7 +595,7 @@ void EEVEE_volumes_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
effects->volume_transmit = e_data.dummy_transmit;
}
-void EEVEE_volumes_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+void EEVEE_volumes_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
EEVEE_TextureList *txl = vedata->txl;
@@ -605,6 +605,15 @@ void EEVEE_volumes_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda
if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
DRW_stats_group_start("Volumetrics");
+ /* We sample the shadowmaps using shadow sampler. We need to enable Comparison mode.
+ * TODO(fclem) avoid this by using sampler objects.*/
+ GPU_texture_bind(sldata->shadow_cube_pool, 0);
+ GPU_texture_compare_mode(sldata->shadow_cube_pool, true);
+ GPU_texture_unbind(sldata->shadow_cube_pool);
+ GPU_texture_bind(sldata->shadow_cascade_pool, 0);
+ GPU_texture_compare_mode(sldata->shadow_cascade_pool, true);
+ GPU_texture_unbind(sldata->shadow_cascade_pool);
+
GPU_framebuffer_bind(fbl->volumetric_fb);
DRW_draw_pass(psl->volumetric_world_ps);
DRW_draw_pass(psl->volumetric_objects_ps);
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 7f795eaac2b..98012aea303 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -56,12 +56,12 @@ struct LightData {
#endif
struct ShadowData {
- vec4 near_far_bias_exp;
- vec4 shadow_data_start_end;
+ vec4 near_far_bias_id;
vec4 contact_shadow_data;
};
struct ShadowCubeData {
+ mat4 shadowmat;
vec4 position;
};
@@ -69,22 +69,20 @@ struct ShadowCascadeData {
mat4 shadowmat[MAX_CASCADE_NUM];
vec4 split_start_distances;
vec4 split_end_distances;
+ vec4 shadow_vec_id;
};
/* convenience aliases */
-#define sh_near near_far_bias_exp.x
-#define sh_far near_far_bias_exp.y
-#define sh_bias near_far_bias_exp.z
-#define sh_exp near_far_bias_exp.w
-#define sh_bleed near_far_bias_exp.w
-#define sh_tex_start shadow_data_start_end.x
-#define sh_data_start shadow_data_start_end.y
-#define sh_multi_nbr shadow_data_start_end.z
-#define sh_blur shadow_data_start_end.w
+#define sh_near near_far_bias_id.x
+#define sh_far near_far_bias_id.y
+#define sh_bias near_far_bias_id.z
+#define sh_data_index near_far_bias_id.w
#define sh_contact_dist contact_shadow_data.x
#define sh_contact_offset contact_shadow_data.y
#define sh_contact_spread contact_shadow_data.z
#define sh_contact_thickness contact_shadow_data.w
+#define sh_shadow_vec shadow_vec_id.xyz
+#define sh_tex_index shadow_vec_id.w
/* ------- Convenience functions --------- */
@@ -777,10 +775,9 @@ struct Closure {
vec3 transmittance;
float holdout;
# ifdef USE_SSS
- vec4 sss_data;
-# ifdef USE_SSS_ALBEDO
+ vec3 sss_irradiance;
vec3 sss_albedo;
-# endif
+ float sss_radius;
# endif
vec4 ssr_data;
vec2 ssr_normal;
@@ -796,13 +793,8 @@ Closure nodetree_exec(void); /* Prototype */
# define CLOSURE_HOLDOUT_FLAG 4
# ifdef USE_SSS
-# ifdef USE_SSS_ALBEDO
-# define CLOSURE_DEFAULT \
- Closure(vec3(0.0), vec3(0.0), 0.0, vec4(0.0), vec3(0.0), vec4(0.0), vec2(0.0), 0)
-# else
-# define CLOSURE_DEFAULT \
- Closure(vec3(0.0), vec3(0.0), 0.0, vec4(0.0), vec4(0.0), vec2(0.0), 0)
-# endif
+# define CLOSURE_DEFAULT \
+ Closure(vec3(0.0), vec3(0.0), 0.0, vec3(0.0), vec3(0.0), 0.0, vec4(0.0), vec2(0.0), 0)
# else
# define CLOSURE_DEFAULT Closure(vec3(0.0), vec3(0.0), 0.0, vec4(0.0), vec2(0.0), 0)
# endif
@@ -823,30 +815,22 @@ void closure_load_ssr_data(
}
}
-# ifdef USE_SSS
-void closure_load_sss_data(float radius,
- vec3 sss_radiance,
-# ifdef USE_SSS_ALBEDO
- vec3 sss_albedo,
-# endif
- int sss_id,
- inout Closure cl)
+void closure_load_sss_data(
+ float radius, vec3 sss_irradiance, vec3 sss_albedo, int sss_id, inout Closure cl)
{
+# ifdef USE_SSS
if (sss_id == outputSssId) {
- cl.sss_data = vec4(sss_radiance, radius);
-# ifdef USE_SSS_ALBEDO
+ cl.sss_irradiance = sss_irradiance;
+ cl.sss_radius = radius;
cl.sss_albedo = sss_albedo;
-# endif
cl.flag |= CLOSURE_SSS_FLAG;
}
- else {
- cl.radiance += sss_radiance;
-# ifdef USE_SSS_ALBEDO
- cl.radiance += sss_radiance * sss_albedo;
-# endif
+ else
+# endif
+ {
+ cl.radiance += sss_irradiance * sss_albedo;
}
}
-# endif
Closure closure_mix(Closure cl1, Closure cl2, float fac)
{
@@ -862,13 +846,11 @@ Closure closure_mix(Closure cl1, Closure cl2, float fac)
cl.ssr_normal = (use_cl1_ssr) ? cl1.ssr_normal : cl2.ssr_normal;
# ifdef USE_SSS
- cl.sss_data = mix(cl1.sss_data, cl2.sss_data, fac);
+ cl.sss_albedo = mix(cl1.sss_albedo, cl2.sss_albedo, fac);
bool use_cl1_sss = FLAG_TEST(cl1.flag, CLOSURE_SSS_FLAG);
- /* It also does not make sense to mix SSS radius or albedo. */
- cl.sss_data.w = (use_cl1_sss) ? cl1.sss_data.w : cl2.sss_data.w;
-# ifdef USE_SSS_ALBEDO
- cl.sss_albedo = (use_cl1_sss) ? cl1.sss_albedo : cl2.sss_albedo;
-# endif
+ /* It also does not make sense to mix SSS radius or irradiance. */
+ cl.sss_radius = (use_cl1_sss) ? cl1.sss_radius : cl2.sss_radius;
+ cl.sss_irradiance = (use_cl1_sss) ? cl1.sss_irradiance : cl2.sss_irradiance;
# endif
return cl;
}
@@ -887,13 +869,11 @@ Closure closure_add(Closure cl1, Closure cl2)
cl.ssr_normal = (use_cl1_ssr) ? cl1.ssr_normal : cl2.ssr_normal;
# ifdef USE_SSS
- cl.sss_data = cl1.sss_data + cl2.sss_data;
+ cl.sss_albedo = cl1.sss_albedo + cl2.sss_albedo;
bool use_cl1_sss = FLAG_TEST(cl1.flag, CLOSURE_SSS_FLAG);
- /* It also does not make sense to mix SSS radius or albedo. */
- cl.sss_data.w = (use_cl1_sss) ? cl1.sss_data.w : cl2.sss_data.w;
-# ifdef USE_SSS_ALBEDO
- cl.sss_albedo = (use_cl1_sss) ? cl1.sss_albedo : cl2.sss_albedo;
-# endif
+ /* It also does not make sense to mix SSS radius or irradiance. */
+ cl.sss_radius = (use_cl1_sss) ? cl1.sss_radius : cl2.sss_radius;
+ cl.sss_irradiance = (use_cl1_sss) ? cl1.sss_irradiance : cl2.sss_irradiance;
# endif
return cl;
}
@@ -914,10 +894,9 @@ layout(location = 0) out vec4 outRadiance;
layout(location = 1) out vec2 ssrNormals;
layout(location = 2) out vec4 ssrData;
# ifdef USE_SSS
-layout(location = 3) out vec4 sssData;
-# ifdef USE_SSS_ALBEDO
-layout(location = 4) out vec4 sssAlbedo;
-# endif
+layout(location = 3) out vec3 sssIrradiance;
+layout(location = 4) out float sssRadius;
+layout(location = 5) out vec3 sssAlbedo;
# endif
# else /* USE_ALPHA_BLEND */
/* Use dual source blending to be able to make a whole range of effects. */
@@ -953,10 +932,9 @@ void main()
ssrNormals = cl.ssr_normal;
ssrData = cl.ssr_data;
# ifdef USE_SSS
- sssData = cl.sss_data;
-# ifdef USE_SSS_ALBEDO
- sssAlbedo = cl.sss_albedo.rgbb;
-# endif
+ sssIrradiance = cl.sss_irradiance;
+ sssRadius = cl.sss_radius;
+ sssAlbedo = cl.sss_albedo;
# endif
# endif
@@ -964,6 +942,8 @@ void main()
# ifdef USE_SSS
float fac = float(!sssToggle);
+ /* TODO(fclem) we shouldn't need this.
+ * Just disable USE_SSS when USE_REFRACTION is enabled. */
# ifdef USE_REFRACTION
/* SSRefraction pass is done after the SSS pass.
* In order to not loose the diffuse light totally we
@@ -971,11 +951,7 @@ void main()
fac = 1.0;
# endif
-# ifdef USE_SSS_ALBEDO
- outRadiance.rgb += cl.sss_data.rgb * cl.sss_albedo.rgb * fac;
-# else
- outRadiance.rgb += cl.sss_data.rgb * fac;
-# endif
+ outRadiance.rgb += cl.sss_irradiance.rgb * cl.sss_albedo.rgb * fac;
# endif
}
diff --git a/source/blender/draw/engines/eevee/shaders/default_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_frag.glsl
index 1f60661d234..ca06d458f6e 100644
--- a/source/blender/draw/engines/eevee/shaders/default_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/default_frag.glsl
@@ -31,7 +31,7 @@ Closure nodetree_exec(void)
vec3 f0 = mix(dielectric, basecol, metallic);
vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic);
vec3 out_diff, out_spec, ssr_spec;
- eevee_closure_default(N, albedo, f0, f90, 1, roughness, 1.0, out_diff, out_spec, ssr_spec);
+ eevee_closure_default(N, albedo, f0, f90, 1, roughness, 1.0, true, out_diff, out_spec, ssr_spec);
Closure cl = CLOSURE_DEFAULT;
cl.radiance = out_spec + out_diff * albedo;
diff --git a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
index 4260c601543..1241cf0e387 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
@@ -10,7 +10,8 @@ layout(std140) uniform sssProfile
};
uniform sampler2D depthBuffer;
-uniform sampler2D sssData;
+uniform sampler2D sssIrradiance;
+uniform sampler2D sssRadius;
uniform sampler2D sssAlbedo;
#ifndef UTIL_TEX
@@ -19,9 +20,12 @@ uniform sampler2DArray utilTex;
# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
#endif /* UTIL_TEX */
-layout(location = 0) out vec4 FragColor;
#ifdef RESULT_ACCUM
+/* Render Passes Accumulation */
+layout(location = 0) out vec4 sssDirect;
layout(location = 1) out vec4 sssColor;
+#else
+layout(location = 0) out vec4 sssRadiance;
#endif
float get_view_z_from_depth(float depth)
@@ -43,7 +47,8 @@ void main(void)
{
vec2 pixel_size = 1.0 / vec2(textureSize(depthBuffer, 0).xy); /* TODO precompute */
vec2 uvs = gl_FragCoord.xy * pixel_size;
- vec4 sss_data = texture(sssData, uvs).rgba;
+ vec3 sss_irradiance = texture(sssIrradiance, uvs).rgb;
+ float sss_radius = texture(sssRadius, uvs).r;
float depth_view = get_view_z_from_depth(texture(depthBuffer, uvs).r);
float rand = texelfetch_noise_tex(gl_FragCoord.xy).r;
@@ -58,44 +63,36 @@ void main(void)
/* Compute kernel bounds in 2D. */
float homcoord = ProjectionMatrix[2][3] * depth_view + ProjectionMatrix[3][3];
- vec2 scale = vec2(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) * sss_data.aa / homcoord;
+ vec2 scale = vec2(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) * sss_radius / homcoord;
vec2 finalStep = scale * radii_max_radius.w;
finalStep *= 0.5; /* samples range -1..1 */
/* Center sample */
- vec3 accum = sss_data.rgb * kernel[0].rgb;
+ vec3 accum = sss_irradiance * kernel[0].rgb;
for (int i = 1; i < sss_samples && i < MAX_SSS_SAMPLES; i++) {
vec2 sample_uv = uvs + kernel[i].a * finalStep *
((abs(kernel[i].a) > sssJitterThreshold) ? dir : dir_rand);
- vec3 color = texture(sssData, sample_uv).rgb;
+ vec3 color = texture(sssIrradiance, sample_uv).rgb;
float sample_depth = texture(depthBuffer, sample_uv).r;
sample_depth = get_view_z_from_depth(sample_depth);
-
/* Depth correction factor. */
float depth_delta = depth_view - sample_depth;
- float s = clamp(1.0 - exp(-(depth_delta * depth_delta) / (2.0 * sss_data.a)), 0.0, 1.0);
-
+ float s = clamp(1.0 - exp(-(depth_delta * depth_delta) / (2.0 * sss_radius)), 0.0, 1.0);
/* Out of view samples. */
if (any(lessThan(sample_uv, vec2(0.0))) || any(greaterThan(sample_uv, vec2(1.0)))) {
s = 1.0;
}
-
- accum += kernel[i].rgb * mix(color, sss_data.rgb, s);
+ /* Mix with first sample in failure case and apply kernel color. */
+ accum += kernel[i].rgb * mix(color, sss_irradiance, s);
}
-#ifdef FIRST_PASS
- FragColor = vec4(accum, sss_data.a);
+#ifdef RESULT_ACCUM
+ sssDirect = vec4(accum, 1.0);
+ sssColor = vec4(texture(sssAlbedo, uvs).rgb, 1.0);
+#elif defined(FIRST_PASS)
+ sssRadiance = vec4(accum, 1.0);
#else /* SECOND_PASS */
-# ifdef USE_SEP_ALBEDO
-# ifdef RESULT_ACCUM
- FragColor = vec4(accum, 1.0);
- sssColor = texture(sssAlbedo, uvs);
-# else
- FragColor = vec4(accum * texture(sssAlbedo, uvs).rgb, 1.0);
-# endif
-# else
- FragColor = vec4(accum, 1.0);
-# endif
+ sssRadiance = vec4(accum * texture(sssAlbedo, uvs).rgb, 1.0);
#endif
}
diff --git a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
new file mode 100644
index 00000000000..7edb0053da7
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
@@ -0,0 +1,165 @@
+
+in vec4 uvcoordsvar;
+
+out vec4 FragColor;
+
+uniform sampler1D sssTexProfile;
+uniform sampler2D sssRadius;
+
+uniform sampler2DArray sssShadowCubes;
+uniform sampler2DArray sssShadowCascades;
+
+#define MAX_SSS_SAMPLES 65
+#define SSS_LUT_SIZE 64.0
+#define SSS_LUT_SCALE ((SSS_LUT_SIZE - 1.0) / float(SSS_LUT_SIZE))
+#define SSS_LUT_BIAS (0.5 / float(SSS_LUT_SIZE))
+
+layout(std140) uniform sssProfile
+{
+ vec4 kernel[MAX_SSS_SAMPLES];
+ vec4 radii_max_radius;
+ int sss_samples;
+};
+
+vec3 sss_profile(float s)
+{
+ s /= radii_max_radius.w;
+ return texture(sssTexProfile, saturate(s) * SSS_LUT_SCALE + SSS_LUT_BIAS).rgb;
+}
+
+#ifndef UTIL_TEX
+# define UTIL_TEX
+uniform sampler2DArray utilTex;
+# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
+#endif /* UTIL_TEX */
+
+float light_translucent_power_with_falloff(LightData ld, vec3 N, vec4 l_vector)
+{
+ float power, falloff;
+ /* XXX : Removing Area Power. */
+ /* TODO : put this out of the shader. */
+ if (ld.l_type >= AREA_RECT) {
+ power = (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0);
+ if (ld.l_type == AREA_ELLIPSE) {
+ power *= M_PI * 0.25;
+ }
+ power *= 0.3 * 20.0 *
+ max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */
+ power /= (l_vector.w * l_vector.w);
+ falloff = dot(N, l_vector.xyz / l_vector.w);
+ }
+ else if (ld.l_type == SUN) {
+ power = 1.0 / (1.0 + (ld.l_radius * ld.l_radius * 0.5));
+ power *= ld.l_radius * ld.l_radius * M_PI; /* Removing area light power*/
+ power *= M_2PI * 0.78; /* Matching cycles with point light. */
+ power *= 0.082; /* XXX ad hoc, empirical */
+ falloff = dot(N, -ld.l_forward);
+ }
+ else {
+ power = (4.0 * ld.l_radius * ld.l_radius) * (1.0 / 10.0);
+ power *= 1.5; /* XXX ad hoc, empirical */
+ power /= (l_vector.w * l_vector.w);
+ falloff = dot(N, l_vector.xyz / l_vector.w);
+ }
+ /* No transmittance at grazing angle (hide artifacts) */
+ return power * saturate(falloff * 2.0);
+}
+
+/* Some driver poorly optimize this code. Use direct reference to matrices. */
+#define sd(x) shadows_data[x]
+#define scube(x) shadows_cube_data[x]
+#define scascade(x) shadows_cascade_data[x]
+
+vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, vec2 rand, float sss_scale)
+{
+ int shadow_id = int(ld.l_shadowid);
+
+ vec4 L = (ld.l_type != SUN) ? l_vector : vec4(-ld.l_forward, 1.0);
+
+ /* We use the full l_vector.xyz so that the spread is minimize
+ * if the shading point is further away from the light source */
+ /* TODO(fclem) do something better than this. */
+ // vec3 T, B;
+ // make_orthonormal_basis(L.xyz / L.w, T, B);
+ // rand.xy *= data.sh_blur;
+ // W = W + T * rand.x + B * rand.y;
+
+ float s, dist;
+ int data_id = int(sd(shadow_id).sh_data_index);
+ if (ld.l_type == SUN) {
+ vec4 view_z = vec4(dot(W - cameraPos, cameraForward));
+
+ vec4 weights = step(scascade(data_id).split_end_distances, view_z);
+ float id = abs(4.0 - dot(weights, weights));
+ if (id > 3.0) {
+ return vec3(0.0);
+ }
+
+ /* Same factor as in get_cascade_world_distance(). */
+ float range = abs(sd(shadow_id).sh_far - sd(shadow_id).sh_near);
+
+ vec4 shpos = scascade(data_id).shadowmat[int(id)] * vec4(W, 1.0);
+ dist = shpos.z * range;
+
+ if (shpos.z > 1.0 || shpos.z < 0.0) {
+ return vec3(0.0);
+ }
+
+ float tex_id = scascade(data_id).sh_tex_index;
+ s = sample_cascade(sssShadowCascades, shpos.xy, tex_id + id).r;
+ s *= range;
+ }
+ else {
+ vec3 cubevec = transform_point(scube(data_id).shadowmat, W);
+ dist = length(cubevec);
+ cubevec /= dist;
+ /* tex_id == data_id for cube shadowmap */
+ float tex_id = float(data_id);
+ s = sample_cube(sssShadowCubes, cubevec, tex_id).r;
+ s = length(cubevec / max_v3(abs(cubevec))) *
+ linear_depth(true, s, sd(shadow_id).sh_far, sd(shadow_id).sh_near);
+ }
+ float delta = dist - s;
+
+ float power = light_translucent_power_with_falloff(ld, N, l_vector);
+
+ return power * sss_profile(abs(delta) / sss_scale);
+}
+
+#undef sd
+#undef scube
+#undef scsmd
+
+void main(void)
+{
+ vec2 uvs = uvcoordsvar.xy;
+ float sss_scale = texture(sssRadius, uvs).r;
+ vec3 W = get_world_space_from_depth(uvs, texture(depthBuffer, uvs).r);
+ vec3 N = normalize(cross(dFdx(W), dFdy(W)));
+
+ vec3 rand = texelfetch_noise_tex(gl_FragCoord.xy).zwy;
+ rand.xy *= fast_sqrt(rand.z);
+
+ vec3 accum = vec3(0.0);
+ for (int i = 0; i < MAX_LIGHT && i < laNumLight; ++i) {
+ LightData ld = lights_data[i];
+
+ /* Only shadowed light can produce translucency */
+ if (ld.l_shadowid < 0.0) {
+ continue;
+ }
+
+ vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */
+ l_vector.xyz = ld.l_position - W;
+ l_vector.w = length(l_vector.xyz);
+
+ float att = light_attenuation(ld, l_vector);
+ if (att < 1e-8) {
+ continue;
+ }
+
+ accum += att * ld.l_color * light_translucent(ld, W, -N, l_vector, rand.xy, sss_scale);
+ }
+
+ FragColor = vec4(accum, 1.0);
+}
diff --git a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl
index c3643cccbfc..72017e971fc 100644
--- a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl
@@ -1,6 +1,6 @@
-uniform sampler2DArray shadowCubeTexture;
-uniform sampler2DArray shadowCascadeTexture;
+uniform sampler2DArrayShadow shadowCubeTexture;
+uniform sampler2DArrayShadow shadowCascadeTexture;
#define LAMPS_LIB
@@ -24,129 +24,115 @@ layout(std140) uniform light_block
/* Used to define the area light shape, doesn't directly correspond to a Blender light type. */
#define AREA_ELLIPSE 100.0
-#if defined(SHADOW_VSM)
-# define ShadowSample vec2
-# define sample_cube(vec, id) texture_octahedron(shadowCubeTexture, vec4(vec, id)).rg
-# define sample_cascade(vec, id) texture(shadowCascadeTexture, vec3(vec, id)).rg
-#elif defined(SHADOW_ESM)
-# define ShadowSample float
-# define sample_cube(vec, id) texture_octahedron(shadowCubeTexture, vec4(vec, id)).r
-# define sample_cascade(vec, id) texture(shadowCascadeTexture, vec3(vec, id)).r
-#else
-# define ShadowSample float
-# define sample_cube(vec, id) texture_octahedron(shadowCubeTexture, vec4(vec, id)).r
-# define sample_cascade(vec, id) texture(shadowCascadeTexture, vec3(vec, id)).r
-#endif
-
-#if defined(SHADOW_VSM)
-# define get_depth_delta(dist, s) (dist - s.x)
-#else
-# define get_depth_delta(dist, s) (dist - s)
-#endif
-
- /* ----------------------------------------------------------- */
- /* ----------------------- Shadow tests ---------------------- */
- /* ----------------------------------------------------------- */
-
-#if defined(SHADOW_VSM)
-
-float shadow_test(ShadowSample moments, float dist, ShadowData sd)
+float cubeFaceIndexEEVEE(vec3 P)
{
- float p = 0.0;
-
- if (dist <= moments.x) {
- p = 1.0;
+ vec3 aP = abs(P);
+ if (all(greaterThan(aP.xx, aP.yz))) {
+ return (P.x > 0.0) ? 0.0 : 1.0;
+ }
+ else if (all(greaterThan(aP.yy, aP.xz))) {
+ return (P.y > 0.0) ? 2.0 : 3.0;
+ }
+ else {
+ return (P.z > 0.0) ? 4.0 : 5.0;
}
-
- float variance = moments.y - (moments.x * moments.x);
- variance = max(variance, sd.sh_bias / 10.0);
-
- float d = moments.x - dist;
- float p_max = variance / (variance + d * d);
-
- /* Now reduce light-bleeding by removing the [0, x] tail and linearly rescaling (x, 1] */
- p_max = clamp((p_max - sd.sh_bleed) / (1.0 - sd.sh_bleed), 0.0, 1.0);
-
- return max(p, p_max);
}
-#elif defined(SHADOW_ESM)
-
-float shadow_test(ShadowSample z, float dist, ShadowData sd)
+vec2 cubeFaceCoordEEVEE(vec3 P, float face, float scale)
{
- return saturate(exp(sd.sh_exp * (z - dist + sd.sh_bias)));
+ if (face < 2.0) {
+ return (P.zy / P.x) * scale * vec2(-0.5, -sign(P.x) * 0.5) + 0.5;
+ }
+ else if (face < 4.0) {
+ return (P.xz / P.y) * scale * vec2(sign(P.y) * 0.5, 0.5) + 0.5;
+ }
+ else {
+ return (P.xy / P.z) * scale * vec2(0.5, -sign(P.z) * 0.5) + 0.5;
+ }
}
-#else
-
-float shadow_test(ShadowSample z, float dist, ShadowData sd)
+vec2 cubeFaceCoordEEVEE(vec3 P, float face, sampler2DArray tex)
{
- return step(0, z - dist + sd.sh_bias);
+ /* Scaling to compensate the 1px border around the face. */
+ float cube_res = float(textureSize(tex, 0).x);
+ float scale = (cube_res) / (cube_res + 1.0);
+ return cubeFaceCoordEEVEE(P, face, scale);
}
-#endif
-
-/* ----------------------------------------------------------- */
-/* ----------------------- Shadow types ---------------------- */
-/* ----------------------------------------------------------- */
-
-float shadow_cubemap(ShadowData sd, ShadowCubeData scd, float texid, vec3 W)
+vec2 cubeFaceCoordEEVEE(vec3 P, float face, sampler2DArrayShadow tex)
{
- vec3 cubevec = W - scd.position.xyz;
- float dist = length(cubevec);
+ /* Scaling to compensate the 1px border around the face. */
+ float cube_res = float(textureSize(tex, 0).x);
+ float scale = (cube_res) / (cube_res + 1.0);
+ return cubeFaceCoordEEVEE(P, face, scale);
+}
- cubevec /= dist;
+vec4 sample_cube(sampler2DArray tex, vec3 cubevec, float cube)
+{
+ /* Manual Shadow Cube Layer indexing. */
+ /* TODO Shadow Cube Array. */
+ float face = cubeFaceIndexEEVEE(cubevec);
+ vec2 uv = cubeFaceCoordEEVEE(cubevec, face, tex);
- ShadowSample s = sample_cube(cubevec, texid);
- return shadow_test(s, dist, sd);
+ vec3 coord = vec3(uv, cube * 6.0 + face);
+ return texture(tex, coord);
}
-float evaluate_cascade(ShadowData sd, mat4 shadowmat, vec3 W, float range, float texid)
+vec4 sample_cascade(sampler2DArray tex, vec2 co, float cascade_id)
{
- vec4 shpos = shadowmat * vec4(W, 1.0);
- float dist = shpos.z * range;
+ return texture(tex, vec3(co, cascade_id));
+}
- ShadowSample s = sample_cascade(shpos.xy, texid);
- float vis = shadow_test(s, dist, sd);
+/* Some driver poorly optimize this code. Use direct reference to matrices. */
+#define sd(x) shadows_data[x]
+#define scube(x) shadows_cube_data[x]
+#define scascade(x) shadows_cascade_data[x]
- /* If fragment is out of shadowmap range, do not occlude */
- if (shpos.z < 1.0 && shpos.z > 0.0) {
- return vis;
- }
- else {
- return 1.0;
- }
+float sample_cube_shadow(int shadow_id, vec3 W)
+{
+ int data_id = int(sd(shadow_id).sh_data_index);
+ vec3 cubevec = transform_point(scube(data_id).shadowmat, W);
+ float dist = max_v3(abs(cubevec)) - sd(shadow_id).sh_bias;
+ dist = buffer_depth(true, dist, sd(shadow_id).sh_far, sd(shadow_id).sh_near);
+ /* Manual Shadow Cube Layer indexing. */
+ /* TODO Shadow Cube Array. */
+ float face = cubeFaceIndexEEVEE(cubevec);
+ vec2 coord = cubeFaceCoordEEVEE(cubevec, face, shadowCubeTexture);
+ /* tex_id == data_id for cube shadowmap */
+ float tex_id = float(data_id);
+ return texture(shadowCubeTexture, vec4(coord, tex_id * 6.0 + face, dist));
}
-float shadow_cascade(ShadowData sd, int scd_id, float texid, vec3 W)
+float sample_cascade_shadow(int shadow_id, vec3 W)
{
+ int data_id = int(sd(shadow_id).sh_data_index);
+ float tex_id = scascade(data_id).sh_tex_index;
vec4 view_z = vec4(dot(W - cameraPos, cameraForward));
- vec4 weights = smoothstep(shadows_cascade_data[scd_id].split_end_distances,
- shadows_cascade_data[scd_id].split_start_distances.yzwx,
- view_z);
-
- weights.yzw -= weights.xyz;
-
- vec4 vis = vec4(1.0);
- float range = abs(sd.sh_far - sd.sh_near); /* Same factor as in get_cascade_world_distance(). */
-
- /* Branching using (weights > 0.0) is reaally slooow on intel so avoid it for now. */
- /* TODO OPTI: Only do 2 samples and blend. */
- vis.x = evaluate_cascade(sd, shadows_cascade_data[scd_id].shadowmat[0], W, range, texid + 0);
- vis.y = evaluate_cascade(sd, shadows_cascade_data[scd_id].shadowmat[1], W, range, texid + 1);
- vis.z = evaluate_cascade(sd, shadows_cascade_data[scd_id].shadowmat[2], W, range, texid + 2);
- vis.w = evaluate_cascade(sd, shadows_cascade_data[scd_id].shadowmat[3], W, range, texid + 3);
-
- float weight_sum = dot(vec4(1.0), weights);
- if (weight_sum > 0.9999) {
- float vis_sum = dot(vec4(1.0), vis * weights);
- return vis_sum / weight_sum;
- }
- else {
- float vis_sum = dot(vec4(1.0), vis * step(0.001, weights));
- return mix(1.0, vis_sum, weight_sum);
- }
+ vec4 weights = 1.0 - smoothstep(scascade(data_id).split_end_distances,
+ scascade(data_id).split_start_distances.yzwx,
+ view_z);
+ float tot_weight = dot(weights.xyz, vec3(1.0));
+
+ int cascade = int(clamp(tot_weight, 0.0, 3.0));
+ float blend = fract(tot_weight);
+ float vis = weights.w;
+ vec4 coord, shpos;
+ /* Main cascade. */
+ shpos = scascade(data_id).shadowmat[cascade] * vec4(W, 1.0);
+ coord = vec4(shpos.xy, tex_id + float(cascade), shpos.z - sd(shadow_id).sh_bias);
+ vis += texture(shadowCascadeTexture, coord) * (1.0 - blend);
+
+ cascade = min(3, cascade + 1);
+ /* Second cascade. */
+ shpos = scascade(data_id).shadowmat[cascade] * vec4(W, 1.0);
+ coord = vec4(shpos.xy, tex_id + float(cascade), shpos.z - sd(shadow_id).sh_bias);
+ vis += texture(shadowCascadeTexture, coord) * blend;
+
+ return saturate(vis);
}
+#undef sd
+#undef scube
+#undef scsmd
/* ----------------------------------------------------------- */
/* --------------------- Light Functions --------------------- */
@@ -173,16 +159,9 @@ float spot_attenuation(LightData ld, vec3 l_vector)
return spotmask;
}
-float light_visibility(LightData ld,
- vec3 W,
-#ifndef VOLUMETRICS
- vec3 viewPosition,
- vec3 vN,
-#endif
- vec4 l_vector)
+float light_attenuation(LightData ld, vec4 l_vector)
{
float vis = 1.0;
-
if (ld.l_type == SPOT) {
vis *= spot_attenuation(ld, l_vector.xyz);
}
@@ -192,69 +171,66 @@ float light_visibility(LightData ld,
if (ld.l_type != SUN) {
vis *= distance_attenuation(l_vector.w * l_vector.w, ld.l_influence);
}
+ return vis;
+}
+
+float light_visibility(LightData ld,
+ vec3 W,
+#ifndef VOLUMETRICS
+ vec3 viewPosition,
+ float tracing_depth,
+ vec3 true_normal,
+ float rand_x,
+ const bool use_contact_shadows,
+#endif
+ vec4 l_vector)
+{
+ float vis = light_attenuation(ld, l_vector);
#if !defined(VOLUMETRICS) || defined(VOLUME_SHADOW)
/* shadowing */
if (ld.l_shadowid >= 0.0 && vis > 0.001) {
- ShadowData data = shadows_data[int(ld.l_shadowid)];
if (ld.l_type == SUN) {
- vis *= shadow_cascade(data, int(data.sh_data_start), data.sh_tex_start, W);
+ vis *= sample_cascade_shadow(int(ld.l_shadowid), W);
}
else {
- vis *= shadow_cubemap(
- data, shadows_cube_data[int(data.sh_data_start)], data.sh_tex_start, W);
+ vis *= sample_cube_shadow(int(ld.l_shadowid), W);
}
# ifndef VOLUMETRICS
+ ShadowData sd = shadows_data[int(ld.l_shadowid)];
/* Only compute if not already in shadow. */
- if (data.sh_contact_dist > 0.0) {
- vec4 L = (ld.l_type != SUN) ? l_vector : vec4(-ld.l_forward, 1.0);
- float trace_distance = (ld.l_type != SUN) ? min(data.sh_contact_dist, l_vector.w) :
- data.sh_contact_dist;
-
- vec3 T, B;
- make_orthonormal_basis(L.xyz / L.w, T, B);
-
- vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
- rand.zw *= fast_sqrt(rand.y) * data.sh_contact_spread;
-
- /* We use the full l_vector.xyz so that the spread is minimize
- * if the shading point is further away from the light source */
- vec3 ray_dir = L.xyz + T * rand.z + B * rand.w;
- ray_dir = transform_direction(ViewMatrix, ray_dir);
- ray_dir = normalize(ray_dir);
-
- vec3 ray_ori = viewPosition;
-
- /* Fix translucency shadowed by contact shadows. */
- vN = (gl_FrontFacing) ? vN : -vN;
-
- if (dot(vN, ray_dir) <= 0.0) {
- return vis;
+ if (use_contact_shadows && sd.sh_contact_dist > 0.0 && vis > 1e-8) {
+ /* Contact Shadows. */
+ vec3 ray_ori, ray_dir;
+ float trace_distance;
+
+ if (ld.l_type == SUN) {
+ trace_distance = sd.sh_contact_dist;
+ ray_dir = shadows_cascade_data[int(sd.sh_data_index)].sh_shadow_vec * trace_distance;
+ }
+ else {
+ ray_dir = shadows_cube_data[int(sd.sh_data_index)].position.xyz - W;
+ float len = length(ray_dir);
+ trace_distance = min(sd.sh_contact_dist, len);
+ ray_dir *= trace_distance / len;
}
- float bias = 0.5; /* Constant Bias */
- bias += 1.0 - abs(dot(vN, ray_dir)); /* Angle dependent bias */
- bias *= gl_FrontFacing ? data.sh_contact_offset : -data.sh_contact_offset;
-
- vec3 nor_bias = vN * bias;
- ray_ori += nor_bias;
-
- ray_dir *= trace_distance;
- ray_dir -= nor_bias;
+ ray_dir = transform_direction(ViewMatrix, ray_dir);
+ ray_ori = vec3(viewPosition.xy, tracing_depth) + true_normal * sd.sh_contact_offset;
vec3 hit_pos = raycast(
- -1, ray_ori, ray_dir, data.sh_contact_thickness, rand.x, 0.1, 0.001, false);
+ -1, ray_ori, ray_dir, sd.sh_contact_thickness, rand_x, 0.1, 0.001, false);
if (hit_pos.z > 0.0) {
hit_pos = get_view_space_from_depth(hit_pos.xy, hit_pos.z);
float hit_dist = distance(viewPosition, hit_pos);
float dist_ratio = hit_dist / trace_distance;
- return vis * saturate(dist_ratio * dist_ratio * dist_ratio);
+ return vis * saturate(dist_ratio * 3.0 - 2.0);
}
}
-# endif
+# endif /* VOLUMETRICS */
}
#endif
@@ -325,134 +301,3 @@ float light_specular(LightData ld, vec4 ltc_mat, vec3 N, vec3 V, vec4 l_vector)
}
}
#endif
-
-#define MAX_SSS_SAMPLES 65
-#define SSS_LUT_SIZE 64.0
-#define SSS_LUT_SCALE ((SSS_LUT_SIZE - 1.0) / float(SSS_LUT_SIZE))
-#define SSS_LUT_BIAS (0.5 / float(SSS_LUT_SIZE))
-
-#ifdef USE_TRANSLUCENCY
-layout(std140) uniform sssProfile
-{
- vec4 kernel[MAX_SSS_SAMPLES];
- vec4 radii_max_radius;
- int sss_samples;
-};
-
-uniform sampler1D sssTexProfile;
-
-vec3 sss_profile(float s)
-{
- s /= radii_max_radius.w;
- return texture(sssTexProfile, saturate(s) * SSS_LUT_SCALE + SSS_LUT_BIAS).rgb;
-}
-#endif
-
-vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale)
-{
-#if !defined(USE_TRANSLUCENCY) || defined(VOLUMETRICS)
- return vec3(0.0);
-#else
- vec3 vis = vec3(1.0);
-
- if (ld.l_type == SPOT) {
- vis *= spot_attenuation(ld, l_vector.xyz);
- }
- if (ld.l_type >= SPOT) {
- vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward));
- }
- if (ld.l_type != SUN) {
- vis *= distance_attenuation(l_vector.w * l_vector.w, ld.l_influence);
- }
-
- /* Only shadowed light can produce translucency */
- if (ld.l_shadowid >= 0.0 && vis.x > 0.001) {
- ShadowData data = shadows_data[int(ld.l_shadowid)];
- float delta;
-
- vec4 L = (ld.l_type != SUN) ? l_vector : vec4(-ld.l_forward, 1.0);
-
- vec3 T, B;
- make_orthonormal_basis(L.xyz / L.w, T, B);
-
- vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
- rand.zw *= fast_sqrt(rand.y) * data.sh_blur;
-
- /* We use the full l_vector.xyz so that the spread is minimize
- * if the shading point is further away from the light source */
- W = W + T * rand.z + B * rand.w;
-
- if (ld.l_type == SUN) {
- int scd_id = int(data.sh_data_start);
- vec4 view_z = vec4(dot(W - cameraPos, cameraForward));
-
- vec4 weights = step(shadows_cascade_data[scd_id].split_end_distances, view_z);
- float id = abs(4.0 - dot(weights, weights));
-
- if (id > 3.0) {
- return vec3(0.0);
- }
-
- /* Same factor as in get_cascade_world_distance(). */
- float range = abs(data.sh_far - data.sh_near);
-
- vec4 shpos = shadows_cascade_data[scd_id].shadowmat[int(id)] * vec4(W, 1.0);
- float dist = shpos.z * range;
-
- if (shpos.z > 1.0 || shpos.z < 0.0) {
- return vec3(0.0);
- }
-
- ShadowSample s = sample_cascade(shpos.xy, data.sh_tex_start + id);
- delta = get_depth_delta(dist, s);
- }
- else {
- vec3 cubevec = W - shadows_cube_data[int(data.sh_data_start)].position.xyz;
- float dist = length(cubevec);
- cubevec /= dist;
-
- ShadowSample s = sample_cube(cubevec, data.sh_tex_start);
- delta = get_depth_delta(dist, s);
- }
-
- /* XXX : Removing Area Power. */
- /* TODO : put this out of the shader. */
- float falloff;
- if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) {
- vis *= (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0);
- if (ld.l_type == AREA_ELLIPSE) {
- vis *= M_PI * 0.25;
- }
- vis *= 0.3 * 20.0 *
- max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */
- vis /= (l_vector.w * l_vector.w);
- falloff = dot(N, l_vector.xyz / l_vector.w);
- }
- else if (ld.l_type == SUN) {
- vis /= 1.0f + (ld.l_radius * ld.l_radius * 0.5f);
- vis *= ld.l_radius * ld.l_radius * M_PI; /* Removing area light power*/
- vis *= M_2PI * 0.78; /* Matching cycles with point light. */
- vis *= 0.082; /* XXX ad hoc, empirical */
- falloff = dot(N, -ld.l_forward);
- }
- else {
- vis *= (4.0 * ld.l_radius * ld.l_radius) * (1.0 / 10.0);
- vis *= 1.5; /* XXX ad hoc, empirical */
- vis /= (l_vector.w * l_vector.w);
- falloff = dot(N, l_vector.xyz / l_vector.w);
- }
- // vis *= M_1_PI; /* Normalize */
-
- /* Applying profile */
- vis *= sss_profile(abs(delta) / scale);
-
- /* No transmittance at grazing angle (hide artifacts) */
- vis *= saturate(falloff * 2.0);
- }
- else {
- vis = vec3(0.0);
- }
-
- return vis;
-#endif
-}
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
index 53f1517505c..e9bdfec008f 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -144,14 +144,12 @@ void CLOSURE_NAME(vec3 N
,
float ior
#endif
+ ,
+ const bool use_contact_shadows
#ifdef CLOSURE_DIFFUSE
,
out vec3 out_diff
#endif
-#ifdef CLOSURE_SUBSURFACE
- ,
- out vec3 out_trans
-#endif
#ifdef CLOSURE_GLOSSY
,
out vec3 out_spec
@@ -170,10 +168,6 @@ void CLOSURE_NAME(vec3 N
out_diff = vec3(0.0);
#endif
-#ifdef CLOSURE_SUBSURFACE
- out_trans = vec3(0.0);
-#endif
-
#ifdef CLOSURE_GLOSSY
out_spec = vec3(0.0);
#endif
@@ -230,6 +224,16 @@ void CLOSURE_NAME(vec3 N
vec3 out_spec_clear = vec3(0.0);
# endif
+ float tracing_depth = gl_FragCoord.z;
+ /* Constant bias (due to depth buffer precision) */
+ /* Magic numbers for 24bits of precision.
+ * From http://terathon.com/gdc07_lengyel.pdf (slide 26) */
+ tracing_depth -= mix(2.4e-7, 4.8e-7, gl_FragCoord.z);
+ /* Convert to view Z. */
+ tracing_depth = get_view_z_from_depth(tracing_depth);
+
+ vec3 true_normal = normalize(cross(dFdx(viewPosition), dFdy(viewPosition)));
+
for (int i = 0; i < MAX_LIGHT && i < laNumLight; ++i) {
LightData ld = lights_data[i];
@@ -237,7 +241,14 @@ void CLOSURE_NAME(vec3 N
l_vector.xyz = ld.l_position - worldPosition;
l_vector.w = length(l_vector.xyz);
- float l_vis = light_visibility(ld, worldPosition, viewPosition, viewNormal, l_vector);
+ float l_vis = light_visibility(ld,
+ worldPosition,
+ viewPosition,
+ tracing_depth,
+ true_normal,
+ rand.x,
+ use_contact_shadows,
+ l_vector);
if (l_vis < 1e-8) {
continue;
@@ -249,10 +260,6 @@ void CLOSURE_NAME(vec3 N
out_diff += l_color_vis * light_diffuse(ld, N, V, l_vector);
# endif
-# ifdef CLOSURE_SUBSURFACE
- out_trans += ld.l_color * light_translucent(ld, worldPosition, -N, l_vector, sss_scale);
-# endif
-
# ifdef CLOSURE_GLOSSY
out_spec += l_color_vis * light_specular(ld, ltc_mat, N, V, l_vector) * ld.l_spec;
# endif
@@ -441,10 +448,17 @@ void CLOSURE_NAME(vec3 N
/* Ambient Occlusion */
/* ---------------------------- */
# if defined(CLOSURE_GLOSSY) || defined(CLOSURE_DIFFUSE)
- /* HACK: Fix for translucent BSDF. (see T65631) */
- bool same_side = dot((gl_FrontFacing) ? worldNormal : -worldNormal, N) > 0.0;
+ if (!use_contact_shadows) {
+ /* HACK: Fix for translucent BSDF. (see T65631) */
+ N = -N;
+ }
vec3 bent_normal;
- float final_ao = occlusion_compute(same_side ? N : -N, viewPosition, ao, rand, bent_normal);
+ float final_ao = occlusion_compute(gl_FrontFacing ? N : -N, viewPosition, ao, rand, bent_normal);
+ if (!use_contact_shadows) {
+ N = -N;
+ /* Bypass bent normal. */
+ bent_normal = N;
+ }
# endif
/* ---------------------------- */
diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
index 14e0c947b47..f88cfdf3787 100644
--- a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
@@ -120,7 +120,8 @@ void prepare_raycast(vec3 ray_origin,
ss_ray = ss_start * m.xyyy + 0.5;
ss_step *= m.xyyy;
- ss_ray.xy += m * ssrPixelSize * 2.0; /* take the center of the texel. * 2 because halfres. */
+ /* take the center of the texel. */
+ // ss_ray.xy += sign(ss_ray.xy) * m * ssrPixelSize * (1.0 + hizMipOffset);
}
/* See times_and_deltas. */
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl
deleted file mode 100644
index 5646c257562..00000000000
--- a/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl
+++ /dev/null
@@ -1,199 +0,0 @@
-/* Copy the depth only shadowmap into another texture while converting
- * to linear depth (or other storage method) and doing a 3x3 box filter. */
-
-layout(std140) uniform shadow_render_block
-{
- /* Use vectors to avoid alignment padding. */
- ivec4 shadowSampleCount;
- vec4 shadowInvSampleCount;
- vec4 filterSize;
- int viewCount;
- int baseId;
- float cubeTexelSize;
- float storedTexelSize;
- float nearClip;
- float farClip;
- float exponent;
-};
-
-#ifdef CSM
-uniform sampler2DArray shadowTexture;
-#else
-uniform samplerCube shadowTexture;
-#endif
-
-flat in int layerID;
-
-#ifdef CSM
-# define cascadeID layerID
-#else
-# define cascadeID 0
-#endif
-
-out vec4 FragColor;
-
-#define linear_depth(z) \
- ((nearClip * farClip) / (clamp(z, 0.0, 0.999999) * (nearClip - farClip) + farClip))
-
-/* add bias so background filtering does not bleed into shadow map */
-#define BACKGROUND_BIAS 0.05
-
-#ifdef CSM
-vec4 get_world_distance(vec4 depths, vec3 cos[4])
-{
- depths += step(vec4(0.9999), depths) * BACKGROUND_BIAS;
- return clamp(
- depths * abs(farClip - nearClip), 0.0, 1e10); /* Same factor as in shadow_cascade(). */
-}
-
-float get_world_distance(float depth, vec3 cos)
-{
- depth += step(0.9999, depth) * BACKGROUND_BIAS;
- return clamp(
- depth * abs(farClip - nearClip), 0.0, 1e10); /* Same factor as in shadow_cascade(). */
-}
-
-#else /* CUBEMAP */
-vec4 get_world_distance(vec4 depths, vec3 cos[4])
-{
- depths = linear_depth(depths);
- cos[0] = normalize(abs(cos[0]));
- cos[1] = normalize(abs(cos[1]));
- cos[2] = normalize(abs(cos[2]));
- cos[3] = normalize(abs(cos[3]));
- vec4 cos_vec;
- cos_vec.x = max(cos[0].x, max(cos[0].y, cos[0].z));
- cos_vec.y = max(cos[1].x, max(cos[1].y, cos[1].z));
- cos_vec.z = max(cos[2].x, max(cos[2].y, cos[2].z));
- cos_vec.w = max(cos[3].x, max(cos[3].y, cos[3].z));
- return depths / cos_vec;
-}
-
-float get_world_distance(float depth, vec3 cos)
-{
- depth = linear_depth(depth);
- cos = normalize(abs(cos));
- float cos_vec = max(cos.x, max(cos.y, cos.z));
- return depth / cos_vec;
-}
-#endif
-
-/* Marco Salvi's GDC 2008 presentation about shadow maps pre-filtering techniques slide 24 */
-#define ln_space_prefilter_step(ref, sample) exp(sample - ref)
-#define ln_space_prefilter_finalize(ref, sum) (ref + log(SAMPLE_WEIGHT * sum))
-
-#define SAMPLE_WEIGHT 0.11111
-
-#ifdef ESM
-void prefilter(vec4 depths, float ref, inout float accum)
-{
- accum += dot(ln_space_prefilter_step(ref, depths), vec4(1.0));
-}
-#else /* VSM */
-void prefilter(vec4 depths, float ref, inout vec2 accum)
-{
- vec4 depths_sqr = depths * depths;
- accum += vec2(dot(vec4(1.0), depths), dot(vec4(1.0), depths_sqr)) * SAMPLE_WEIGHT;
-}
-#endif
-
-#ifdef CSM
-vec3 get_texco(vec2 uvs, vec2 ofs)
-{
- return vec3(uvs + ofs, float(cascadeID));
-}
-#else /* CUBEMAP */
-const vec3 minorAxisX[6] = vec3[6](vec3(0.0f, 0.0f, -1.0f),
- vec3(0.0f, 0.0f, 1.0f),
- vec3(1.0f, 0.0f, 0.0f),
- vec3(1.0f, 0.0f, 0.0f),
- vec3(1.0f, 0.0f, 0.0f),
- vec3(-1.0f, 0.0f, 0.0f));
-
-const vec3 minorAxisY[6] = vec3[6](vec3(0.0f, -1.0f, 0.0f),
- vec3(0.0f, -1.0f, 0.0f),
- vec3(0.0f, 0.0f, 1.0f),
- vec3(0.0f, 0.0f, -1.0f),
- vec3(0.0f, -1.0f, 0.0f),
- vec3(0.0f, -1.0f, 0.0f));
-
-const vec3 majorAxis[6] = vec3[6](vec3(1.0f, 0.0f, 0.0f),
- vec3(-1.0f, 0.0f, 0.0f),
- vec3(0.0f, 1.0f, 0.0f),
- vec3(0.0f, -1.0f, 0.0f),
- vec3(0.0f, 0.0f, 1.0f),
- vec3(0.0f, 0.0f, -1.0f));
-
-vec3 get_texco(vec2 uvs, vec2 ofs)
-{
- uvs += ofs;
- return majorAxis[layerID] + uvs.x * minorAxisX[layerID] + uvs.y * minorAxisY[layerID];
-}
-#endif
-
-void main()
-{
- /* Copy the depth only shadowmap into another texture while converting
- * to linear depth and do a 3x3 box blur. */
-
-#ifdef CSM
- vec2 uvs = gl_FragCoord.xy * storedTexelSize;
-#else /* CUBEMAP */
- vec2 uvs = gl_FragCoord.xy * cubeTexelSize * 2.0 - 1.0;
-#endif
-
- /* Center texel */
- vec3 co = get_texco(uvs, vec2(0.0));
- float depth = texture(shadowTexture, co).r;
- depth = get_world_distance(depth, co);
-
- if (filterSize[cascadeID] == 0.0) {
-#ifdef ESM
- FragColor = vec4(depth);
-#else /* VSM */
- FragColor = vec2(depth, depth * depth).xyxy;
-#endif
- return;
- }
-
-#ifdef ESM
- float ref = depth;
- float accum = 1.0;
-#else /* VSM */
- float ref = 0.0; /* UNUSED */
- vec2 accum = vec2(depth, depth * depth) * SAMPLE_WEIGHT;
-#endif
-
- vec3 ofs = vec3(1.0, 0.0, -1.0) * filterSize[cascadeID];
-
- vec3 cos[4];
- cos[0] = get_texco(uvs, ofs.zz);
- cos[1] = get_texco(uvs, ofs.yz);
- cos[2] = get_texco(uvs, ofs.xz);
- cos[3] = get_texco(uvs, ofs.zy);
-
- vec4 depths;
- depths.x = texture(shadowTexture, cos[0]).r;
- depths.y = texture(shadowTexture, cos[1]).r;
- depths.z = texture(shadowTexture, cos[2]).r;
- depths.w = texture(shadowTexture, cos[3]).r;
- depths = get_world_distance(depths, cos);
- prefilter(depths, ref, accum);
-
- cos[0] = get_texco(uvs, ofs.xy);
- cos[1] = get_texco(uvs, ofs.zx);
- cos[2] = get_texco(uvs, ofs.yx);
- cos[3] = get_texco(uvs, ofs.xx);
- depths.x = texture(shadowTexture, cos[0]).r;
- depths.y = texture(shadowTexture, cos[1]).r;
- depths.z = texture(shadowTexture, cos[2]).r;
- depths.w = texture(shadowTexture, cos[3]).r;
- depths = get_world_distance(depths, cos);
- prefilter(depths, ref, accum);
-
-#ifdef ESM
- accum = ln_space_prefilter_finalize(ref, accum);
-#endif
- /* Clamp infinite sum. */
- FragColor = vec2(clamp(accum, 0.0, 1e16)).xyxy;
-}
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_process_geom.glsl b/source/blender/draw/engines/eevee/shaders/shadow_process_geom.glsl
deleted file mode 100644
index 591666560c4..00000000000
--- a/source/blender/draw/engines/eevee/shaders/shadow_process_geom.glsl
+++ /dev/null
@@ -1,36 +0,0 @@
-
-layout(triangles) in;
-layout(triangle_strip, max_vertices = 3) out;
-
-layout(std140) uniform shadow_render_block
-{
- /* Use vectors to avoid alignment padding. */
- ivec4 shadowSampleCount;
- vec4 shadowInvSampleCount;
- vec4 filterSize;
- int viewCount;
- int baseId;
- float cubeTexelSize;
- float storedTexelSize;
- float nearClip;
- float farClip;
- float exponent;
-};
-
-in int layerID_g[];
-
-flat out int layerID;
-
-void main()
-{
- gl_Layer = layerID_g[0];
- layerID = gl_Layer - baseId;
-
- gl_Position = gl_in[0].gl_Position;
- EmitVertex();
- gl_Position = gl_in[1].gl_Position;
- EmitVertex();
- gl_Position = gl_in[2].gl_Position;
- EmitVertex();
- EndPrimitive();
-}
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_process_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_process_vert.glsl
deleted file mode 100644
index 95e6a48b81f..00000000000
--- a/source/blender/draw/engines/eevee/shaders/shadow_process_vert.glsl
+++ /dev/null
@@ -1,32 +0,0 @@
-
-layout(std140) uniform shadow_render_block
-{
- /* Use vectors to avoid alignment padding. */
- ivec4 shadowSampleCount;
- vec4 shadowInvSampleCount;
- vec4 filterSize;
- int viewCount;
- int baseId;
- float cubeTexelSize;
- float storedTexelSize;
- float nearClip;
- float farClip;
- float exponent;
-};
-
-out int layerID_g;
-
-void main()
-{
- int v = gl_VertexID % 3;
- layerID_g = gl_VertexID / 3;
- float x = -1.0 + float((v & 1) << 2);
- float y = -1.0 + float((v & 2) << 1);
- gl_Position = vec4(x, y, 1.0, 1.0);
-
- /* HACK avoid changing drawcall parameters. */
- if (layerID_g >= viewCount) {
- gl_Position = vec4(0.0);
- }
- layerID_g += baseId;
-}
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl
deleted file mode 100644
index 5c19ccd5ce1..00000000000
--- a/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl
+++ /dev/null
@@ -1,322 +0,0 @@
-
-layout(std140) uniform shadow_render_block
-{
- /* Use vectors to avoid alignment padding. */
- ivec4 shadowSampleCount;
- vec4 shadowInvSampleCount;
- vec4 filterSize;
- int viewCount;
- int baseId;
- float cubeTexelSize;
- float storedTexelSize;
- float nearClip;
- float farClip;
- float exponent;
-};
-
-#ifdef CSM
-uniform sampler2DArray shadowTexture;
-#else
-uniform samplerCube shadowTexture;
-#endif
-
-flat in int layerID;
-
-#ifdef CSM
-# define cascadeID layerID
-#else
-# define cascadeID 0
-#endif
-
-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;
-}
-
-/* Marco Salvi's GDC 2008 presentation about shadow maps pre-filtering techniques slide 24 */
-/* http://advances.realtimerendering.com/s2009/SIGGRAPH%202009%20-%20Lighting%20Research%20at%20Bungie.pdf
- * Slide 55. */
-#define ln_space_prefilter_step(ref, sample) exp(sample - ref)
-#define ln_space_prefilter_finalize(ref, sum) (ref + log(shadowInvSampleCount[cascadeID] * sum))
-
-#ifdef CSM
-vec3 get_texco(vec3 cos, const vec2 ofs)
-{
- cos.xy += ofs * filterSize[cascadeID];
- return cos;
-}
-#else /* CUBEMAP */
-/* global vars */
-vec3 T = vec3(0.0);
-vec3 B = vec3(0.0);
-
-void make_orthonormal_basis(vec3 N)
-{
- vec3 UpVector = (abs(N.z) < 0.999) ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
- T = normalize(cross(UpVector, N));
- B = cross(N, T);
-}
-
-vec3 get_texco(vec3 cos, const vec2 ofs)
-{
- return cos + ofs.x * T + ofs.y * B;
-}
-
-#endif
-
-#ifdef ESM
-void grouped_samples_accum(vec3 cos,
- const vec2 co1,
- const vec2 co2,
- const vec2 co3,
- const vec2 co4,
- float ref,
- inout vec4 accum)
-{
- vec4 depths;
- depths.x = texture(shadowTexture, get_texco(cos, co1)).r;
- depths.y = texture(shadowTexture, get_texco(cos, co2)).r;
- depths.z = texture(shadowTexture, get_texco(cos, co3)).r;
- depths.w = texture(shadowTexture, get_texco(cos, co4)).r;
-
- accum += ln_space_prefilter_step(ref, depths);
-}
-#else /* VSM */
-void grouped_samples_accum(vec3 cos,
- const vec2 co1,
- const vec2 co2,
- const vec2 co3,
- const vec2 co4,
- float ref,
- inout vec2 accum)
-{
- vec4 depths1, depths2;
- depths1.xy = texture(shadowTexture, get_texco(cos, co1)).rg;
- depths1.zw = texture(shadowTexture, get_texco(cos, co2)).rg;
- depths2.xy = texture(shadowTexture, get_texco(cos, co3)).rg;
- depths2.zw = texture(shadowTexture, get_texco(cos, co4)).rg;
-
- accum += depths1.xy + depths1.zw + depths2.xy + depths2.zw;
-}
-#endif
-
-void main()
-{
- vec3 cos;
-
- cos.xy = gl_FragCoord.xy * storedTexelSize;
-
-#ifdef CSM
- cos.z = float(cascadeID);
-#else /* CUBEMAP */
- /* 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));
- make_orthonormal_basis(cos);
-
- T *= filterSize[cascadeID];
- B *= filterSize[cascadeID];
-#endif
-
-#ifdef ESM
- /* disc blur in log space. */
- vec4 depths;
- depths.x = texture(shadowTexture, get_texco(cos, concentric[0])).r;
- depths.y = texture(shadowTexture, get_texco(cos, concentric[1])).r;
- depths.z = texture(shadowTexture, get_texco(cos, concentric[2])).r;
- depths.w = texture(shadowTexture, get_texco(cos, concentric[3])).r;
- float ref = depths.x;
- vec4 accum = ln_space_prefilter_step(ref, depths);
-
-#else /* VSM */
- float ref = 0.0; /* UNUSED */
- vec2 accum = vec2(0.0);
- grouped_samples_accum(
- cos, concentric[0], concentric[1], concentric[2], concentric[3], ref, accum);
-#endif
-
- /**
- * Making the `grouped_samples_accum` be called within a loop would be
- * the most conventional solution, however in some older gpus, transverse the huge
- * `const vec2 concentric[]` array with variable indices is extremely slow.
- * The solution is to use constant indices to access the array.
- */
- if (shadowSampleCount[cascadeID] > 4) {
- grouped_samples_accum(
- cos, concentric[4], concentric[5], concentric[6], concentric[7], ref, accum);
- grouped_samples_accum(
- cos, concentric[8], concentric[9], concentric[10], concentric[11], ref, accum);
- grouped_samples_accum(
- cos, concentric[12], concentric[13], concentric[14], concentric[15], ref, accum);
- }
- if (shadowSampleCount[cascadeID] > 16) {
- grouped_samples_accum(
- cos, concentric[16], concentric[17], concentric[18], concentric[19], ref, accum);
- grouped_samples_accum(
- cos, concentric[20], concentric[21], concentric[22], concentric[23], ref, accum);
- grouped_samples_accum(
- cos, concentric[24], concentric[25], concentric[26], concentric[27], ref, accum);
- grouped_samples_accum(
- cos, concentric[28], concentric[29], concentric[30], concentric[31], ref, accum);
- grouped_samples_accum(
- cos, concentric[32], concentric[33], concentric[34], concentric[35], ref, accum);
- }
-#ifdef HIGH_BLUR
- if (shadowSampleCount[cascadeID] > 36) {
- grouped_samples_accum(
- cos, concentric[36], concentric[37], concentric[38], concentric[39], ref, accum);
- grouped_samples_accum(
- cos, concentric[40], concentric[41], concentric[42], concentric[43], ref, accum);
- grouped_samples_accum(
- cos, concentric[44], concentric[45], concentric[46], concentric[47], ref, accum);
- grouped_samples_accum(
- cos, concentric[48], concentric[49], concentric[50], concentric[51], ref, accum);
- grouped_samples_accum(
- cos, concentric[52], concentric[53], concentric[54], concentric[55], ref, accum);
- grouped_samples_accum(
- cos, concentric[56], concentric[57], concentric[58], concentric[59], ref, accum);
- grouped_samples_accum(
- cos, concentric[60], concentric[61], concentric[62], concentric[63], ref, accum);
- }
- if (shadowSampleCount[cascadeID] > 64) {
- grouped_samples_accum(
- cos, concentric[64], concentric[65], concentric[66], concentric[67], ref, accum);
- grouped_samples_accum(
- cos, concentric[68], concentric[69], concentric[70], concentric[71], ref, accum);
- grouped_samples_accum(
- cos, concentric[72], concentric[73], concentric[74], concentric[75], ref, accum);
- grouped_samples_accum(
- cos, concentric[76], concentric[77], concentric[78], concentric[79], ref, accum);
- grouped_samples_accum(
- cos, concentric[80], concentric[81], concentric[82], concentric[83], ref, accum);
- grouped_samples_accum(
- cos, concentric[84], concentric[85], concentric[86], concentric[87], ref, accum);
- grouped_samples_accum(
- cos, concentric[88], concentric[89], concentric[90], concentric[91], ref, accum);
- grouped_samples_accum(
- cos, concentric[92], concentric[93], concentric[94], concentric[95], ref, accum);
- grouped_samples_accum(
- cos, concentric[96], concentric[97], concentric[98], concentric[99], ref, accum);
- }
- if (shadowSampleCount[cascadeID] > 100) {
- grouped_samples_accum(
- cos, concentric[100], concentric[101], concentric[102], concentric[103], ref, accum);
- grouped_samples_accum(
- cos, concentric[104], concentric[105], concentric[106], concentric[107], ref, accum);
- grouped_samples_accum(
- cos, concentric[108], concentric[109], concentric[110], concentric[111], ref, accum);
- grouped_samples_accum(
- cos, concentric[112], concentric[113], concentric[114], concentric[115], ref, accum);
- grouped_samples_accum(
- cos, concentric[116], concentric[117], concentric[118], concentric[119], ref, accum);
- grouped_samples_accum(
- cos, concentric[120], concentric[121], concentric[122], concentric[123], ref, accum);
- grouped_samples_accum(
- cos, concentric[124], concentric[125], concentric[126], concentric[127], ref, accum);
- grouped_samples_accum(
- cos, concentric[128], concentric[129], concentric[130], concentric[131], ref, accum);
- grouped_samples_accum(
- cos, concentric[132], concentric[133], concentric[134], concentric[135], ref, accum);
- grouped_samples_accum(
- cos, concentric[136], concentric[137], concentric[138], concentric[139], ref, accum);
- grouped_samples_accum(
- cos, concentric[140], concentric[141], concentric[142], concentric[143], ref, accum);
- }
- if (shadowSampleCount[cascadeID] > 144) {
- grouped_samples_accum(
- cos, concentric[144], concentric[145], concentric[146], concentric[147], ref, accum);
- grouped_samples_accum(
- cos, concentric[148], concentric[149], concentric[150], concentric[151], ref, accum);
- grouped_samples_accum(
- cos, concentric[152], concentric[153], concentric[154], concentric[155], ref, accum);
- grouped_samples_accum(
- cos, concentric[156], concentric[157], concentric[158], concentric[159], ref, accum);
- grouped_samples_accum(
- cos, concentric[160], concentric[161], concentric[162], concentric[163], ref, accum);
- grouped_samples_accum(
- cos, concentric[164], concentric[165], concentric[166], concentric[167], ref, accum);
- grouped_samples_accum(
- cos, concentric[168], concentric[169], concentric[170], concentric[171], ref, accum);
- grouped_samples_accum(
- cos, concentric[172], concentric[173], concentric[174], concentric[175], ref, accum);
- grouped_samples_accum(
- cos, concentric[176], concentric[177], concentric[178], concentric[179], ref, accum);
- grouped_samples_accum(
- cos, concentric[180], concentric[181], concentric[182], concentric[183], ref, accum);
- grouped_samples_accum(
- cos, concentric[184], concentric[185], concentric[186], concentric[187], ref, accum);
- grouped_samples_accum(
- cos, concentric[188], concentric[189], concentric[190], concentric[191], ref, accum);
- grouped_samples_accum(
- cos, concentric[192], concentric[193], concentric[194], concentric[195], ref, accum);
- }
- if (shadowSampleCount[cascadeID] > 196) {
- grouped_samples_accum(
- cos, concentric[196], concentric[197], concentric[198], concentric[199], ref, accum);
- grouped_samples_accum(
- cos, concentric[200], concentric[201], concentric[202], concentric[203], ref, accum);
- grouped_samples_accum(
- cos, concentric[204], concentric[205], concentric[206], concentric[207], ref, accum);
- grouped_samples_accum(
- cos, concentric[208], concentric[209], concentric[210], concentric[211], ref, accum);
- grouped_samples_accum(
- cos, concentric[212], concentric[213], concentric[114], concentric[215], ref, accum);
- grouped_samples_accum(
- cos, concentric[216], concentric[217], concentric[218], concentric[219], ref, accum);
- grouped_samples_accum(
- cos, concentric[220], concentric[221], concentric[222], concentric[223], ref, accum);
- grouped_samples_accum(
- cos, concentric[224], concentric[225], concentric[226], concentric[227], ref, accum);
- grouped_samples_accum(
- cos, concentric[228], concentric[229], concentric[230], concentric[231], ref, accum);
- grouped_samples_accum(
- cos, concentric[232], concentric[233], concentric[234], concentric[235], ref, accum);
- grouped_samples_accum(
- cos, concentric[236], concentric[237], concentric[238], concentric[239], ref, accum);
- grouped_samples_accum(
- cos, concentric[240], concentric[241], concentric[242], concentric[243], ref, accum);
- grouped_samples_accum(
- cos, concentric[244], concentric[245], concentric[246], concentric[247], ref, accum);
- grouped_samples_accum(
- cos, concentric[248], concentric[249], concentric[250], concentric[251], ref, accum);
- grouped_samples_accum(
- cos, concentric[252], concentric[253], concentric[254], concentric[255], ref, accum);
- }
-#endif
-
-#ifdef ESM
- accum.x = dot(vec4(1.0), accum);
- accum.x = ln_space_prefilter_finalize(ref, accum.x);
- FragColor = accum.xxxx;
-
-#else /* VSM */
- FragColor = accum.xyxy * shadowInvSampleCount[cascadeID];
-#endif
-}
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 10ab7c13631..e3713fdee8f 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -346,6 +346,7 @@ typedef enum {
/** Use dual source blending. WARNING: Only one color buffer allowed. */
DRW_STATE_BLEND_CUSTOM = (1 << 23),
+ DRW_STATE_SHADOW_OFFSET = (1 << 27),
DRW_STATE_CLIP_PLANES = (1 << 28),
DRW_STATE_WIRE_SMOOTH = (1 << 29),
DRW_STATE_FIRST_VERTEX_CONVENTION = (1 << 30),
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 50408015fbc..0d19a257cfa 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -279,6 +279,23 @@ void drw_state_set(DRWState state)
}
}
+ /* Shadow Bias */
+ {
+ int test;
+ if ((test = CHANGED_TO(DRW_STATE_SHADOW_OFFSET))) {
+ if (test == 1) {
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glEnable(GL_POLYGON_OFFSET_LINE);
+ /* 2.0 Seems to be the lowest possible slope bias that works in every case. */
+ glPolygonOffset(2.0f, 1.0f);
+ }
+ else {
+ glDisable(GL_POLYGON_OFFSET_FILL);
+ glDisable(GL_POLYGON_OFFSET_LINE);
+ }
+ }
+ }
+
/* Clip Planes */
{
int test;
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index 7d096058e4c..2930b6d13cc 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -46,8 +46,9 @@ typedef enum {
GPU_FB_COLOR_ATTACHMENT2,
GPU_FB_COLOR_ATTACHMENT3,
GPU_FB_COLOR_ATTACHMENT4,
+ GPU_FB_COLOR_ATTACHMENT5,
/* Number of maximum output slots.
- * We support 5 outputs for now (usually we wouldn't need more to preserve fill rate). */
+ * We support 6 outputs for now (usually we wouldn't need more to preserve fill rate). */
/* Keep in mind that GL max is GL_MAX_DRAW_BUFFERS and is at least 8, corresponding to
* the maximum number of COLOR attachments specified by glDrawBuffers. */
GPU_FB_MAX_ATTACHEMENT,
@@ -82,6 +83,7 @@ static GLenum convert_attachment_type_to_gl(GPUAttachmentType type)
[GPU_FB_COLOR_ATTACHMENT2] = GL_COLOR_ATTACHMENT2,
[GPU_FB_COLOR_ATTACHMENT3] = GL_COLOR_ATTACHMENT3,
[GPU_FB_COLOR_ATTACHMENT4] = GL_COLOR_ATTACHMENT4,
+ [GPU_FB_COLOR_ATTACHMENT5] = GL_COLOR_ATTACHMENT5,
};
return table[type];
}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl
index 14acf9925a2..e029905a908 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl
@@ -3,7 +3,7 @@ void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result)
{
N = normalize(N);
result = CLOSURE_DEFAULT;
- eevee_closure_diffuse(N, color.rgb, 1.0, result.radiance);
+ eevee_closure_diffuse(N, color.rgb, 1.0, true, result.radiance);
closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result);
result.radiance *= color.rgb;
}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl
index e69a53b6596..34062cc8d02 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl
@@ -25,6 +25,7 @@ void node_eevee_specular(vec4 diffuse,
clearcoat * 0.25,
clearcoat_roughness,
occlusion,
+ true,
out_diff,
out_spec,
ssr_spec);
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl
index 8cc8ba2dd15..5038cb3892f 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl
@@ -6,8 +6,17 @@ void node_bsdf_glass(
vec3 out_spec, out_refr, ssr_spec;
vec3 refr_color = (refractionDepth > 0.0) ? color.rgb * color.rgb :
color.rgb; /* Simulate 2 transmission event */
- eevee_closure_glass(
- N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec);
+ eevee_closure_glass(N,
+ vec3(1.0),
+ vec3(1.0),
+ int(ssr_id),
+ roughness,
+ 1.0,
+ ior,
+ true,
+ out_spec,
+ out_refr,
+ ssr_spec);
out_refr *= refr_color;
out_spec *= color.rgb;
float fresnel = F_eta(ior, dot(N, cameraVec));
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl
index 4d582e63725..75cc2e770c5 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl
@@ -3,7 +3,8 @@ void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Clo
{
N = normalize(N);
vec3 out_spec, ssr_spec;
- eevee_closure_glossy(N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, out_spec, ssr_spec);
+ eevee_closure_glossy(
+ N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, true, out_spec, ssr_spec);
vec3 vN = mat3(ViewMatrix) * N;
result = CLOSURE_DEFAULT;
result.radiance = out_spec * color.rgb;
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
index c6b640c572d..140213a9ed9 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
@@ -66,7 +66,7 @@ void node_bsdf_principled(vec4 base_color,
sheen *= dielectric;
subsurface_color *= dielectric;
- vec3 diffuse, f0, out_diff, out_spec, out_trans, out_refr, ssr_spec;
+ vec3 diffuse, f0, out_diff, out_spec, out_refr, ssr_spec;
vec3 ctint = tint_from_color(base_color.rgb);
convert_metallic_to_specular_tinted(
base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0);
@@ -99,8 +99,8 @@ void node_bsdf_principled(vec4 base_color,
1.0,
sss_scalef,
ior,
+ true,
out_diff,
- out_trans,
out_spec,
out_refr,
ssr_spec);
@@ -116,24 +116,8 @@ void node_bsdf_principled(vec4 base_color,
closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
- vec3 sss_radiance = (out_diff + out_trans) * alpha;
-# ifndef USE_SSS
- result.radiance += sss_radiance * mixed_ss_base_color * (1.0 - transmission);
-# else
-# ifdef USE_SSS_ALBEDO
- vec3 sss_albedo = mixed_ss_base_color;
-# else
- sss_radiance *= mixed_ss_base_color;
-# endif
- sss_radiance *= (1.0 - transmission);
- closure_load_sss_data(sss_scalef,
- sss_radiance,
-# ifdef USE_SSS_ALBEDO
- sss_albedo,
-# endif
- int(sss_id),
- result);
-# endif /* USE_SSS */
+ mixed_ss_base_color *= alpha * (1.0 - transmission);
+ closure_load_sss_data(sss_scalef, out_diff, mixed_ss_base_color, int(sss_id), result);
result.radiance += emission.rgb;
result.radiance *= alpha;
@@ -181,7 +165,7 @@ void node_bsdf_principled_dielectric(vec4 base_color,
vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint);
eevee_closure_default(
- N, diffuse, f0, vec3(1.0), int(ssr_id), roughness, 1.0, out_diff, out_spec, ssr_spec);
+ N, diffuse, f0, vec3(1.0), int(ssr_id), roughness, 1.0, true, out_diff, out_spec, ssr_spec);
result = CLOSURE_DEFAULT;
result.radiance = out_spec + out_diff * (diffuse + out_sheen);
@@ -224,7 +208,8 @@ void node_bsdf_principled_metallic(vec4 base_color,
vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic);
- eevee_closure_glossy(N, base_color.rgb, f90, int(ssr_id), roughness, 1.0, out_spec, ssr_spec);
+ eevee_closure_glossy(
+ N, base_color.rgb, f90, int(ssr_id), roughness, 1.0, true, out_spec, ssr_spec);
result = CLOSURE_DEFAULT;
result.radiance = out_spec;
@@ -276,6 +261,7 @@ void node_bsdf_principled_clearcoat(vec4 base_color,
clearcoat * 0.25,
clearcoat_roughness,
1.0,
+ true,
out_spec,
ssr_spec);
@@ -318,7 +304,7 @@ void node_bsdf_principled_subsurface(vec4 base_color,
metallic = saturate(metallic);
N = normalize(N);
- vec3 diffuse, f0, out_diff, out_spec, out_trans, ssr_spec;
+ vec3 diffuse, f0, out_diff, out_spec, ssr_spec;
vec3 ctint = tint_from_color(base_color.rgb);
convert_metallic_to_specular_tinted(
base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0);
@@ -340,8 +326,8 @@ void node_bsdf_principled_subsurface(vec4 base_color,
roughness,
1.0,
sss_scalef,
+ true,
out_diff,
- out_trans,
out_spec,
ssr_spec);
@@ -349,24 +335,8 @@ void node_bsdf_principled_subsurface(vec4 base_color,
result.radiance = out_spec;
closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
- vec3 sss_radiance = (out_diff + out_trans) * alpha;
-# ifndef USE_SSS
- result.radiance += sss_radiance * mixed_ss_base_color * (1.0 - transmission);
-# else
-# ifdef USE_SSS_ALBEDO
- vec3 sss_albedo = mixed_ss_base_color;
-# else
- sss_radiance *= mixed_ss_base_color;
-# endif
- sss_radiance *= (1.0 - transmission);
- closure_load_sss_data(sss_scalef,
- sss_radiance,
-# ifdef USE_SSS_ALBEDO
- sss_albedo,
-# endif
- int(sss_id),
- result);
-# endif /* USE_SSS */
+ mixed_ss_base_color *= alpha * (1.0 - transmission);
+ closure_load_sss_data(sss_scalef, out_diff, mixed_ss_base_color, int(sss_id), result);
result.radiance += out_diff * out_sheen;
result.radiance += emission.rgb;
@@ -408,8 +378,17 @@ void node_bsdf_principled_glass(vec4 base_color,
vec3 f0, out_spec, out_refr, ssr_spec;
f0 = mix(vec3(1.0), base_color.rgb, specular_tint);
- eevee_closure_glass(
- N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec);
+ eevee_closure_glass(N,
+ vec3(1.0),
+ vec3(1.0),
+ int(ssr_id),
+ roughness,
+ 1.0,
+ ior,
+ true,
+ out_spec,
+ out_refr,
+ ssr_spec);
vec3 refr_color = base_color.rgb;
refr_color *= (refractionDepth > 0.0) ? refr_color :
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl
index 04394a9420b..906964e1539 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl
@@ -4,7 +4,7 @@ void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Cl
N = normalize(N);
vec3 out_refr;
color.rgb *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0); /* Simulate 2 absorption event. */
- eevee_closure_refraction(N, roughness, ior, out_refr);
+ eevee_closure_refraction(N, roughness, ior, true, out_refr);
vec3 vN = mat3(ViewMatrix) * N;
result = CLOSURE_DEFAULT;
result.ssr_normal = normal_encode(vN, viewCameraVec);
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_shader_to_rgba.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_shader_to_rgba.glsl
index 0a587c7e471..4f6df238789 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_shader_to_rgba.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_shader_to_rgba.glsl
@@ -15,11 +15,7 @@ void node_shader_to_rgba(Closure cl, out vec4 outcol, out float outalpha)
outcol = vec4((spec_accum.rgb * cl.ssr_data.rgb) + cl.radiance, 1.0);
# ifdef USE_SSS
-# ifdef USE_SSS_ALBEDO
- outcol.rgb += cl.sss_data.rgb * cl.sss_albedo;
-# else
- outcol.rgb += cl.sss_data.rgb;
-# endif
+ outcol.rgb += cl.sss_irradiance.rgb * cl.sss_albedo;
# endif
}
#endif /* VOLUMETRICS */
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl
index fc81f3c4674..241228c0d4c 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl
@@ -8,33 +8,18 @@ void node_subsurface_scattering(vec4 color,
float sss_id,
out Closure result)
{
-# if defined(USE_SSS)
N = normalize(N);
- vec3 out_diff, out_trans;
+ vec3 out_diff;
vec3 vN = mat3(ViewMatrix) * N;
result = CLOSURE_DEFAULT;
closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result);
- eevee_closure_subsurface(N, color.rgb, 1.0, scale, out_diff, out_trans);
+ eevee_closure_subsurface(N, color.rgb, 1.0, scale, true, out_diff);
- vec3 sss_radiance = out_diff + out_trans;
-# ifdef USE_SSS_ALBEDO
/* Not perfect for texture_blur not exactly equal to 0.0 or 1.0. */
vec3 sss_albedo = mix(color.rgb, vec3(1.0), texture_blur);
- sss_radiance *= mix(vec3(1.0), color.rgb, texture_blur);
-# else
- sss_radiance *= color.rgb;
-# endif
- closure_load_sss_data(scale,
- sss_radiance,
-# ifdef USE_SSS_ALBEDO
- sss_albedo,
-# endif
- int(sss_id),
- result);
-# else
- node_bsdf_diffuse(color, 0.0, N, result);
-# endif
+ out_diff *= mix(vec3(1.0), color.rgb, texture_blur);
+ closure_load_sss_data(scale, out_diff, sss_albedo, int(sss_id), result);
}
#else
/* Stub subsurface scattering because it is not compatible with volumetrics. */
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl
index ea41790e6aa..749b3a4c11f 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl
@@ -1,7 +1,11 @@
#ifndef VOLUMETRICS
void node_bsdf_translucent(vec4 color, vec3 N, out Closure result)
{
- node_bsdf_diffuse(color, 0.0, -N, result);
+ N = normalize(N);
+ result = CLOSURE_DEFAULT;
+ eevee_closure_diffuse(-N, color.rgb, 1.0, false, result.radiance);
+ closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result);
+ result.radiance *= color.rgb;
}
#else
/* Stub translucent because it is not compatible with volumetrics. */
diff --git a/source/blender/makesdna/DNA_light_types.h b/source/blender/makesdna/DNA_light_types.h
index 82cab5d1594..ec83d53da5e 100644
--- a/source/blender/makesdna/DNA_light_types.h
+++ b/source/blender/makesdna/DNA_light_types.h
@@ -58,7 +58,10 @@ typedef struct Light {
char _pad2[2];
float clipsta, clipend;
- float bias, soft, bleedbias, bleedexp;
+ float bias;
+ float soft; /* DEPRECATED kept for compatibility. */
+ float bleedbias; /* DEPRECATED kept for compatibility. */
+ float bleedexp; /* DEPRECATED kept for compatibility. */
short bufsize, samp, buffers, filtertype;
char bufflag, buftype;
@@ -82,7 +85,10 @@ typedef struct Light {
float cascade_fade;
int cascade_count;
- float contact_dist, contact_bias, contact_spread, contact_thickness;
+ float contact_dist;
+ float contact_bias;
+ float contact_spread; /* DEPRECATED kept for compatibility. */
+ float contact_thickness;
float spec_fac, att_dist;
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 5e96759bc90..58778bebf4a 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1637,7 +1637,7 @@ typedef struct SceneEEVEE {
int motion_blur_samples;
float motion_blur_shutter;
- int shadow_method;
+ int shadow_method DNA_DEPRECATED;
int shadow_cube_size;
int shadow_cascade_size;
@@ -2392,7 +2392,7 @@ enum {
SCE_EEVEE_SHADOW_HIGH_BITDEPTH = (1 << 10),
SCE_EEVEE_TAA_REPROJECTION = (1 << 11),
// SCE_EEVEE_SSS_ENABLED = (1 << 12), /* Unused */
- SCE_EEVEE_SSS_SEPARATE_ALBEDO = (1 << 13),
+ // SCE_EEVEE_SSS_SEPARATE_ALBEDO = (1 << 13), /* Unused */
SCE_EEVEE_SSR_ENABLED = (1 << 14),
SCE_EEVEE_SSR_REFRACTION = (1 << 15),
SCE_EEVEE_SSR_HALF_RESOLUTION = (1 << 16),
diff --git a/source/blender/makesrna/intern/rna_light.c b/source/blender/makesrna/intern/rna_light.c
index 8640c35f1b8..7357bd870fb 100644
--- a/source/blender/makesrna/intern/rna_light.c
+++ b/source/blender/makesrna/intern/rna_light.c
@@ -297,16 +297,6 @@ static void rna_def_light_shadow(StructRNA *srna, bool sun)
"Shadow map clip start, below which objects will not generate shadows");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
- prop = RNA_def_property(srna, "shadow_buffer_clip_end", PROP_FLOAT, PROP_DISTANCE);
- RNA_def_property_float_sdna(prop, NULL, "clipend");
- RNA_def_property_float_default(prop, 40.0f);
- RNA_def_property_range(prop, 1e-6f, FLT_MAX);
- RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
- RNA_def_property_ui_text(prop,
- "Shadow Buffer Clip End",
- "Shadow map clip end, beyond which objects will not generate shadows");
- RNA_def_property_update(prop, 0, "rna_Light_draw_update");
-
prop = RNA_def_property(srna, "shadow_buffer_bias", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "bias");
RNA_def_property_float_default(prop, 1.0f);
@@ -315,28 +305,6 @@ static void rna_def_light_shadow(StructRNA *srna, bool sun)
RNA_def_property_ui_text(prop, "Shadow Buffer Bias", "Bias for reducing self shadowing");
RNA_def_property_update(prop, 0, "rna_Light_update");
- prop = RNA_def_property(srna, "shadow_buffer_bleed_bias", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "bleedbias");
- RNA_def_property_range(prop, 0.f, 1.f);
- RNA_def_property_ui_text(
- prop, "Shadow Buffer Bleed Bias", "Bias for reducing light-bleed on variance shadow maps");
- RNA_def_property_update(prop, 0, "rna_Light_update");
-
- prop = RNA_def_property(srna, "shadow_buffer_exp", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "bleedexp");
- RNA_def_property_float_default(prop, 2.5f);
- RNA_def_property_range(prop, 1.0f, 9999.0f);
- RNA_def_property_ui_text(
- prop, "Shadow Buffer Exponent", "Bias for reducing light-bleed on exponential shadow maps");
- RNA_def_property_update(prop, 0, "rna_Light_update");
-
- prop = RNA_def_property(srna, "shadow_buffer_soft", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "soft");
- RNA_def_property_float_default(prop, 3.0f);
- RNA_def_property_range(prop, 0.0f, 100.0f);
- RNA_def_property_ui_text(prop, "Shadow Buffer Soft", "Size of shadow buffer sampling area");
- RNA_def_property_update(prop, 0, "rna_Light_update");
-
prop = RNA_def_property(srna, "shadow_buffer_samples", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "samp");
RNA_def_property_range(prop, 1, 16);
@@ -386,14 +354,6 @@ static void rna_def_light_shadow(StructRNA *srna, bool sun)
RNA_def_property_ui_text(prop, "Contact Shadow Bias", "Bias to avoid self shadowing");
RNA_def_property_update(prop, 0, "rna_Light_update");
- prop = RNA_def_property(srna, "contact_shadow_soft_size", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "contact_spread");
- RNA_def_property_float_default(prop, 0.2f);
- RNA_def_property_range(prop, 0.0f, 9999.0f);
- RNA_def_property_ui_text(
- prop, "Contact Shadow Soft", "Control how soft the contact shadows will be");
- RNA_def_property_update(prop, 0, "rna_Light_update");
-
prop = RNA_def_property(srna, "contact_shadow_thickness", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "contact_thickness");
RNA_def_property_float_default(prop, 0.2f);
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index f37ee5ff817..0ddf91d24db 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -6662,12 +6662,6 @@ static void rna_def_scene_eevee(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
- static const EnumPropertyItem eevee_shadow_method_items[] = {
- {SHADOW_ESM, "ESM", 0, "ESM", "Exponential Shadow Mapping"},
- {SHADOW_VSM, "VSM", 0, "VSM", "Variance Shadow Mapping"},
- {0, NULL, 0, NULL, NULL},
- };
-
static const EnumPropertyItem eevee_shadow_size_items[] = {
{64, "64", 0, "64px", ""},
{128, "128", 0, "128px", ""},
@@ -6837,16 +6831,6 @@ static void rna_def_scene_eevee(BlenderRNA *brna)
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
- prop = RNA_def_property(srna, "use_sss_separate_albedo", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SSS_SEPARATE_ALBEDO);
- RNA_def_property_boolean_default(prop, 0);
- RNA_def_property_ui_text(prop,
- "Separate Albedo",
- "Avoid albedo being blurred by the subsurface scattering "
- "but uses more video memory");
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-
/* Screen Space Reflection */
prop = RNA_def_property(srna, "use_ssr", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SSR_ENABLED);
@@ -7127,13 +7111,6 @@ static void rna_def_scene_eevee(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
/* Shadows */
- prop = RNA_def_property(srna, "shadow_method", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_default(prop, SHADOW_ESM);
- RNA_def_property_enum_items(prop, eevee_shadow_method_items);
- RNA_def_property_ui_text(prop, "Method", "Technique use to compute the shadows");
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-
prop = RNA_def_property(srna, "shadow_cube_size", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_default(prop, 512);
RNA_def_property_enum_items(prop, eevee_shadow_size_items);