- Added linear and nearest shadowmap filters (enabled with defines)

This commit is contained in:
Magnus Norddahl 2017-08-13 13:49:02 +02:00
parent 4afface97c
commit a6d4bfc748

View file

@ -138,27 +138,57 @@ float R_DoomLightingEquation(float light)
#ifdef SUPPORTS_SHADOWMAPS #ifdef SUPPORTS_SHADOWMAPS
float sampleShadowmap(vec2 dir, float v) float shadowDirToU(vec2 dir)
{ {
float u;
if (abs(dir.x) > abs(dir.y)) if (abs(dir.x) > abs(dir.y))
{ {
if (dir.x >= 0.0) 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 else
u = dir.y / dir.x * 0.125 + (0.75 + 0.125); return dir.y / dir.x * 0.125 + (0.75 + 0.125);
} }
else else
{ {
if (dir.y >= 0.0) if (dir.y >= 0.0)
u = dir.x / dir.y * 0.125 + 0.125; return dir.x / dir.y * 0.125 + 0.125;
else 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); float dist2 = dot(dir, dir);
return texture(ShadowMap, vec2(u, v)).x > dist2 ? 1.0 : 0.0; 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) // 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_FILTER_STEP_COUNT 3
#define PCF_COUNT (PCF_FILTER_STEP_COUNT * 2 + 1) #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) float shadowmapAttenuation(vec4 lightpos, float shadowIndex)
{ {
if (shadowIndex >= 1024.0) if (shadowIndex >= 1024.0)
@ -182,7 +215,11 @@ float shadowmapAttenuation(vec4 lightpos, float shadowIndex)
vec2 dir = ray / length; 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 dir = dir * min(length / 50.0, 1.0); // avoid sampling behind light
vec2 normal = vec2(-dir.y, dir.x); 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); sum += sampleShadowmap(ray + normal * x - bias * abs(x), v);
} }
return sum / PCF_COUNT; return sum / PCF_COUNT;
#else // nearest shadow filter
ray -= dir * 6.0; // Shadow acne margin
return sampleShadowmap(ray, v);
#endif
} }
#endif #endif