diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2018-11-11 19:45:29 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2018-11-12 15:50:22 +0300 |
commit | 36a3a40033298227cfc55f59580e03863c09699d (patch) | |
tree | 133a4081e18fc000efcf9db8c2fa8ebaaa7a99bf /source/blender/draw/engines/eevee | |
parent | e51dae4af852be1d67ff04b0dc2fb448c25dc913 (diff) |
Eevee: Fix ESM not working after a certain distance
This was caused by overflow caused by the background and precision during
filtering.
Diffstat (limited to 'source/blender/draw/engines/eevee')
4 files changed, 101 insertions, 114 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index 83fd1bf68cc..02667bf7087 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -1241,6 +1241,7 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) copy_v3_v3(srd->position, cube_data->position); srd->stored_texel_size = 1.0 / (float)linfo->shadow_cube_store_size; + srd->exponent = la->bleedexp; DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd); diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 1c04dc81aad..a07f6f05f45 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -384,6 +384,7 @@ typedef struct EEVEE_ShadowRender { float clip_far; int shadow_samples_len; float shadow_samples_len_inv; + float exponent; } EEVEE_ShadowRender; /* This is just a really long bitflag with special function to access it. */ diff --git a/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl index 4ae22b480f1..3ac214bfde2 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl @@ -9,6 +9,7 @@ layout(std140) uniform shadow_render_block { float farClip; int shadowSampleCount; float shadowInvSampleCount; + float exponent; }; #ifdef CSM @@ -22,40 +23,28 @@ uniform float shadowFilterSize; out vec4 FragColor; -float linear_depth(float z) -{ - return (nearClip * farClip) / (z * (nearClip - farClip) + farClip); -} +#define linear_depth(z) ((nearClip * farClip) / (clamp(z, 0.0, 0.999999) * (nearClip - farClip) + farClip)) -vec4 linear_depth(vec4 z) -{ - return (nearClip * farClip) / (z * (nearClip - farClip) + farClip); -} +/* add bias so background filtering does not bleed into shadow map */ +#define BACKGROUND_BIAS 0.05 #ifdef CSM vec4 get_world_distance(vec4 depths, vec3 cos[4]) { - /* 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; + depths += step(vec4(0.9999), depths) * BACKGROUND_BIAS; + return clamp(depths * abs(farClip - nearClip), 0.0, 1e10); /* Same factor as in shadow_cascade(). */ } float get_world_distance(float depth, vec3 cos) { - /* 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; + depth += step(0.9999, depth) * BACKGROUND_BIAS; + return clamp(depth * abs(farClip - nearClip), 0.0, 1e10); /* Same factor as in shadow_cascade(). */ } + #else /* CUBEMAP */ vec4 get_world_distance(vec4 depths, vec3 cos[4]) { - vec4 is_background = step(vec4(1.0), depths); depths = linear_depth(depths); - depths += vec4(1e1) * is_background; cos[0] = normalize(abs(cos[0])); cos[1] = normalize(abs(cos[1])); cos[2] = normalize(abs(cos[2])); @@ -70,9 +59,7 @@ vec4 get_world_distance(vec4 depths, vec3 cos[4]) float get_world_distance(float depth, vec3 cos) { - float is_background = step(1.0, depth); depth = linear_depth(depth); - depth += 1e1 * is_background; cos = normalize(abs(cos)); float cos_vec = max(cos.x, max(cos.y, cos.z)); return depth / cos_vec; @@ -80,23 +67,18 @@ float get_world_distance(float depth, vec3 cos) #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 ln_space_prefilter_step(ref, sample) exp(sample - ref) +#define ln_space_prefilter_finalize(ref, sum) (ref + log(SAMPLE_WEIGHT * sum)) #define SAMPLE_WEIGHT 0.11111 #ifdef ESM -void prefilter(vec4 depths, inout float accum) +void prefilter(vec4 depths, float ref, 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); + accum += dot(ln_space_prefilter_step(ref, depths), vec4(1.0)); } #else /* VSM */ -void prefilter(vec4 depths, inout vec2 accum) +void prefilter(vec4 depths, float ref, inout vec2 accum) { vec4 depths_sqr = depths * depths; accum += vec2(dot(vec4(1.0), depths), dot(vec4(1.0), depths_sqr)) * SAMPLE_WEIGHT; @@ -168,8 +150,10 @@ void main() { } #ifdef ESM - float accum = ln_space_prefilter(0.0, 0.0, SAMPLE_WEIGHT, depth); + float accum = 1.0; + float ref = depth; #else /* VSM */ + float ref = 0.0; /* UNUSED */ vec2 accum = vec2(depth, depth * depth) * SAMPLE_WEIGHT; #endif @@ -191,7 +175,7 @@ void main() { depths.z = texture(shadowTexture, cos[2]).r; depths.w = texture(shadowTexture, cos[3]).r; depths = get_world_distance(depths, cos); - prefilter(depths, accum); + prefilter(depths, ref, accum); cos[0] = get_texco(uvs, ofs.xy); cos[1] = get_texco(uvs, ofs.zx); @@ -202,7 +186,11 @@ void main() { depths.z = texture(shadowTexture, cos[2]).r; depths.w = texture(shadowTexture, cos[3]).r; depths = get_world_distance(depths, cos); - prefilter(depths, accum); + prefilter(depths, ref, accum); + +#ifdef ESM + accum = ln_space_prefilter_finalize(ref, accum); +#endif 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 d5ac821c3fa..cb7b2b0312a 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl @@ -7,6 +7,7 @@ layout(std140) uniform shadow_render_block { float farClip; int shadowSampleCount; float shadowInvSampleCount; + float exponent; }; #ifdef CSM @@ -34,15 +35,9 @@ vec3 octahedral_to_cubemap_proj(vec2 co) } /* 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)); -} - -vec4 ln_space_prefilter(float w0, vec4 x, float w1, vec4 y) -{ - return x + log(w0 + w1 * exp(y - x)); -} +/* http://advances.realtimerendering.com/s2009/SIGGRAPH%202009%20-%20Lighting%20Research%20at%20Bungie.pdf Slide 55*/ +#define ln_space_prefilter_step(ref, sample) exp(sample - ref) +#define ln_space_prefilter_finalize(ref, sum) (ref + log(shadowInvSampleCount * sum)) #ifdef CSM vec3 get_texco(vec3 cos, const vec2 ofs) @@ -73,6 +68,7 @@ vec3 get_texco(vec3 cos, const vec2 ofs) void grouped_samples_accum( vec3 cos, const vec2 co1, const vec2 co2, const vec2 co3, const vec2 co4, + float ref, inout vec4 accum) { vec4 depths; @@ -81,12 +77,13 @@ void grouped_samples_accum( depths.z = texture(shadowTexture, get_texco(cos, co3)).r; depths.w = texture(shadowTexture, get_texco(cos, co4)).r; - accum = ln_space_prefilter(1.0, accum, shadowInvSampleCount, depths); + accum += ln_space_prefilter_step(ref, depths); } #else /* VSM */ void grouped_samples_accum( vec3 cos, const vec2 co1, const vec2 co2, const vec2 co3, const vec2 co4, + float ref, inout vec2 accum) { vec4 depths1, depths2; @@ -134,17 +131,18 @@ void main() { #ifdef ESM /* disc blur in log space. */ - vec4 accum = vec4(0.0); 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, shadowInvSampleCount, depths); + float ref = depths.x; + vec4 accum = ln_space_prefilter_step(ref, depths); #else /* VSM */ + float ref = 0.0; /* UNUSED */ vec2 accum = vec2(0.0); - grouped_samples_accum(cos, concentric[0], concentric[1], concentric[2], concentric[3], accum); + grouped_samples_accum(cos, concentric[0], concentric[1], concentric[2], concentric[3], ref, accum); #endif /** @@ -154,89 +152,88 @@ void main() { * The solution is to use constant indices to access the array. */ if (shadowSampleCount > 4) { - grouped_samples_accum(cos, concentric[4], concentric[5], concentric[6], concentric[7], accum); - grouped_samples_accum(cos, concentric[8], concentric[9], concentric[10], concentric[11], accum); - grouped_samples_accum(cos, concentric[12], concentric[13], concentric[14], concentric[15], accum); + grouped_samples_accum(cos, concentric[4], concentric[5], concentric[6], concentric[7], ref, accum); + grouped_samples_accum(cos, concentric[8], concentric[9], concentric[10], concentric[11], ref, accum); + grouped_samples_accum(cos, concentric[12], concentric[13], concentric[14], concentric[15], ref, accum); } if (shadowSampleCount > 16) { - grouped_samples_accum(cos, concentric[16], concentric[17], concentric[18], concentric[19], accum); - grouped_samples_accum(cos, concentric[20], concentric[21], concentric[22], concentric[23], accum); - grouped_samples_accum(cos, concentric[24], concentric[25], concentric[26], concentric[27], accum); - grouped_samples_accum(cos, concentric[28], concentric[29], concentric[30], concentric[31], accum); - grouped_samples_accum(cos, concentric[32], concentric[33], concentric[34], concentric[35], accum); + grouped_samples_accum(cos, concentric[16], concentric[17], concentric[18], concentric[19], ref, accum); + grouped_samples_accum(cos, concentric[20], concentric[21], concentric[22], concentric[23], ref, accum); + grouped_samples_accum(cos, concentric[24], concentric[25], concentric[26], concentric[27], ref, accum); + grouped_samples_accum(cos, concentric[28], concentric[29], concentric[30], concentric[31], ref, accum); + grouped_samples_accum(cos, concentric[32], concentric[33], concentric[34], concentric[35], ref, accum); } #ifdef HIGH_BLUR if (shadowSampleCount > 36) { - grouped_samples_accum(cos, concentric[36], concentric[37], concentric[38], concentric[39], accum); - grouped_samples_accum(cos, concentric[40], concentric[41], concentric[42], concentric[43], accum); - grouped_samples_accum(cos, concentric[44], concentric[45], concentric[46], concentric[47], accum); - grouped_samples_accum(cos, concentric[48], concentric[49], concentric[50], concentric[51], accum); - grouped_samples_accum(cos, concentric[52], concentric[53], concentric[54], concentric[55], accum); - grouped_samples_accum(cos, concentric[56], concentric[57], concentric[58], concentric[59], accum); - grouped_samples_accum(cos, concentric[60], concentric[61], concentric[62], concentric[63], accum); + grouped_samples_accum(cos, concentric[36], concentric[37], concentric[38], concentric[39], ref, accum); + grouped_samples_accum(cos, concentric[40], concentric[41], concentric[42], concentric[43], ref, accum); + grouped_samples_accum(cos, concentric[44], concentric[45], concentric[46], concentric[47], ref, accum); + grouped_samples_accum(cos, concentric[48], concentric[49], concentric[50], concentric[51], ref, accum); + grouped_samples_accum(cos, concentric[52], concentric[53], concentric[54], concentric[55], ref, accum); + grouped_samples_accum(cos, concentric[56], concentric[57], concentric[58], concentric[59], ref, accum); + grouped_samples_accum(cos, concentric[60], concentric[61], concentric[62], concentric[63], ref, accum); } if (shadowSampleCount > 64) { - grouped_samples_accum(cos, concentric[64], concentric[65], concentric[66], concentric[67], accum); - grouped_samples_accum(cos, concentric[68], concentric[69], concentric[70], concentric[71], accum); - grouped_samples_accum(cos, concentric[72], concentric[73], concentric[74], concentric[75], accum); - grouped_samples_accum(cos, concentric[76], concentric[77], concentric[78], concentric[79], accum); - grouped_samples_accum(cos, concentric[80], concentric[81], concentric[82], concentric[83], accum); - grouped_samples_accum(cos, concentric[84], concentric[85], concentric[86], concentric[87], accum); - grouped_samples_accum(cos, concentric[88], concentric[89], concentric[90], concentric[91], accum); - grouped_samples_accum(cos, concentric[92], concentric[93], concentric[94], concentric[95], accum); - grouped_samples_accum(cos, concentric[96], concentric[97], concentric[98], concentric[99], accum); + grouped_samples_accum(cos, concentric[64], concentric[65], concentric[66], concentric[67], ref, accum); + grouped_samples_accum(cos, concentric[68], concentric[69], concentric[70], concentric[71], ref, accum); + grouped_samples_accum(cos, concentric[72], concentric[73], concentric[74], concentric[75], ref, accum); + grouped_samples_accum(cos, concentric[76], concentric[77], concentric[78], concentric[79], ref, accum); + grouped_samples_accum(cos, concentric[80], concentric[81], concentric[82], concentric[83], ref, accum); + grouped_samples_accum(cos, concentric[84], concentric[85], concentric[86], concentric[87], ref, accum); + grouped_samples_accum(cos, concentric[88], concentric[89], concentric[90], concentric[91], ref, accum); + grouped_samples_accum(cos, concentric[92], concentric[93], concentric[94], concentric[95], ref, accum); + grouped_samples_accum(cos, concentric[96], concentric[97], concentric[98], concentric[99], ref, accum); } if (shadowSampleCount > 100) { - grouped_samples_accum(cos, concentric[100], concentric[101], concentric[102], concentric[103], accum); - grouped_samples_accum(cos, concentric[104], concentric[105], concentric[106], concentric[107], accum); - grouped_samples_accum(cos, concentric[108], concentric[109], concentric[110], concentric[111], accum); - grouped_samples_accum(cos, concentric[112], concentric[113], concentric[114], concentric[115], accum); - grouped_samples_accum(cos, concentric[116], concentric[117], concentric[118], concentric[119], accum); - grouped_samples_accum(cos, concentric[120], concentric[121], concentric[122], concentric[123], accum); - grouped_samples_accum(cos, concentric[124], concentric[125], concentric[126], concentric[127], accum); - grouped_samples_accum(cos, concentric[128], concentric[129], concentric[130], concentric[131], accum); - grouped_samples_accum(cos, concentric[132], concentric[133], concentric[134], concentric[135], accum); - grouped_samples_accum(cos, concentric[136], concentric[137], concentric[138], concentric[139], accum); - grouped_samples_accum(cos, concentric[140], concentric[141], concentric[142], concentric[143], accum); + grouped_samples_accum(cos, concentric[100], concentric[101], concentric[102], concentric[103], ref, accum); + grouped_samples_accum(cos, concentric[104], concentric[105], concentric[106], concentric[107], ref, accum); + grouped_samples_accum(cos, concentric[108], concentric[109], concentric[110], concentric[111], ref, accum); + grouped_samples_accum(cos, concentric[112], concentric[113], concentric[114], concentric[115], ref, accum); + grouped_samples_accum(cos, concentric[116], concentric[117], concentric[118], concentric[119], ref, accum); + grouped_samples_accum(cos, concentric[120], concentric[121], concentric[122], concentric[123], ref, accum); + grouped_samples_accum(cos, concentric[124], concentric[125], concentric[126], concentric[127], ref, accum); + grouped_samples_accum(cos, concentric[128], concentric[129], concentric[130], concentric[131], ref, accum); + grouped_samples_accum(cos, concentric[132], concentric[133], concentric[134], concentric[135], ref, accum); + grouped_samples_accum(cos, concentric[136], concentric[137], concentric[138], concentric[139], ref, accum); + grouped_samples_accum(cos, concentric[140], concentric[141], concentric[142], concentric[143], ref, accum); } if (shadowSampleCount > 144) { - grouped_samples_accum(cos, concentric[144], concentric[145], concentric[146], concentric[147], accum); - grouped_samples_accum(cos, concentric[148], concentric[149], concentric[150], concentric[151], accum); - grouped_samples_accum(cos, concentric[152], concentric[153], concentric[154], concentric[155], accum); - grouped_samples_accum(cos, concentric[156], concentric[157], concentric[158], concentric[159], accum); - grouped_samples_accum(cos, concentric[160], concentric[161], concentric[162], concentric[163], accum); - grouped_samples_accum(cos, concentric[164], concentric[165], concentric[166], concentric[167], accum); - grouped_samples_accum(cos, concentric[168], concentric[169], concentric[170], concentric[171], accum); - grouped_samples_accum(cos, concentric[172], concentric[173], concentric[174], concentric[175], accum); - grouped_samples_accum(cos, concentric[176], concentric[177], concentric[178], concentric[179], accum); - grouped_samples_accum(cos, concentric[180], concentric[181], concentric[182], concentric[183], accum); - grouped_samples_accum(cos, concentric[184], concentric[185], concentric[186], concentric[187], accum); - grouped_samples_accum(cos, concentric[188], concentric[189], concentric[190], concentric[191], accum); - grouped_samples_accum(cos, concentric[192], concentric[193], concentric[194], concentric[195], accum); + grouped_samples_accum(cos, concentric[144], concentric[145], concentric[146], concentric[147], ref, accum); + grouped_samples_accum(cos, concentric[148], concentric[149], concentric[150], concentric[151], ref, accum); + grouped_samples_accum(cos, concentric[152], concentric[153], concentric[154], concentric[155], ref, accum); + grouped_samples_accum(cos, concentric[156], concentric[157], concentric[158], concentric[159], ref, accum); + grouped_samples_accum(cos, concentric[160], concentric[161], concentric[162], concentric[163], ref, accum); + grouped_samples_accum(cos, concentric[164], concentric[165], concentric[166], concentric[167], ref, accum); + grouped_samples_accum(cos, concentric[168], concentric[169], concentric[170], concentric[171], ref, accum); + grouped_samples_accum(cos, concentric[172], concentric[173], concentric[174], concentric[175], ref, accum); + grouped_samples_accum(cos, concentric[176], concentric[177], concentric[178], concentric[179], ref, accum); + grouped_samples_accum(cos, concentric[180], concentric[181], concentric[182], concentric[183], ref, accum); + grouped_samples_accum(cos, concentric[184], concentric[185], concentric[186], concentric[187], ref, accum); + grouped_samples_accum(cos, concentric[188], concentric[189], concentric[190], concentric[191], ref, accum); + grouped_samples_accum(cos, concentric[192], concentric[193], concentric[194], concentric[195], ref, accum); } if (shadowSampleCount > 196) { - grouped_samples_accum(cos, concentric[196], concentric[197], concentric[198], concentric[199], accum); - grouped_samples_accum(cos, concentric[200], concentric[201], concentric[202], concentric[203], accum); - grouped_samples_accum(cos, concentric[204], concentric[205], concentric[206], concentric[207], accum); - grouped_samples_accum(cos, concentric[208], concentric[209], concentric[210], concentric[211], accum); - grouped_samples_accum(cos, concentric[212], concentric[213], concentric[114], concentric[215], accum); - grouped_samples_accum(cos, concentric[216], concentric[217], concentric[218], concentric[219], accum); - grouped_samples_accum(cos, concentric[220], concentric[221], concentric[222], concentric[223], accum); - grouped_samples_accum(cos, concentric[224], concentric[225], concentric[226], concentric[227], accum); - grouped_samples_accum(cos, concentric[228], concentric[229], concentric[230], concentric[231], accum); - grouped_samples_accum(cos, concentric[232], concentric[233], concentric[234], concentric[235], accum); - grouped_samples_accum(cos, concentric[236], concentric[237], concentric[238], concentric[239], accum); - grouped_samples_accum(cos, concentric[240], concentric[241], concentric[242], concentric[243], accum); - grouped_samples_accum(cos, concentric[244], concentric[245], concentric[246], concentric[247], accum); - grouped_samples_accum(cos, concentric[248], concentric[249], concentric[250], concentric[251], accum); - grouped_samples_accum(cos, concentric[252], concentric[253], concentric[254], concentric[255], accum); + grouped_samples_accum(cos, concentric[196], concentric[197], concentric[198], concentric[199], ref, accum); + grouped_samples_accum(cos, concentric[200], concentric[201], concentric[202], concentric[203], ref, accum); + grouped_samples_accum(cos, concentric[204], concentric[205], concentric[206], concentric[207], ref, accum); + grouped_samples_accum(cos, concentric[208], concentric[209], concentric[210], concentric[211], ref, accum); + grouped_samples_accum(cos, concentric[212], concentric[213], concentric[114], concentric[215], ref, accum); + grouped_samples_accum(cos, concentric[216], concentric[217], concentric[218], concentric[219], ref, accum); + grouped_samples_accum(cos, concentric[220], concentric[221], concentric[222], concentric[223], ref, accum); + grouped_samples_accum(cos, concentric[224], concentric[225], concentric[226], concentric[227], ref, accum); + grouped_samples_accum(cos, concentric[228], concentric[229], concentric[230], concentric[231], ref, accum); + grouped_samples_accum(cos, concentric[232], concentric[233], concentric[234], concentric[235], ref, accum); + grouped_samples_accum(cos, concentric[236], concentric[237], concentric[238], concentric[239], ref, accum); + grouped_samples_accum(cos, concentric[240], concentric[241], concentric[242], concentric[243], ref, accum); + grouped_samples_accum(cos, concentric[244], concentric[245], concentric[246], concentric[247], ref, accum); + grouped_samples_accum(cos, concentric[248], concentric[249], concentric[250], concentric[251], ref, accum); + grouped_samples_accum(cos, concentric[252], concentric[253], concentric[254], concentric[255], ref, accum); } #endif #ifdef ESM - accum.x = 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); + accum.x = dot(vec4(1.0), accum); + accum.x = ln_space_prefilter_finalize(ref, accum.x); FragColor = accum.xxxx; #else /* VSM */ |