[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