Eevee: Fix ESM not working after a certain distance

This was caused by overflow caused by the background and precision during
filtering.
This commit is contained in:
Clément Foucault 2018-11-11 17:45:29 +01:00
parent e51dae4af8
commit 36a3a40033
4 changed files with 101 additions and 114 deletions

View File

@ -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);

View File

@ -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. */

View File

@ -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;
}

View File

@ -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 */