Improve shadow quality and performance in gl33

If CONFIG_QUALITY_SHADOWS is defined (which it always is) then the
fragment shader code that samples the shadow map will take five samples
in a cross shape around the point to be sampled, to apply antialiasing.

Currently, the offset of these samples is hardcoded to 0.00025× the
shadow map resolution. This is very inconsistent: if the shadow map
resolution is 128×128, then these samples are 0.032 texels apart, which
is a waste of four texture samples, and essentially means that no
antialiasing is applied. If the shadow map resolution is 8192×8192, then
these samples are 2.048 texels apart, which causes visual artefacts
around shadow edges, instead of giving smoother shadows.

The correct thing to do is to always sample exactly one texel away from
the original position. This is easy in GLSL 3.30, as it includes a
textureOffset function which offsets a texture fetch by an exact number
of texels. This is faster than manually calculating an offset ourselves,
it fixes visual artefacts at high resolutions, and it properly applies
antialiasing at low resolutions.
1008-fix
AbigailBuccaneer 2018-05-02 16:30:45 +01:00
parent fdf67b8217
commit 0d6fffd91f
1 changed files with 7 additions and 11 deletions

View File

@ -96,19 +96,15 @@ void main()
if (uni_ShadowTextureEnabled)
{
float value = texture(uni_ShadowTexture, data.ShadowCoord.xyz);
#ifdef CONFIG_QUALITY_SHADOWS
float offset = 0.00025f;
float value = (1.0f / 5.0f) * (texture(uni_ShadowTexture, data.ShadowCoord.xyz)
+ texture(uni_ShadowTexture, data.ShadowCoord.xyz + vec3( offset, 0.0f, 0.0f))
+ texture(uni_ShadowTexture, data.ShadowCoord.xyz + vec3(-offset, 0.0f, 0.0f))
+ texture(uni_ShadowTexture, data.ShadowCoord.xyz + vec3( 0.0f, offset, 0.0f))
+ texture(uni_ShadowTexture, data.ShadowCoord.xyz + vec3( 0.0f, -offset, 0.0f)));
shadow = mix(uni_ShadowColor, 1.0f, value);
#else
shadow = mix(uni_ShadowColor, 1.0f, texture(uni_ShadowTexture, data.ShadowCoord.xyz));
value += textureOffset(uni_ShadowTexture, data.ShadowCoord.xyz, ivec2( 1, 0))
+ textureOffset(uni_ShadowTexture, data.ShadowCoord.xyz, ivec2(-1, 0))
+ textureOffset(uni_ShadowTexture, data.ShadowCoord.xyz, ivec2( 0, 1))
+ textureOffset(uni_ShadowTexture, data.ShadowCoord.xyz, ivec2( 0,-1));
value = value * (1.0f / 5.0f);
#endif
shadow = mix(uni_ShadowColor, 1.0f, value);
}
vec4 result = uni_AmbientColor * ambient