Skip to content

Commit

Permalink
Improve shadow bias
Browse files Browse the repository at this point in the history
  • Loading branch information
CodingJellyfish committed Feb 5, 2025
1 parent b08bc20 commit d0670f4
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 14 deletions.
46 changes: 35 additions & 11 deletions data/shaders/sunlightshadow.frag
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ uniform float splitmax;
uniform float shadow_res;
uniform float overlap_proportion;

uniform vec3 box0;
uniform vec3 box1;
uniform vec3 box2;
uniform vec3 box3;

uniform vec3 sundirection;
uniform vec3 sun_color;

Expand All @@ -32,12 +37,12 @@ out vec4 Spec;
#stk_include "utils/SunMRP.frag"

// https://web.archive.org/web/20230210095515/http://the-witness.net/news/2013/09/shadow-mapping-summary-part-1
float getShadowFactor(vec3 pos, int index, float bias)
float getShadowFactor(vec3 pos, int index)
{
vec4 shadowcoord = (u_shadow_projection_view_matrices[index] * u_inverse_view_matrix * vec4(pos, 1.0));
shadowcoord.xy /= shadowcoord.w;
vec2 shadowtexcoord = shadowcoord.xy * 0.5 + 0.5;
float d = .5 * shadowcoord.z + .5 - bias;
float d = .5 * shadowcoord.z + .5;

vec2 uv = shadowtexcoord * shadow_res;
vec2 base_uv = floor(uv + 0.5);
Expand Down Expand Up @@ -83,13 +88,26 @@ float blend_start(float x) {
return x * (1.0 - overlap_proportion);
}

vec3 getXcYcZc(int x, int y, float zC)
{
// We use perspective symetric projection matrix hence P(0,2) = P(1, 2) = 0
float xC= (2. * (float(x)) / u_screen.x - 1.) * zC / u_projection_matrix[0][0];
float yC= (2. * (float(y)) / u_screen.y - 1.) * zC / u_projection_matrix[1][1];
return vec3(xC, yC, zC);
}

void main() {
vec2 uv = gl_FragCoord.xy / u_screen;
float z = texture(dtex, uv).x;
vec4 xpos = getPosFromUVDepth(vec3(uv, z), u_inverse_projection_matrix);

// get the normal of current fragment
vec3 ddx = dFdx(xpos.xyz);
vec3 ddy = dFdy(xpos.xyz);
vec3 geo_norm = normalize(cross(ddy, ddx));

vec3 norm = DecodeNormal(texture(ntex, uv).xy);
float roughness =texture(ntex, uv).z;
float roughness = texture(ntex, uv).z;
vec3 eyedir = -normalize(xpos.xyz);

vec3 Lightdir = SunMRP(norm, eyedir);
Expand All @@ -100,24 +118,30 @@ void main() {

// Shadows
float factor;
float bias = max(1.0 - NdotL, .2) / shadow_res;
vec3 lbias = 40. * Lightdir / shadow_res; // Scale with blur kernel size
vec3 nbias = geo_norm * (1.0 - max(dot(-geo_norm, Lightdir), 0.)) / shadow_res;
nbias -= Lightdir * dot(nbias, Lightdir); // Slope-scaled normal bias

if (xpos.z < split0) {
factor = getShadowFactor(xpos.xyz, 0, bias);
factor = getShadowFactor(xpos.xyz + lbias + nbias * max(box0.x, box0.y), 0);
if (xpos.z > blend_start(split0)) {
factor = mix(factor, getShadowFactor(xpos.xyz, 1, bias), (xpos.z - blend_start(split0)) / split0 / overlap_proportion);
factor = mix(factor, getShadowFactor(xpos.xyz + lbias + nbias * max(box1.x, box1.y), 1),
(xpos.z - blend_start(split0)) / split0 / overlap_proportion);
}
} else if (xpos.z < split1) {
factor = getShadowFactor(xpos.xyz, 1, bias);
factor = getShadowFactor(xpos.xyz + lbias + nbias * max(box1.x, box1.y), 1);
if (xpos.z > blend_start(split1)) {
factor = mix(factor, getShadowFactor(xpos.xyz, 2, bias), (xpos.z - blend_start(split1)) / split1 / overlap_proportion);
factor = mix(factor, getShadowFactor(xpos.xyz + lbias + nbias * max(box2.x, box2.y), 2),
(xpos.z - blend_start(split1)) / split1 / overlap_proportion);
}
} else if (xpos.z < split2) {
factor = getShadowFactor(xpos.xyz, 2, bias);
factor = getShadowFactor(xpos.xyz + lbias + nbias * max(box2.x, box2.y), 2);
if (xpos.z > blend_start(split2)) {
factor = mix(factor, getShadowFactor(xpos.xyz, 3, bias), (xpos.z - blend_start(split2)) / split2 / overlap_proportion);
factor = mix(factor, getShadowFactor(xpos.xyz + lbias + nbias * max(box3.x, box3.y), 3),
(xpos.z - blend_start(split2)) / split2 / overlap_proportion);
}
} else if (xpos.z < splitmax) {
factor = getShadowFactor(xpos.xyz, 3, bias);
factor = getShadowFactor(xpos.xyz + lbias + nbias * max(box3.x, box3.y), 3);
if (xpos.z > blend_start(splitmax)) {
factor = mix(factor, 1.0, (xpos.z - blend_start(splitmax)) / splitmax / overlap_proportion);
}
Expand Down
12 changes: 9 additions & 3 deletions src/graphics/lighting_passes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ class DegradedIBLShader : public TextureShader<DegradedIBLShader, 2>
class ShadowedSunLightShaderPCF : public TextureShader<ShadowedSunLightShaderPCF,
3, float, float, float,
float, float, float,
core::vector3df, core::vector3df,
core::vector3df, core::vector3df,
core::vector3df, video::SColorf>
{
public:
Expand All @@ -218,14 +220,15 @@ class ShadowedSunLightShaderPCF : public TextureShader<ShadowedSunLightShaderPCF
1, "dtex", ST_NEAREST_FILTERED,
8, "shadowtex", ST_SHADOW_SAMPLER);
assignUniforms("split0", "split1", "split2", "splitmax", "shadow_res",
"overlap_proportion", "sundirection", "sun_color");
"overlap_proportion", "box0", "box1", "box2", "box3", "sundirection", "sun_color");
} // ShadowedSunLightShaderPCF
// ------------------------------------------------------------------------
void render(GLuint normal_depth_texture,
GLuint depth_stencil_texture,
const FrameBuffer* shadow_framebuffer,
const core::vector3df &direction,
const video::SColorf &col)
const video::SColorf &col,
const core::vector3df* shadow_box_extents)
{
setTextureUnits(normal_depth_texture,
depth_stencil_texture,
Expand All @@ -236,6 +239,8 @@ class ShadowedSunLightShaderPCF : public TextureShader<ShadowedSunLightShaderPCF
ShadowMatrices::m_shadow_split[4],
float(UserConfigParams::m_shadows_resolution),
ShadowMatrices::m_shadow_overlap_proportion,
shadow_box_extents[0], shadow_box_extents[1],
shadow_box_extents[2], shadow_box_extents[3],
direction, col);

} // render
Expand Down Expand Up @@ -529,7 +534,8 @@ void LightingPasses::renderLights( bool has_shadow,
depth_stencil_texture,
shadow_framebuffer,
irr_driver->getSunDirection(),
irr_driver->getSunColor());
irr_driver->getSunColor(),
shadow_box_extents);
}
}
else
Expand Down

0 comments on commit d0670f4

Please sign in to comment.