diff --git a/projects/voxelization/resources/shaders/lightInfo.inc b/projects/voxelization/resources/shaders/lightInfo.inc index ed7f8d8bfc4795fcb9307e73506065a6ee82b2c7..c0df6551059d283a117b6dfa12ac21ec5109f0ae 100644 --- a/projects/voxelization/resources/shaders/lightInfo.inc +++ b/projects/voxelization/resources/shaders/lightInfo.inc @@ -6,7 +6,7 @@ struct LightInfo{ vec3 sunColor; float sunStrength; mat4 lightMatrix; - float exponentialWarp; + vec2 warps; }; #endif // #ifndef LIGHT_INFO_INC \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/shadow.frag b/projects/voxelization/resources/shaders/shadow.frag index a0bc121d34fa735bc5002fe7ba63665b4840c1a3..83500f941e5b74f640e5558e69d97b8d872b3821 100644 --- a/projects/voxelization/resources/shaders/shadow.frag +++ b/projects/voxelization/resources/shaders/shadow.frag @@ -8,11 +8,12 @@ layout(set=0, binding=0) uniform LightInfoBuffer { LightInfo lightInfo; }; -layout(location = 0) out float outExponentialDepth; +layout(location = 0) out vec4 outMoments; layout(location = 0) in vec4 passPos; void main() { - float z = passPos.z / passPos.w; - outExponentialDepth = exp(z * lightInfo.exponentialWarp); + float z = passPos.z / passPos.w; + vec2 zWarped = applyDepthWarp(z, lightInfo.warps); + outMoments = vec4(zWarped, zWarped*zWarped); } \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/shadowMapping.inc b/projects/voxelization/resources/shaders/shadowMapping.inc index e0a218d57e86f269cfc72c335c5c6cf01a1de930..91461c91c111ff66c463ca7dbf8d837dcf1bc9c6 100644 --- a/projects/voxelization/resources/shaders/shadowMapping.inc +++ b/projects/voxelization/resources/shaders/shadowMapping.inc @@ -3,6 +3,32 @@ #include "lightInfo.inc" +vec2 applyDepthWarp(float z, vec2 warp){ + z = 2 * z - 1; + float positive = exp( z * warp.x); + float negative = -exp(-z * warp.y); + return vec2(positive, negative); +} + +float rescale(float a, float b, float v) +{ + return clamp((v - a) / (b - a), 0, 1); +} + +float reduceVSMBleeding(float shadowValue, float newMin) +{ + return rescale(newMin, 1.0f, shadowValue); +} + +float chebyshevInequality(float mean, float meanSquare, float sampleIn){ + float variance = meanSquare - mean * mean; + float d = sampleIn - mean; + float pMax = clamp(variance / (variance + d*d), 0, 1); + pMax = reduceVSMBleeding(pMax, 0.1); + + return pMax; +} + float shadowTest(vec3 worldPos, LightInfo lightInfo, texture2D shadowMap, sampler shadowMapSampler){ vec4 lightPos = lightInfo.lightMatrix * vec4(worldPos, 1); lightPos /= lightPos.w; @@ -12,11 +38,18 @@ float shadowTest(vec3 worldPos, LightInfo lightInfo, texture2D shadowMap, sample return 1; } - lightPos.z = clamp(lightPos.z, 0, 1); + lightPos.z = clamp(lightPos.z, 0, 1); + vec2 warpedSample = applyDepthWarp(lightPos.z, lightInfo.warps); - // using exponential shadow mapping - float shadowMapSample = texture(sampler2D(shadowMap, shadowMapSampler), lightPos.xy).r; - return clamp(exp(-lightInfo.exponentialWarp * lightPos.z) * shadowMapSample, 0, 1); + // using exponential variance shadow mapping + vec4 shadowMapSample = texture(sampler2D(shadowMap, shadowMapSampler), lightPos.xy); + vec2 positiveMoments = shadowMapSample.rb; + vec2 negativeMoments = shadowMapSample.ga; + + float s1 = chebyshevInequality(positiveMoments.r, positiveMoments.g, warpedSample.x); + float s2 = chebyshevInequality(negativeMoments.r, negativeMoments.g, warpedSample.y); + + return min(s1, s2); } #endif // #ifndef SHADOW_MAPPING_INC \ No newline at end of file diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp index 456ef2cd16cadb04121d27d9787c82ede5759551..83ce118a2f3c3df296bed2caac2386977f7dc47a 100644 --- a/projects/voxelization/src/ShadowMapping.cpp +++ b/projects/voxelization/src/ShadowMapping.cpp @@ -103,7 +103,7 @@ glm::mat4 computeShadowViewProjectionMatrix( return vulkanCorrectionMatrix * crop * view; } -const vk::Format shadowMapFormat = vk::Format::eR32Sfloat; +const vk::Format shadowMapFormat = vk::Format::eR32G32B32A32Sfloat; const vk::Format shadowMapDepthFormat = vk::Format::eD16Unorm; const uint32_t shadowMapResolution = 2048; @@ -156,7 +156,8 @@ void ShadowMapping::recordShadowMapRendering( const glm::vec3& lightColor, float lightStrength, float maxShadowDistance, - float exponentialWarp, + float exponentialWarpPositive, + float exponentialWarpNegative, const std::vector<vkcv::Mesh>& meshes, const std::vector<glm::mat4>& modelMatrices, const vkcv::camera::Camera& camera, @@ -170,7 +171,8 @@ void ShadowMapping::recordShadowMapRendering( std::cos(lightAngleRadian.x) * std::cos(lightAngleRadian.y), std::sin(lightAngleRadian.x), std::cos(lightAngleRadian.x) * std::sin(lightAngleRadian.y))); - lightInfo.exponentialWarp = exponentialWarp; + lightInfo.exponentialWarpPositive = exponentialWarpPositive; + lightInfo.exponentialWarpNegative = exponentialWarpNegative; lightInfo.lightMatrix = computeShadowViewProjectionMatrix( lightInfo.direction, diff --git a/projects/voxelization/src/ShadowMapping.hpp b/projects/voxelization/src/ShadowMapping.hpp index d72ca06c45a281d25709e54676bc973d21636e4d..541ad383c3494d72849188c4e2d31f8583fb6e6b 100644 --- a/projects/voxelization/src/ShadowMapping.hpp +++ b/projects/voxelization/src/ShadowMapping.hpp @@ -13,7 +13,8 @@ struct LightInfo { glm::vec3 sunColor; float sunStrength; glm::mat4 lightMatrix; - float exponentialWarp; + float exponentialWarpPositive; + float exponentialWarpNegative; }; class ShadowMapping { @@ -27,6 +28,7 @@ public: float lightStrength, float maxShadowDistance, float exponentialWarp, + float exponentialWarpNegative, const std::vector<vkcv::Mesh>& meshes, const std::vector<glm::mat4>& modelMatrices, const vkcv::camera::Camera& camera, diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index a56113d0cdcffe0a40fdb2b8337438154a565ffb..b488426d6e24a69d2267c0d1f4f3d847d5f331e9 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -325,11 +325,12 @@ int main(int argc, const char** argv) { vkcv::gui::GUI gui(core, window); - glm::vec2 lightAnglesDegree = glm::vec2(90.f, 0.f); - glm::vec3 lightColor = glm::vec3(1); - float lightStrength = 25.f; - float maxShadowDistance = 30.f; - float shadowExponentialWarp = 60.f; + glm::vec2 lightAnglesDegree = glm::vec2(90.f, 0.f); + glm::vec3 lightColor = glm::vec3(1); + float lightStrength = 25.f; + float maxShadowDistance = 30.f; + float shadowExponentialWarpPositive = 60.f; + float shadowExponentialWarpNegative = 60.f; int voxelVisualisationMip = 0; float voxelizationExtent = 30.f; @@ -378,7 +379,8 @@ int main(int argc, const char** argv) { lightColor, lightStrength, maxShadowDistance, - shadowExponentialWarp, + shadowExponentialWarpPositive, + shadowExponentialWarpNegative, meshes, modelMatrices, cameraManager.getActiveCamera(), @@ -446,7 +448,8 @@ int main(int argc, const char** argv) { ImGui::DragFloat("Sun strength", &lightStrength); ImGui::DragFloat("Max shadow distance", &maxShadowDistance); maxShadowDistance = std::max(maxShadowDistance, 1.f); - ImGui::DragFloat("Shadow exponential warp", &shadowExponentialWarp); + ImGui::DragFloat("Shadow exponential warp positive", &shadowExponentialWarpPositive); + ImGui::DragFloat("Shadow exponential warp negative", &shadowExponentialWarpNegative); ImGui::Checkbox("Draw voxel visualisation", &renderVoxelVis); ImGui::SliderInt("Visualisation mip", &voxelVisualisationMip, 0, 7);