Skip to content
Snippets Groups Projects

Resolve "Basic voxelization"

Merged Ghost User requested to merge 70-basic-voxelization into develop
4 files
+ 315
198
Compare changes
  • Side-by-side
  • Inline
Files
4
  • 7077401d
    [#70] Put voxelization in separate class to improve readability · 7077401d
    Alexander Gauggel authored
+ 234
0
#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
Loading