diff --git a/engine/art/shaderlib/shadowmap.glsl b/engine/art/shaderlib/shadowmap.glsl index 5d53f74..bf536b4 100644 --- a/engine/art/shaderlib/shadowmap.glsl +++ b/engine/art/shaderlib/shadowmap.glsl @@ -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); } -//// 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) { distance = distance / 200; 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); 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++) { ofs_coord.x = i; 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); 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); 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++) { ofs_coord.x = i; 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); 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); ofs_sum += min(max(step(distance, variance.y), variance.x), 1.0); }