From 0d6fffd91f28ef837c86bad7c3b646cf3c3cb230 Mon Sep 17 00:00:00 2001 From: AbigailBuccaneer Date: Wed, 2 May 2018 16:30:45 +0100 Subject: [PATCH] Improve shadow quality and performance in gl33 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .../opengl/shaders/gl33/fs_normal.glsl | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/graphics/opengl/shaders/gl33/fs_normal.glsl b/src/graphics/opengl/shaders/gl33/fs_normal.glsl index 2827d7a2..e6fd1e07 100644 --- a/src/graphics/opengl/shaders/gl33/fs_normal.glsl +++ b/src/graphics/opengl/shaders/gl33/fs_normal.glsl @@ -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