ADD: CSM with base shadow map
This commit is contained in:
@@ -8,7 +8,8 @@ layout(location=0) out vec4 outColor;
|
||||
layout(set=1, binding=0) uniform sampler2D posTex;
|
||||
layout(set=1, binding=1) uniform sampler2D normalTex;
|
||||
layout(set=1, binding=2) uniform sampler2D albedoTex;
|
||||
layout(set=2, binding=0) uniform sampler2D shadowTex;
|
||||
// Mixed near + CSM: shadowTex[0] is the near/simple map, 1..N-1 are cascades
|
||||
layout(set=2, binding=0) uniform sampler2D shadowTex[4];
|
||||
|
||||
const float PI = 3.14159265359;
|
||||
|
||||
@@ -29,14 +30,29 @@ const vec2 POISSON_16[16] = vec2[16](
|
||||
vec2(0.1197, 0.0779), vec2(-0.0905, -0.1203)
|
||||
);
|
||||
|
||||
uint selectCascadeIndex(vec3 worldPos)
|
||||
{
|
||||
// Compute view-space positive depth
|
||||
vec4 vpos = sceneData.view * vec4(worldPos, 1.0);
|
||||
float depthVS = -vpos.z;
|
||||
// Near/simple map covers [0, sceneData.cascadeSplitsView.x)
|
||||
if (depthVS < sceneData.cascadeSplitsView.x) return 0u;
|
||||
if (depthVS < sceneData.cascadeSplitsView.y) return 1u;
|
||||
if (depthVS < sceneData.cascadeSplitsView.z) return 2u;
|
||||
return 3u; // last cascade extends to w
|
||||
}
|
||||
|
||||
float calcShadowVisibility(vec3 worldPos, vec3 N, vec3 L)
|
||||
{
|
||||
vec4 lclip = sceneData.lightViewProj * vec4(worldPos, 1.0);
|
||||
uint ci = selectCascadeIndex(worldPos);
|
||||
mat4 lightMat = sceneData.lightViewProjCascades[ci];
|
||||
|
||||
vec4 lclip = lightMat * vec4(worldPos, 1.0);
|
||||
vec3 ndc = lclip.xyz / lclip.w;
|
||||
vec2 suv = ndc.xy * 0.5 + 0.5;
|
||||
|
||||
if (any(lessThan(suv, vec2(0.0))) || any(greaterThan(suv, vec2(1.0))))
|
||||
return 1.0;
|
||||
return 1.0;
|
||||
|
||||
float current = clamp(ndc.z, 0.0, 1.0);
|
||||
|
||||
@@ -48,19 +64,20 @@ float calcShadowVisibility(vec3 worldPos, vec3 N, vec3 L)
|
||||
float ddz = max(abs(dzdx), abs(dzdy));
|
||||
float bias = slopeBias + ddz * 0.75;
|
||||
|
||||
ivec2 dim = textureSize(shadowTex, 0);
|
||||
ivec2 dim = textureSize(shadowTex[ci], 0);
|
||||
vec2 texelSize = 1.0 / vec2(dim);
|
||||
|
||||
float baseRadius = 1.25;
|
||||
float radius = mix(baseRadius, baseRadius * 4.0, current);
|
||||
// Slightly increase filter for farther cascades
|
||||
float radius = mix(baseRadius, baseRadius * 3.0, float(ci) / 3.0);
|
||||
|
||||
float ang = hash12(suv * 4096.0) * 6.2831853;
|
||||
vec2 r = vec2(cos(ang), sin(ang));
|
||||
mat2 rot = mat2(r.x, -r.y, r.y, r.x);
|
||||
|
||||
const int TAP_COUNT = 16;
|
||||
float occluded = 0.0;
|
||||
float wsum = 0.0;
|
||||
float visible = 0.0;
|
||||
float wsum = 0.0;
|
||||
|
||||
for (int i = 0; i < TAP_COUNT; ++i)
|
||||
{
|
||||
@@ -70,16 +87,16 @@ float calcShadowVisibility(vec3 worldPos, vec3 N, vec3 L)
|
||||
float pr = length(pu);
|
||||
float w = 1.0 - smoothstep(0.0, 0.65, pr);
|
||||
|
||||
float mapD = texture(shadowTex, suv + off).r;
|
||||
float mapD = texture(shadowTex[ci], suv + off).r;
|
||||
// Reversed-Z friendly compare: visible when current <= map depth
|
||||
float vis = step(mapD, current + bias);
|
||||
|
||||
float occ = step(current + bias, mapD);
|
||||
|
||||
occluded += occ * w;
|
||||
wsum += w;
|
||||
visible += vis * w;
|
||||
wsum += w;
|
||||
}
|
||||
|
||||
float shadow = (wsum > 0.0) ? (occluded / wsum) : 0.0;
|
||||
return 1.0 - shadow;
|
||||
float visibility = (wsum > 0.0) ? (visible / wsum) : 1.0;
|
||||
return visibility;
|
||||
}
|
||||
|
||||
vec3 fresnelSchlick(float cosTheta, vec3 F0)
|
||||
|
||||
Reference in New Issue
Block a user