Add normal-offset shadow mapping to remove shadow acne (flicker)

pull/1547/head
AnyOldName3 6 years ago
parent 8482236a82
commit 556c9a3382

@ -125,6 +125,10 @@ namespace SceneUtil
else
definesWithShadows["perspectiveShadowMaps"] = "0";
definesWithShadows["disableNormalOffsetShadows"] = Settings::Manager::getFloat("normal offset distance", "Shadows") == 0.0 ? "1" : "0";
definesWithShadows["shadowNormalOffset"] = std::to_string(Settings::Manager::getFloat("normal offset distance", "Shadows"));
return definesWithShadows;
}
@ -140,6 +144,10 @@ namespace SceneUtil
definesWithShadows["perspectiveShadowMaps"] = "0";
definesWithShadows["enableNormalOffsetShadows"] = "0";
definesWithShadows["shadowNormalOffset"] = "0.0";
return definesWithShadows;
}
void ShadowManager::enableIndoorMode()

@ -669,6 +669,8 @@ minimum lispsm near far ratio = 0.25
polygon offset factor = 1.1
# Used as the units parameter for the polygon offset used for shadow map rendering. Higher values reduce shadow flicker, but risk increasing Peter Panning. See https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPolygonOffset.xhtml for details.
polygon offset units = 4.0
# How far along the surface normal to project shadow coordinates. Higher values significantly reduce shadow flicker, usually with a lower increase of Peter Panning than the Polygon Offset settings. This value is in in-game units, so 1.0 is roughly 1.4 cm.
normal offset distance = 1.0
# Excludes theoretically unnecessary faces from shadow maps, slightly increasing performance. In practice, Peter Panning can be much less visible with these faces included, so if you have high polygon offset values, disabling this may help minimise the side effects.
use front face culling = true
# Allow actors to cast shadows. Potentially decreases performance.

@ -103,5 +103,5 @@ void main(void)
passViewPos = viewPos.xyz;
passNormal = gl_Normal.xyz;
setupShadowCoords(viewPos);
setupShadowCoords(viewPos, viewNormal);
}

@ -10,20 +10,44 @@
varying vec4 shadowRegionCoords@shadow_texture_unit_index;
#endif
@endforeach
// Enabling this may reduce peter panning. Probably unnecessary.
const bool onlyNormalOffsetUV = false;
#endif // SHADOWS
void setupShadowCoords(vec4 viewPos)
void setupShadowCoords(vec4 viewPos, vec3 viewNormal)
{
#if SHADOWS
// This matrix has the opposite handedness to the others used here, so multiplication must have the vector to the left. Alternatively it could be transposed after construction, but that's extra work for the GPU just to make the code look a tiny bit cleaner.
mat4 eyePlaneMat;
vec4 shadowOffset;
@foreach shadow_texture_unit_index @shadow_texture_unit_list
eyePlaneMat = mat4(gl_EyePlaneS[shadowTextureUnit@shadow_texture_unit_index], gl_EyePlaneT[shadowTextureUnit@shadow_texture_unit_index], gl_EyePlaneR[shadowTextureUnit@shadow_texture_unit_index], gl_EyePlaneQ[shadowTextureUnit@shadow_texture_unit_index]);
shadowSpaceCoords@shadow_texture_unit_index = viewPos * eyePlaneMat;
#if @perspectiveShadowMaps
shadowRegionCoords@shadow_texture_unit_index = validRegionMatrix@shadow_texture_unit_index * viewPos;
#endif
#if @disableNormalOffsetShadows
shadowSpaceCoords@shadow_texture_unit_index = viewPos * eyePlaneMat;
#else
shadowOffset = vec4(viewNormal * @shadowNormalOffset, 0.0);
if (onlyNormalOffsetUV)
{
shadowSpaceCoords@shadow_texture_unit_index = viewPos * eyePlaneMat;
vec4 lightSpaceXY = viewPos + shadowOffset;
lightSpaceXY = lightSpaceXY * eyePlaneMat;
shadowSpaceCoords@shadow_texture_unit_index.xy = lightSpaceXY.xy;
}
else
{
vec4 offsetViewPosition = viewPos + shadowOffset;
shadowSpaceCoords@shadow_texture_unit_index = offsetViewPosition * eyePlaneMat;
}
#endif
@endforeach
#endif // SHADOWS
}

@ -25,9 +25,10 @@ void main(void)
vec4 viewPos = (gl_ModelViewMatrix * gl_Vertex);
gl_ClipVertex = viewPos;
vec3 viewNormal = normalize((gl_NormalMatrix * gl_Normal).xyz);
#if !PER_PIXEL_LIGHTING
vec3 viewNormal = normalize((gl_NormalMatrix * gl_Normal).xyz);
lighting = doLighting(viewPos.xyz, viewNormal, gl_Color, shadowDiffuseLighting);
#else
passColor = gl_Color;
@ -37,5 +38,5 @@ void main(void)
uv = gl_MultiTexCoord0.xy;
setupShadowCoords(viewPos);
setupShadowCoords(viewPos, viewNormal);
}

@ -22,5 +22,5 @@ void main(void)
depthPassthrough = gl_Position.z;
setupShadowCoords(gl_ModelViewMatrix * gl_Vertex);
setupShadowCoords(gl_ModelViewMatrix * gl_Vertex, normalize((gl_NormalMatrix * gl_Normal).xyz));
}

Loading…
Cancel
Save