improve pcss for vsm shadowmaps

main
Dominik Madarász 2024-09-02 15:58:13 +02:00
parent 80aad50ed3
commit 7cfbd8c9f8
1 changed files with 15 additions and 6 deletions

View File

@ -23,7 +23,6 @@ vec2 shadow_vsm_variance(vec3 dir, int light_index, float distance, float min_va
return vec2(linstep(variance_transition, 1.0, variance / (variance + d * d)), moments.x); return vec2(linstep(variance_transition, 1.0, variance / (variance + d * d)), moments.x);
} }
//// From http://fabiensanglard.net/shadowmappingVSM/index.php
float shadow_vsm(float distance, vec3 dir, int light_index, float min_variance, float variance_transition, float shadow_softness_raw) { float shadow_vsm(float distance, vec3 dir, int light_index, float min_variance, float variance_transition, float shadow_softness_raw) {
distance = distance / 200; distance = distance / 200;
float shadow_softness = shadow_softness_raw * 10.0; float shadow_softness = shadow_softness_raw * 10.0;
@ -37,16 +36,23 @@ float shadow_vsm(float distance, vec3 dir, int light_index, float min_variance,
vec4 sc = vec4(dir, 1.0); vec4 sc = vec4(dir, 1.0);
sc.z = dir.z; sc.z = dir.z;
vec2 texelSize = 1.0 / textureSize(shadowMap[light_index], 0); vec2 tex_size = textureSize(shadowMap[light_index], 0);
vec3 texelSize = 1.0 / vec3(tex_size.xyy);
vec3 light_plane_normal = normalize(dir);
vec3 tangent = normalize(cross(light_plane_normal, vec3(0.0, 1.0, 0.0)));
vec3 bitangent = cross(light_plane_normal, tangent);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
ofs_coord.x = i; ofs_coord.x = i;
vec4 offsets = texelFetch(shadow_offsets, ofs_coord, 0) * shadow_softness; vec4 offsets = texelFetch(shadow_offsets, ofs_coord, 0) * shadow_softness;
sc.xy = dir.xy + offsets.rg * texelSize;
vec3 offset_dir = tangent * offsets.r + bitangent * offsets.g;
sc.xyz = dir.xyz + offset_dir * texelSize;
vec2 variance = shadow_vsm_variance(sc.xyz, light_index, distance, min_variance, variance_transition); vec2 variance = shadow_vsm_variance(sc.xyz, light_index, distance, min_variance, variance_transition);
ofs_sum += min(max(step(distance, variance.y), variance.x), 1.0); ofs_sum += min(max(step(distance, variance.y), variance.x), 1.0);
sc.xy = dir.xy + offsets.ba * texelSize; offset_dir = tangent * offsets.b + bitangent * offsets.a;
sc.xyz = dir.xyz + offset_dir * texelSize;
variance = shadow_vsm_variance(sc.xyz, light_index, distance, min_variance, variance_transition); variance = shadow_vsm_variance(sc.xyz, light_index, distance, min_variance, variance_transition);
ofs_sum += min(max(step(distance, variance.y), variance.x), 1.0); ofs_sum += min(max(step(distance, variance.y), variance.x), 1.0);
} }
@ -57,11 +63,14 @@ float shadow_vsm(float distance, vec3 dir, int light_index, float min_variance,
for (int i = 4; i < samples_div2; i++) { for (int i = 4; i < samples_div2; i++) {
ofs_coord.x = i; ofs_coord.x = i;
vec4 offsets = texelFetch(shadow_offsets, ofs_coord, 0) * shadow_softness; vec4 offsets = texelFetch(shadow_offsets, ofs_coord, 0) * shadow_softness;
sc.xy = dir.xy + offsets.rg * texelSize;
vec3 offset_dir = tangent * offsets.r + bitangent * offsets.g;
sc.xyz = dir.xyz + offset_dir * texelSize;
vec2 variance = shadow_vsm_variance(sc.xyz, light_index, distance, min_variance, variance_transition); vec2 variance = shadow_vsm_variance(sc.xyz, light_index, distance, min_variance, variance_transition);
ofs_sum += min(max(step(distance, variance.y), variance.x), 1.0); ofs_sum += min(max(step(distance, variance.y), variance.x), 1.0);
sc.xy = dir.xy + offsets.ba * texelSize; offset_dir = tangent * offsets.b + bitangent * offsets.a;
sc.xyz = dir.xyz + offset_dir * texelSize;
variance = shadow_vsm_variance(sc.xyz, light_index, distance, min_variance, variance_transition); variance = shadow_vsm_variance(sc.xyz, light_index, distance, min_variance, variance_transition);
ofs_sum += min(max(step(distance, variance.y), variance.x), 1.0); ofs_sum += min(max(step(distance, variance.y), variance.x), 1.0);
} }