]> git.lizzy.rs Git - dragonfireclient.git/commitdiff
Improve shadow filters (#12195)
authorx2048 <codeforsmile@gmail.com>
Sat, 21 May 2022 14:49:30 +0000 (16:49 +0200)
committerGitHub <noreply@github.com>
Sat, 21 May 2022 14:49:30 +0000 (16:49 +0200)
* Rewrite shadow filtering for the new distortion
* Calculate penumbra radius using a single sample
* Avoid peter-panning effect due to filtering of short shadows
* Add adaptive filter quality for soft shadows
* Avoid sharp shadows on surfaces without normals (e.g. plants)
* Increase default and maximum soft shadow radius
* Make line numbers in shader errors match the code

builtin/settingtypes.txt
client/shaders/nodes_shader/opengl_fragment.glsl
client/shaders/nodes_shader/opengl_vertex.glsl
client/shaders/object_shader/opengl_fragment.glsl
client/shaders/object_shader/opengl_vertex.glsl
src/client/clientmap.cpp
src/client/shader.cpp
src/client/shadows/dynamicshadowsrender.cpp
src/defaultsettings.cpp

index ff69d97412768cbc4d8c4e457edb989a4dd5203a..3f6f6c9fc32731fbaddbc79e302a508c1a21d2a0 100644 (file)
@@ -631,8 +631,8 @@ shadow_update_frames (Map shadows update frames) int 8 1 16
 
 #    Set the soft shadow radius size.
 #    Lower values mean sharper shadows, bigger values mean softer shadows.
-#    Minimum value: 1.0; maximum value: 10.0
-shadow_soft_radius (Soft shadow radius) float 1.0 1.0 10.0
+#    Minimum value: 1.0; maximum value: 15.0
+shadow_soft_radius (Soft shadow radius) float 5.0 1.0 15.0
 
 #    Set the tilt of Sun/Moon orbit in degrees.
 #    Value of 0 means no tilt / vertical orbit.
index 8110f6fd3dfbc2297ad4908d8ff9d2da9ae9968a..c4b947e72a0e07e76e742bda83b01237346885e7 100644 (file)
@@ -25,6 +25,7 @@ uniform float animationTimer;
        varying float cosLight;
        varying float f_normal_length;
        varying vec3 shadow_position;
+       varying float perspective_factor;
 #endif
 
 
@@ -116,23 +117,16 @@ float getHardShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance
 
 
 #if SHADOW_FILTER == 2
-       #define PCFBOUND 3.5
-       #define PCFSAMPLES 64.0
+       #define PCFBOUND 2.0 // 5x5
+       #define PCFSAMPLES 25
 #elif SHADOW_FILTER == 1
-       #define PCFBOUND 1.5
-       #if defined(POISSON_FILTER)
-               #define PCFSAMPLES 32.0
-       #else
-               #define PCFSAMPLES 16.0
-       #endif
+       #define PCFBOUND 1.0 // 3x3
+       #define PCFSAMPLES 9
 #else
        #define PCFBOUND 0.0
-       #if defined(POISSON_FILTER)
-               #define PCFSAMPLES 4.0
-       #else
-               #define PCFSAMPLES 1.0
-       #endif
+       #define PCFSAMPLES 1
 #endif
+
 #ifdef COLORED_SHADOWS
 float getHardShadowDepth(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
 {
@@ -149,59 +143,31 @@ float getHardShadowDepth(sampler2D shadowsampler, vec2 smTexCoord, float realDis
 }
 #endif
 
-float getBaseLength(vec2 smTexCoord)
-{
-       float l = length(2.0 * smTexCoord.xy - 1.0 - CameraPos.xy);     // length in texture coords
-       return xyPerspectiveBias1 / (1.0 / l - xyPerspectiveBias0);                              // return to undistorted coords
-}
-
-float getDeltaPerspectiveFactor(float l)
-{
-       return 0.04 * pow(512.0 / f_textureresolution, 0.4) / (xyPerspectiveBias0 * l + xyPerspectiveBias1);                      // original distortion factor, divided by 10
-}
+#define BASEFILTERRADIUS 1.0
 
-float getPenumbraRadius(sampler2D shadowsampler, vec2 smTexCoord, float realDistance, float multiplier)
+float getPenumbraRadius(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
 {
-       float baseLength = getBaseLength(smTexCoord);
-       float perspectiveFactor;
-
        // Return fast if sharp shadows are requested
-       if (PCFBOUND == 0.0)
+       if (PCFBOUND == 0.0 || SOFTSHADOWRADIUS <= 0.0)
                return 0.0;
 
-       if (SOFTSHADOWRADIUS <= 1.0) {
-               perspectiveFactor = getDeltaPerspectiveFactor(baseLength);
-               return max(2 * length(smTexCoord.xy) * 2048 / f_textureresolution / pow(perspectiveFactor, 3), SOFTSHADOWRADIUS);
-       }
-
        vec2 clampedpos;
-       float texture_size = 1.0 / (2048 /*f_textureresolution*/ * 0.5);
        float y, x;
-       float depth = 0.0;
-       float pointDepth;
-       float maxRadius = SOFTSHADOWRADIUS * 5.0 * multiplier;
-
-       float bound = clamp(PCFBOUND * (1 - baseLength), 0.0, PCFBOUND);
-       int n = 0;
-
-       for (y = -bound; y <= bound; y += 1.0)
-       for (x = -bound; x <= bound; x += 1.0) {
-               clampedpos = vec2(x,y);
-               perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * maxRadius);
-               clampedpos = clampedpos * texture_size * perspectiveFactor * maxRadius * perspectiveFactor + smTexCoord.xy;
-
-               pointDepth = getHardShadowDepth(shadowsampler, clampedpos.xy, realDistance);
-               if (pointDepth > -0.01) {
-                       depth += pointDepth;
-                       n += 1;
-               }
-       }
-
-       depth = depth / n;
-       depth = pow(clamp(depth, 0.0, 1000.0), 1.6) / 0.001;
-
-       perspectiveFactor = getDeltaPerspectiveFactor(baseLength);
-       return max(length(smTexCoord.xy) * 2 * 2048 / f_textureresolution / pow(perspectiveFactor, 3), depth * maxRadius);
+       float depth = getHardShadowDepth(shadowsampler, smTexCoord.xy, realDistance);
+       // A factor from 0 to 1 to reduce blurring of short shadows
+       float sharpness_factor = 1.0;
+       // conversion factor from shadow depth to blur radius
+       float depth_to_blur = f_shadowfar / SOFTSHADOWRADIUS / xyPerspectiveBias0;
+       if (depth > 0.0 && f_normal_length > 0.0)
+               // 5 is empirical factor that controls how fast shadow loses sharpness
+               sharpness_factor = clamp(5 * depth * depth_to_blur, 0.0, 1.0);
+       depth = 0.0;
+
+       float world_to_texture = xyPerspectiveBias1 / perspective_factor / perspective_factor
+                       * f_textureresolution / 2.0 / f_shadowfar;
+       float world_radius = 0.2; // shadow blur radius in world float coordinates, e.g. 0.2 = 0.02 of one node
+
+       return max(BASEFILTERRADIUS * f_textureresolution / 4096.0,  sharpness_factor * world_radius * world_to_texture * SOFTSHADOWRADIUS);
 }
 
 #ifdef POISSON_FILTER
@@ -276,26 +242,23 @@ const vec2[64] poissonDisk = vec2[64](
 
 vec4 getShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
 {
-       vec2 clampedpos;
-       vec4 visibility = vec4(0.0);
-       float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance, 1.5); // scale to align with PCF
+       float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance);
        if (radius < 0.1) {
                // we are in the middle of even brightness, no need for filtering
                return getHardShadowColor(shadowsampler, smTexCoord.xy, realDistance);
        }
 
-       float baseLength = getBaseLength(smTexCoord);
-       float perspectiveFactor;
+       vec2 clampedpos;
+       vec4 visibility = vec4(0.0);
+       float scale_factor = radius / f_textureresolution;
 
-       float texture_size = 1.0 / (f_textureresolution * 0.5);
-       int samples = int(clamp(PCFSAMPLES * (1 - baseLength) * (1 - baseLength), PCFSAMPLES / 4, PCFSAMPLES));
+       int samples = (1 + 1 * int(SOFTSHADOWRADIUS > 1.0)) * PCFSAMPLES; // scale max samples for the soft shadows
+       samples = int(clamp(pow(4.0 * radius + 1.0, 2.0), 1.0, float(samples)));
        int init_offset = int(floor(mod(((smTexCoord.x * 34.0) + 1.0) * smTexCoord.y, 64.0-samples)));
        int end_offset = int(samples) + init_offset;
 
        for (int x = init_offset; x < end_offset; x++) {
-               clampedpos = poissonDisk[x];
-               perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * radius);
-               clampedpos = clampedpos * texture_size * perspectiveFactor * radius * perspectiveFactor + smTexCoord.xy;
+               clampedpos = poissonDisk[x] * scale_factor + smTexCoord.xy;
                visibility += getHardShadowColor(shadowsampler, clampedpos.xy, realDistance);
        }
 
@@ -306,26 +269,23 @@ vec4 getShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance
 
 float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
 {
-       vec2 clampedpos;
-       float visibility = 0.0;
-       float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance, 1.5); // scale to align with PCF
+       float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance);
        if (radius < 0.1) {
                // we are in the middle of even brightness, no need for filtering
                return getHardShadow(shadowsampler, smTexCoord.xy, realDistance);
        }
 
-       float baseLength = getBaseLength(smTexCoord);
-       float perspectiveFactor;
+       vec2 clampedpos;
+       float visibility = 0.0;
+       float scale_factor = radius / f_textureresolution;
 
-       float texture_size = 1.0 / (f_textureresolution * 0.5);
-       int samples = int(clamp(PCFSAMPLES * (1 - baseLength) * (1 - baseLength), PCFSAMPLES / 4, PCFSAMPLES));
+       int samples = (1 + 1 * int(SOFTSHADOWRADIUS > 1.0)) * PCFSAMPLES; // scale max samples for the soft shadows
+       samples = int(clamp(pow(4.0 * radius + 1.0, 2.0), 1.0, float(samples)));
        int init_offset = int(floor(mod(((smTexCoord.x * 34.0) + 1.0) * smTexCoord.y, 64.0-samples)));
        int end_offset = int(samples) + init_offset;
 
        for (int x = init_offset; x < end_offset; x++) {
-               clampedpos = poissonDisk[x];
-               perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * radius);
-               clampedpos = clampedpos * texture_size * perspectiveFactor * radius * perspectiveFactor + smTexCoord.xy;
+               clampedpos = poissonDisk[x] * scale_factor + smTexCoord.xy;
                visibility += getHardShadow(shadowsampler, clampedpos.xy, realDistance);
        }
 
@@ -341,65 +301,57 @@ float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
 
 vec4 getShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
 {
-       vec2 clampedpos;
-       vec4 visibility = vec4(0.0);
-       float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance, 1.0);
+       float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance);
        if (radius < 0.1) {
                // we are in the middle of even brightness, no need for filtering
                return getHardShadowColor(shadowsampler, smTexCoord.xy, realDistance);
        }
 
-       float baseLength = getBaseLength(smTexCoord);
-       float perspectiveFactor;
-
-       float texture_size = 1.0 / (f_textureresolution * 0.5);
-       float y, x;
-       float bound = clamp(PCFBOUND * (1 - baseLength), PCFBOUND / 2, PCFBOUND);
-       int n = 0;
+       vec2 clampedpos;
+       vec4 visibility = vec4(0.0);
+       float x, y;
+       float bound = (1 + 0.5 * int(SOFTSHADOWRADIUS > 1.0)) * PCFBOUND; // scale max bound for soft shadows
+       bound = clamp(0.5 * (4.0 * radius - 1.0), 0.5, bound);
+       float scale_factor = radius / bound / f_textureresolution;
+       float n = 0.0;
 
        // basic PCF filter
        for (y = -bound; y <= bound; y += 1.0)
        for (x = -bound; x <= bound; x += 1.0) {
-               clampedpos = vec2(x,y);     // screen offset
-               perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * radius / bound);
-               clampedpos =  clampedpos * texture_size * perspectiveFactor * radius * perspectiveFactor / bound + smTexCoord.xy; // both dx,dy and radius are adjusted
+               clampedpos = vec2(x,y) * scale_factor + smTexCoord.xy;
                visibility += getHardShadowColor(shadowsampler, clampedpos.xy, realDistance);
-               n += 1;
+               n += 1.0;
        }
 
-       return visibility / n;
+       return visibility / max(n, 1.0);
 }
 
 #else
 float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
 {
-       vec2 clampedpos;
-       float visibility = 0.0;
-       float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance, 1.0);
+       float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance);
        if (radius < 0.1) {
                // we are in the middle of even brightness, no need for filtering
                return getHardShadow(shadowsampler, smTexCoord.xy, realDistance);
        }
 
-       float baseLength = getBaseLength(smTexCoord);
-       float perspectiveFactor;
-
-       float texture_size = 1.0 / (f_textureresolution * 0.5);
-       float y, x;
-       float bound = clamp(PCFBOUND * (1 - baseLength), PCFBOUND / 2, PCFBOUND);
-       int n = 0;
+       vec2 clampedpos;
+       float visibility = 0.0;
+       float x, y;
+       float bound = (1 + 0.5 * int(SOFTSHADOWRADIUS > 1.0)) * PCFBOUND; // scale max bound for soft shadows
+       bound = clamp(0.5 * (4.0 * radius - 1.0), 0.5, bound);
+       float scale_factor = radius / bound / f_textureresolution;
+       float n = 0.0;
 
        // basic PCF filter
        for (y = -bound; y <= bound; y += 1.0)
        for (x = -bound; x <= bound; x += 1.0) {
-               clampedpos = vec2(x,y);     // screen offset
-               perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * radius / bound);
-               clampedpos =  clampedpos * texture_size * perspectiveFactor * radius * perspectiveFactor / bound + smTexCoord.xy; // both dx,dy and radius are adjusted
+               clampedpos = vec2(x,y) * scale_factor + smTexCoord.xy;
                visibility += getHardShadow(shadowsampler, clampedpos.xy, realDistance);
-               n += 1;
+               n += 1.0;
        }
 
-       return visibility / n;
+       return visibility / max(n, 1.0);
 }
 
 #endif
index 3ea0faa36d0b2865cb0eaf1b1ac51b6a2f5c15b3..d1fba283021057a7667ce046e4f61b0a7b6711f7 100644 (file)
@@ -39,6 +39,7 @@ centroid varying vec2 varTexCoord;
        varying float adj_shadow_strength;
        varying float f_normal_length;
        varying vec3 shadow_position;
+       varying float perspective_factor;
 #endif
 
 
@@ -253,6 +254,7 @@ void main(void)
 
                shadow_position = applyPerspectiveDistortion(m_ShadowViewProj * mWorld * (inVertexPosition + vec4(normalOffsetScale * nNormal, 0.0))).xyz;
                shadow_position.z -= z_bias;
+               perspective_factor = pFactor;
 
                if (f_timeofday < 0.2) {
                        adj_shadow_strength = f_shadow_strength * 0.5 *
index 7baf5826ffaa3ab4126b931de6a263fe89c2528d..1fefc764b37bff4c741de7f49270b81f6ce59919 100644 (file)
@@ -1,6 +1,5 @@
 uniform sampler2D baseTexture;
 
-uniform vec4 emissiveColor;
 uniform vec3 dayLight;
 uniform vec4 skyBgColor;
 uniform float fogDistance;
@@ -26,6 +25,7 @@ uniform float animationTimer;
        varying float cosLight;
        varying float f_normal_length;
        varying vec3 shadow_position;
+       varying float perspective_factor;
 #endif
 
 
@@ -119,23 +119,16 @@ float getHardShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance
 
 
 #if SHADOW_FILTER == 2
-       #define PCFBOUND 3.5
-       #define PCFSAMPLES 64.0
+       #define PCFBOUND 2.0 // 5x5
+       #define PCFSAMPLES 25
 #elif SHADOW_FILTER == 1
-       #define PCFBOUND 1.5
-       #if defined(POISSON_FILTER)
-               #define PCFSAMPLES 32.0
-       #else
-               #define PCFSAMPLES 16.0
-       #endif
+       #define PCFBOUND 1.0 // 3x3
+       #define PCFSAMPLES 9
 #else
        #define PCFBOUND 0.0
-       #if defined(POISSON_FILTER)
-               #define PCFSAMPLES 4.0
-       #else
-               #define PCFSAMPLES 1.0
-       #endif
+       #define PCFSAMPLES 1
 #endif
+
 #ifdef COLORED_SHADOWS
 float getHardShadowDepth(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
 {
@@ -152,59 +145,31 @@ float getHardShadowDepth(sampler2D shadowsampler, vec2 smTexCoord, float realDis
 }
 #endif
 
-float getBaseLength(vec2 smTexCoord)
-{
-       float l = length(2.0 * smTexCoord.xy - 1.0 - CameraPos.xy);     // length in texture coords
-       return xyPerspectiveBias1 / (1.0 / l - xyPerspectiveBias0);                              // return to undistorted coords
-}
-
-float getDeltaPerspectiveFactor(float l)
-{
-       return 0.04 * pow(512.0 / f_textureresolution, 0.4) / (xyPerspectiveBias0 * l + xyPerspectiveBias1);                      // original distortion factor, divided by 10
-}
+#define BASEFILTERRADIUS 1.0
 
-float getPenumbraRadius(sampler2D shadowsampler, vec2 smTexCoord, float realDistance, float multiplier)
+float getPenumbraRadius(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
 {
-       float baseLength = getBaseLength(smTexCoord);
-       float perspectiveFactor;
-
        // Return fast if sharp shadows are requested
-       if (PCFBOUND == 0.0)
+       if (PCFBOUND == 0.0 || SOFTSHADOWRADIUS <= 0.0)
                return 0.0;
 
-       if (SOFTSHADOWRADIUS <= 1.0) {
-               perspectiveFactor = getDeltaPerspectiveFactor(baseLength);
-               return max(2 * length(smTexCoord.xy) * 2048 / f_textureresolution / pow(perspectiveFactor, 3), SOFTSHADOWRADIUS);
-       }
-
        vec2 clampedpos;
-       float texture_size = 1.0 / (2048 /*f_textureresolution*/ * 0.5);
        float y, x;
-       float depth = 0.0;
-       float pointDepth;
-       float maxRadius = SOFTSHADOWRADIUS * 5.0 * multiplier;
-
-       float bound = clamp(PCFBOUND * (1 - baseLength), 0.0, PCFBOUND);
-       int n = 0;
-
-       for (y = -bound; y <= bound; y += 1.0)
-       for (x = -bound; x <= bound; x += 1.0) {
-               clampedpos = vec2(x,y);
-               perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * maxRadius);
-               clampedpos = clampedpos * texture_size * perspectiveFactor * maxRadius * perspectiveFactor + smTexCoord.xy;
-
-               pointDepth = getHardShadowDepth(shadowsampler, clampedpos.xy, realDistance);
-               if (pointDepth > -0.01) {
-                       depth += pointDepth;
-                       n += 1;
-               }
-       }
-
-       depth = depth / n;
-       depth = pow(clamp(depth, 0.0, 1000.0), 1.6) / 0.001;
-
-       perspectiveFactor = getDeltaPerspectiveFactor(baseLength);
-       return max(length(smTexCoord.xy) * 2 * 2048 / f_textureresolution / pow(perspectiveFactor, 3), depth * maxRadius);
+       float depth = getHardShadowDepth(shadowsampler, smTexCoord.xy, realDistance);
+       // A factor from 0 to 1 to reduce blurring of short shadows
+       float sharpness_factor = 1.0;
+       // conversion factor from shadow depth to blur radius
+       float depth_to_blur = f_shadowfar / SOFTSHADOWRADIUS / xyPerspectiveBias0;
+       if (depth > 0.0 && f_normal_length > 0.0)
+               // 5 is empirical factor that controls how fast shadow loses sharpness
+               sharpness_factor = clamp(5 * depth * depth_to_blur, 0.0, 1.0);
+       depth = 0.0;
+
+       float world_to_texture = xyPerspectiveBias1 / perspective_factor / perspective_factor
+                       * f_textureresolution / 2.0 / f_shadowfar;
+       float world_radius = 0.2; // shadow blur radius in world float coordinates, e.g. 0.2 = 0.02 of one node
+
+       return max(BASEFILTERRADIUS * f_textureresolution / 4096.0,  sharpness_factor * world_radius * world_to_texture * SOFTSHADOWRADIUS);
 }
 
 #ifdef POISSON_FILTER
@@ -279,26 +244,23 @@ const vec2[64] poissonDisk = vec2[64](
 
 vec4 getShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
 {
-       vec2 clampedpos;
-       vec4 visibility = vec4(0.0);
-       float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance, 1.5); // scale to align with PCF
+       float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance);
        if (radius < 0.1) {
                // we are in the middle of even brightness, no need for filtering
                return getHardShadowColor(shadowsampler, smTexCoord.xy, realDistance);
        }
 
-       float baseLength = getBaseLength(smTexCoord);
-       float perspectiveFactor;
+       vec2 clampedpos;
+       vec4 visibility = vec4(0.0);
+       float scale_factor = radius / f_textureresolution;
 
-       float texture_size = 1.0 / (f_textureresolution * 0.5);
-       int samples = int(clamp(PCFSAMPLES * (1 - baseLength) * (1 - baseLength), PCFSAMPLES / 4, PCFSAMPLES));
+       int samples = (1 + 1 * int(SOFTSHADOWRADIUS > 1.0)) * PCFSAMPLES; // scale max samples for the soft shadows
+       samples = int(clamp(pow(4.0 * radius + 1.0, 2.0), 1.0, float(samples)));
        int init_offset = int(floor(mod(((smTexCoord.x * 34.0) + 1.0) * smTexCoord.y, 64.0-samples)));
        int end_offset = int(samples) + init_offset;
 
        for (int x = init_offset; x < end_offset; x++) {
-               clampedpos = poissonDisk[x];
-               perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * radius);
-               clampedpos = clampedpos * texture_size * perspectiveFactor * radius * perspectiveFactor + smTexCoord.xy;
+               clampedpos = poissonDisk[x] * scale_factor + smTexCoord.xy;
                visibility += getHardShadowColor(shadowsampler, clampedpos.xy, realDistance);
        }
 
@@ -309,26 +271,23 @@ vec4 getShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance
 
 float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
 {
-       vec2 clampedpos;
-       float visibility = 0.0;
-       float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance, 1.5); // scale to align with PCF
+       float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance);
        if (radius < 0.1) {
                // we are in the middle of even brightness, no need for filtering
                return getHardShadow(shadowsampler, smTexCoord.xy, realDistance);
        }
 
-       float baseLength = getBaseLength(smTexCoord);
-       float perspectiveFactor;
+       vec2 clampedpos;
+       float visibility = 0.0;
+       float scale_factor = radius / f_textureresolution;
 
-       float texture_size = 1.0 / (f_textureresolution * 0.5);
-       int samples = int(clamp(PCFSAMPLES * (1 - baseLength) * (1 - baseLength), PCFSAMPLES / 4, PCFSAMPLES));
+       int samples = (1 + 1 * int(SOFTSHADOWRADIUS > 1.0)) * PCFSAMPLES; // scale max samples for the soft shadows
+       samples = int(clamp(pow(4.0 * radius + 1.0, 2.0), 1.0, float(samples)));
        int init_offset = int(floor(mod(((smTexCoord.x * 34.0) + 1.0) * smTexCoord.y, 64.0-samples)));
        int end_offset = int(samples) + init_offset;
 
        for (int x = init_offset; x < end_offset; x++) {
-               clampedpos = poissonDisk[x];
-               perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * radius);
-               clampedpos = clampedpos * texture_size * perspectiveFactor * radius * perspectiveFactor + smTexCoord.xy;
+               clampedpos = poissonDisk[x] * scale_factor + smTexCoord.xy;
                visibility += getHardShadow(shadowsampler, clampedpos.xy, realDistance);
        }
 
@@ -344,65 +303,57 @@ float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
 
 vec4 getShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
 {
-       vec2 clampedpos;
-       vec4 visibility = vec4(0.0);
-       float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance, 1.0);
+       float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance);
        if (radius < 0.1) {
                // we are in the middle of even brightness, no need for filtering
                return getHardShadowColor(shadowsampler, smTexCoord.xy, realDistance);
        }
 
-       float baseLength = getBaseLength(smTexCoord);
-       float perspectiveFactor;
-
-       float texture_size = 1.0 / (f_textureresolution * 0.5);
-       float y, x;
-       float bound = clamp(PCFBOUND * (1 - baseLength), PCFBOUND / 2, PCFBOUND);
-       int n = 0;
+       vec2 clampedpos;
+       vec4 visibility = vec4(0.0);
+       float x, y;
+       float bound = (1 + 0.5 * int(SOFTSHADOWRADIUS > 1.0)) * PCFBOUND; // scale max bound for soft shadows
+       bound = clamp(0.5 * (4.0 * radius - 1.0), 0.5, bound);
+       float scale_factor = radius / bound / f_textureresolution;
+       float n = 0.0;
 
        // basic PCF filter
        for (y = -bound; y <= bound; y += 1.0)
        for (x = -bound; x <= bound; x += 1.0) {
-               clampedpos = vec2(x,y);     // screen offset
-               perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * radius / bound);
-               clampedpos =  clampedpos * texture_size * perspectiveFactor * radius * perspectiveFactor / bound + smTexCoord.xy; // both dx,dy and radius are adjusted
+               clampedpos = vec2(x,y) * scale_factor + smTexCoord.xy;
                visibility += getHardShadowColor(shadowsampler, clampedpos.xy, realDistance);
-               n += 1;
+               n += 1.0;
        }
 
-       return visibility / n;
+       return visibility / max(n, 1.0);
 }
 
 #else
 float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
 {
-       vec2 clampedpos;
-       float visibility = 0.0;
-       float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance, 1.0);
+       float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance);
        if (radius < 0.1) {
                // we are in the middle of even brightness, no need for filtering
                return getHardShadow(shadowsampler, smTexCoord.xy, realDistance);
        }
 
-       float baseLength = getBaseLength(smTexCoord);
-       float perspectiveFactor;
-
-       float texture_size = 1.0 / (f_textureresolution * 0.5);
-       float y, x;
-       float bound = clamp(PCFBOUND * (1 - baseLength), PCFBOUND / 2, PCFBOUND);
-       int n = 0;
+       vec2 clampedpos;
+       float visibility = 0.0;
+       float x, y;
+       float bound = (1 + 0.5 * int(SOFTSHADOWRADIUS > 1.0)) * PCFBOUND; // scale max bound for soft shadows
+       bound = clamp(0.5 * (4.0 * radius - 1.0), 0.5, bound);
+       float scale_factor = radius / bound / f_textureresolution;
+       float n = 0.0;
 
        // basic PCF filter
        for (y = -bound; y <= bound; y += 1.0)
        for (x = -bound; x <= bound; x += 1.0) {
-               clampedpos = vec2(x,y);     // screen offset
-               perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * radius / bound);
-               clampedpos =  clampedpos * texture_size * perspectiveFactor * radius * perspectiveFactor / bound + smTexCoord.xy; // both dx,dy and radius are adjusted
+               clampedpos = vec2(x,y) * scale_factor + smTexCoord.xy;
                visibility += getHardShadow(shadowsampler, clampedpos.xy, realDistance);
-               n += 1;
+               n += 1.0;
        }
 
-       return visibility / n;
+       return visibility / max(n, 1.0);
 }
 
 #endif
@@ -489,7 +440,6 @@ void main(void)
                        shadow_color = visibility.gba;
 #else
                        if (cosLight > 0.0 || f_normal_length < 1e-3)
-                       if (cosLight > 0.0)
                                shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z);
                        else
                                shadow_int = 1.0;
@@ -540,6 +490,6 @@ void main(void)
                - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0);
        col = mix(skyBgColor, col, clarity);
        col = vec4(col.rgb, base.a);
-       
+
        gl_FragColor = col;
 }
index 6dc25f85481ef86e93e237741ffb88f3858ef2dd..dc9c70cdfd9ef2a8a047f9c0f8c9737af9624009 100644 (file)
@@ -30,6 +30,7 @@ centroid varying vec2 varTexCoord;
        varying float adj_shadow_strength;
        varying float f_normal_length;
        varying vec3 shadow_position;
+       varying float perspective_factor;
 #endif
 
 varying vec3 eyeVec;
@@ -162,6 +163,7 @@ void main(void)
 
                shadow_position = applyPerspectiveDistortion(m_ShadowViewProj * mWorld * (inVertexPosition + vec4(normalOffsetScale * nNormal, 0.0))).xyz;
                shadow_position.z -= z_bias;
+               perspective_factor = pFactor;
 
                if (f_timeofday < 0.2) {
                        adj_shadow_strength = f_shadow_strength * 0.5 *
index 10967c0cb1eec4009b307528d4eb8a8e64f0ca49..46cb115aae398ed25b0cda8486d6392268de6063 100644 (file)
@@ -489,6 +489,8 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
                                // Do not enable filter on shadow texture to avoid visual artifacts
                                // with colored shadows.
                                // Filtering is done in shader code anyway
+                               layer.BilinearFilter = false;
+                               layer.AnisotropicFilter = false;
                                layer.TrilinearFilter = false;
                        }
                        driver->setMaterial(material);
index bbb8727612862810c0fb91fde47236773a4cf7be..009a4b3d706c48d27d72119e36dc9dcd59e3aab1 100644 (file)
@@ -771,6 +771,8 @@ ShaderInfo ShaderSource::generateShader(const std::string &name,
                shaders_header << "#define SOFTSHADOWRADIUS " << shadow_soft_radius << "\n";
        }
 
+       shaders_header << "#line 0\n"; // reset the line counter for meaningful diagnostics
+
        std::string common_header = shaders_header.str();
 
        std::string vertex_shader = m_sourcecache.getOrLoad(name, "opengl_vertex.glsl");
index 07dc6daf265595b6bcba690b9f976bf2c5d77687..c13cfe252894af9adc2e63ed137d5ad0df399b9e 100644 (file)
@@ -670,6 +670,7 @@ std::string ShadowRenderer::readShaderFile(const std::string &path)
        std::string prefix;
        if (m_shadow_map_colored)
                prefix.append("#define COLORED_SHADOWS 1\n");
+       prefix.append("#line 0\n");
 
        std::string content;
        fs::ReadFile(path, content);
index 11d52efd3dc0d70b26097e0a8609f7379e0a7f6f..0087f8d48e3b54e3b9f80c519de6dc45a9f6b301 100644 (file)
@@ -274,7 +274,7 @@ void set_default_settings()
        settings->setDefault("shadow_filters", "1");
        settings->setDefault("shadow_poisson_filter", "true");
        settings->setDefault("shadow_update_frames", "8");
-       settings->setDefault("shadow_soft_radius", "1.0");
+       settings->setDefault("shadow_soft_radius", "5.0");
        settings->setDefault("shadow_sky_body_orbit_tilt", "0.0");
 
        // Input