diff --git a/src/refresh/vkpt/shader/god_rays.comp b/src/refresh/vkpt/shader/god_rays.comp index dd480e3..ae6e940 100644 --- a/src/refresh/vkpt/shader/god_rays.comp +++ b/src/refresh/vkpt/shader/god_rays.comp @@ -47,17 +47,46 @@ #include "water.glsl" - -float GetShadow(vec3 worldPos, out float distanceToWater) -{ - vec4 uvzShadow = global_ubo.shadow_map_VP * vec4(worldPos, 1); - uvzShadow.x = uvzShadow.x * 0.5 + 0.5; - uvzShadow.y = 0.5 - 0.5 * uvzShadow.y; - - float depthOpaque = textureLod(TEX_SHADOW_MAP, vec3(uvzShadow.xy, 0), 0).x; - float depthWater = textureLod(TEX_SHADOW_MAP, vec3(uvzShadow.xy, 1), 0).x; - - distanceToWater = max(0, uvzShadow.z - depthWater) * global_ubo.shadow_map_depth_scale; - - return depthOpaque > uvzShadow.z ? 1 : 0; -} - + +float FetchShadowDepth(ivec2 texel, int layer, ivec2 size) +{ + if(any(lessThan(texel, ivec2(0))) || any(greaterThanEqual(texel, size))) + { + // Match VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE outside the shadow map. + return 1.0; + } + + return texelFetch(TEX_SHADOW_MAP, ivec3(texel, layer), 0).x; +} + +float SampleShadowMin(vec2 uv, int layer) +{ + ivec2 size = ivec2(SHADOWMAP_SIZE); + vec2 position = uv * vec2(size) - vec2(0.5); + ivec2 base = ivec2(floor(position)); + vec2 fraction = fract(position); + + float depth = FetchShadowDepth(base, layer, size); + if(fraction.x > 0.0) + depth = min(depth, FetchShadowDepth(base + ivec2(1, 0), layer, size)); + if(fraction.y > 0.0) + depth = min(depth, FetchShadowDepth(base + ivec2(0, 1), layer, size)); + if(fraction.x > 0.0 && fraction.y > 0.0) + depth = min(depth, FetchShadowDepth(base + ivec2(1, 1), layer, size)); + + return depth; +} + +float GetShadow(vec3 worldPos, out float distanceToWater) +{ + vec4 uvzShadow = global_ubo.shadow_map_VP * vec4(worldPos, 1); + uvzShadow.x = uvzShadow.x * 0.5 + 0.5; + uvzShadow.y = 0.5 - 0.5 * uvzShadow.y; + + float depthOpaque = SampleShadowMin(uvzShadow.xy, 0); + float depthWater = SampleShadowMin(uvzShadow.xy, 1); + + distanceToWater = max(0, uvzShadow.z - depthWater) * global_ubo.shadow_map_depth_scale; + + return depthOpaque > uvzShadow.z ? 1 : 0; +} + float rand(ivec2 pos)