diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp index 5e4901e56a2633c4ec49448186832e87bcb90b7f..938aae1f94cb9c9b0351128510727b118c8c130a 100644 --- a/projects/voxelization/src/ShadowMapping.cpp +++ b/projects/voxelization/src/ShadowMapping.cpp @@ -15,8 +15,96 @@ vkcv::ShaderProgram loadShadowShader() { return shader; } +glm::mat4 computeShadowViewProjectionMatrix( + const glm::vec3& lightDirection, + const vkcv::camera::Camera& camera, + float maxShadowDistance, + const glm::vec3& voxelVolumeOffset, + float voxelVolumeExtent) { + + const glm::vec3 cameraPos = camera.getPosition(); + const glm::vec3 forward = glm::normalize(camera.getFront()); + glm::vec3 up = glm::normalize(camera.getUp()); + const glm::vec3 right = glm::normalize(glm::cross(forward, up)); + up = glm::cross(right, forward); + + const float fov = camera.getFov(); + const float aspectRatio = camera.getRatio(); + + float near; + float far; + camera.getNearFar(near, far); + far = std::min(maxShadowDistance, far); + + const glm::vec3 nearCenter = cameraPos + forward * near; + const float nearUp = near * tan(fov * 0.5); + const float nearRight = nearUp * aspectRatio; + + const glm::vec3 farCenter = cameraPos + forward * far; + const float farUp = far * tan(fov * 0.5); + const float farRight = farUp * aspectRatio; + + std::array<glm::vec3, 8> viewFrustumCorners = { + nearCenter + right * nearRight + nearUp * up, + nearCenter + right * nearRight - nearUp * up, + nearCenter - right * nearRight + nearUp * up, + nearCenter - right * nearRight - nearUp * up, + + farCenter + right * farRight + farUp * up, + farCenter + right * farRight - farUp * up, + farCenter - right * farRight + farUp * up, + farCenter - right * farRight - farUp * up + }; + + std::array<glm::vec3, 8> voxelVolumeCorners = { + voxelVolumeOffset + voxelVolumeExtent * glm::vec3(1, 1, 1), + voxelVolumeOffset + voxelVolumeExtent * glm::vec3(1, 1, -1), + voxelVolumeOffset + voxelVolumeExtent * glm::vec3(1, -1, 1), + voxelVolumeOffset + voxelVolumeExtent * glm::vec3(1, -1, -1), + + voxelVolumeOffset + voxelVolumeExtent * glm::vec3(-1, 1, 1), + voxelVolumeOffset + voxelVolumeExtent * glm::vec3(-1, 1, -1), + voxelVolumeOffset + voxelVolumeExtent * glm::vec3(-1, -1, 1), + voxelVolumeOffset + voxelVolumeExtent * glm::vec3(-1, -1, -1), + }; + + glm::vec3 minView(std::numeric_limits<float>::max()); + glm::vec3 maxView(std::numeric_limits<float>::lowest()); + + const glm::mat4 view = glm::lookAt(glm::vec3(0), -lightDirection, glm::vec3(0, -1, 0)); + + auto getMinMaxView = [&](std::array<glm::vec3, 8> points) { + for (const glm::vec3& p : points) { + const auto& pView = glm::vec3(view * glm::vec4(p, 1)); + minView = glm::min(minView, pView); + maxView = glm::max(maxView, pView); + } + }; + + getMinMaxView(viewFrustumCorners); + getMinMaxView(voxelVolumeCorners); + + glm::vec3 scale = glm::vec3(2) / (maxView - minView); + glm::vec3 offset = -0.5f * (maxView + minView) * scale; + + glm::mat4 crop(1); + crop[0][0] = scale.x; + crop[1][1] = scale.y; + crop[2][2] = scale.z; + + crop[3][0] = offset.x; + crop[3][1] = offset.y; + crop[3][2] = offset.z; + + glm::mat4 vulkanCorrectionMatrix(1.f); + vulkanCorrectionMatrix[2][2] = 0.5; + vulkanCorrectionMatrix[3][2] = 0.5; + + return vulkanCorrectionMatrix * crop * view; +} + const vk::Format shadowMapFormat = vk::Format::eD16Unorm; -const uint32_t shadowMapResolution = 1024; +const uint32_t shadowMapResolution = 2048; ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vertexLayout) : m_corePtr(corePtr), @@ -55,10 +143,13 @@ void ShadowMapping::recordShadowMapRendering( const vkcv::CommandStreamHandle& cmdStream, const glm::vec2& lightAngleRadian, const glm::vec3& lightColor, - const float lightStrength, + float lightStrength, + float maxShadowDistance, const std::vector<vkcv::Mesh>& meshes, const std::vector<glm::mat4>& modelMatrices, - const vkcv::camera::Camera& camera) { + const vkcv::camera::Camera& camera, + const glm::vec3& voxelVolumeOffset, + float voxelVolumeExtent) { LightInfo lightInfo; lightInfo.sunColor = lightColor; @@ -68,23 +159,12 @@ void ShadowMapping::recordShadowMapRendering( std::sin(lightAngleRadian.x), std::cos(lightAngleRadian.x) * std::sin(lightAngleRadian.y))); - const float shadowProjectionSize = 20.f; - glm::mat4 projectionLight = glm::ortho( - -shadowProjectionSize, - shadowProjectionSize, - -shadowProjectionSize, - shadowProjectionSize, - -shadowProjectionSize, - shadowProjectionSize); - - glm::mat4 vulkanCorrectionMatrix(1.f); - vulkanCorrectionMatrix[2][2] = 0.5; - vulkanCorrectionMatrix[3][2] = 0.5; - projectionLight = vulkanCorrectionMatrix * projectionLight; - - const glm::mat4 viewLight = glm::lookAt(glm::vec3(0), lightInfo.direction, glm::vec3(0, -1, 0)); - - lightInfo.lightMatrix = projectionLight * viewLight; + lightInfo.lightMatrix = computeShadowViewProjectionMatrix( + lightInfo.direction, + camera, + maxShadowDistance, + voxelVolumeOffset, + voxelVolumeExtent); m_lightInfoBuffer.fill({ lightInfo }); std::vector<glm::mat4> mvpLight; diff --git a/projects/voxelization/src/ShadowMapping.hpp b/projects/voxelization/src/ShadowMapping.hpp index 295dbae319beb222c96538c359debef7583f4045..6bbceff9320ef9605d02168aaad31c73faa63702 100644 --- a/projects/voxelization/src/ShadowMapping.hpp +++ b/projects/voxelization/src/ShadowMapping.hpp @@ -24,9 +24,12 @@ public: const glm::vec2& lightAngleRadian, const glm::vec3& lightColor, const float lightStrength, + float maxShadowDistance, const std::vector<vkcv::Mesh>& meshes, const std::vector<glm::mat4>& modelMatrices, - const vkcv::camera::Camera& camera); + const vkcv::camera::Camera& camera, + const glm::vec3& voxelVolumeOffset, + float voxelVolumeExtent); vkcv::ImageHandle getShadowMap(); vkcv::SamplerHandle getShadowSampler(); diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp index a14a880c208de2eb20fb9f77b2d8ff8948c98316..b62bb42ae1557eafca67475d760a8af502db3c62 100644 --- a/projects/voxelization/src/Voxelization.cpp +++ b/projects/voxelization/src/Voxelization.cpp @@ -69,9 +69,10 @@ vkcv::ShaderProgram loadSecondaryBounceShader() { return shader; } -const uint32_t voxelResolution = 128; -uint32_t voxelCount = voxelResolution * voxelResolution * voxelResolution; -const vk::Format voxelizationDummyFormat = vk::Format::eR8Unorm; +const uint32_t voxelResolution = 128; +uint32_t voxelCount = voxelResolution * voxelResolution * voxelResolution; +const vk::Format voxelizationDummyFormat = vk::Format::eR8Unorm; +const int maxStableMip = 4; // must be the same as in voxelConeTrace shader function Voxelization::Voxelization( vkcv::Core* corePtr, @@ -211,27 +212,13 @@ Voxelization::Voxelization( void Voxelization::voxelizeMeshes( vkcv::CommandStreamHandle cmdStream, - const glm::vec3& cameraPosition, - const glm::vec3& cameraLookDirection, const std::vector<vkcv::Mesh>& meshes, const std::vector<glm::mat4>& modelMatrices, const std::vector<vkcv::DescriptorSetHandle>& perMeshDescriptorSets) { - VoxelizationInfo voxelizationInfo; - voxelizationInfo.extent = m_voxelExtent; + m_voxelInfoBuffer.fill({ m_voxelInfo }); - // move voxel offset with camera in voxel sized steps - const float voxelSize = m_voxelExtent / voxelResolution; - const int maxStableMip = 4; // must be the same as in voxelConeTrace shader function - const float snapSize = voxelSize * exp2(maxStableMip); - - glm::vec3 voxelVolumeCenter = cameraPosition + (1.f / 3.f) * m_voxelExtent * cameraLookDirection; - voxelVolumeCenter.y = cameraPosition.y; - voxelizationInfo.offset = glm::floor(voxelVolumeCenter / snapSize) * snapSize; - - m_voxelInfoBuffer.fill({ voxelizationInfo }); - - const float voxelizationHalfExtent = 0.5f * m_voxelExtent; + const float voxelizationHalfExtent = 0.5f * m_voxelInfo.extent; const glm::mat4 voxelizationProjection = glm::ortho( -voxelizationHalfExtent, voxelizationHalfExtent, @@ -240,7 +227,7 @@ void Voxelization::voxelizeMeshes( -voxelizationHalfExtent, voxelizationHalfExtent); - const glm::mat4 voxelizationView = glm::translate(glm::mat4(1.f), -voxelizationInfo.offset); + const glm::mat4 voxelizationView = glm::translate(glm::mat4(1.f), -m_voxelInfo.offset); const glm::mat4 voxelizationViewProjection = voxelizationProjection * voxelizationView; std::vector<std::array<glm::mat4, 2>> voxelizationMatrices; @@ -357,8 +344,19 @@ void Voxelization::renderVoxelVisualisation( renderTargets); } +void Voxelization::updateVoxelOffset(const vkcv::camera::Camera& camera) { + + // move voxel offset with camera in voxel sized steps + const float voxelSize = m_voxelInfo.extent / voxelResolution; + const float snapSize = voxelSize * exp2(maxStableMip); + + glm::vec3 voxelVolumeCenter = camera.getPosition() + (1.f / 3.f) * m_voxelInfo.extent * glm::normalize(camera.getFront()); + voxelVolumeCenter.y = camera.getPosition().y; + m_voxelInfo.offset = glm::floor(voxelVolumeCenter / snapSize) * snapSize; +} + void Voxelization::setVoxelExtent(float extent) { - m_voxelExtent = extent; + m_voxelInfo.extent = extent; } vkcv::ImageHandle Voxelization::getVoxelImageHandle() const { @@ -367,4 +365,12 @@ vkcv::ImageHandle Voxelization::getVoxelImageHandle() const { vkcv::BufferHandle Voxelization::getVoxelInfoBufferHandle() const { return m_voxelInfoBuffer.getHandle(); -} \ No newline at end of file +} + +glm::vec3 Voxelization::getVoxelOffset() const{ + return m_voxelInfo.offset; +} + +float Voxelization::getVoxelExtent() const { + return m_voxelInfo.extent; +} diff --git a/projects/voxelization/src/Voxelization.hpp b/projects/voxelization/src/Voxelization.hpp index 6f8d155dbf05ddf8caad2d94e8b25cee5b70e3f6..e200f660d005e2a26eb8cbf7dd1020b072cd50d2 100644 --- a/projects/voxelization/src/Voxelization.hpp +++ b/projects/voxelization/src/Voxelization.hpp @@ -1,6 +1,7 @@ #pragma once #include <vkcv/Core.hpp> #include <glm/glm.hpp> +#include <vkcv/camera/Camera.hpp> class Voxelization{ public: @@ -19,8 +20,6 @@ public: void voxelizeMeshes( vkcv::CommandStreamHandle cmdStream, - const glm::vec3& cameraPosition, - const glm::vec3& cameraLookDirection, const std::vector<vkcv::Mesh>& meshes, const std::vector<glm::mat4>& modelMatrices, const std::vector<vkcv::DescriptorSetHandle>& perMeshDescriptorSets); @@ -31,10 +30,14 @@ public: const std::vector<vkcv::ImageHandle>& renderTargets, uint32_t mipLevel); + void updateVoxelOffset(const vkcv::camera::Camera& camera); void setVoxelExtent(float extent); - vkcv::ImageHandle getVoxelImageHandle() const; - vkcv::BufferHandle getVoxelInfoBufferHandle() const; + vkcv::ImageHandle getVoxelImageHandle() const; + vkcv::BufferHandle getVoxelInfoBufferHandle() const; + + glm::vec3 getVoxelOffset() const; + float getVoxelExtent() const; private: vkcv::Core* m_corePtr; @@ -74,5 +77,5 @@ private: }; vkcv::Buffer<VoxelizationInfo> m_voxelInfoBuffer; - float m_voxelExtent = 30.f; + VoxelizationInfo m_voxelInfo; }; \ No newline at end of file diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index d86b8297c8206ce02030bbfcd9f4c53abfe92844..36b6f9d11d868ab7884c903d6122caa6a9feaeef 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -328,6 +328,7 @@ int main(int argc, const char** argv) { glm::vec2 lightAnglesDegree = glm::vec2(90.f, 0.f); glm::vec3 lightColor = glm::vec3(1); float lightStrength = 25.f; + float maxShadowDistance = 30.f; int voxelVisualisationMip = 0; float voxelizationExtent = 30.f; @@ -366,6 +367,8 @@ int main(int argc, const char** argv) { auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics); + voxelization.updateVoxelOffset(cameraManager.getActiveCamera()); + // shadow map glm::vec2 lightAngleRadian = glm::radians(lightAnglesDegree); shadowMapping.recordShadowMapRendering( @@ -373,16 +376,17 @@ int main(int argc, const char** argv) { lightAngleRadian, lightColor, lightStrength, + maxShadowDistance, meshes, modelMatrices, - cameraManager.getActiveCamera()); + cameraManager.getActiveCamera(), + voxelization.getVoxelOffset(), + voxelization.getVoxelExtent()); // voxelization voxelization.setVoxelExtent(voxelizationExtent); voxelization.voxelizeMeshes( - cmdStream, - cameraManager.getActiveCamera().getPosition(), - cameraManager.getActiveCamera().getFront(), + cmdStream, meshes, modelMatrices, perMeshDescriptorSets); @@ -438,6 +442,9 @@ int main(int argc, const char** argv) { ImGui::DragFloat2("Light angles", &lightAnglesDegree.x); ImGui::ColorEdit3("Sun color", &lightColor.x); ImGui::DragFloat("Sun strength", &lightStrength); + ImGui::DragFloat("Max shadow distance", &maxShadowDistance); + maxShadowDistance = std::max(maxShadowDistance, 1.f); + ImGui::Checkbox("Draw voxel visualisation", &renderVoxelVis); ImGui::SliderInt("Visualisation mip", &voxelVisualisationMip, 0, 7); ImGui::DragFloat("Voxelization extent", &voxelizationExtent, 1.f, 0.f);