mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 23:02:08 +00:00
- remove shadow acne from PCF shadowmap filter and add three quality levels
This commit is contained in:
parent
09bc6614cf
commit
6135e867a9
4 changed files with 72 additions and 68 deletions
|
@ -2442,7 +2442,9 @@ OPTVAL_FOO_DUMB = "foo_dumb";
|
|||
OPTVAL_ALIASING = "Aliasing";
|
||||
OPTVAL_LINEAR = "Linear";
|
||||
OPTVAL_NEAREST = "Nearest";
|
||||
OPTVAL_PCF = "PCF";
|
||||
OPTVAL_PCF_LOW = "PCF (Low)";
|
||||
OPTVAL_PCF_MEDIUM = "PCF (Medium)";
|
||||
OPTVAL_PCF_HIGH = "PCF (High)";
|
||||
OPTVAL_CUBIC = "Cubic";
|
||||
OPTVAL_BLEP = "Band-limited step";
|
||||
OPTVAL_LINEARSLOW = "Linear (Slower)";
|
||||
|
|
|
@ -2419,7 +2419,9 @@ OPTVAL_DEFAULT = "Défaut";
|
|||
OPTVAL_SOUNDSYSTEM = "Système Sonore";
|
||||
OPTVAL_LINEAR = "Linéaire";
|
||||
OPTVAL_NEAREST = "Nearest";
|
||||
OPTVAL_PCF = "PCF";
|
||||
OPTVAL_PCF_LOW = "PCF (Low)";
|
||||
OPTVAL_PCF_MEDIUM = "PCF (Medium)";
|
||||
OPTVAL_PCF_HIGH = "PCF (High)";
|
||||
OPTVAL_CUBIC = "Cubique";
|
||||
OPTVAL_BLEP = "Step limité sur bande";
|
||||
OPTVAL_LINEARSLOW = "Linéaire (Lent)";
|
||||
|
|
|
@ -2259,7 +2259,9 @@ OptionValue ShadowMapQuality
|
|||
OptionValue ShadowMapFilter
|
||||
{
|
||||
0, "$OPTVAL_NEAREST"
|
||||
1, "$OPTVAL_PCF"
|
||||
1, "$OPTVAL_PCF_LOW"
|
||||
2, "$OPTVAL_PCF_MEDIUM"
|
||||
3, "$OPTVAL_PCF_HIGH"
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -178,47 +178,26 @@ float shadowDirToU(vec2 dir)
|
|||
}
|
||||
}
|
||||
|
||||
float sampleShadowmap(vec2 dir, float v)
|
||||
vec2 shadowUToDir(float u)
|
||||
{
|
||||
float u = shadowDirToU(dir);
|
||||
float dist2 = dot(dir, dir);
|
||||
return step(dist2, texture(ShadowMap, vec2(u, v)).x);
|
||||
u *= 4.0;
|
||||
vec2 raydir;
|
||||
switch (int(u))
|
||||
{
|
||||
case 0: raydir = vec2(u * 2.0 - 1.0, 1.0); break;
|
||||
case 1: raydir = vec2(1.0, 1.0 - (u - 1.0) * 2.0); break;
|
||||
case 2: raydir = vec2(1.0 - (u - 2.0) * 2.0, -1.0); break;
|
||||
case 3: raydir = vec2(-1.0, (u - 3.0) * 2.0 - 1.0); break;
|
||||
}
|
||||
return raydir;
|
||||
}
|
||||
|
||||
float sampleShadowmapLinear(vec2 dir, float v)
|
||||
float sampleShadowmap(vec3 planePoint, float v)
|
||||
{
|
||||
float u = shadowDirToU(dir);
|
||||
float dist2 = dot(dir, dir);
|
||||
float bias = 1.0;
|
||||
float negD = dot(vWorldNormal.xyz, planePoint);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
vec2 shadowmapAdjustedRay(vec4 lightpos)
|
||||
{
|
||||
vec3 planePoint = pixelpos.xyz - lightpos.xyz;
|
||||
|
||||
if (dot(planePoint.xz, planePoint.xz) < 1.0)
|
||||
return planePoint.xz * 0.5;
|
||||
|
||||
vec3 ray = normalize(planePoint);
|
||||
vec3 ray = planePoint;
|
||||
|
||||
vec2 isize = textureSize(ShadowMap, 0);
|
||||
float scale = float(isize.x) * 0.25;
|
||||
|
@ -239,51 +218,70 @@ vec2 shadowmapAdjustedRay(vec4 lightpos)
|
|||
ray.x = sign(ray.x);
|
||||
}
|
||||
|
||||
float bias = 1.0;
|
||||
float negD = dot(vWorldNormal.xyz, planePoint);
|
||||
float t = negD / dot(vWorldNormal.xyz, ray) - bias;
|
||||
return ray.xz * t;
|
||||
vec2 dir = ray.xz * t;
|
||||
|
||||
float u = shadowDirToU(dir);
|
||||
float dist2 = dot(dir, dir);
|
||||
return step(dist2, texture(ShadowMap, vec2(u, v)).x);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Check if light is in shadow using Percentage Closer Filtering (PCF)
|
||||
//
|
||||
//===========================================================================
|
||||
float sampleShadowmapPCF(vec3 planePoint, float v)
|
||||
{
|
||||
float bias = 1.0;
|
||||
float negD = dot(vWorldNormal.xyz, planePoint);
|
||||
|
||||
vec3 ray = planePoint;
|
||||
|
||||
if (abs(ray.z) > abs(ray.x))
|
||||
ray.y = ray.y / abs(ray.z);
|
||||
else
|
||||
ray.y = ray.y / abs(ray.x);
|
||||
|
||||
vec2 isize = textureSize(ShadowMap, 0);
|
||||
float scale = float(isize.x);
|
||||
float texelPos = floor(shadowDirToU(ray.xz) * scale);
|
||||
|
||||
float sum = 0.0;
|
||||
float step_count = uShadowmapFilter;
|
||||
|
||||
texelPos -= step_count + 0.5;
|
||||
for (float x = -step_count; x <= step_count; x++)
|
||||
{
|
||||
float u = texelPos / scale;
|
||||
vec2 dir = shadowUToDir(u);
|
||||
|
||||
ray.x = dir.x;
|
||||
ray.z = dir.y;
|
||||
float t = negD / dot(vWorldNormal.xyz, ray) - bias;
|
||||
dir = ray.xz * t;
|
||||
|
||||
float dist2 = dot(dir, dir);
|
||||
sum += step(dist2, texture(ShadowMap, vec2(u, v)).x);
|
||||
texelPos++;
|
||||
}
|
||||
return sum / (uShadowmapFilter * 2.0 + 1.0);
|
||||
}
|
||||
|
||||
float shadowmapAttenuation(vec4 lightpos, float shadowIndex)
|
||||
{
|
||||
if (shadowIndex >= 1024.0)
|
||||
return 1.0; // No shadowmap available for this light
|
||||
|
||||
float v = (shadowIndex + 0.5) / 1024.0;
|
||||
vec3 planePoint = pixelpos.xyz - lightpos.xyz;
|
||||
|
||||
vec2 ray = shadowmapAdjustedRay(lightpos);
|
||||
if (dot(planePoint.xz, planePoint.xz) < 1.0)
|
||||
return 1.0; // Light is too close
|
||||
|
||||
float v = (shadowIndex + 0.5) / 1024.0;
|
||||
|
||||
if (uShadowmapFilter <= 0)
|
||||
{
|
||||
return sampleShadowmap(ray, v);
|
||||
//return sampleShadowmapLinear(ray, v);
|
||||
return sampleShadowmap(planePoint, v);
|
||||
}
|
||||
else
|
||||
{
|
||||
float length = length(ray);
|
||||
if (length < 3.0)
|
||||
return 1.0;
|
||||
|
||||
vec2 dir = ray / length * min(length / 50.0, 1.0); // avoid sampling behind light
|
||||
|
||||
vec2 normal = vec2(-dir.y, dir.x);
|
||||
vec2 bias = dir * 10.0;
|
||||
|
||||
float sum = 0.0;
|
||||
float step_count = ((uShadowmapFilter - 1) / 2.);
|
||||
|
||||
for (float x = -step_count; x <= step_count; x++)
|
||||
{
|
||||
sum += sampleShadowmap(ray + normal * x /*- bias * abs(x)*/, v);
|
||||
}
|
||||
return sum / uShadowmapFilter;
|
||||
return sampleShadowmapPCF(planePoint, v);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue