Skip to content
Snippets Groups Projects
Commit 6eedb5e3 authored by Alexander Gauggel's avatar Alexander Gauggel
Browse files

[#82] Move shadow map with camera frustum and voxel volume

parent 16afca0e
Branches
Tags
1 merge request!70Resolve "Voxel cone tracing"
Pipeline #25950 failed
......@@ -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;
......
......@@ -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();
......
......@@ -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;
}
#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
......@@ -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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment