[Bf-blender-cvs] [36a3a400332] blender2.8: Eevee: Fix ESM not working after a certain distance

Clément Foucault noreply at git.blender.org
Mon Nov 12 13:50:32 CET 2018


Commit: 36a3a40033298227cfc55f59580e03863c09699d
Author: Clément Foucault
Date:   Sun Nov 11 17:45:29 2018 +0100
Branches: blender2.8
https://developer.blender.org/rB36a3a40033298227cfc55f59580e03863c09699d

Eevee: Fix ESM not working after a certain distance

This was caused by overflow caused by the background and precision during
filtering.

===================================================================

M	source/blender/draw/engines/eevee/eevee_lights.c
M	source/blender/draw/engines/eevee/eevee_private.h
M	source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl
M	source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl

===================================================================

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,

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list