diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp index cab4f5d9b..83cabbd0d 100644 --- a/wadsrc/static/shaders/glsl/main.fp +++ b/wadsrc/static/shaders/glsl/main.fp @@ -138,27 +138,57 @@ float R_DoomLightingEquation(float light) #ifdef SUPPORTS_SHADOWMAPS -float sampleShadowmap(vec2 dir, float v) +float shadowDirToU(vec2 dir) { - float u; if (abs(dir.x) > abs(dir.y)) { if (dir.x >= 0.0) - u = dir.y / dir.x * 0.125 + (0.25 + 0.125); + return dir.y / dir.x * 0.125 + (0.25 + 0.125); else - u = dir.y / dir.x * 0.125 + (0.75 + 0.125); + return dir.y / dir.x * 0.125 + (0.75 + 0.125); } else { if (dir.y >= 0.0) - u = dir.x / dir.y * 0.125 + 0.125; + return dir.x / dir.y * 0.125 + 0.125; else - u = dir.x / dir.y * 0.125 + (0.50 + 0.125); + return dir.x / dir.y * 0.125 + (0.50 + 0.125); } +} + +float sampleShadowmap(vec2 dir, float v) +{ + float u = shadowDirToU(dir); float dist2 = dot(dir, dir); return texture(ShadowMap, vec2(u, v)).x > dist2 ? 1.0 : 0.0; } +float sampleShadowmapLinear(vec2 dir, float v) +{ + float u = shadowDirToU(dir); + float dist2 = dot(dir, dir); + + vec2 isize = textureSize(ShadowMap, 0); + vec2 size = vec2(isize); + + vec2 fetchPos = vec2(u, v) * size - vec2(0.5, 0.0); + if (fetchPos.x < 0.0) + fetchPos.x += size.x; + + ivec2 ifetchPos = ivec2(fetchPos); + int y = ifetchPos.y; + + float t = fract(fetchPos.x); + int x0 = ifetchPos.x; + int x1 = ifetchPos.x + 1; + if (x1 == isize.x) + x1 = 0; + + float depth0 = texelFetch(ShadowMap, ivec2(x0, y), 0).x; + float depth1 = texelFetch(ShadowMap, ivec2(x1, y), 0).x; + return mix(step(dist2, depth0), step(dist2, depth1), t); +} + //=========================================================================== // // Check if light is in shadow using Percentage Closer Filtering (PCF) @@ -168,6 +198,9 @@ float sampleShadowmap(vec2 dir, float v) #define PCF_FILTER_STEP_COUNT 3 #define PCF_COUNT (PCF_FILTER_STEP_COUNT * 2 + 1) +// #define USE_LINEAR_SHADOW_FILTER +#define USE_PCF_SHADOW_FILTER 1 + float shadowmapAttenuation(vec4 lightpos, float shadowIndex) { if (shadowIndex >= 1024.0) @@ -182,7 +215,11 @@ float shadowmapAttenuation(vec4 lightpos, float shadowIndex) vec2 dir = ray / length; - ray -= dir * 2.0; // margin +#if defined(USE_LINEAR_SHADOW_FILTER) + ray -= dir * 6.0; // Shadow acne margin + return sampleShadowmapLinear(ray, v); +#elif defined(USE_PCF_SHADOW_FILTER) + ray -= dir * 2.0; // Shadow acne margin dir = dir * min(length / 50.0, 1.0); // avoid sampling behind light vec2 normal = vec2(-dir.y, dir.x); @@ -194,6 +231,10 @@ float shadowmapAttenuation(vec4 lightpos, float shadowIndex) sum += sampleShadowmap(ray + normal * x - bias * abs(x), v); } return sum / PCF_COUNT; +#else // nearest shadow filter + ray -= dir * 6.0; // Shadow acne margin + return sampleShadowmap(ray, v); +#endif } #endif