From 423bc642a118a7d9c58dac2068d9aa0e4a94de7a Mon Sep 17 00:00:00 2001 From: Alexander Gauggel <agauggel@uni-koblenz.de> Date: Tue, 22 Jun 2021 21:03:46 +0200 Subject: [PATCH] [#82] Exponential shadow mapping prototype --- .../resources/shaders/lightInfo.inc | 8 ++++- .../resources/shaders/shadow.frag | 14 +++++++- .../resources/shaders/shadow.vert | 7 ++++ .../resources/shaders/shadowMapping.inc | 14 +++++--- projects/voxelization/src/ShadowMapping.cpp | 33 +++++++++++++------ projects/voxelization/src/ShadowMapping.hpp | 6 +++- projects/voxelization/src/main.cpp | 11 ++++--- 7 files changed, 72 insertions(+), 21 deletions(-) diff --git a/projects/voxelization/resources/shaders/lightInfo.inc b/projects/voxelization/resources/shaders/lightInfo.inc index 4345d4f1..ed7f8d8b 100644 --- a/projects/voxelization/resources/shaders/lightInfo.inc +++ b/projects/voxelization/resources/shaders/lightInfo.inc @@ -1,6 +1,12 @@ +#ifndef LIGHT_INFO_INC +#define LIGHT_INFO_INC + struct LightInfo{ vec3 L; float padding; vec3 sunColor; float sunStrength; mat4 lightMatrix; -}; \ No newline at end of file + float exponentialWarp; +}; + +#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 848f853f..a0bc121d 100644 --- a/projects/voxelization/resources/shaders/shadow.frag +++ b/projects/voxelization/resources/shaders/shadow.frag @@ -1,6 +1,18 @@ #version 450 #extension GL_ARB_separate_shader_objects : enable +#extension GL_GOOGLE_include_directive : enable -void main() { +#include "shadowMapping.inc" + +layout(set=0, binding=0) uniform LightInfoBuffer { + LightInfo lightInfo; +}; + +layout(location = 0) out float outExponentialDepth; +layout(location = 0) in vec4 passPos; + +void main() { + float z = passPos.z / passPos.w; + outExponentialDepth = exp(z * lightInfo.exponentialWarp); } \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/shadow.vert b/projects/voxelization/resources/shaders/shadow.vert index e0f41d42..f6b99c39 100644 --- a/projects/voxelization/resources/shaders/shadow.vert +++ b/projects/voxelization/resources/shaders/shadow.vert @@ -1,12 +1,19 @@ #version 450 #extension GL_ARB_separate_shader_objects : enable +#extension GL_GOOGLE_include_directive : enable + +#include "lightInfo.inc" + layout(location = 0) in vec3 inPosition; layout( push_constant ) uniform constants{ mat4 mvp; }; +layout(location = 0) out vec4 passPos; + void main() { gl_Position = mvp * vec4(inPosition, 1.0); + passPos = gl_Position; } \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/shadowMapping.inc b/projects/voxelization/resources/shaders/shadowMapping.inc index 1fa34a38..e0a218d5 100644 --- a/projects/voxelization/resources/shaders/shadowMapping.inc +++ b/projects/voxelization/resources/shaders/shadowMapping.inc @@ -1,3 +1,8 @@ +#ifndef SHADOW_MAPPING_INC +#define SHADOW_MAPPING_INC + +#include "lightInfo.inc" + float shadowTest(vec3 worldPos, LightInfo lightInfo, texture2D shadowMap, sampler shadowMapSampler){ vec4 lightPos = lightInfo.lightMatrix * vec4(worldPos, 1); lightPos /= lightPos.w; @@ -9,8 +14,9 @@ float shadowTest(vec3 worldPos, LightInfo lightInfo, texture2D shadowMap, sample lightPos.z = clamp(lightPos.z, 0, 1); + // using exponential shadow mapping float shadowMapSample = texture(sampler2D(shadowMap, shadowMapSampler), lightPos.xy).r; - float bias = 0.01f; - shadowMapSample += bias; - return shadowMapSample < lightPos.z ? 0 : 1; -} \ No newline at end of file + return clamp(exp(-lightInfo.exponentialWarp * lightPos.z) * shadowMapSample, 0, 1); +} + +#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 938aae1f..456ef2cd 100644 --- a/projects/voxelization/src/ShadowMapping.cpp +++ b/projects/voxelization/src/ShadowMapping.cpp @@ -103,37 +103,48 @@ glm::mat4 computeShadowViewProjectionMatrix( return vulkanCorrectionMatrix * crop * view; } -const vk::Format shadowMapFormat = vk::Format::eD16Unorm; -const uint32_t shadowMapResolution = 2048; +const vk::Format shadowMapFormat = vk::Format::eR32Sfloat; +const vk::Format shadowMapDepthFormat = vk::Format::eD16Unorm; +const uint32_t shadowMapResolution = 2048; ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vertexLayout) : m_corePtr(corePtr), - m_shadowMap(corePtr->createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution)), + m_shadowMap(corePtr->createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution, 1, false, false, true)), + m_shadowMapDepth(corePtr->createImage(shadowMapDepthFormat, shadowMapResolution, shadowMapResolution)), m_lightInfoBuffer(corePtr->createBuffer<LightInfo>(vkcv::BufferType::UNIFORM, sizeof(glm::vec3))){ vkcv::ShaderProgram shadowShader = loadShadowShader(); + // descriptor set + m_shadowDescriptorSet = corePtr->createDescriptorSet(shadowShader.getReflectedDescriptors()[0]); + vkcv::DescriptorWrites shadowDescriptorWrites; + shadowDescriptorWrites.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(0, m_lightInfoBuffer.getHandle()) }; + corePtr->writeDescriptorSet(m_shadowDescriptorSet, shadowDescriptorWrites); + + // pass const std::vector<vkcv::AttachmentDescription> shadowAttachments = { - vkcv::AttachmentDescription(vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, shadowMapFormat) + vkcv::AttachmentDescription(vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, shadowMapFormat), + vkcv::AttachmentDescription(vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, shadowMapDepthFormat) }; const vkcv::PassConfig shadowPassConfig(shadowAttachments); m_shadowMapPass = corePtr->createPass(shadowPassConfig); + + // pipeline vkcv::PipelineConfig shadowPipeConfig{ shadowShader, shadowMapResolution, shadowMapResolution, m_shadowMapPass, vertexLayout, - {}, + { corePtr->getDescriptorSet(m_shadowDescriptorSet).layout }, false }; shadowPipeConfig.m_EnableDepthClamping = true; m_shadowMapPipe = corePtr->createGraphicsPipeline(shadowPipeConfig); - // shadow map m_shadowSampler = corePtr->createSampler( - vkcv::SamplerFilterType::NEAREST, - vkcv::SamplerFilterType::NEAREST, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, vkcv::SamplerMipmapMode::NEAREST, vkcv::SamplerAddressMode::CLAMP_TO_EDGE ); @@ -145,6 +156,7 @@ void ShadowMapping::recordShadowMapRendering( const glm::vec3& lightColor, float lightStrength, float maxShadowDistance, + float exponentialWarp, const std::vector<vkcv::Mesh>& meshes, const std::vector<glm::mat4>& modelMatrices, const vkcv::camera::Camera& camera, @@ -158,6 +170,7 @@ 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.lightMatrix = computeShadowViewProjectionMatrix( lightInfo.direction, @@ -175,7 +188,7 @@ void ShadowMapping::recordShadowMapRendering( std::vector<vkcv::DrawcallInfo> drawcalls; for (const auto& mesh : meshes) { - drawcalls.push_back(vkcv::DrawcallInfo(mesh, {})); + drawcalls.push_back(vkcv::DrawcallInfo(mesh, { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_shadowDescriptorSet).vulkanHandle) })); } m_corePtr->recordDrawcallsToCmdStream( @@ -184,7 +197,7 @@ void ShadowMapping::recordShadowMapRendering( m_shadowMapPipe, shadowPushConstantData, drawcalls, - { m_shadowMap.getHandle() }); + { m_shadowMap.getHandle(), m_shadowMapDepth.getHandle() }); m_corePtr->prepareImageForSampling(cmdStream, m_shadowMap.getHandle()); } diff --git a/projects/voxelization/src/ShadowMapping.hpp b/projects/voxelization/src/ShadowMapping.hpp index 6bbceff9..d72ca06c 100644 --- a/projects/voxelization/src/ShadowMapping.hpp +++ b/projects/voxelization/src/ShadowMapping.hpp @@ -13,6 +13,7 @@ struct LightInfo { glm::vec3 sunColor; float sunStrength; glm::mat4 lightMatrix; + float exponentialWarp; }; class ShadowMapping { @@ -23,8 +24,9 @@ public: const vkcv::CommandStreamHandle& cmdStream, const glm::vec2& lightAngleRadian, const glm::vec3& lightColor, - const float lightStrength, + float lightStrength, float maxShadowDistance, + float exponentialWarp, const std::vector<vkcv::Mesh>& meshes, const std::vector<glm::mat4>& modelMatrices, const vkcv::camera::Camera& camera, @@ -39,8 +41,10 @@ private: vkcv::Core* m_corePtr; vkcv::Image m_shadowMap; + vkcv::Image m_shadowMapDepth; vkcv::SamplerHandle m_shadowSampler; vkcv::Buffer<LightInfo> m_lightInfoBuffer; + vkcv::DescriptorSetHandle m_shadowDescriptorSet; vkcv::PassHandle m_shadowMapPass; vkcv::PipelineHandle m_shadowMapPipe; diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index 36b6f9d1..a56113d0 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -325,10 +325,11 @@ 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; + 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; int voxelVisualisationMip = 0; float voxelizationExtent = 30.f; @@ -377,6 +378,7 @@ int main(int argc, const char** argv) { lightColor, lightStrength, maxShadowDistance, + shadowExponentialWarp, meshes, modelMatrices, cameraManager.getActiveCamera(), @@ -444,6 +446,7 @@ 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::Checkbox("Draw voxel visualisation", &renderVoxelVis); ImGui::SliderInt("Visualisation mip", &voxelVisualisationMip, 0, 7); -- GitLab