From 8b7a83a868c03f3d721eb83498923673c2addb27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Fri, 1 Sep 2017 15:59:01 +0200 Subject: Eevee: Refactor Shadow System - Use only one 2d texture array to store all shadowmaps. - Allow to change shadow maps resolution. - Do not output radial distance when rendering shadowmaps. This will allow fast rendering of shadowmaps when we will drop the use of geometry shaders. --- source/blender/draw/CMakeLists.txt | 2 - source/blender/draw/engines/eevee/eevee_data.c | 14 +- source/blender/draw/engines/eevee/eevee_effects.c | 2 +- source/blender/draw/engines/eevee/eevee_engine.c | 3 + source/blender/draw/engines/eevee/eevee_lights.c | 233 ++++++++++----------- .../blender/draw/engines/eevee/eevee_materials.c | 4 +- source/blender/draw/engines/eevee/eevee_private.h | 49 ++--- .../engines/eevee/shaders/bsdf_common_lib.glsl | 34 ++- .../draw/engines/eevee/shaders/lamps_lib.glsl | 27 ++- .../draw/engines/eevee/shaders/prepass_frag.glsl | 9 - .../draw/engines/eevee/shaders/shadow_frag.glsl | 15 +- .../draw/engines/eevee/shaders/shadow_geom.glsl | 8 +- .../engines/eevee/shaders/shadow_store_frag.glsl | 158 +++++++++----- .../engines/eevee/shaders/shadow_store_geom.glsl | 24 --- .../engines/eevee/shaders/shadow_store_vert.glsl | 8 - source/blender/draw/intern/draw_manager.c | 2 + 16 files changed, 289 insertions(+), 303 deletions(-) delete mode 100644 source/blender/draw/engines/eevee/shaders/shadow_store_geom.glsl delete mode 100644 source/blender/draw/engines/eevee/shaders/shadow_store_vert.glsl diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 63f466d3792..c9f0dedfbdd 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -154,8 +154,6 @@ data_to_c_simple(engines/eevee/shaders/shadow_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/shadow_geom.glsl SRC) data_to_c_simple(engines/eevee/shaders/shadow_vert.glsl SRC) data_to_c_simple(engines/eevee/shaders/shadow_store_frag.glsl SRC) -data_to_c_simple(engines/eevee/shaders/shadow_store_geom.glsl SRC) -data_to_c_simple(engines/eevee/shaders/shadow_store_vert.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_direct_lib.glsl SRC) diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c index 36d91c0cc28..28c049ae53e 100644 --- a/source/blender/draw/engines/eevee/eevee_data.c +++ b/source/blender/draw/engines/eevee/eevee_data.c @@ -39,15 +39,11 @@ static void eevee_scene_layer_data_free(void *storage) DRW_UBO_FREE_SAFE(sldata->light_ubo); DRW_UBO_FREE_SAFE(sldata->shadow_ubo); DRW_UBO_FREE_SAFE(sldata->shadow_render_ubo); - DRW_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cube_target_fb); - DRW_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cube_fb); - DRW_FRAMEBUFFER_FREE_SAFE(sldata->shadow_map_fb); - DRW_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cascade_fb); - DRW_TEXTURE_FREE_SAFE(sldata->shadow_depth_cube_target); - DRW_TEXTURE_FREE_SAFE(sldata->shadow_color_cube_target); - DRW_TEXTURE_FREE_SAFE(sldata->shadow_depth_cube_pool); - DRW_TEXTURE_FREE_SAFE(sldata->shadow_depth_map_pool); - DRW_TEXTURE_FREE_SAFE(sldata->shadow_depth_cascade_pool); + DRW_FRAMEBUFFER_FREE_SAFE(sldata->shadow_target_fb); + DRW_FRAMEBUFFER_FREE_SAFE(sldata->shadow_store_fb); + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_target); + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_target); + DRW_TEXTURE_FREE_SAFE(sldata->shadow_pool); BLI_freelistN(&sldata->shadow_casters); /* Probes */ diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index ace350cada1..cacfd5a5957 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -811,7 +811,7 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) if (grp != NULL) { DRW_shgroup_uniform_buffer(grp, "depthFull", &e_data.depth_src); - DRW_shgroup_uniform_buffer(grp, "shadowCubes", &sldata->shadow_depth_cube_pool); + DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_pool); DRW_shgroup_uniform_buffer(grp, "irradianceGrid", &sldata->irradiance_pool); DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 9ab551ad949..735c3a77c5d 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -309,6 +309,9 @@ static void EEVEE_scene_layer_settings_create(RenderEngine *UNUSED(engine), IDPr BKE_collection_engine_property_add_bool(props, "motion_blur_enable", false); BKE_collection_engine_property_add_int(props, "motion_blur_samples", 8); BKE_collection_engine_property_add_float(props, "motion_blur_shutter", 1.0f); + + BKE_collection_engine_property_add_int(props, "shadow_method", SHADOW_ESM); + BKE_collection_engine_property_add_int(props, "shadow_size", 512); } static const DrawEngineDataSize EEVEE_data_size = DRW_VIEWPORT_DATA_SIZE(EEVEE_Data); diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index 8f5c633c24a..6af1ad63fd7 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -42,11 +42,6 @@ typedef struct EEVEE_ShadowCubeData { float viewprojmat[6][4][4]; } EEVEE_ShadowCubeData; -typedef struct EEVEE_ShadowMapData { - short light_id, shadow_id; - float viewprojmat[4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */ -} EEVEE_ShadowMapData; - typedef struct EEVEE_ShadowCascadeData { short light_id, shadow_id; float viewprojmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */ @@ -60,14 +55,13 @@ typedef struct ShadowCaster { static struct { struct GPUShader *shadow_sh; - struct GPUShader *shadow_store_sh; + struct GPUShader *shadow_store_cube_sh; + struct GPUShader *shadow_store_cascade_sh; } e_data = {NULL}; /* Engine data */ extern char datatoc_shadow_vert_glsl[]; extern char datatoc_shadow_geom_glsl[]; extern char datatoc_shadow_frag_glsl[]; -extern char datatoc_shadow_store_vert_glsl[]; -extern char datatoc_shadow_store_geom_glsl[]; extern char datatoc_shadow_store_frag_glsl[]; /* *********** FUNCTIONS *********** */ @@ -75,15 +69,18 @@ extern char datatoc_shadow_store_frag_glsl[]; void EEVEE_lights_init(EEVEE_SceneLayerData *sldata) { const unsigned int shadow_ubo_size = sizeof(EEVEE_ShadowCube) * MAX_SHADOW_CUBE + - sizeof(EEVEE_ShadowMap) * MAX_SHADOW_MAP + sizeof(EEVEE_ShadowCascade) * MAX_SHADOW_CASCADE; + const DRWContextState *draw_ctx = DRW_context_state_get(); + SceneLayer *scene_layer = draw_ctx->scene_layer; + IDProperty *props = BKE_scene_layer_engine_evaluated_get(scene_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE); + if (!e_data.shadow_sh) { e_data.shadow_sh = DRW_shader_create( datatoc_shadow_vert_glsl, datatoc_shadow_geom_glsl, datatoc_shadow_frag_glsl, NULL); - e_data.shadow_store_sh = DRW_shader_create( - datatoc_shadow_store_vert_glsl, datatoc_shadow_store_geom_glsl, datatoc_shadow_store_frag_glsl, NULL); + e_data.shadow_store_cube_sh = DRW_shader_create_fullscreen(datatoc_shadow_store_frag_glsl, NULL); + e_data.shadow_store_cascade_sh = DRW_shader_create_fullscreen(datatoc_shadow_store_frag_glsl, "#define CSM"); } if (!sldata->lamps) { @@ -92,23 +89,58 @@ void EEVEE_lights_init(EEVEE_SceneLayerData *sldata) sldata->shadow_ubo = DRW_uniformbuffer_create(shadow_ubo_size, NULL); sldata->shadow_render_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_ShadowRender), NULL); } + + int sh_method = BKE_collection_engine_property_value_get_int(props, "shadow_method"); + int sh_size = BKE_collection_engine_property_value_get_int(props, "shadow_size"); + UNUSED_VARS(sh_method); + + EEVEE_LampsInfo *linfo = sldata->lamps; + if (linfo->shadow_size != sh_size) { + BLI_assert((sh_size > 0) && (sh_size <= 8192)); + DRW_TEXTURE_FREE_SAFE(sldata->shadow_pool); + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_target); + + linfo->shadow_size = sh_size; + linfo->shadow_render_data.stored_texel_size = 1.0 / (float)linfo->shadow_size; + + /* Compute adequate size for the cubemap render target. + * The 3.0f factor is here to make sure there is no under sampling between + * the octahedron mapping and the cubemap. */ + int new_cube_target_size = (int)ceil(sqrt((float)(sh_size * sh_size) / 6.0f) * 3.0f); + + CLAMP(new_cube_target_size, 1, 4096); + + if (linfo->shadow_cube_target_size != new_cube_target_size) { + linfo->shadow_cube_target_size = new_cube_target_size; + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_target); + linfo->shadow_render_data.cube_texel_size = 1.0 / (float)linfo->shadow_cube_target_size; + } + } } void EEVEE_lights_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl) { EEVEE_LampsInfo *linfo = sldata->lamps; - linfo->num_light = linfo->num_cube = linfo->num_map = linfo->num_cascade = 0; + linfo->num_light = linfo->num_cube = linfo->num_cascade = linfo->num_shadow = 0; memset(linfo->light_ref, 0, sizeof(linfo->light_ref)); memset(linfo->shadow_cube_ref, 0, sizeof(linfo->shadow_cube_ref)); - memset(linfo->shadow_map_ref, 0, sizeof(linfo->shadow_map_ref)); memset(linfo->shadow_cascade_ref, 0, sizeof(linfo->shadow_cascade_ref)); { psl->shadow_cube_store_pass = DRW_pass_create("Shadow Storage Pass", DRW_STATE_WRITE_COLOR); - DRWShadingGroup *grp = DRW_shgroup_create(e_data.shadow_store_sh, psl->shadow_cube_store_pass); - DRW_shgroup_uniform_buffer(grp, "shadowCube", &sldata->shadow_color_cube_target); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.shadow_store_cube_sh, psl->shadow_cube_store_pass); + DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cube_target); + DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + + { + psl->shadow_cascade_store_pass = DRW_pass_create("Shadow Cascade Storage Pass", DRW_STATE_WRITE_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_create(e_data.shadow_store_cascade_sh, psl->shadow_cascade_store_pass); + DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cascade_target); DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo); DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); } @@ -118,7 +150,7 @@ void EEVEE_lights_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl) } { - psl->shadow_cascade_pass = DRW_pass_create("Shadow Cascade Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); + psl->shadow_cascade_pass = DRW_pass_create("Shadow Cascade Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); } /* Reset shadow casters list */ @@ -147,19 +179,19 @@ void EEVEE_lights_cache_add(EEVEE_SceneLayerData *sldata, Object *ob) #if 1 /* TODO Waiting for notified refresh. only on scene change. Else too much perf cost. */ if (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY)) { if (la->type == LA_SUN && linfo->num_cascade < MAX_SHADOW_CASCADE) { -#if 0 /* TODO filter cascaded shadow map */ led->storage = MEM_mallocN(sizeof(EEVEE_ShadowCascadeData), "EEVEE_ShadowCascadeData"); - ((EEVEE_ShadowCascadeData *)led->storage)->shadow_id = linfo->num_cascade; + ((EEVEE_ShadowCascadeData *)led->storage)->shadow_id = linfo->num_shadow; linfo->shadow_cascade_ref[linfo->num_cascade] = ob; linfo->num_cascade++; -#endif + linfo->num_shadow += MAX_CASCADE_NUM; } else if ((la->type == LA_SPOT || la->type == LA_LOCAL || la->type == LA_AREA) && linfo->num_cube < MAX_SHADOW_CUBE) { led->storage = MEM_mallocN(sizeof(EEVEE_ShadowCubeData), "EEVEE_ShadowCubeData"); - ((EEVEE_ShadowCubeData *)led->storage)->shadow_id = linfo->num_cube; + ((EEVEE_ShadowCubeData *)led->storage)->shadow_id = linfo->num_shadow; linfo->shadow_cube_ref[linfo->num_cube] = ob; linfo->num_cube++; + linfo->num_shadow += 1; } } @@ -226,70 +258,58 @@ void EEVEE_lights_cache_shcaster_material_add( void EEVEE_lights_cache_finish(EEVEE_SceneLayerData *sldata) { EEVEE_LampsInfo *linfo = sldata->lamps; + DRWTextureFormat shadow_pool_format; /* Setup enough layers. */ /* Free textures if number mismatch. */ - if (linfo->num_cube != linfo->cache_num_cube) { - DRW_TEXTURE_FREE_SAFE(sldata->shadow_depth_cube_pool); + if ((linfo->num_shadow != linfo->cache_num_shadow) || + (linfo->num_cube != linfo->cache_num_cube) || + (linfo->num_cascade != linfo->cache_num_cascade)) + { + DRW_TEXTURE_FREE_SAFE(sldata->shadow_pool); linfo->cache_num_cube = linfo->num_cube; - linfo->update_flag |= LIGHT_UPDATE_SHADOW_CUBE; - } - if (linfo->num_map != linfo->cache_num_map) { - DRW_TEXTURE_FREE_SAFE(sldata->shadow_depth_map_pool); - linfo->cache_num_map = linfo->num_map; - } - if (linfo->num_cascade != linfo->cache_num_cascade) { - DRW_TEXTURE_FREE_SAFE(sldata->shadow_depth_cascade_pool); linfo->cache_num_cascade = linfo->num_cascade; + linfo->cache_num_shadow = linfo->num_shadow; + linfo->update_flag |= LIGHT_UPDATE_SHADOW_CUBE; } - /* Initialize Textures Arrays first so DRW_framebuffer_init just bind them. */ - if (!sldata->shadow_depth_cube_target) { - /* Render Cubemap */ - sldata->shadow_depth_cube_target = DRW_texture_create_cube(512, DRW_TEX_DEPTH_24, 0, NULL); - sldata->shadow_color_cube_target = DRW_texture_create_cube(512, DRW_TEX_R_32, DRW_TEX_FILTER, NULL); - if (sldata->shadow_cube_fb) { - DRW_framebuffer_texture_attach(sldata->shadow_cube_fb, sldata->shadow_depth_cube_target, 0, 0); - DRW_framebuffer_texture_attach(sldata->shadow_cube_fb, sldata->shadow_color_cube_target, 0, 0); - } - } - if (!sldata->shadow_depth_cube_pool) { - /* Cubemap / octahedral map pool */ - /* TODO Cubemap array */ - sldata->shadow_depth_cube_pool = DRW_texture_create_2D_array( - 512, 512, max_ff(1, linfo->num_cube), DRW_TEX_R_16, - DRW_TEX_FILTER | DRW_TEX_COMPARE, NULL); - if (sldata->shadow_cube_fb) { - DRW_framebuffer_texture_attach(sldata->shadow_cube_fb, sldata->shadow_depth_cube_pool, 0, 0); - } + /* TODO Variance Shadow Map */ + shadow_pool_format = DRW_TEX_R_32; + + if (!sldata->shadow_cube_target) { + /* TODO render everything on the same 2d render target using clip planes and no Geom Shader. */ + /* Cubemaps */ + sldata->shadow_cube_target = DRW_texture_create_cube(linfo->shadow_cube_target_size, DRW_TEX_DEPTH_24, 0, NULL); } - if (!sldata->shadow_depth_map_pool) { - sldata->shadow_depth_map_pool = DRW_texture_create_2D_array( - 512, 512, max_ff(1, linfo->num_map), DRW_TEX_DEPTH_24, - DRW_TEX_FILTER | DRW_TEX_COMPARE, NULL); - if (sldata->shadow_map_fb) { - DRW_framebuffer_texture_attach(sldata->shadow_map_fb, sldata->shadow_depth_map_pool, 0, 0); - } + + if (!sldata->shadow_cascade_target) { + /* CSM */ + sldata->shadow_cascade_target = DRW_texture_create_2D_array( + linfo->shadow_size, linfo->shadow_size, MAX_CASCADE_NUM, DRW_TEX_DEPTH_24, 0, NULL); } - if (!sldata->shadow_depth_cascade_pool) { - sldata->shadow_depth_cascade_pool = DRW_texture_create_2D_array( - 512, 512, max_ff(1, linfo->num_cascade * MAX_CASCADE_NUM), DRW_TEX_DEPTH_24, - DRW_TEX_FILTER | DRW_TEX_COMPARE, NULL); - if (sldata->shadow_cascade_fb) { - DRW_framebuffer_texture_attach(sldata->shadow_cascade_fb, sldata->shadow_depth_map_pool, 0, 0); - } + + /* Initialize Textures Array first so DRW_framebuffer_init just bind them. */ + if (!sldata->shadow_pool) { + /* All shadows fit in this array */ + sldata->shadow_pool = DRW_texture_create_2D_array( + linfo->shadow_size, linfo->shadow_size, max_ff(1, linfo->num_cube + linfo->num_cascade), + shadow_pool_format, DRW_TEX_FILTER, NULL); } - DRWFboTexture tex_cube_target[2] = { - {&sldata->shadow_depth_cube_target, DRW_TEX_DEPTH_24, 0}, - {&sldata->shadow_color_cube_target, DRW_TEX_R_16, DRW_TEX_FILTER}}; - DRW_framebuffer_init(&sldata->shadow_cube_target_fb, &draw_engine_eevee_type, 512, 512, tex_cube_target, 2); + /* Render FB */ + DRWFboTexture tex_cascade = {&sldata->shadow_cube_target, DRW_TEX_DEPTH_24, 0}; + DRW_framebuffer_init(&sldata->shadow_target_fb, &draw_engine_eevee_type, + linfo->shadow_size, linfo->shadow_size, + &tex_cascade, 1); - DRWFboTexture tex_cube = {&sldata->shadow_depth_cube_pool, DRW_TEX_R_16, DRW_TEX_FILTER}; - DRW_framebuffer_init(&sldata->shadow_cube_fb, &draw_engine_eevee_type, 512, 512, &tex_cube, 1); + /* Storage FB */ + DRWFboTexture tex_pool = {&sldata->shadow_pool, shadow_pool_format, DRW_TEX_FILTER}; + DRW_framebuffer_init(&sldata->shadow_store_fb, &draw_engine_eevee_type, + linfo->shadow_size, linfo->shadow_size, + &tex_pool, 1); - DRWFboTexture tex_cascade = {&sldata->shadow_depth_cascade_pool, DRW_TEX_DEPTH_24, DRW_TEX_FILTER | DRW_TEX_COMPARE}; - DRW_framebuffer_init(&sldata->shadow_cascade_fb, &draw_engine_eevee_type, 512, 512, &tex_cascade, 1); + /* Restore */ + DRW_framebuffer_texture_detach(sldata->shadow_cube_target); /* Update Lamps UBOs. */ EEVEE_lights_update(sldata); @@ -397,31 +417,6 @@ static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_La evli->shadowid = (float)(evsmp->shadow_id); } -static void eevee_shadow_map_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led) -{ - float viewmat[4][4], projmat[4][4]; - - EEVEE_ShadowMapData *evsmp = (EEVEE_ShadowMapData *)led->storage; - EEVEE_Light *evli = linfo->light_data + evsmp->light_id; - EEVEE_ShadowMap *evsh = linfo->shadow_map_data + evsmp->shadow_id; - Lamp *la = (Lamp *)ob->data; - - invert_m4_m4(viewmat, ob->obmat); - normalize_v3(viewmat[0]); - normalize_v3(viewmat[1]); - normalize_v3(viewmat[2]); - - float wsize = la->shadow_frustum_size; - orthographic_m4(projmat, -wsize, wsize, -wsize, wsize, la->clipsta, la->clipend); - - mul_m4_m4m4(evsmp->viewprojmat, projmat, viewmat); - mul_m4_m4m4(evsh->shadowmat, texcomat, evsmp->viewprojmat); - - evsh->bias = 0.005f * la->bias; - - evli->shadowid = (float)(MAX_SHADOW_CUBE + evsmp->shadow_id); -} - #define LERP(t, a, b) ((a) + (t) * ((b) - (a))) static void frustum_min_bounding_sphere(const float corners[8][4], float r_center[3], float *r_radius) @@ -589,10 +584,10 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE mul_m4_m4m4(evsh->shadowmat[c], texcomat, evscp->viewprojmat[c]); /* TODO modify bias depending on the cascade radius */ - evsh->bias[c] = 0.005f * la->bias; + evsh->bias = 0.005f * la->bias; } - evli->shadowid = (float)(MAX_SHADOW_CUBE + MAX_SHADOW_MAP + evscp->shadow_id); + evli->shadowid = (float)(MAX_SHADOW_CUBE + evscp->shadow_id); } /* Used for checking if object is inside the shadow volume. */ @@ -718,11 +713,6 @@ void EEVEE_lights_update(EEVEE_SceneLayerData *sldata) delete_pruned_shadowcaster(led); } - for (i = 0; (ob = linfo->shadow_map_ref[i]) && (i < MAX_SHADOW_MAP); i++) { - EEVEE_LampEngineData *led = EEVEE_lamp_data_get(ob); - eevee_shadow_map_setup(ob, linfo, led); - } - for (i = 0; (ob = linfo->shadow_cascade_ref[i]) && (i < MAX_SHADOW_CASCADE); i++) { EEVEE_LampEngineData *led = EEVEE_lamp_data_get(ob); eevee_shadow_cascade_setup(ob, linfo, led); @@ -738,7 +728,7 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl) EEVEE_LampsInfo *linfo = sldata->lamps; Object *ob; int i; - float clear_color[4] = {FLT_MAX, FLT_MAX, FLT_MAX, 0.0f}; + float clear_col[4] = {FLT_MAX}; /* Cube Shadow Maps */ /* Render each shadow to one layer of the array */ @@ -750,8 +740,10 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl) EEVEE_ShadowCubeData *evscd = (EEVEE_ShadowCubeData *)led->storage; EEVEE_ShadowRender *srd = &linfo->shadow_render_data; - srd->layer = i; - srd->exponent = la->bleedexp; + srd->shadow_samples_ct = 32.0f; + srd->shadow_inv_samples_ct = 1.0f / srd->shadow_samples_ct; + srd->clip_near = la->clipsta; + srd->clip_far = la->clipend; copy_v3_v3(srd->position, ob->obmat[3]); for (int j = 0; j < 6; j++) { float tmp[4][4]; @@ -762,15 +754,17 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl) copy_m4_m4(srd->shadowmat[j], evscd->viewprojmat[j]); } - DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data); + DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd); - DRW_framebuffer_bind(sldata->shadow_cube_target_fb); - DRW_framebuffer_clear(true, true, false, clear_color, 1.0f); + DRW_framebuffer_texture_attach(sldata->shadow_target_fb, sldata->shadow_cube_target, 0, 0); + DRW_framebuffer_bind(sldata->shadow_target_fb); + DRW_framebuffer_clear(true, true, false, clear_col, 1.0f); /* Render shadow cube */ DRW_draw_pass(psl->shadow_cube_pass); /* Push it to shadowmap array */ - DRW_framebuffer_bind(sldata->shadow_cube_fb); + DRW_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_pool, 0, i, 0); + DRW_framebuffer_bind(sldata->shadow_store_fb); DRW_draw_pass(psl->shadow_cube_store_pass); led->need_update = false; @@ -778,21 +772,7 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl) } linfo->update_flag &= ~LIGHT_UPDATE_SHADOW_CUBE; -#if 0 - /* Standard Shadow Maps */ - DRW_framebuffer_bind(fbl->shadow_map_fb); - DRW_framebuffer_clear(false, true, false, NULL, 1.0); - - /* Render each shadow to one layer of the array */ - for (i = 0; (ob = linfo->shadow_map_ref[i]) && (i < MAX_SHADOW_MAP); i++) { - EEVEE_LampEngineData *led = EEVEE_lamp_data_get(ob); - EEVEE_ShadowMapData *evsmd = (EEVEE_ShadowMapData *)led->storage; - - linfo->layer = i; - copy_m4_m4(linfo->shadowmat, evsmd->viewprojmat); - DRW_draw_pass(vedata->psl->shadow_pass); - } -#endif + DRW_framebuffer_texture_detach(sldata->shadow_cube_target); /* Cascaded Shadow Maps */ // DRW_framebuffer_bind(fbl->shadow_cascade_fb); @@ -817,5 +797,6 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl) void EEVEE_lights_free(void) { DRW_SHADER_FREE_SAFE(e_data.shadow_sh); - DRW_SHADER_FREE_SAFE(e_data.shadow_store_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_store_cube_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_store_cascade_sh); } \ No newline at end of file diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index a9425139ebf..e1852e44722 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -58,7 +58,6 @@ "#define MAX_PLANAR " STRINGIFY(MAX_PLANAR) "\n" \ "#define MAX_LIGHT " STRINGIFY(MAX_LIGHT) "\n" \ "#define MAX_SHADOW_CUBE " STRINGIFY(MAX_SHADOW_CUBE) "\n" \ - "#define MAX_SHADOW_MAP " STRINGIFY(MAX_SHADOW_MAP) "\n" \ "#define MAX_SHADOW_CASCADE " STRINGIFY(MAX_SHADOW_CASCADE) "\n" \ "#define MAX_CASCADE_NUM " STRINGIFY(MAX_CASCADE_NUM) "\n" \ SHADER_IRRADIANCE @@ -370,8 +369,7 @@ static void add_standard_uniforms( DRW_shgroup_uniform_buffer(shgrp, "probeCubes", &sldata->probe_pool); DRW_shgroup_uniform_buffer(shgrp, "probePlanars", &vedata->txl->planar_pool); DRW_shgroup_uniform_buffer(shgrp, "irradianceGrid", &sldata->irradiance_pool); - DRW_shgroup_uniform_buffer(shgrp, "shadowCubes", &sldata->shadow_depth_cube_pool); - DRW_shgroup_uniform_buffer(shgrp, "shadowCascades", &sldata->shadow_depth_cascade_pool); + DRW_shgroup_uniform_buffer(shgrp, "shadowTexture", &sldata->shadow_pool); DRW_shgroup_uniform_int(shgrp, "outputSsrId", ssr_id, 1); DRW_shgroup_uniform_vec4(shgrp, "aoParameters[0]", &vedata->stl->effects->ao_dist, 2); if (refract_depth != NULL) { diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 723b7789377..1089fd2c5b9 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -36,7 +36,6 @@ 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_SHADOW_CUBE 42 /* TODO : Make this depends on GL_MAX_ARRAY_TEXTURE_LAYERS */ -#define MAX_SHADOW_MAP 64 #define MAX_SHADOW_CASCADE 8 #define MAX_CASCADE_NUM 4 #define MAX_BLOOM_STEP 16 @@ -78,12 +77,19 @@ enum { VAR_MAT_REFRACT = (1 << 12), }; +/* Shadow Technique */ +enum { + SHADOW_ESM = 1, + SHADOW_VSM = 2, +}; + typedef struct EEVEE_PassList { /* Shadows */ struct DRWPass *shadow_pass; struct DRWPass *shadow_cube_pass; struct DRWPass *shadow_cube_store_pass; struct DRWPass *shadow_cascade_pass; + struct DRWPass *shadow_cascade_store_pass; /* Probes */ struct DRWPass *probe_background; @@ -206,24 +212,22 @@ typedef struct EEVEE_ShadowCube { float near, far, bias, exp; } EEVEE_ShadowCube; -typedef struct EEVEE_ShadowMap { - float shadowmat[4][4]; /* World->Lamp->NDC->Tex : used for sampling the shadow map. */ - float near, far, bias, pad; -} EEVEE_ShadowMap; - typedef struct EEVEE_ShadowCascade { float shadowmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC->Tex : used for sampling the shadow map. */ float split[4]; - float bias[4]; + float near, far, bias, pad; } EEVEE_ShadowCascade; typedef struct EEVEE_ShadowRender { - float shadowmat[6][4][4]; /* World->Lamp->NDC : used to render the shadow map. 6 frustrum for cubemap shadow */ + float shadowmat[6][4][4]; /* World->Lamp->NDC : used to render the shadow map. 6 frustum for cubemap shadow */ float viewmat[6][4][4]; /* World->Lamp : used to render the shadow map. 6 viewmat for cubemap shadow */ - float position[3]; - float pad; - int layer; - float exponent; + float position[3], pad; + float cube_texel_size; + float stored_texel_size; + float clip_near; + float clip_far; + float shadow_samples_ct; + float shadow_inv_samples_ct; } EEVEE_ShadowRender; /* ************ VOLUME DATA ************ */ @@ -237,20 +241,20 @@ typedef struct EEVEE_VolumetricsInfo { typedef struct EEVEE_LampsInfo { int num_light, cache_num_light; int num_cube, cache_num_cube; - int num_map, cache_num_map; int num_cascade, cache_num_cascade; + int num_shadow, cache_num_shadow; int update_flag; + int shadow_size, shadow_method; + int shadow_cube_target_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_map_ref[MAX_SHADOW_MAP]; 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_ShadowCube shadow_cube_data[MAX_SHADOW_CUBE]; - struct EEVEE_ShadowMap shadow_map_data[MAX_SHADOW_MAP]; struct EEVEE_ShadowCascade shadow_cascade_data[MAX_SHADOW_CASCADE]; } EEVEE_LampsInfo; @@ -401,17 +405,14 @@ typedef struct EEVEE_SceneLayerData { 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_fb; - struct GPUFrameBuffer *shadow_map_fb; - struct GPUFrameBuffer *shadow_cascade_fb; + struct GPUFrameBuffer *shadow_target_fb; + struct GPUFrameBuffer *shadow_store_fb; - struct GPUTexture *shadow_depth_cube_target; - struct GPUTexture *shadow_color_cube_target; - struct GPUTexture *shadow_depth_cube_pool; - struct GPUTexture *shadow_depth_map_pool; - struct GPUTexture *shadow_depth_cascade_pool; + struct GPUTexture *shadow_cube_target; + struct GPUTexture *shadow_cascade_target; + struct GPUTexture *shadow_pool; struct ListBase shadow_casters; /* Shadow casters gathered during cache iteration */ 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 fc339e93927..0da95349bba 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -19,8 +19,12 @@ layout(std140) uniform shadow_render_block { mat4 ShadowMatrix[6]; mat4 FaceViewMatrix[6]; vec4 lampPosition; - int layer; - float exponent; + float cubeTexelSize; + float storedTexelSize; + float nearClip; + float farClip; + float shadowSampleCount; + float shadowInvSampleCount; }; flat in int shFace; /* Shadow layer we are rendering to. */ @@ -72,23 +76,6 @@ struct ShadowCubeData { vec4 near_far_bias_exp; }; -/* convenience aliases */ -#define sh_cube_near near_far_bias_exp.x -#define sh_cube_far near_far_bias_exp.y -#define sh_cube_bias near_far_bias_exp.z -#define sh_cube_exp near_far_bias_exp.w - - -struct ShadowMapData { - mat4 shadowmat; - vec4 near_far_bias; -}; - -/* convenience aliases */ -#define sh_map_near near_far_bias.x -#define sh_map_far near_far_bias.y -#define sh_map_bias near_far_bias.z - #ifndef MAX_CASCADE_NUM #define MAX_CASCADE_NUM 4 #endif @@ -97,9 +84,15 @@ struct ShadowCascadeData { mat4 shadowmat[MAX_CASCADE_NUM]; /* arrays of float are not aligned so use vec4 */ vec4 split_distances; - vec4 bias; + vec4 near_far_bias_exp; }; +/* convenience aliases */ +#define sh_cube_near near_far_bias_exp.x +#define sh_cube_far near_far_bias_exp.y +#define sh_cube_bias near_far_bias_exp.z +#define sh_cube_exp near_far_bias_exp.w + /* ------- Convenience functions --------- */ vec3 mul(mat3 m, vec3 v) { return m * v; } @@ -114,6 +107,7 @@ vec3 project_point(mat4 m, vec3 v) { float min_v2(vec2 v) { return min(v.x, v.y); } float min_v3(vec3 v) { return min(v.x, min(v.y, v.z)); } float max_v2(vec2 v) { return max(v.x, v.y); } +float max_v3(vec3 v) { return max(v.x, max(v.y, v.z)); } float saturate(float a) { return clamp(a, 0.0, 1.0); } vec2 saturate(vec2 a) { return clamp(a, 0.0, 1.0); } diff --git a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl index 75ec5ade58d..79c04409161 100644 --- a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl @@ -1,10 +1,8 @@ -uniform sampler2DArray shadowCubes; -uniform sampler2DArrayShadow shadowCascades; +uniform sampler2DArray shadowTexture; layout(std140) uniform shadow_block { ShadowCubeData shadows_cube_data[MAX_SHADOW_CUBE]; - ShadowMapData shadows_map_data[MAX_SHADOW_MAP]; ShadowCascadeData shadows_cascade_data[MAX_SHADOW_CASCADE]; }; @@ -26,23 +24,25 @@ float shadow_cubemap(float shid, vec4 l_vector) vec3 cubevec = -l_vector.xyz / l_vector.w; float dist = l_vector.w - scd.sh_cube_bias; - float z = texture_octahedron(shadowCubes, vec4(cubevec, shid)).r; + float z = texture_octahedron(shadowTexture, vec4(cubevec, shid)).r; float esm_test = saturate(exp(scd.sh_cube_exp * (z - dist))); - // float sh_test = step(0, z - dist); + float sh_test = step(0, z - dist); return esm_test; } float shadow_cascade(float shid, vec3 W) { + return 1.0; + #if 0 /* Shadow Cascade */ - shid -= (MAX_SHADOW_CUBE + MAX_SHADOW_MAP); + shid -= MAX_SHADOW_CUBE; ShadowCascadeData smd = shadows_cascade_data[int(shid)]; /* Finding Cascade index */ - vec4 z = vec4(-dot(cameraPos - W, cameraForward)); - vec4 comp = step(z, smd.split_distances); + vec4 view_z = vec4(-dot(cameraPos - W, cameraForward)); + vec4 comp = step(view_z, smd.split_distances); float cascade = dot(comp, comp); mat4 shadowmat; float bias; @@ -68,10 +68,15 @@ float shadow_cascade(float shid, vec3 W) } vec4 shpos = shadowmat * vec4(W, 1.0); - shpos.z -= bias * shpos.w; + float dist = shpos.z - bias * shpos.w; shpos.xyz /= shpos.w; - return texture(shadowCascades, vec4(shpos.xy, shid * float(MAX_CASCADE_NUM) + cascade, shpos.z)); + float z = texture(shadowTexture, vec4(shpos.xy, shid * float(MAX_CASCADE_NUM) + cascade, shpos.z)).r; + + float esm_test = saturate(exp(smd.sh_cube_exp * (z - dist))); + + return esm_test; + #endif } float light_visibility(LightData ld, vec3 W, vec4 l_vector) @@ -97,7 +102,7 @@ float light_visibility(LightData ld, vec3 W, vec4 l_vector) #if !defined(VOLUMETRICS) || defined(VOLUME_SHADOW) /* shadowing */ - if (ld.l_shadowid >= (MAX_SHADOW_MAP + MAX_SHADOW_CUBE)) { + if (ld.l_shadowid >= MAX_SHADOW_CUBE) { vis *= shadow_cascade(ld.l_shadowid, W); } else if (ld.l_shadowid >= 0.0) { diff --git a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl index cf59b29548a..f921d56e3bc 100644 --- a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl @@ -62,10 +62,6 @@ float hashed_alpha_threshold(vec3 co) uniform float alphaThreshold; #endif -#ifdef SHADOW_SHADER -out vec4 FragColor; -#endif - void main() { /* For now do nothing. @@ -86,9 +82,4 @@ void main() discard; #endif #endif - -#ifdef SHADOW_SHADER - float dist = distance(lampPosition.xyz, worldPosition.xyz); - FragColor = vec4(dist, 0.0, 0.0, 1.0); -#endif } diff --git a/source/blender/draw/engines/eevee/shaders/shadow_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_frag.glsl index df6fbc4c2fe..160fcee4c73 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_frag.glsl @@ -1,17 +1,4 @@ -layout(std140) uniform shadow_render_block { - mat4 ShadowMatrix[6]; - mat4 FaceViewMatrix[6]; - vec4 lampPosition; - int layer; - float exponent; -}; - -in vec3 worldPosition; - -out vec4 FragColor; - void main() { - float dist = distance(lampPosition.xyz, worldPosition.xyz); - FragColor = vec4(dist, 0.0, 0.0, 1.0); + /* Do nothing */ } diff --git a/source/blender/draw/engines/eevee/shaders/shadow_geom.glsl b/source/blender/draw/engines/eevee/shaders/shadow_geom.glsl index 164b6a9940b..508df7a6b37 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_geom.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_geom.glsl @@ -3,8 +3,12 @@ layout(std140) uniform shadow_render_block { mat4 ShadowMatrix[6]; mat4 FaceViewMatrix[6]; vec4 lampPosition; - int layer; - float exponent; + float cubeTexelSize; + float storedTexelSize; + float nearClip; + float farClip; + float shadowSampleCount; + float shadowInvSampleCount; }; layout(triangles) in; diff --git a/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl index 6782922a2e4..1c0d2556e10 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl @@ -3,11 +3,19 @@ layout(std140) uniform shadow_render_block { mat4 ShadowMatrix[6]; mat4 FaceViewMatrix[6]; vec4 lampPosition; - int layer; - float exponent; + float cubeTexelSize; + float storedTexelSize; + float nearClip; + float farClip; + float shadowSampleCount; + float shadowInvSampleCount; }; -uniform samplerCube shadowCube; +#ifdef CSM +uniform sampler2DArray shadowTexture; +#else +uniform samplerCube shadowTexture; +#endif out vec4 FragColor; @@ -25,35 +33,31 @@ vec3 octahedral_to_cubemap_proj(vec2 co) return v; } -void make_orthonormal_basis(vec3 N, out vec3 T, out vec3 B) +void make_orthonormal_basis(vec3 N, float rot, out vec3 T, out vec3 B) { - vec3 UpVector = abs(N.z) < 0.99999 ? vec3(0.0,0.0,1.0) : vec3(1.0,0.0,0.0); - T = normalize( cross(UpVector, N) ); - B = cross(N, T); + vec3 UpVector = (abs(N.z) < max(abs(N.x), abs(N.y))) ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 nT = normalize(cross(UpVector, N)); + vec3 nB = cross(N, nT); + + /* Rotate tangent space */ + vec2 dir = vec2(cos(rot * 3.1415 * 2.0), sin(rot * 3.1415 * 2.0)); + T = dir.x * nT + dir.y * nB; + B = -dir.y * nT + dir.x * nB; } -#define NUM_SAMPLE 32 -vec2 poisson_disc[32] = vec2[32]( - vec2( 0.476, 0.854), vec2(-0.659, -0.670), - vec2( 0.905, -0.270), vec2( 0.215, -0.133), - vec2(-0.595, 0.242), vec2(-0.146, 0.519), - vec2( 0.108, -0.930), vec2( 0.807, 0.449), - - vec2(-0.476, -0.854), vec2( 0.659, 0.670), - vec2(-0.905, 0.270), vec2(-0.215, 0.133), - vec2( 0.595, -0.242), vec2( 0.146, -0.519), - vec2(-0.108, 0.930), vec2(-0.807, -0.449), - - vec2(-0.854, 0.476), vec2( 0.670, -0.659), - vec2( 0.270, 0.905), vec2( 0.133, 0.215), - vec2(-0.242, -0.595), vec2(-0.519, -0.146), - vec2( 0.930, 0.108), vec2(-0.449, 0.807), - - vec2( 0.854, -0.476), vec2(-0.670, 0.659), - vec2(-0.270, -0.905), vec2(-0.133, -0.215), - vec2( 0.242, 0.595), vec2( 0.519, 0.146), - vec2(-0.930, -0.108), vec2( 0.449, -0.807) -); +float linear_depth(float z) +{ + return (nearClip * farClip) / (z * (nearClip - farClip) + farClip); +} + +float get_cube_radial_distance(vec3 cubevec) +{ + float zdepth = texture(shadowTexture, cubevec).r; + float linear_zdepth = linear_depth(zdepth); + cubevec = normalize(abs(cubevec)); + float cos_vec = max(cubevec.x, max(cubevec.y, cubevec.z)); + return linear_zdepth / cos_vec; +} /* Marco Salvi's GDC 2008 presentation about shadow maps pre-filtering techniques slide 24 */ float ln_space_prefilter(float w0, float x, float w1, float y) @@ -61,14 +65,66 @@ float ln_space_prefilter(float w0, float x, float w1, float y) return x + log(w0 + w1 * exp(y - x)); } -void main() { - const vec2 texelSize = vec2(1.0 / 512.0); +const int SAMPLE_NUM = 32; +const float INV_SAMPLE_NUM = 1.0 / float(SAMPLE_NUM); +const vec2 poisson[32] = vec2[32]( + vec2(-0.31889129888, 0.945170187163), + vec2(0.0291070069348, 0.993645382622), + vec2(0.453968568675, 0.882119488776), + vec2(-0.59142811398, 0.775098624552), + vec2(0.0672147039953, 0.677233646792), + vec2(0.632546991242, 0.60080388224), + vec2(-0.846282545004, 0.478266943968), + vec2(-0.304563967348, 0.550414788876), + vec2(0.343951542639, 0.482122717676), + vec2(0.903371461134, 0.419225918868), + vec2(-0.566433506581, 0.326544955645), + vec2(-0.0174468029403, 0.345927250589), + vec2(-0.970838848328, 0.131541221423), + vec2(-0.317404956404, 0.102175571059), + vec2(0.309107085158, 0.136502232088), + vec2(0.67009683403, 0.198922062526), + vec2(-0.62544683989, -0.0237682928336), + vec2(0.0, 0.0), + vec2(0.260779995092, -0.192490308513), + vec2(0.555635503398, -0.0918935341973), + vec2(0.989587880961, -0.03629312269), + vec2(-0.93440130633, -0.213478602005), + vec2(-0.615716455579, -0.335329659339), + vec2(0.813589336772, -0.292544036149), + vec2(-0.821106257666, -0.568279197395), + vec2(-0.298092257627, -0.457929494012), + vec2(0.263233114326, -0.515552889911), + vec2(-0.0311374378304, -0.643310533036), + vec2(0.785838482787, -0.615972502555), + vec2(-0.444079211316, -0.836548440017), + vec2(-0.0253421088433, -0.96112294526), + vec2(0.350411908643, -0.89783206142) +); + +float wang_hash_noise(uint s) +{ + uint seed = (uint(gl_FragCoord.x) * 1664525u + uint(gl_FragCoord.y)) + s; - vec2 uvs = gl_FragCoord.xy * texelSize; + seed = (seed ^ 61u) ^ (seed >> 16u); + seed *= 9u; + seed = seed ^ (seed >> 4u); + seed *= 0x27d4eb2du; + seed = seed ^ (seed >> 15u); + + float value = float(seed); + value *= 1.0 / 4294967296.0; + return fract(value); +} + +#define ESM + +void main() { + vec2 uvs = gl_FragCoord.xy * storedTexelSize; /* add a 2 pixel border to ensure filtering is correct */ - uvs.xy *= 1.0 + texelSize * 2.0; - uvs.xy -= texelSize; + uvs.xy *= 1.0 + storedTexelSize * 2.0; + uvs.xy -= storedTexelSize; float pattern = 1.0; @@ -86,28 +142,30 @@ void main() { /* get cubemap vector */ vec3 cubevec = octahedral_to_cubemap_proj(uvs.xy); +/* TODO Can be optimized by groupping fetches + * and by converting to radial distance beforehand. */ +#if defined(ESM) vec3 T, B; - make_orthonormal_basis(cubevec, T, B); + make_orthonormal_basis(cubevec, wang_hash_noise(0u), T, B); + + T *= 0.01; + B *= 0.01; - /* get cubemap shadow value */ - const float blur_radius = 5.0 / 512.0; /* Totally arbitrary */ - const float weight = 1.0 / float(NUM_SAMPLE); float accum = 0.0; /* Poisson disc blur in log space. */ - vec2 offsetvec = poisson_disc[0].xy * blur_radius; - float depth1 = texture(shadowCube, cubevec + offsetvec.x * T + offsetvec.y * B).r; - - offsetvec = poisson_disc[1].xy * blur_radius; - float depth2 = texture(shadowCube, cubevec + offsetvec.x * T + offsetvec.y * B).r; + float depth1 = get_cube_radial_distance(cubevec + poisson[0].x * T + poisson[0].y * B); + float depth2 = get_cube_radial_distance(cubevec + poisson[1].x * T + poisson[1].y * B); + accum = ln_space_prefilter(INV_SAMPLE_NUM, depth1, INV_SAMPLE_NUM, depth2); - accum = ln_space_prefilter(weight, depth1, weight, depth2); - - for (int i = 2; i < NUM_SAMPLE; ++i) { - vec2 offsetvec = poisson_disc[i].xy * blur_radius; - depth1 = texture(shadowCube, cubevec + offsetvec.x * T + offsetvec.y * B).r; - accum = ln_space_prefilter(1.0, accum, weight, depth1); + for (int i = 2; i < SAMPLE_NUM; ++i) { + depth1 = get_cube_radial_distance(cubevec + poisson[i].x * T + poisson[i].y * B); + accum = ln_space_prefilter(1.0, accum, INV_SAMPLE_NUM, depth1); } - FragColor = vec4(accum, accum, accum, 1.0); + FragColor = vec4(accum); + +#else /* PCF (no prefilter) */ + FragColor = vec4(get_cube_radial_distance(cubevec)); +#endif } \ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/shadow_store_geom.glsl b/source/blender/draw/engines/eevee/shaders/shadow_store_geom.glsl deleted file mode 100644 index 78ccb025ce6..00000000000 --- a/source/blender/draw/engines/eevee/shaders/shadow_store_geom.glsl +++ /dev/null @@ -1,24 +0,0 @@ - -layout(std140) uniform shadow_render_block { - mat4 ShadowMatrix[6]; - mat4 FaceViewMatrix[6]; - vec4 lampPosition; - int layer; - float exponent; -}; - -layout(triangles) in; -layout(triangle_strip, max_vertices=3) out; - -in vec4 vPos[]; - -void main() { - gl_Layer = layer; - - for (int v = 0; v < 3; ++v) { - gl_Position = vPos[v]; - EmitVertex(); - } - - EndPrimitive(); -} \ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/shadow_store_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_store_vert.glsl deleted file mode 100644 index dee020f19b4..00000000000 --- a/source/blender/draw/engines/eevee/shaders/shadow_store_vert.glsl +++ /dev/null @@ -1,8 +0,0 @@ - -in vec3 pos; - -out vec4 vPos; - -void main() { - vPos = vec4(pos, 1.0); -} \ No newline at end of file diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 601ea35f8c1..7d2c7819ba3 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -2222,7 +2222,9 @@ static GPUTextureFormat convert_tex_format( case DRW_TEX_RGBA_8: *r_channels = 4; return GPU_RGBA8; case DRW_TEX_RGBA_16: *r_channels = 4; return GPU_RGBA16F; case DRW_TEX_RGBA_32: *r_channels = 4; return GPU_RGBA32F; + case DRW_TEX_DEPTH_16: *r_channels = 1; return GPU_DEPTH_COMPONENT16; case DRW_TEX_DEPTH_24: *r_channels = 1; return GPU_DEPTH_COMPONENT24; + case DRW_TEX_DEPTH_32: *r_channels = 1; return GPU_DEPTH_COMPONENT32F; case DRW_TEX_RGB_11_11_10: *r_channels = 3; return GPU_R11F_G11F_B10F; default: BLI_assert(false && "Texture format unsupported as render target!"); -- cgit v1.2.3