- 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
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