diff --git a/projects/voxelization/CMakeLists.txt b/projects/voxelization/CMakeLists.txt index d9f12a54fd32ef342059cf9be0d302c18b401304..33cfaef6197079b72ab2f295a4503e80be724db4 100644 --- a/projects/voxelization/CMakeLists.txt +++ b/projects/voxelization/CMakeLists.txt @@ -11,6 +11,10 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) # adding source files to the project add_executable(voxelization src/main.cpp) +target_sources(voxelization PRIVATE + src/Voxelization.hpp + src/Voxelization.cpp) + # this should fix the execution path to load local files from the project (for MSVC) if(MSVC) set_target_properties(voxelization PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9cd71ea087acbf85094d4b87c049264da2fbf3e8 --- /dev/null +++ b/projects/voxelization/src/Voxelization.cpp @@ -0,0 +1,234 @@ +#include "Voxelization.hpp" +#include <vkcv/shader/GLSLCompiler.hpp> +#include <glm/gtc/matrix_transform.hpp> + +vkcv::ShaderProgram loadVoxelizationShader() { + vkcv::shader::GLSLCompiler compiler; + vkcv::ShaderProgram shader; + compiler.compile(vkcv::ShaderStage::VERTEX, "resources/shaders/voxelization.vert", + [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { + shader.addShader(shaderStage, path); + }); + compiler.compile(vkcv::ShaderStage::GEOMETRY, "resources/shaders/voxelization.geom", + [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { + shader.addShader(shaderStage, path); + }); + compiler.compile(vkcv::ShaderStage::FRAGMENT, "resources/shaders/voxelization.frag", + [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { + shader.addShader(shaderStage, path); + }); + return shader; +} + +vkcv::ShaderProgram loadVoxelVisualisationShader() { + vkcv::shader::GLSLCompiler compiler; + vkcv::ShaderProgram shader; + compiler.compile(vkcv::ShaderStage::VERTEX, "resources/shaders/voxelVisualisation.vert", + [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { + shader.addShader(shaderStage, path); + }); + compiler.compile(vkcv::ShaderStage::GEOMETRY, "resources/shaders/voxelVisualisation.geom", + [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { + shader.addShader(shaderStage, path); + }); + compiler.compile(vkcv::ShaderStage::FRAGMENT, "resources/shaders/voxelVisualisation.frag", + [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { + shader.addShader(shaderStage, path); + }); + return shader; +} + +vkcv::ShaderProgram loadVoxelResetShader() { + vkcv::shader::GLSLCompiler compiler; + vkcv::ShaderProgram shader; + compiler.compile(vkcv::ShaderStage::COMPUTE, "resources/shaders/voxelReset.comp", + [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { + shader.addShader(shaderStage, path); + }); + return shader; +} + +const uint32_t voxelResolution = 32; +const size_t voxelCount = voxelResolution * voxelResolution * voxelResolution; +const vk::Format voxelizationDummyFormat = vk::Format::eR8Unorm; + +Voxelization::Voxelization(vkcv::Core* corePtr, const Dependencies& dependencies) + : + m_corePtr(corePtr), + m_voxelImage(m_corePtr->createImage(vk::Format::eR8Unorm, voxelResolution, voxelResolution, voxelResolution, true)), + m_dummyRenderTarget(m_corePtr->createImage(voxelizationDummyFormat, voxelResolution, voxelResolution, 1, false, true)), + m_voxelInfoBuffer(m_corePtr->createBuffer<VoxelizationInfo>(vkcv::BufferType::UNIFORM, 1)), + m_visualisationIndexBuffer(m_corePtr->createBuffer<uint16_t>(vkcv::BufferType::INDEX, voxelCount)) { + + assert(corePtr); + + const vkcv::ShaderProgram voxelizationShader = loadVoxelizationShader(); + + vkcv::PassConfig voxelizationPassConfig({ + vkcv::AttachmentDescription(vkcv::AttachmentOperation::DONT_CARE, vkcv::AttachmentOperation::DONT_CARE, voxelizationDummyFormat) }); + m_voxelizationPass = m_corePtr->createPass(voxelizationPassConfig); + + std::vector<vkcv::DescriptorBinding> voxelizationDescriptorBindings = { voxelizationShader.getReflectedDescriptors()[0] }; + m_voxelizationDescriptorSet = m_corePtr->createDescriptorSet(voxelizationDescriptorBindings); + + const vkcv::PipelineConfig voxelizationPipeConfig{ + voxelizationShader, + voxelResolution, + voxelResolution, + m_voxelizationPass, + dependencies.vertexLayout, + { m_corePtr->getDescriptorSet(m_voxelizationDescriptorSet).layout }, + false, + true }; + m_voxelizationPipe = m_corePtr->createGraphicsPipeline(voxelizationPipeConfig); + + vkcv::DescriptorWrites voxelizationDescriptorWrites; + voxelizationDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(0, m_voxelImage.getHandle()) }; + voxelizationDescriptorWrites.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(1, m_voxelInfoBuffer.getHandle()) }; + m_corePtr->writeDescriptorSet(m_voxelizationDescriptorSet, voxelizationDescriptorWrites); + + vkcv::ShaderProgram voxelVisualisationShader = loadVoxelVisualisationShader(); + + const std::vector<vkcv::DescriptorBinding> voxelVisualisationDescriptorBindings = { voxelVisualisationShader.getReflectedDescriptors()[0] }; + m_visualisationDescriptorSet = m_corePtr->createDescriptorSet(voxelVisualisationDescriptorBindings); + + const vkcv::AttachmentDescription voxelVisualisationColorAttachments( + vkcv::AttachmentOperation::STORE, + vkcv::AttachmentOperation::LOAD, + dependencies.colorBufferFormat + ); + + const vkcv::AttachmentDescription voxelVisualisationDepthAttachments( + vkcv::AttachmentOperation::STORE, + vkcv::AttachmentOperation::LOAD, + dependencies.depthBufferFormat + ); + + vkcv::PassConfig voxelVisualisationPassDefinition({ voxelVisualisationColorAttachments, voxelVisualisationDepthAttachments }); + m_visualisationPass = m_corePtr->createPass(voxelVisualisationPassDefinition); + + const vkcv::PipelineConfig voxelVisualisationPipeConfig{ + voxelVisualisationShader, + 0, + 0, + m_visualisationPass, + {}, + { m_corePtr->getDescriptorSet(m_visualisationDescriptorSet).layout }, + true, + false, + vkcv::PrimitiveTopology::PointList }; // points are extended to cubes in the geometry shader + m_visualisationPipe = m_corePtr->createGraphicsPipeline(voxelVisualisationPipeConfig); + + std::vector<uint16_t> voxelIndexData; + for (int i = 0; i < voxelCount; i++) { + voxelIndexData.push_back(i); + } + m_visualisationIndexBuffer.fill(voxelIndexData); + + vkcv::DescriptorWrites voxelVisualisationDescriptorWrite; + voxelVisualisationDescriptorWrite.storageImageWrites = { vkcv::StorageImageDescriptorWrite(0, m_voxelImage.getHandle()) }; + voxelVisualisationDescriptorWrite.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(1, m_voxelInfoBuffer.getHandle()) }; + m_corePtr->writeDescriptorSet(m_visualisationDescriptorSet, voxelVisualisationDescriptorWrite); + + const vkcv::DescriptorSetUsage voxelizationDescriptorUsage(0, m_corePtr->getDescriptorSet(m_visualisationDescriptorSet).vulkanHandle); + + vkcv::ShaderProgram resetVoxelShader = loadVoxelResetShader(); + + m_voxelResetDescriptorSet = m_corePtr->createDescriptorSet(resetVoxelShader.getReflectedDescriptors()[0]); + m_voxelResetPipe = m_corePtr->createComputePipeline( + resetVoxelShader, + { m_corePtr->getDescriptorSet(m_voxelResetDescriptorSet).layout }); + + vkcv::DescriptorWrites resetVoxelWrites; + resetVoxelWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(0, m_voxelImage.getHandle()) }; + m_corePtr->writeDescriptorSet(m_voxelResetDescriptorSet, resetVoxelWrites); +} + +void Voxelization::voxelizeMeshes( + vkcv::CommandStreamHandle cmdStream, + const glm::vec3& cameraPosition, + const std::vector<vkcv::Mesh>& meshes, + const std::vector<glm::mat4>& modelMatrices) { + + const float voxelizationExtent = 20.f; + VoxelizationInfo voxelizationInfo; + voxelizationInfo.extent = voxelizationExtent; + + // move voxel offset with camera in voxel sized steps + const float voxelSize = voxelizationExtent / voxelResolution; + voxelizationInfo.offset = glm::floor(cameraPosition / voxelSize) * voxelSize; + + m_voxelInfoBuffer.fill({ voxelizationInfo }); + + const float voxelizationHalfExtent = 0.5f * voxelizationExtent; + const glm::mat4 voxelizationProjection = glm::ortho( + -voxelizationHalfExtent, + voxelizationHalfExtent, + -voxelizationHalfExtent, + voxelizationHalfExtent, + -voxelizationHalfExtent, + voxelizationHalfExtent); + + const glm::mat4 voxelizationView = glm::translate(glm::mat4(1.f), -voxelizationInfo.offset); + const glm::mat4 voxelizationViewProjection = voxelizationProjection * voxelizationView; + + std::vector<std::array<glm::mat4, 2>> voxelizationMatrices; + for (const auto& m : modelMatrices) { + voxelizationMatrices.push_back({ voxelizationViewProjection * m, m }); + } + + const vkcv::PushConstantData voxelizationPushConstantData((void*)voxelizationMatrices.data(), 2 * sizeof(glm::mat4)); + + // reset voxels + const uint32_t resetVoxelGroupSize[3] = { 4, 4, 4 }; + uint32_t resetVoxelDispatchCount[3]; + for (int i = 0; i < 3; i++) { + resetVoxelDispatchCount[i] = glm::ceil(voxelResolution / float(resetVoxelGroupSize[i])); + } + + m_corePtr->prepareImageForStorage(cmdStream, m_voxelImage.getHandle()); + m_corePtr->recordComputeDispatchToCmdStream( + cmdStream, + m_voxelResetPipe, + resetVoxelDispatchCount, + { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_voxelResetDescriptorSet).vulkanHandle) }, + vkcv::PushConstantData(nullptr, 0)); + m_corePtr->recordImageMemoryBarrier(cmdStream, m_voxelImage.getHandle()); + + std::vector<vkcv::DrawcallInfo> drawcalls; + for (const auto& mesh : meshes) { + drawcalls.push_back(vkcv::DrawcallInfo( + mesh, + { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_voxelizationDescriptorSet).vulkanHandle) })); + } + + // voxelization + m_corePtr->recordDrawcallsToCmdStream( + cmdStream, + m_voxelizationPass, + m_voxelizationPipe, + voxelizationPushConstantData, + drawcalls, + { m_dummyRenderTarget.getHandle() }); + m_corePtr->recordImageMemoryBarrier(cmdStream, m_voxelImage.getHandle()); +} + +void Voxelization::renderVoxelVisualisation( + vkcv::CommandStreamHandle cmdStream, + const glm::mat4& viewProjectin, + const std::vector<vkcv::ImageHandle>& renderTargets) { + + const vkcv::PushConstantData voxelVisualisationPushConstantData((void*)&viewProjectin, sizeof(glm::mat4)); + + const auto drawcall = vkcv::DrawcallInfo( + vkcv::Mesh({}, m_visualisationIndexBuffer.getVulkanHandle(), voxelCount), + { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_visualisationDescriptorSet).vulkanHandle) }); + + m_corePtr->recordDrawcallsToCmdStream( + cmdStream, + m_visualisationPass, + m_visualisationPipe, + voxelVisualisationPushConstantData, + { drawcall }, + renderTargets); +} \ No newline at end of file diff --git a/projects/voxelization/src/Voxelization.hpp b/projects/voxelization/src/Voxelization.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b23b30216f0e9ed11bd7b6097ba531b1dfc3a66f --- /dev/null +++ b/projects/voxelization/src/Voxelization.hpp @@ -0,0 +1,48 @@ +#pragma once +#include <vkcv/Core.hpp> +#include <glm/glm.hpp> + +class Voxelization{ +public: + struct Dependencies { + vkcv::VertexLayout vertexLayout; + vk::Format colorBufferFormat; + vk::Format depthBufferFormat; + }; + Voxelization(vkcv::Core* corePtr, const Dependencies& dependencies); + + void voxelizeMeshes( + vkcv::CommandStreamHandle cmdStream, + const glm::vec3& cameraPosition, + const std::vector<vkcv::Mesh>& meshes, + const std::vector<glm::mat4>& modelMatrices); + + void renderVoxelVisualisation( + vkcv::CommandStreamHandle cmdStream, + const glm::mat4& viewProjectin, + const std::vector<vkcv::ImageHandle>& renderTargets); + +private: + vkcv::Core* m_corePtr; + + vkcv::Image m_voxelImage; + vkcv::Image m_dummyRenderTarget; + vkcv::PassHandle m_voxelizationPass; + vkcv::PipelineHandle m_voxelizationPipe; + vkcv::DescriptorSetHandle m_voxelizationDescriptorSet; + + vkcv::PipelineHandle m_voxelResetPipe; + vkcv::DescriptorSetHandle m_voxelResetDescriptorSet; + + vkcv::PassHandle m_visualisationPass; + vkcv::PipelineHandle m_visualisationPipe; + vkcv::Buffer<uint16_t> m_visualisationIndexBuffer; + + vkcv::DescriptorSetHandle m_visualisationDescriptorSet; + + struct VoxelizationInfo { + glm::vec3 offset; + float extent; + }; + vkcv::Buffer<VoxelizationInfo> m_voxelInfoBuffer; +}; \ No newline at end of file diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index 620547d30c14ce28af6fd889560864199915de2e..bd7046f14fca8af06bdf95a29ffe2504a43ebc7f 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -6,6 +6,7 @@ #include <vkcv/asset/asset_loader.hpp> #include <vkcv/shader/GLSLCompiler.hpp> #include <vkcv/Logger.hpp> +#include "Voxelization.hpp" int main(int argc, const char** argv) { const char* applicationName = "Voxelization"; @@ -145,10 +146,10 @@ int main(int argc, const char** argv) { vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorBindings); const vkcv::PipelineConfig forwardPipelineConfig { - forwardProgram, + forwardProgram, windowWidth, windowHeight, - forwardPass, + forwardPass, vertexLayout, { core.getDescriptorSet(descriptorSet).layout }, true @@ -219,123 +220,11 @@ int main(int argc, const char** argv) { LightInfo lightInfo; vkcv::Buffer lightBuffer = core.createBuffer<LightInfo>(vkcv::BufferType::UNIFORM, sizeof(glm::vec3)); - const uint32_t voxelResolution = 32; - vkcv::Image voxelImage = core.createImage(vk::Format::eR8Unorm, voxelResolution, voxelResolution, voxelResolution, true); - const vk::Format voxelizationDummyFormat = vk::Format::eR8Unorm; - vkcv::Image voxelizationDummyRenderTarget = core.createImage(voxelizationDummyFormat, voxelResolution, voxelResolution, 1, false, true); - - vkcv::ShaderProgram voxelizationShader; - compiler.compile(vkcv::ShaderStage::VERTEX, "resources/shaders/voxelization.vert", - [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - voxelizationShader.addShader(shaderStage, path); - }); - compiler.compile(vkcv::ShaderStage::GEOMETRY, "resources/shaders/voxelization.geom", - [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - voxelizationShader.addShader(shaderStage, path); - }); - compiler.compile(vkcv::ShaderStage::FRAGMENT, "resources/shaders/voxelization.frag", - [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - voxelizationShader.addShader(shaderStage, path); - }); - - vkcv::PassConfig voxelizationPassConfig({ - vkcv::AttachmentDescription(vkcv::AttachmentOperation::DONT_CARE, vkcv::AttachmentOperation::DONT_CARE, voxelizationDummyFormat)}); - vkcv::PassHandle voxelizationPass = core.createPass(voxelizationPassConfig); - - std::vector<vkcv::DescriptorBinding> voxelizationDescriptorBindings = { voxelizationShader.getReflectedDescriptors()[0] }; - vkcv::DescriptorSetHandle voxelizationDescriptorSet = core.createDescriptorSet(voxelizationDescriptorBindings); - - const vkcv::PipelineConfig voxelizationPipeConfig{ - voxelizationShader, - voxelResolution, - voxelResolution, - voxelizationPass, - vertexLayout, - { core.getDescriptorSet(voxelizationDescriptorSet).layout }, - false, - true }; - const vkcv::PipelineHandle voxelizationPipe = core.createGraphicsPipeline(voxelizationPipeConfig); - - struct VoxelizationInfo { - glm::vec3 offset; - float extent; - }; - vkcv::Buffer voxelizationInfoBuffer = core.createBuffer<VoxelizationInfo>(vkcv::BufferType::UNIFORM, sizeof(VoxelizationInfo)); - - vkcv::DescriptorWrites voxelizationDescriptorWrites; - voxelizationDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(0, voxelImage.getHandle()) }; - voxelizationDescriptorWrites.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(1, voxelizationInfoBuffer.getHandle()) }; - core.writeDescriptorSet(voxelizationDescriptorSet, voxelizationDescriptorWrites); - - const size_t voxelCount = voxelResolution * voxelResolution * voxelResolution; - - vkcv::ShaderProgram voxelVisualisationShader; - compiler.compile(vkcv::ShaderStage::VERTEX, "resources/shaders/voxelVisualisation.vert", - [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - voxelVisualisationShader.addShader(shaderStage, path); - }); - compiler.compile(vkcv::ShaderStage::GEOMETRY, "resources/shaders/voxelVisualisation.geom", - [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - voxelVisualisationShader.addShader(shaderStage, path); - }); - compiler.compile(vkcv::ShaderStage::FRAGMENT, "resources/shaders/voxelVisualisation.frag", - [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - voxelVisualisationShader.addShader(shaderStage, path); - }); - - const std::vector<vkcv::DescriptorBinding> voxelVisualisationDescriptorBindings = { voxelVisualisationShader.getReflectedDescriptors()[0] }; - vkcv::DescriptorSetHandle voxelVisualisationDescriptorSet = core.createDescriptorSet(voxelVisualisationDescriptorBindings); - - const vkcv::AttachmentDescription voxelVisualisationColorAttachments( - vkcv::AttachmentOperation::STORE, - vkcv::AttachmentOperation::LOAD, - colorBufferFormat - ); - - const vkcv::AttachmentDescription voxelVisualisationDepthAttachments( - vkcv::AttachmentOperation::STORE, - vkcv::AttachmentOperation::LOAD, - depthBufferFormat - ); - - vkcv::PassConfig voxelVisualisationPassDefinition({ voxelVisualisationColorAttachments, voxelVisualisationDepthAttachments }); - vkcv::PassHandle voxelVisualisationPass = core.createPass(voxelVisualisationPassDefinition); - - const vkcv::PipelineConfig voxelVisualisationPipeConfig{ - voxelVisualisationShader, - 0, - 0, - voxelVisualisationPass, - {}, - { core.getDescriptorSet(voxelVisualisationDescriptorSet).layout }, - true, - false, - vkcv::PrimitiveTopology::PointList }; // points are extended to cubes in the geometry shader - const vkcv::PipelineHandle voxelVisualisationPipe = core.createGraphicsPipeline(voxelVisualisationPipeConfig); - - vkcv::Buffer<uint16_t> voxelVisualisationIndexBuffer = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, voxelCount); - std::vector<uint16_t> voxelIndexData; - for (int i = 0; i < voxelCount; i++) { - voxelIndexData.push_back(i); - } - - vkcv::DescriptorWrites voxelVisualisationDescriptorWrite; - voxelVisualisationDescriptorWrite.storageImageWrites = { vkcv::StorageImageDescriptorWrite(0, voxelImage.getHandle()) }; - voxelVisualisationDescriptorWrite.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(1, voxelizationInfoBuffer.getHandle()) }; - core.writeDescriptorSet(voxelVisualisationDescriptorSet, voxelVisualisationDescriptorWrite); - - voxelVisualisationIndexBuffer.fill(voxelIndexData); - const vkcv::DrawcallInfo voxelVisualisationDrawcall( - vkcv::Mesh({}, voxelVisualisationIndexBuffer.getVulkanHandle(), voxelCount), - { vkcv::DescriptorSetUsage(0, core.getDescriptorSet(voxelVisualisationDescriptorSet).vulkanHandle) }); - const vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle); - const vkcv::DescriptorSetUsage voxelizationDescriptorUsage(0, core.getDescriptorSet(voxelizationDescriptorSet).vulkanHandle); std::vector<std::array<glm::mat4, 2>> mainPassMatrices; std::vector<glm::mat4> mvpLight; - std::vector<std::array<glm::mat4, 2>> voxelizationMatrices; bool renderVoxelVis = false; window.e_key.add([&renderVoxelVis](int key ,int scancode, int action, int mods) { @@ -344,21 +233,6 @@ int main(int argc, const char** argv) { } }); - vkcv::ShaderProgram resetVoxelShader; - compiler.compile(vkcv::ShaderStage::COMPUTE, "resources/shaders/voxelReset.comp", - [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - resetVoxelShader.addShader(shaderStage, path); - }); - - vkcv::DescriptorSetHandle resetVoxelDescriptorSet = core.createDescriptorSet(resetVoxelShader.getReflectedDescriptors()[0]); - vkcv::PipelineHandle resetVoxelPipeline = core.createComputePipeline( - resetVoxelShader, - { core.getDescriptorSet(resetVoxelDescriptorSet).layout }); - - vkcv::DescriptorWrites resetVoxelWrites; - resetVoxelWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(0, voxelImage.getHandle()) }; - core.writeDescriptorSet(resetVoxelDescriptorSet, resetVoxelWrites); - // gamma correction compute shader vkcv::ShaderProgram gammaCorrectionProgram; compiler.compile(vkcv::ShaderStage::COMPUTE, "resources/shaders/gammaCorrection.comp", @@ -412,19 +286,30 @@ int main(int argc, const char** argv) { } // prepare drawcalls - std::vector<vkcv::DrawcallInfo> drawcalls; - std::vector<vkcv::DrawcallInfo> shadowDrawcalls; - std::vector<vkcv::DrawcallInfo> voxelizationDrawcalls; + std::vector<vkcv::Mesh> meshes; for (int i = 0; i < scene.vertexGroups.size(); i++) { - vkcv::Mesh mesh(vertexBufferBindings[i], indexBuffers[i].getVulkanHandle(), scene.vertexGroups[i].numIndices); + vkcv::Mesh mesh( + vertexBufferBindings[i], + indexBuffers[i].getVulkanHandle(), + scene.vertexGroups[i].numIndices); + meshes.push_back(mesh); + } + std::vector<vkcv::DrawcallInfo> drawcalls; + std::vector<vkcv::DrawcallInfo> shadowDrawcalls; + for (int i = 0; i < meshes.size(); i++) { vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSets[i]).vulkanHandle); - drawcalls.push_back(vkcv::DrawcallInfo(mesh, { descriptorUsage })); - shadowDrawcalls.push_back(vkcv::DrawcallInfo(mesh, {})); - voxelizationDrawcalls.push_back(vkcv::DrawcallInfo(mesh, { voxelizationDescriptorUsage })); + drawcalls.push_back(vkcv::DrawcallInfo(meshes[i], { descriptorUsage })); + shadowDrawcalls.push_back(vkcv::DrawcallInfo(meshes[i], {})); } + Voxelization::Dependencies voxelDependencies; + voxelDependencies.colorBufferFormat = colorBufferFormat; + voxelDependencies.depthBufferFormat = depthBufferFormat; + voxelDependencies.vertexLayout = vertexLayout; + Voxelization voxelization(&core, voxelDependencies); + auto start = std::chrono::system_clock::now(); const auto appStartTime = start; while (window.isWindowOpen()) { @@ -482,43 +367,18 @@ int main(int argc, const char** argv) { const glm::mat4 viewProjectionCamera = cameraManager.getActiveCamera().getMVP(); - const float voxelizationExtent = 20.f; - VoxelizationInfo voxelizationInfo; - voxelizationInfo.extent = voxelizationExtent; - - // move voxel offset with camera in voxel sized steps - const glm::vec3 cameraPos = cameraManager.getActiveCamera().getPosition(); - const float voxelSize = voxelizationExtent / voxelResolution; - voxelizationInfo.offset = glm::floor(cameraPos / voxelSize) * voxelSize; - - voxelizationInfoBuffer.fill({ voxelizationInfo }); - - const float voxelizationHalfExtent = 0.5f * voxelizationExtent; - const glm::mat4 voxelizationProjection = glm::ortho( - -voxelizationHalfExtent, - voxelizationHalfExtent, - -voxelizationHalfExtent, - voxelizationHalfExtent, - -voxelizationHalfExtent, - voxelizationHalfExtent); - - const glm::mat4 voxelizationView = glm::translate(glm::mat4(1.f), -voxelizationInfo.offset); - const glm::mat4 voxelizationViewProjection = voxelizationProjection * voxelizationView; - mainPassMatrices.clear(); mvpLight.clear(); - voxelizationMatrices.clear(); for (const auto& m : modelMatrices) { mainPassMatrices.push_back({ viewProjectionCamera * m, m }); mvpLight.push_back(lightInfo.lightMatrix * m); - voxelizationMatrices.push_back({ voxelizationViewProjection * m, m }); } vkcv::PushConstantData pushConstantData((void*)mainPassMatrices.data(), 2 * sizeof(glm::mat4)); const std::vector<vkcv::ImageHandle> renderTargets = { colorBuffer, depthBuffer }; const vkcv::PushConstantData shadowPushConstantData((void*)mvpLight.data(), sizeof(glm::mat4)); - const vkcv::PushConstantData voxelizationPushConstantData((void*)voxelizationMatrices.data(), 2 * sizeof(glm::mat4)); + auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics); @@ -530,34 +390,14 @@ int main(int argc, const char** argv) { shadowPushConstantData, shadowDrawcalls, { shadowMap.getHandle() }); - - // reset voxels - const uint32_t resetVoxelGroupSize[3] = { 4, 4, 4 }; - uint32_t resetVoxelDispatchCount[3]; - for(int i = 0; i < 3; i++) { - resetVoxelDispatchCount[i] = glm::ceil(voxelResolution / float(resetVoxelGroupSize[i])); - } - - core.prepareImageForStorage(cmdStream, voxelImage.getHandle()); - core.recordComputeDispatchToCmdStream( - cmdStream, - resetVoxelPipeline, - resetVoxelDispatchCount, - { vkcv::DescriptorSetUsage(0, core.getDescriptorSet(resetVoxelDescriptorSet).vulkanHandle) }, - vkcv::PushConstantData(nullptr, 0)); - core.recordImageMemoryBarrier(cmdStream, voxelImage.getHandle()); - - // voxelization - core.recordDrawcallsToCmdStream( - cmdStream, - voxelizationPass, - voxelizationPipe, - voxelizationPushConstantData, - voxelizationDrawcalls, - { voxelizationDummyRenderTarget.getHandle() }); - core.prepareImageForSampling(cmdStream, shadowMap.getHandle()); + voxelization.voxelizeMeshes( + cmdStream, + cameraManager.getActiveCamera().getPosition(), + meshes, + modelMatrices); + // main pass core.recordDrawcallsToCmdStream( cmdStream, @@ -568,16 +408,7 @@ int main(int argc, const char** argv) { renderTargets); if (renderVoxelVis) { - const vkcv::PushConstantData voxelVisualisationPushConstantData((void*)&viewProjectionCamera, sizeof(glm::mat4)); - - core.recordImageMemoryBarrier(cmdStream, voxelImage.getHandle()); - core.recordDrawcallsToCmdStream( - cmdStream, - voxelVisualisationPass, - voxelVisualisationPipe, - voxelVisualisationPushConstantData, - { voxelVisualisationDrawcall }, - renderTargets); + voxelization.renderVoxelVisualisation(cmdStream, viewProjectionCamera, renderTargets); } const uint32_t gammaCorrectionLocalGroupSize = 8;