diff --git a/projects/voxelization/resources/shaders/perMeshResources.inc b/projects/voxelization/resources/shaders/perMeshResources.inc new file mode 100644 index 0000000000000000000000000000000000000000..95e4fb7c27009965659d14a9c72acfec950c37e3 --- /dev/null +++ b/projects/voxelization/resources/shaders/perMeshResources.inc @@ -0,0 +1,2 @@ +layout(set=1, binding=0) uniform texture2D albedoTexture; +layout(set=1, binding=1) uniform sampler textureSampler; \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/shader.frag b/projects/voxelization/resources/shaders/shader.frag index 95f1b3319e1ca5c7c34ff94e5e7198819c0233c1..edafc8c0077416cb57aedc4e7358126846507e18 100644 --- a/projects/voxelization/resources/shaders/shader.frag +++ b/projects/voxelization/resources/shaders/shader.frag @@ -1,5 +1,8 @@ #version 450 #extension GL_ARB_separate_shader_objects : enable +#extension GL_GOOGLE_include_directive : enable + +#include "perMeshResources.inc" layout(location = 0) in vec3 passNormal; layout(location = 1) in vec2 passUV; @@ -7,14 +10,12 @@ layout(location = 2) in vec3 passPos; layout(location = 0) out vec3 outColor; -layout(set=0, binding=0) uniform texture2D meshTexture; -layout(set=0, binding=1) uniform sampler textureSampler; -layout(set=0, binding=2) uniform sunBuffer { +layout(set=0, binding=0) uniform sunBuffer { vec3 L; float padding; mat4 lightMatrix; }; -layout(set=0, binding=3) uniform texture2D shadowMap; -layout(set=0, binding=4) uniform sampler shadowMapSampler; +layout(set=0, binding=1) uniform texture2D shadowMap; +layout(set=0, binding=2) uniform sampler shadowMapSampler; float shadowTest(vec3 worldPos){ vec4 lightPos = lightMatrix * vec4(worldPos, 1); @@ -39,6 +40,6 @@ void main() { vec3 sun = sunColor * clamp(dot(N, L), 0, 1); sun *= shadowTest(passPos); vec3 ambient = vec3(0.1); - vec3 albedo = texture(sampler2D(meshTexture, textureSampler), passUV).rgb; + vec3 albedo = texture(sampler2D(albedoTexture, textureSampler), passUV).rgb; outColor = albedo * (sun + ambient); } \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/voxelBufferToImage.comp b/projects/voxelization/resources/shaders/voxelBufferToImage.comp index 20c56e31b0f8b6e6503bdaf347ea730bcbc87f01..5e8298886cb2bacbc81f981e8e90310cdc876d5d 100644 --- a/projects/voxelization/resources/shaders/voxelBufferToImage.comp +++ b/projects/voxelization/resources/shaders/voxelBufferToImage.comp @@ -3,7 +3,7 @@ #include "voxel.inc" layout(set=0, binding=0, std430) buffer voxelBuffer{ - uint isFilled[]; + uint packedVoxelData[]; }; layout(set=0, binding=1, rgba16f) uniform image3D voxelImage; @@ -19,6 +19,6 @@ void main(){ ivec3 UV = ivec3(gl_GlobalInvocationID); uint flatIndex = flattenVoxelUVToIndex(UV, voxelImageSize); - vec4 color = unpackVoxelInfo(isFilled[flatIndex]); + vec4 color = unpackVoxelInfo(packedVoxelData[flatIndex]); imageStore(voxelImage, UV, vec4(color)); } \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/voxelization.frag b/projects/voxelization/resources/shaders/voxelization.frag index 69e2052cf0f6e979c18b6e7a48102c06b43213b1..7ea161ce4f5a4d59bb3d50c78553df0dfb5ab4ec 100644 --- a/projects/voxelization/resources/shaders/voxelization.frag +++ b/projects/voxelization/resources/shaders/voxelization.frag @@ -3,11 +3,13 @@ #extension GL_GOOGLE_include_directive : enable #include "voxel.inc" +#include "perMeshResources.inc" -layout(location = 0) in vec3 passPos; +layout(location = 0) in vec3 passPos; +layout(location = 1) out vec2 passUV; layout(set=0, binding=0, std430) buffer voxelizationBuffer{ - uint isFilled[]; + uint packedVoxelData[]; }; layout(set=0, binding=1) uniform voxelizationInfo{ @@ -33,6 +35,6 @@ void main() { } uint flatIndex = flattenVoxelUVToIndex(UV, voxelImageSize); - vec3 color = vec3(1, 1, 0); - isFilled[flatIndex] = packVoxelInfo(color); + vec3 color = texture(sampler2D(albedoTexture, textureSampler), passUV).rgb; + atomicMax(packedVoxelData[flatIndex], packVoxelInfo(color)); } \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/voxelization.geom b/projects/voxelization/resources/shaders/voxelization.geom index 23084853e0c8809eb55f88c44c254b4c5ddd12d8..19e31e2d2d032b5a9e5c273f6420c6449be9203e 100644 --- a/projects/voxelization/resources/shaders/voxelization.geom +++ b/projects/voxelization/resources/shaders/voxelization.geom @@ -5,8 +5,10 @@ layout(triangles) in; layout (triangle_strip, max_vertices = 3) out; layout(location = 0) in vec3 passPosIn[3]; +layout(location = 1) in vec2 passUVIn[3]; layout(location = 0) out vec3 passPos; +layout(location = 1) out vec2 passUV; void main() { // compute geometric normal, no normalization necessary @@ -26,6 +28,7 @@ void main() { } gl_Position.z = gl_Position.z * 0.5 + 0.5; // xyz are kept in NDC range [-1, 1] so swizzling works, but vulkan needs final z in range [0, 1] passPos = passPosIn[i]; + passUV = passUVIn[i]; EmitVertex(); } EndPrimitive(); diff --git a/projects/voxelization/resources/shaders/voxelization.vert b/projects/voxelization/resources/shaders/voxelization.vert index 6914e95122125843bdb84baf51c8cfef4c726da5..7a43c08b64d3df384d3a7e627d789db9be99f680 100644 --- a/projects/voxelization/resources/shaders/voxelization.vert +++ b/projects/voxelization/resources/shaders/voxelization.vert @@ -6,6 +6,7 @@ layout(location = 1) in vec3 inNormal; layout(location = 2) in vec2 inUV; layout(location = 0) out vec3 passPos; +layout(location = 1) out vec2 passUV; layout( push_constant ) uniform constants{ mat4 mvp; @@ -15,4 +16,5 @@ layout( push_constant ) uniform constants{ void main() { gl_Position = mvp * vec4(inPosition, 1.0); passPos = (model * vec4(inPosition, 1)).xyz; + passUV = inUV; } \ No newline at end of file diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp index a5658a3870fb5e6df9811d84076d13f0e618a6a2..e9748aa3393588f775cdf977e1e3e16a1fca772d 100644 --- a/projects/voxelization/src/Voxelization.cpp +++ b/projects/voxelization/src/Voxelization.cpp @@ -83,13 +83,18 @@ Voxelization::Voxelization(vkcv::Core* corePtr, const Dependencies& dependencies { voxelizationShader.getReflectedDescriptors()[0] }; m_voxelizationDescriptorSet = m_corePtr->createDescriptorSet(voxelizationDescriptorBindings); + vkcv::DescriptorSetHandle dummyPerMeshDescriptorSet = + m_corePtr->createDescriptorSet({ voxelizationShader.getReflectedDescriptors()[1] }); + const vkcv::PipelineConfig voxelizationPipeConfig{ voxelizationShader, voxelResolution, voxelResolution, m_voxelizationPass, dependencies.vertexLayout, - { m_corePtr->getDescriptorSet(m_voxelizationDescriptorSet).layout }, + { + m_corePtr->getDescriptorSet(m_voxelizationDescriptorSet).layout, + m_corePtr->getDescriptorSet(dummyPerMeshDescriptorSet).layout}, false, true }; m_voxelizationPipe = m_corePtr->createGraphicsPipeline(voxelizationPipeConfig); @@ -175,10 +180,11 @@ Voxelization::Voxelization(vkcv::Core* corePtr, const Dependencies& dependencies } void Voxelization::voxelizeMeshes( - vkcv::CommandStreamHandle cmdStream, - const glm::vec3& cameraPosition, - const std::vector<vkcv::Mesh>& meshes, - const std::vector<glm::mat4>& modelMatrices) { + vkcv::CommandStreamHandle cmdStream, + const glm::vec3& cameraPosition, + const std::vector<vkcv::Mesh>& meshes, + const std::vector<glm::mat4>& modelMatrices, + const std::vector<vkcv::DescriptorSetHandle>& perMeshDescriptorSets) { VoxelizationInfo voxelizationInfo; voxelizationInfo.extent = m_voxelExtent; @@ -226,10 +232,13 @@ void Voxelization::voxelizeMeshes( // voxelization std::vector<vkcv::DrawcallInfo> drawcalls; - for (const auto& mesh : meshes) { + for (int i = 0; i < meshes.size(); i++) { drawcalls.push_back(vkcv::DrawcallInfo( - mesh, - { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_voxelizationDescriptorSet).vulkanHandle) })); + meshes[i], + { + vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_voxelizationDescriptorSet).vulkanHandle), + vkcv::DescriptorSetUsage(1, m_corePtr->getDescriptorSet(perMeshDescriptorSets[i]).vulkanHandle) + })); } m_corePtr->recordDrawcallsToCmdStream( diff --git a/projects/voxelization/src/Voxelization.hpp b/projects/voxelization/src/Voxelization.hpp index db1f1d85ee1e2d937e0bff84c81265fe2b32e611..f0f8849362051b117f447cc9b8d9c61a83ecefaa 100644 --- a/projects/voxelization/src/Voxelization.hpp +++ b/projects/voxelization/src/Voxelization.hpp @@ -12,10 +12,11 @@ public: 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); + vkcv::CommandStreamHandle cmdStream, + const glm::vec3& cameraPosition, + const std::vector<vkcv::Mesh>& meshes, + const std::vector<glm::mat4>& modelMatrices, + const std::vector<vkcv::DescriptorSetHandle>& perMeshDescriptorSets); void renderVoxelVisualisation( vkcv::CommandStreamHandle cmdStream, diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index 0a419ddde855229efb0aaf2c7e8af0e6888f8ffe..b2d1303053f02366912e25bf8bd8871ea9e0d096 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -135,15 +135,76 @@ int main(int argc, const char** argv) { const std::vector<vkcv::VertexAttachment> vertexAttachments = forwardProgram.getVertexAttachments(); - std::vector<vkcv::VertexBinding> vertexBindings; - for (size_t i = 0; i < vertexAttachments.size(); i++) { + std::vector<vkcv::VertexBinding> vertexBindings; + for (size_t i = 0; i < vertexAttachments.size(); i++) { vertexBindings.push_back(vkcv::VertexBinding(i, { vertexAttachments[i] })); - } - - const vkcv::VertexLayout vertexLayout (vertexBindings); + } + const vkcv::VertexLayout vertexLayout (vertexBindings); - std::vector<vkcv::DescriptorBinding> descriptorBindings = { forwardProgram.getReflectedDescriptors()[0] }; - vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorBindings); + // shadow map + vkcv::SamplerHandle shadowSampler = core.createSampler( + vkcv::SamplerFilterType::NEAREST, + vkcv::SamplerFilterType::NEAREST, + vkcv::SamplerMipmapMode::NEAREST, + vkcv::SamplerAddressMode::CLAMP_TO_EDGE + ); + const vk::Format shadowMapFormat = vk::Format::eD16Unorm; + const uint32_t shadowMapResolution = 1024; + const vkcv::Image shadowMap = core.createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution, 1); + + // light info buffer + struct LightInfo { + glm::vec3 direction; + float padding; + glm::mat4 lightMatrix; + }; + LightInfo lightInfo; + vkcv::Buffer lightBuffer = core.createBuffer<LightInfo>(vkcv::BufferType::UNIFORM, sizeof(glm::vec3)); + + vkcv::DescriptorSetHandle forwardShadingDescriptorSet = + core.createDescriptorSet({ forwardProgram.getReflectedDescriptors()[0] }); + + vkcv::DescriptorWrites forwardDescriptorWrites; + forwardDescriptorWrites.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(0, lightBuffer.getHandle()) }; + forwardDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(1, shadowMap.getHandle()) }; + forwardDescriptorWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(2, shadowSampler) }; + core.writeDescriptorSet(forwardShadingDescriptorSet, forwardDescriptorWrites); + + vkcv::SamplerHandle colorSampler = core.createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + vkcv::SamplerAddressMode::REPEAT + ); + + // prepare per mesh descriptor sets + std::vector<vkcv::DescriptorSetHandle> perMeshDescriptorSets; + std::vector<vkcv::Image> sceneImages; + for (const auto& vertexGroup : scene.vertexGroups) { + perMeshDescriptorSets.push_back(core.createDescriptorSet(forwardProgram.getReflectedDescriptors()[1])); + + const auto& material = scene.materials[vertexGroup.materialIndex]; + + int baseColorIndex = material.baseColor; + if (baseColorIndex < 0) { + vkcv_log(vkcv::LogLevel::WARNING, "Material lacks base color"); + baseColorIndex = 0; + } + + vkcv::asset::Texture& sceneTexture = scene.textures[baseColorIndex]; + + sceneImages.push_back(core.createImage(vk::Format::eR8G8B8A8Srgb, sceneTexture.w, sceneTexture.h)); + sceneImages.back().fill(sceneTexture.data.data()); + + vkcv::DescriptorWrites setWrites; + setWrites.sampledImageWrites = { + vkcv::SampledImageDescriptorWrite(0, sceneImages.back().getHandle()) + }; + setWrites.samplerWrites = { + vkcv::SamplerDescriptorWrite(1, colorSampler), + }; + core.writeDescriptorSet(perMeshDescriptorSets.back(), setWrites); + } const vkcv::PipelineConfig forwardPipelineConfig { forwardProgram, @@ -151,7 +212,8 @@ int main(int argc, const char** argv) { windowHeight, forwardPass, vertexLayout, - { core.getDescriptorSet(descriptorSet).layout }, + { core.getDescriptorSet(forwardShadingDescriptorSet).layout, + core.getDescriptorSet(perMeshDescriptorSets[0]).layout }, true }; @@ -161,20 +223,6 @@ int main(int argc, const char** argv) { std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl; return EXIT_FAILURE; } - - vkcv::SamplerHandle colorSampler = core.createSampler( - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerMipmapMode::LINEAR, - vkcv::SamplerAddressMode::REPEAT - ); - - vkcv::SamplerHandle shadowSampler = core.createSampler( - vkcv::SamplerFilterType::NEAREST, - vkcv::SamplerFilterType::NEAREST, - vkcv::SamplerMipmapMode::NEAREST, - vkcv::SamplerAddressMode::CLAMP_TO_EDGE - ); vkcv::ImageHandle depthBuffer = core.createImage(depthBufferFormat, windowWidth, windowHeight).getHandle(); vkcv::ImageHandle colorBuffer = core.createImage(colorBufferFormat, windowWidth, windowHeight, 1, true, true).getHandle(); @@ -191,38 +239,22 @@ int main(int argc, const char** argv) { shadowShader.addShader(shaderStage, path); }); - const vk::Format shadowMapFormat = vk::Format::eD16Unorm; const std::vector<vkcv::AttachmentDescription> shadowAttachments = { vkcv::AttachmentDescription(vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, shadowMapFormat) }; const vkcv::PassConfig shadowPassConfig(shadowAttachments); const vkcv::PassHandle shadowPass = core.createPass(shadowPassConfig); - - const uint32_t shadowMapResolution = 1024; - const vkcv::Image shadowMap = core.createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution, 1); - const vkcv::PipelineConfig shadowPipeConfig { - shadowShader, - shadowMapResolution, - shadowMapResolution, + const vkcv::PipelineConfig shadowPipeConfig{ + shadowShader, + shadowMapResolution, + shadowMapResolution, shadowPass, vertexLayout, {}, false }; - const vkcv::PipelineHandle shadowPipe = core.createGraphicsPipeline(shadowPipeConfig); - struct LightInfo { - glm::vec3 direction; - float padding; - glm::mat4 lightMatrix; - }; - LightInfo lightInfo; - vkcv::Buffer lightBuffer = core.createBuffer<LightInfo>(vkcv::BufferType::UNIFORM, sizeof(glm::vec3)); - - - const vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle); - std::vector<std::array<glm::mat4, 2>> mainPassMatrices; std::vector<glm::mat4> mvpLight; @@ -243,38 +275,6 @@ int main(int argc, const char** argv) { vkcv::PipelineHandle gammaCorrectionPipeline = core.createComputePipeline(gammaCorrectionProgram, { core.getDescriptorSet(gammaCorrectionDescriptorSet).layout }); - // prepare descriptor sets for drawcalls - std::vector<vkcv::Image> sceneImages; - std::vector<vkcv::DescriptorSetHandle> descriptorSets; - for (const auto& vertexGroup : scene.vertexGroups) { - descriptorSets.push_back(core.createDescriptorSet(descriptorBindings)); - - const auto& material = scene.materials[vertexGroup.materialIndex]; - - int baseColorIndex = material.baseColor; - if (baseColorIndex < 0) { - vkcv_log(vkcv::LogLevel::WARNING, "Material lacks base color"); - baseColorIndex = 0; - } - - vkcv::asset::Texture& sceneTexture = scene.textures[baseColorIndex]; - - sceneImages.push_back(core.createImage(vk::Format::eR8G8B8A8Srgb, sceneTexture.w, sceneTexture.h)); - sceneImages.back().fill(sceneTexture.data.data()); - - vkcv::DescriptorWrites setWrites; - setWrites.sampledImageWrites = { - vkcv::SampledImageDescriptorWrite(0, sceneImages.back().getHandle()), - vkcv::SampledImageDescriptorWrite(3, shadowMap.getHandle()) - }; - setWrites.samplerWrites = { - vkcv::SamplerDescriptorWrite(1, colorSampler), - vkcv::SamplerDescriptorWrite(4, shadowSampler), - }; - setWrites.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(2, lightBuffer.getHandle()) }; - core.writeDescriptorSet(descriptorSets.back(), setWrites); - } - // model matrices per mesh std::vector<glm::mat4> modelMatrices; modelMatrices.resize(scene.vertexGroups.size(), glm::mat4(1.f)); @@ -298,9 +298,10 @@ int main(int argc, const char** argv) { 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(meshes[i], { descriptorUsage })); + drawcalls.push_back(vkcv::DrawcallInfo(meshes[i], { + vkcv::DescriptorSetUsage(0, core.getDescriptorSet(forwardShadingDescriptorSet).vulkanHandle), + vkcv::DescriptorSetUsage(1, core.getDescriptorSet(perMeshDescriptorSets[i]).vulkanHandle) })); shadowDrawcalls.push_back(vkcv::DrawcallInfo(meshes[i], {})); } @@ -395,7 +396,8 @@ int main(int argc, const char** argv) { cmdStream, cameraManager.getActiveCamera().getPosition(), meshes, - modelMatrices); + modelMatrices, + perMeshDescriptorSets); // main pass core.recordDrawcallsToCmdStream(