diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-09-01 16:59:01 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-09-10 04:09:45 +0300 |
commit | 8b7a83a868c03f3d721eb83498923673c2addb27 (patch) | |
tree | b51d9a4310e4521cc484b650804fe07e69a9a7f2 | |
parent | 5b026486e4f2a36bf4c988593ebecb135a2ccf84 (diff) |
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.
16 files changed, 289 insertions, 303 deletions
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!"); |