From 9fdf094b852652e10256fedfc6daa50beb5f83bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Fri, 8 Sep 2017 20:21:57 +0200 Subject: Eevee: Shadows: Filtering improvement. - Replace poisson by concentric samples: Less variance. They are sorted by radius then by angle. - Separate filtering into 2 blur. First blur is 3x3 box blur. Second is user dependant. - Group fetches by group of 4. --- source/blender/draw/CMakeLists.txt | 6 +- source/blender/draw/engines/eevee/eevee_data.c | 2 + source/blender/draw/engines/eevee/eevee_lights.c | 93 ++++++- source/blender/draw/engines/eevee/eevee_private.h | 5 + .../eevee/shaders/concentric_samples_lib.glsl | 267 +++++++++++++++++++++ .../engines/eevee/shaders/shadow_copy_frag.glsl | 200 +++++++++++++++ .../engines/eevee/shaders/shadow_store_frag.glsl | 222 +++++------------ 7 files changed, 621 insertions(+), 174 deletions(-) create mode 100644 source/blender/draw/engines/eevee/shaders/concentric_samples_lib.glsl create mode 100644 source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl (limited to 'source/blender/draw') diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index c9f0dedfbdd..8d05e61aaa6 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -117,11 +117,11 @@ data_to_c_simple(engines/clay/shaders/clay_particle_strand_frag.glsl SRC) data_to_c_simple(engines/clay/shaders/ssao_alchemy.glsl SRC) data_to_c_simple(engines/clay/shaders/ssao_groundtruth.glsl SRC) +data_to_c_simple(engines/eevee/shaders/ambient_occlusion_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/default_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/default_world_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/background_vert.glsl SRC) -data_to_c_simple(engines/eevee/shaders/ambient_occlusion_lib.glsl SRC) -data_to_c_simple(engines/eevee/shaders/effect_minmaxz_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/concentric_samples_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/lamps_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/lightprobe_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl SRC) @@ -143,6 +143,7 @@ data_to_c_simple(engines/eevee/shaders/effect_dof_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_downsample_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_downsample_cube_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_gtao_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/effect_minmaxz_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/lightprobe_planar_downsample_frag.glsl SRC) @@ -154,6 +155,7 @@ 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_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_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 28c049ae53e..92a992f578b 100644 --- a/source/blender/draw/engines/eevee/eevee_data.c +++ b/source/blender/draw/engines/eevee/eevee_data.c @@ -42,7 +42,9 @@ static void eevee_scene_layer_data_free(void *storage) 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_cube_blur); DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_target); + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_blur); DRW_TEXTURE_FREE_SAFE(sldata->shadow_pool); BLI_freelistN(&sldata->shadow_casters); diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index 857bdfc47f7..ca25e6e13b0 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -25,6 +25,8 @@ #include "DRW_render.h" +#include "BLI_dynstr.h" + #include "BKE_object.h" #include "eevee_engine.h" @@ -57,12 +59,16 @@ static struct { struct GPUShader *shadow_sh; struct GPUShader *shadow_store_cube_sh[SHADOW_METHOD_MAX]; struct GPUShader *shadow_store_cascade_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_geom_glsl[]; extern char datatoc_shadow_frag_glsl[]; extern char datatoc_shadow_store_frag_glsl[]; +extern char datatoc_shadow_copy_frag_glsl[]; +extern char datatoc_concentric_samples_lib_glsl[]; /* *********** FUNCTIONS *********** */ @@ -80,13 +86,33 @@ void EEVEE_lights_init(EEVEE_SceneLayerData *sldata) e_data.shadow_sh = DRW_shader_create( datatoc_shadow_vert_glsl, datatoc_shadow_geom_glsl, datatoc_shadow_frag_glsl, NULL); - e_data.shadow_store_cube_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(datatoc_shadow_store_frag_glsl, "#define ESM\n"); - e_data.shadow_store_cascade_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(datatoc_shadow_store_frag_glsl, "#define ESM\n" - "#define CSM\n"); + 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); + + e_data.shadow_store_cube_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(store_shadow_shader_str, "#define ESM\n"); + e_data.shadow_store_cascade_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(store_shadow_shader_str, "#define ESM\n" + "#define CSM\n"); + + e_data.shadow_store_cube_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(store_shadow_shader_str, "#define VSM\n"); + e_data.shadow_store_cascade_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(store_shadow_shader_str, "#define VSM\n" + "#define CSM\n"); + + MEM_freeN(store_shadow_shader_str); - e_data.shadow_store_cube_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(datatoc_shadow_store_frag_glsl, "#define VSM\n"); - e_data.shadow_store_cascade_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(datatoc_shadow_store_frag_glsl, "#define VSM\n" - "#define CSM\n"); + e_data.shadow_copy_cube_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(datatoc_shadow_copy_frag_glsl, "#define ESM\n" + "#define COPY\n"); + e_data.shadow_copy_cascade_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(datatoc_shadow_copy_frag_glsl, "#define ESM\n" + "#define COPY\n" + "#define CSM\n"); + + e_data.shadow_copy_cube_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(datatoc_shadow_copy_frag_glsl, "#define VSM\n" + "#define COPY\n"); + e_data.shadow_copy_cascade_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(datatoc_shadow_copy_frag_glsl, "#define VSM\n" + "#define COPY\n" + "#define CSM\n"); } if (!sldata->lamps) { @@ -153,13 +179,35 @@ void EEVEE_lights_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl) 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[linfo->shadow_method], psl->shadow_cascade_store_pass); - DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cascade_target); + DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cascade_blur); DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo); DRW_shgroup_uniform_int(grp, "cascadeId", &linfo->current_shadow_cascade, 1); DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1); DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); } + { + psl->shadow_cube_copy_pass = DRW_pass_create("Shadow 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_buffer(grp, "shadowTexture", &sldata->shadow_cube_target); + DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo); + DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1); + DRW_shgroup_uniform_int(grp, "faceId", &linfo->current_shadow_face, 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + + { + psl->shadow_cascade_copy_pass = DRW_pass_create("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_buffer(grp, "shadowTexture", &sldata->shadow_cascade_target); + DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo); + DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1); + DRW_shgroup_uniform_int(grp, "cascadeId", &linfo->current_shadow_cascade, 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + { psl->shadow_cube_pass = DRW_pass_create("Shadow Cube Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); } @@ -321,12 +369,15 @@ void EEVEE_lights_cache_finish(EEVEE_SceneLayerData *sldata) /* 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); + sldata->shadow_cube_blur = DRW_texture_create_cube(linfo->shadow_cube_target_size, shadow_pool_format, DRW_TEX_FILTER, NULL); } 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); + sldata->shadow_cascade_blur = DRW_texture_create_2D_array( + linfo->shadow_size, linfo->shadow_size, MAX_CASCADE_NUM, shadow_pool_format, DRW_TEX_FILTER, NULL); } /* Initialize Textures Array first so DRW_framebuffer_init just bind them. */ @@ -855,7 +906,6 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl) srd->shadow_inv_samples_ct = 1.0f / srd->shadow_samples_ct; srd->clip_near = la->clipsta; srd->clip_far = la->clipend; - linfo->filter_size = la->soft * 0.0005f; copy_v3_v3(srd->position, ob->obmat[3]); for (int j = 0; j < 6; j++) { float tmp[4][4]; @@ -874,7 +924,20 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl) /* Render shadow cube */ DRW_draw_pass(psl->shadow_cube_pass); + for (linfo->current_shadow_face = 0; + linfo->current_shadow_face < 6; + linfo->current_shadow_face++) + { + /* Copy using a small 3x3 box filter */ + linfo->filter_size = (la->soft > 0.00001f) ? 1.0f : 0.0f; + DRW_framebuffer_cubeface_attach(sldata->shadow_store_fb, sldata->shadow_cube_blur, 0, linfo->current_shadow_face, 0); + DRW_framebuffer_bind(sldata->shadow_store_fb); + DRW_draw_pass(psl->shadow_cube_copy_pass); + DRW_framebuffer_texture_detach(sldata->shadow_cube_blur); + } + /* Push it to shadowmap array */ + linfo->filter_size = la->soft * 0.0005f; 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); @@ -914,9 +977,15 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl) linfo->current_shadow_cascade < la->cascade_count; ++linfo->current_shadow_cascade) { - linfo->filter_size = la->soft * 0.0005f / (evscd->radius[linfo->current_shadow_cascade] * 0.05f); + /* Copy using a small 3x3 box filter */ + linfo->filter_size = (la->soft > 0.00001f) ? 1.0f : 0.0f; + DRW_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_cascade_blur, 0, linfo->current_shadow_cascade, 0); + DRW_framebuffer_bind(sldata->shadow_store_fb); + DRW_draw_pass(psl->shadow_cascade_copy_pass); + DRW_framebuffer_texture_detach(sldata->shadow_cascade_blur); - /* Push it to shadowmap array */ + /* Push it to shadowmap array and blur more */ + linfo->filter_size = la->soft * 0.0005f / (evscd->radius[linfo->current_shadow_cascade] * 0.05f); int layer = evscd->layer_id + linfo->current_shadow_cascade; DRW_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_pool, 0, layer, 0); DRW_framebuffer_bind(sldata->shadow_store_fb); @@ -924,7 +993,7 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl) } } - DRW_framebuffer_texture_detach(sldata->shadow_cube_target); + DRW_framebuffer_texture_detach(sldata->shadow_cascade_target); } void EEVEE_lights_free(void) @@ -933,5 +1002,7 @@ void EEVEE_lights_free(void) 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_cascade_sh[i]); + DRW_SHADER_FREE_SAFE(e_data.shadow_copy_cube_sh[i]); + DRW_SHADER_FREE_SAFE(e_data.shadow_copy_cascade_sh[i]); } } \ No newline at end of file diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 65b1ddfd949..72bd04a5958 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -91,8 +91,10 @@ typedef struct EEVEE_PassList { /* Shadows */ struct DRWPass *shadow_pass; struct DRWPass *shadow_cube_pass; + struct DRWPass *shadow_cube_copy_pass; struct DRWPass *shadow_cube_store_pass; struct DRWPass *shadow_cascade_pass; + struct DRWPass *shadow_cascade_copy_pass; struct DRWPass *shadow_cascade_store_pass; /* Probes */ @@ -257,6 +259,7 @@ typedef struct EEVEE_LampsInfo { bool shadow_high_bitdepth; int shadow_cube_target_size; int current_shadow_cascade; + int current_shadow_face; float filter_size; /* List of lights in the scene. */ /* XXX This is fragile, can get out of sync quickly. */ @@ -424,7 +427,9 @@ typedef struct EEVEE_SceneLayerData { struct GPUFrameBuffer *shadow_store_fb; struct GPUTexture *shadow_cube_target; + struct GPUTexture *shadow_cube_blur; struct GPUTexture *shadow_cascade_target; + struct GPUTexture *shadow_cascade_blur; struct GPUTexture *shadow_pool; struct ListBase shadow_casters; /* Shadow casters gathered during cache iteration */ diff --git a/source/blender/draw/engines/eevee/shaders/concentric_samples_lib.glsl b/source/blender/draw/engines/eevee/shaders/concentric_samples_lib.glsl new file mode 100644 index 00000000000..67bcf603a81 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/concentric_samples_lib.glsl @@ -0,0 +1,267 @@ +/* Precomputed table of concentric samples. + * Generated using this algorithm http://l2program.co.uk/900/concentric-disk-sampling + * Sorted by radius then by rotation angle. + * This way it's better for cache usage and for + * easily restricting to a certain number of + * sample while still having a circular kernel. */ + +#define CONCENTRIC_SAMPLE_NUM 256 +const vec2 concentric[CONCENTRIC_SAMPLE_NUM] = +vec2[CONCENTRIC_SAMPLE_NUM]( + vec2(0.0441941738242, 0.0441941738242), + vec2(-0.0441941738242, -0.0441941738242), + vec2(-0.0441941738242, 0.0441941738242), + vec2(0.0441941738242, -0.0441941738242), + vec2(0.181111092429, 0.0485285709567), + vec2(0.132582521472, 0.132582521472), + vec2(-0.181111092429, 0.0485285709567), + vec2(0.0485285709567, 0.181111092429), + vec2(-0.181111092429, -0.0485285709567), + vec2(-0.0485285709567, 0.181111092429), + vec2(-0.132582521472, -0.132582521472), + vec2(-0.132582521472, 0.132582521472), + vec2(-0.0485285709567, -0.181111092429), + vec2(0.0485285709567, -0.181111092429), + vec2(0.132582521472, -0.132582521472), + vec2(0.181111092429, -0.0485285709567), + vec2(0.308652606436, 0.0488857703251), + vec2(0.278439538809, 0.141872031169), + vec2(0.220970869121, 0.220970869121), + vec2(-0.278439538809, 0.141872031169), + vec2(0.141872031169, 0.278439538809), + vec2(-0.308652606436, 0.0488857703251), + vec2(0.0488857703251, 0.308652606436), + vec2(-0.308652606436, -0.0488857703251), + vec2(-0.0488857703251, 0.308652606436), + vec2(-0.278439538809, -0.141872031169), + vec2(-0.141872031169, 0.278439538809), + vec2(-0.220970869121, -0.220970869121), + vec2(-0.220970869121, 0.220970869121), + vec2(-0.141872031169, -0.278439538809), + vec2(-0.0488857703251, -0.308652606436), + vec2(0.0488857703251, -0.308652606436), + vec2(0.141872031169, -0.278439538809), + vec2(0.220970869121, -0.220970869121), + vec2(0.278439538809, -0.141872031169), + vec2(0.308652606436, -0.0488857703251), + vec2(0.434749091828, 0.0489844582952), + vec2(0.41294895701, 0.144497089605), + vec2(0.370441837162, 0.232764033475), + vec2(0.309359216769, 0.309359216769), + vec2(-0.370441837162, 0.232764033475), + vec2(0.232764033475, 0.370441837162), + vec2(-0.41294895701, 0.144497089605), + vec2(0.144497089605, 0.41294895701), + vec2(-0.434749091828, 0.0489844582952), + vec2(0.0489844582952, 0.434749091828), + vec2(-0.434749091828, -0.0489844582952), + vec2(-0.0489844582952, 0.434749091828), + vec2(-0.41294895701, -0.144497089605), + vec2(-0.144497089605, 0.41294895701), + vec2(-0.370441837162, -0.232764033475), + vec2(-0.232764033475, 0.370441837162), + vec2(-0.309359216769, -0.309359216769), + vec2(-0.309359216769, 0.309359216769), + vec2(-0.232764033475, -0.370441837162), + vec2(-0.144497089605, -0.41294895701), + vec2(-0.0489844582952, -0.434749091828), + vec2(0.0489844582952, -0.434749091828), + vec2(0.144497089605, -0.41294895701), + vec2(0.232764033475, -0.370441837162), + vec2(0.309359216769, -0.309359216769), + vec2(0.370441837162, -0.232764033475), + vec2(0.41294895701, -0.144497089605), + vec2(0.434749091828, -0.0489844582952), + vec2(0.560359517677, 0.0490251052956), + vec2(0.543333277288, 0.14558571287), + vec2(0.509798130208, 0.237722772229), + vec2(0.460773024913, 0.322636745447), + vec2(0.397747564417, 0.397747564417), + vec2(-0.460773024913, 0.322636745447), + vec2(0.322636745447, 0.460773024913), + vec2(-0.509798130208, 0.237722772229), + vec2(0.237722772229, 0.509798130208), + vec2(-0.543333277288, 0.14558571287), + vec2(0.14558571287, 0.543333277288), + vec2(-0.560359517677, 0.0490251052956), + vec2(0.0490251052956, 0.560359517677), + vec2(-0.560359517677, -0.0490251052956), + vec2(-0.0490251052956, 0.560359517677), + vec2(-0.543333277288, -0.14558571287), + vec2(-0.14558571287, 0.543333277288), + vec2(-0.509798130208, -0.237722772229), + vec2(-0.237722772229, 0.509798130208), + vec2(-0.460773024913, -0.322636745447), + vec2(-0.322636745447, 0.460773024913), + vec2(-0.397747564417, -0.397747564417), + vec2(-0.397747564417, 0.397747564417), + vec2(-0.322636745447, -0.460773024913), + vec2(-0.237722772229, -0.509798130208), + vec2(-0.14558571287, -0.543333277288), + vec2(-0.0490251052956, -0.560359517677), + vec2(0.0490251052956, -0.560359517677), + vec2(0.14558571287, -0.543333277288), + vec2(0.237722772229, -0.509798130208), + vec2(0.322636745447, -0.460773024913), + vec2(0.397747564417, -0.397747564417), + vec2(0.460773024913, -0.322636745447), + vec2(0.509798130208, -0.237722772229), + vec2(0.543333277288, -0.14558571287), + vec2(0.560359517677, -0.0490251052956), + vec2(0.685748328795, 0.0490456884495), + vec2(0.671788470355, 0.146138636568), + vec2(0.644152935937, 0.240256623474), + vec2(0.603404305327, 0.32948367837), + vec2(0.550372103135, 0.412003395727), + vec2(0.486135912066, 0.486135912066), + vec2(-0.550372103135, 0.412003395727), + vec2(0.412003395727, 0.550372103135), + vec2(-0.603404305327, 0.32948367837), + vec2(0.32948367837, 0.603404305327), + vec2(-0.644152935937, 0.240256623474), + vec2(0.240256623474, 0.644152935937), + vec2(-0.671788470355, 0.146138636568), + vec2(0.146138636568, 0.671788470355), + vec2(-0.685748328795, 0.0490456884495), + vec2(0.0490456884495, 0.685748328795), + vec2(-0.685748328795, -0.0490456884495), + vec2(-0.0490456884495, 0.685748328795), + vec2(-0.671788470355, -0.146138636568), + vec2(-0.146138636568, 0.671788470355), + vec2(-0.644152935937, -0.240256623474), + vec2(-0.240256623474, 0.644152935937), + vec2(-0.603404305327, -0.32948367837), + vec2(-0.32948367837, 0.603404305327), + vec2(-0.550372103135, -0.412003395727), + vec2(-0.412003395727, 0.550372103135), + vec2(-0.486135912066, -0.486135912066), + vec2(-0.486135912066, 0.486135912066), + vec2(-0.412003395727, -0.550372103135), + vec2(-0.32948367837, -0.603404305327), + vec2(-0.240256623474, -0.644152935937), + vec2(-0.146138636568, -0.671788470355), + vec2(-0.0490456884495, -0.685748328795), + vec2(0.0490456884495, -0.685748328795), + vec2(0.146138636568, -0.671788470355), + vec2(0.240256623474, -0.644152935937), + vec2(0.32948367837, -0.603404305327), + vec2(0.412003395727, -0.550372103135), + vec2(0.486135912066, -0.486135912066), + vec2(0.550372103135, -0.412003395727), + vec2(0.603404305327, -0.32948367837), + vec2(0.644152935937, -0.240256623474), + vec2(0.671788470355, -0.146138636568), + vec2(0.685748328795, -0.0490456884495), + vec2(0.811017637806, 0.0490575291556), + vec2(0.799191174395, 0.146457218224), + vec2(0.775710704038, 0.241721231257), + vec2(0.740918624869, 0.33346040443), + vec2(0.695322283745, 0.420336974019), + vec2(0.639586577995, 0.501084084011), + vec2(0.574524259714, 0.574524259714), + vec2(-0.639586577995, 0.501084084011), + vec2(0.501084084011, 0.639586577995), + vec2(-0.695322283745, 0.420336974019), + vec2(0.420336974019, 0.695322283745), + vec2(-0.740918624869, 0.33346040443), + vec2(0.33346040443, 0.740918624869), + vec2(-0.775710704038, 0.241721231257), + vec2(0.241721231257, 0.775710704038), + vec2(-0.799191174395, 0.146457218224), + vec2(0.146457218224, 0.799191174395), + vec2(-0.811017637806, 0.0490575291556), + vec2(0.0490575291556, 0.811017637806), + vec2(-0.811017637806, -0.0490575291556), + vec2(-0.0490575291556, 0.811017637806), + vec2(-0.799191174395, -0.146457218224), + vec2(-0.146457218224, 0.799191174395), + vec2(-0.775710704038, -0.241721231257), + vec2(-0.241721231257, 0.775710704038), + vec2(-0.740918624869, -0.33346040443), + vec2(-0.33346040443, 0.740918624869), + vec2(-0.695322283745, -0.420336974019), + vec2(-0.420336974019, 0.695322283745), + vec2(-0.639586577995, -0.501084084011), + vec2(-0.501084084011, 0.639586577995), + vec2(-0.574524259714, -0.574524259714), + vec2(-0.574524259714, 0.574524259714), + vec2(-0.501084084011, -0.639586577995), + vec2(-0.420336974019, -0.695322283745), + vec2(-0.33346040443, -0.740918624869), + vec2(-0.241721231257, -0.775710704038), + vec2(-0.146457218224, -0.799191174395), + vec2(-0.0490575291556, -0.811017637806), + vec2(0.0490575291556, -0.811017637806), + vec2(0.146457218224, -0.799191174395), + vec2(0.241721231257, -0.775710704038), + vec2(0.33346040443, -0.740918624869), + vec2(0.420336974019, -0.695322283745), + vec2(0.501084084011, -0.639586577995), + vec2(0.574524259714, -0.574524259714), + vec2(0.639586577995, -0.501084084011), + vec2(0.695322283745, -0.420336974019), + vec2(0.740918624869, -0.33346040443), + vec2(0.775710704038, -0.241721231257), + vec2(0.799191174395, -0.146457218224), + vec2(0.811017637806, -0.0490575291556), + vec2(0.936215188832, 0.0490649589778), + vec2(0.925957819308, 0.146657310975), + vec2(0.905555462146, 0.242642854784), + vec2(0.875231649841, 0.335969952699), + vec2(0.835318616427, 0.425616093506), + vec2(0.786253657449, 0.510599095327), + vec2(0.728574338866, 0.589987866609), + vec2(0.662912607362, 0.662912607362), + vec2(-0.728574338866, 0.589987866609), + vec2(0.589987866609, 0.728574338866), + vec2(-0.786253657449, 0.510599095327), + vec2(0.510599095327, 0.786253657449), + vec2(-0.835318616427, 0.425616093506), + vec2(0.425616093506, 0.835318616427), + vec2(-0.875231649841, 0.335969952699), + vec2(0.335969952699, 0.875231649841), + vec2(-0.905555462146, 0.242642854784), + vec2(0.242642854784, 0.905555462146), + vec2(-0.925957819308, 0.146657310975), + vec2(0.146657310975, 0.925957819308), + vec2(-0.936215188832, 0.0490649589778), + vec2(0.0490649589778, 0.936215188832), + vec2(-0.936215188832, -0.0490649589778), + vec2(-0.0490649589778, 0.936215188832), + vec2(-0.925957819308, -0.146657310975), + vec2(-0.146657310975, 0.925957819308), + vec2(-0.905555462146, -0.242642854784), + vec2(-0.242642854784, 0.905555462146), + vec2(-0.875231649841, -0.335969952699), + vec2(-0.335969952699, 0.875231649841), + vec2(-0.835318616427, -0.425616093506), + vec2(-0.425616093506, 0.835318616427), + vec2(-0.786253657449, -0.510599095327), + vec2(-0.510599095327, 0.786253657449), + vec2(-0.728574338866, -0.589987866609), + vec2(-0.589987866609, 0.728574338866), + vec2(-0.662912607362, -0.662912607362), + vec2(-0.662912607362, 0.662912607362), + vec2(-0.589987866609, -0.728574338866), + vec2(-0.510599095327, -0.786253657449), + vec2(-0.425616093506, -0.835318616427), + vec2(-0.335969952699, -0.875231649841), + vec2(-0.242642854784, -0.905555462146), + vec2(-0.146657310975, -0.925957819308), + vec2(-0.0490649589778, -0.936215188832), + vec2(0.0490649589778, -0.936215188832), + vec2(0.146657310975, -0.925957819308), + vec2(0.242642854784, -0.905555462146), + vec2(0.335969952699, -0.875231649841), + vec2(0.425616093506, -0.835318616427), + vec2(0.510599095327, -0.786253657449), + vec2(0.589987866609, -0.728574338866), + vec2(0.662912607362, -0.662912607362), + vec2(0.728574338866, -0.589987866609), + vec2(0.786253657449, -0.510599095327), + vec2(0.835318616427, -0.425616093506), + vec2(0.875231649841, -0.335969952699), + vec2(0.905555462146, -0.242642854784), + vec2(0.925957819308, -0.146657310975), + vec2(0.936215188832, -0.0490649589778) +); \ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl new file mode 100644 index 00000000000..b70d6faa73d --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl @@ -0,0 +1,200 @@ +/* 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 { + mat4 ShadowMatrix[6]; + mat4 FaceViewMatrix[6]; + vec4 lampPosition; + float cubeTexelSize; + float storedTexelSize; + float nearClip; + float farClip; + float shadowSampleCount; + float shadowInvSampleCount; +}; + +#ifdef CSM +uniform sampler2DArray shadowTexture; +uniform int cascadeId; +#else +uniform samplerCube shadowTexture; +uniform vec3 cubeFaceVec[3]; +#endif +uniform float shadowFilterSize; + +out vec4 FragColor; + +float linear_depth(float z) +{ + return (nearClip * farClip) / (z * (nearClip - farClip) + farClip); +} + +vec4 linear_depth(vec4 z) +{ + return (nearClip * farClip) / (z * (nearClip - farClip) + farClip); +} + +#ifdef CSM +vec4 get_world_distance(vec4 depths, vec3 cos[4]) +{ + /* Background case */ + vec4 is_background = step(vec4(0.99999), depths); + depths *= abs(farClip - nearClip); /* Same factor as in shadow_cascade(). */ + depths += 1e1 * is_background; + return depths; +} + +float get_world_distance(float depth, vec3 cos) +{ + /* Background case */ + float is_background = step(0.9999, depth); + depth *= abs(farClip - nearClip); /* Same factor as in shadow_cascade(). */ + depth += 1e1 * is_background; + return depth; +} +#else /* CUBEMAP */ +vec4 get_world_distance(vec4 depths, vec3 cos[4]) +{ + vec4 is_background = step(vec4(1.0), depths); + depths = linear_depth(depths); + depths += vec4(1e16) * is_background; + 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) +{ + float is_background = step(1.0, depth); + depth = linear_depth(depth); + depth += 1e16 * is_background; + 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 */ +float ln_space_prefilter(float w0, float x, float w1, float y) +{ + return x + log(w0 + w1 * exp(y - x)); +} + +#define SAMPLE_WEIGHT 0.11111 + +#ifdef ESM +void filter(vec4 depths, inout float accum) +{ + accum = ln_space_prefilter(1.0, accum, SAMPLE_WEIGHT, depths.x); + accum = ln_space_prefilter(1.0, accum, SAMPLE_WEIGHT, depths.y); + accum = ln_space_prefilter(1.0, accum, SAMPLE_WEIGHT, depths.z); + accum = ln_space_prefilter(1.0, accum, SAMPLE_WEIGHT, depths.w); +} +#else /* VSM */ +void filter(vec4 depths, 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[0] + uvs.x * minorAxisX[1] + uvs.y * minorAxisY[2]; +} +#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; +#endif + + /* Center texel */ + vec3 co = get_texco(uvs, vec2(0.0)); + float depth = texture(shadowTexture, co).r; + depth = get_world_distance(depth, co); +#ifdef ESM + float accum = ln_space_prefilter(0.0, 0.0, SAMPLE_WEIGHT, depth); +#else /* VSM */ + vec2 accum = vec2(depth, depth * depth) * SAMPLE_WEIGHT; +#endif + +#ifdef CSM + vec3 ofs = storedTexelSize * vec3(1.0, 0.0, -1.0) * shadowFilterSize; +#else /* CUBEMAP */ + vec3 ofs = cubeTexelSize * vec3(1.0, 0.0, -1.0) * shadowFilterSize; +#endif + + 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); + filter(depths, 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); + filter(depths, accum); + + FragColor = vec2(accum).xyxy; +} 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 6564fd87d04..c14107198aa 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl @@ -35,212 +35,112 @@ vec3 octahedral_to_cubemap_proj(vec2 co) return v; } -void make_orthonormal_basis(vec3 N, float rot, out vec3 T, out vec3 B) +void make_orthonormal_basis(vec3 N, out vec3 T, out vec3 B) { vec3 UpVector = (abs(N.z) < 0.999) ? 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 */ - float angle = rot * 3.1415 * 2.0; - vec2 dir = vec2(cos(angle), sin(angle)); - T = dir.x * nT + dir.y * nB; - B = -dir.y * nT + dir.x * nB; +/* 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) +{ + return x + log(w0 + w1 * exp(y - x)); } -float linear_depth(float z) +vec4 ln_space_prefilter(float w0, vec4 x, float w1, vec4 y) { - return (nearClip * farClip) / (z * (nearClip - farClip) + farClip); + return x + log(w0 + w1 * exp(y - x)); } +/* globals */ +vec3 T, B; + #ifdef CSM -float get_cascade_world_distance(vec2 uvs) +vec3 get_texco(vec3 cos, vec2 ofs) { - float zdepth = texture(shadowTexture, vec3(uvs, float(cascadeId))).r; - if (zdepth == 1.0) { - /* Background case */ - return 1e16; - } - return zdepth * abs(farClip - nearClip); /* Same factor as in shadow_cascade(). */ + cos.xy += ofs * shadowFilterSize; + return cos; } -#else -float get_cube_radial_distance(vec3 cubevec) +#else /* CUBEMAP */ +vec3 get_texco(vec3 cos, vec2 ofs) { - 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; + return cos + ofs.x * T + ofs.y * B; } #endif -/* 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) -{ - return x + log(w0 + w1 * exp(y - x)); -} - -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; - - seed = (seed ^ 61u) ^ (seed >> 16u); - seed *= 9u; - seed = seed ^ (seed >> 4u); - seed *= 0x27d4eb2du; - seed = seed ^ (seed >> 15u); +const float INV_SAMPLE_NUM = 1.0 / float(CONCENTRIC_SAMPLE_NUM); - float value = float(seed); - value *= 1.0 / 4294967296.0; - return fract(value); -} - -#ifdef CSM void main() { - vec2 uvs = gl_FragCoord.xy * storedTexelSize; - - vec2 X, Y; - X.x = cos(wang_hash_noise(0u) * 3.1415 * 2.0); - X.y = sqrt(1.0 - X.x * X.x); - - Y = vec2(-X.y, X.x); + vec3 cos; - X *= shadowFilterSize; - Y *= shadowFilterSize; - -/* TODO Can be optimized by groupping fetches - * and by converting to world distance beforehand. */ -#if defined(ESM) || defined(VSM) -#ifdef ESM - float accum = 0.0; - - /* Poisson disc blur in log space. */ - float depth1 = get_cascade_world_distance(uvs + X * poisson[0].x + Y * poisson[0].y); - float depth2 = get_cascade_world_distance(uvs + X * poisson[1].x + Y * poisson[1].y); - accum = ln_space_prefilter(INV_SAMPLE_NUM, depth1, INV_SAMPLE_NUM, depth2); - - for (int i = 2; i < SAMPLE_NUM; ++i) { - depth1 = get_cascade_world_distance(uvs + X * poisson[i].x + Y * poisson[i].y); - accum = ln_space_prefilter(1.0, accum, INV_SAMPLE_NUM, depth1); - } - - FragColor = vec4(accum); -#else /* VSM */ - vec2 accum = vec2(0.0); - - /* Poisson disc blur. */ - for (int i = 0; i < SAMPLE_NUM; ++i) { - float dist = get_cascade_world_distance(uvs + X * poisson[i].x + Y * poisson[i].y); - float dist_sqr = dist * dist; - accum += vec2(dist, dist_sqr); - } - - FragColor = accum.xyxy * shadowInvSampleCount; -#endif /* Prefilter */ -#else /* PCF (no prefilter) */ - FragColor = vec4(get_cascade_world_distance(uvs)); -#endif -} + cos.xy = gl_FragCoord.xy * storedTexelSize; +#ifdef CSM + cos.z = float(cascadeId); #else /* CUBEMAP */ - -void main() { - vec2 uvs = gl_FragCoord.xy * storedTexelSize; - /* add a 2 pixel border to ensure filtering is correct */ - uvs.xy *= 1.0 + storedTexelSize * 2.0; - uvs.xy -= storedTexelSize; + 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(uvs - 0.5) + 0.5; + vec2 m = abs(cos.xy - 0.5) + 0.5; vec2 f = floor(m); if (f.x - f.y != 0.0) { - uvs.xy = 1.0 - uvs.xy; + cos.xy = 1.0 - cos.xy; } /* clamp to [0-1] */ - uvs.xy = fract(uvs.xy); + cos.xy = fract(cos.xy); /* get cubemap vector */ - vec3 cubevec = normalize(octahedral_to_cubemap_proj(uvs.xy)); - -/* TODO Can be optimized by groupping fetches - * and by converting to radial distance beforehand. */ -#if defined(ESM) || defined(VSM) - vec3 T, B; - make_orthonormal_basis(cubevec, wang_hash_noise(0u), T, B); + cos = normalize(octahedral_to_cubemap_proj(cos.xy)); + make_orthonormal_basis(cos, T, B); T *= shadowFilterSize; B *= shadowFilterSize; +#endif #ifdef ESM - float accum = 0.0; - - /* Poisson disc blur in log space. */ - 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); - - 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); + vec4 accum = vec4(0.0); + + /* 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; + accum = ln_space_prefilter(0.0, accum, INV_SAMPLE_NUM, depths); + + for (int i = 4; i < CONCENTRIC_SAMPLE_NUM; i += 4) { + depths.x = texture(shadowTexture, get_texco(cos, concentric[i+0])).r; + depths.y = texture(shadowTexture, get_texco(cos, concentric[i+1])).r; + depths.z = texture(shadowTexture, get_texco(cos, concentric[i+2])).r; + depths.w = texture(shadowTexture, get_texco(cos, concentric[i+3])).r; + accum = ln_space_prefilter(1.0, accum, INV_SAMPLE_NUM, depths); } - FragColor = vec4(accum); + accum.x = ln_space_prefilter(1.0, accum.x, 1.0, accum.y); + accum.x = ln_space_prefilter(1.0, accum.x, 1.0, accum.z); + accum.x = ln_space_prefilter(1.0, accum.x, 1.0, accum.w); + FragColor = accum.xxxx; + #else /* VSM */ vec2 accum = vec2(0.0); - /* Poisson disc blur. */ - for (int i = 0; i < SAMPLE_NUM; ++i) { - float dist = get_cube_radial_distance(cubevec + poisson[i].x * T + poisson[i].y * B); - float dist_sqr = dist * dist; - accum += vec2(dist, dist_sqr); + /* disc blur. */ + vec4 depths1, depths2; + for (int i = 0; i < CONCENTRIC_SAMPLE_NUM; i += 4) { + depths1.xy = texture(shadowTexture, get_texco(cos, concentric[i+0])).rg; + depths1.zw = texture(shadowTexture, get_texco(cos, concentric[i+1])).rg; + depths2.xy = texture(shadowTexture, get_texco(cos, concentric[i+2])).rg; + depths2.zw = texture(shadowTexture, get_texco(cos, concentric[i+3])).rg; + accum += depths1.xy + depths1.zw + depths2.xy + depths2.zw; } - FragColor = accum.xyxy * shadowInvSampleCount; -#endif /* Prefilter */ -#else /* PCF (no prefilter) */ - FragColor = vec4(get_cube_radial_distance(cubevec)); + FragColor = accum.xyxy * INV_SAMPLE_NUM; #endif -} -#endif \ No newline at end of file +} \ No newline at end of file -- cgit v1.2.3