From 424334dfac6e9b1c51fb4ded7f02d3366f8fec38 Mon Sep 17 00:00:00 2001
From: Alexander Gauggel <agauggel@uni-koblenz.de>
Date: Thu, 17 Jun 2021 17:02:00 +0200
Subject: [PATCH] [#70] Albedo color now voxelized

---
 .../resources/shaders/perMeshResources.inc    |   2 +
 .../resources/shaders/shader.frag             |  13 +-
 .../resources/shaders/voxelBufferToImage.comp |   4 +-
 .../resources/shaders/voxelization.frag       |  10 +-
 .../resources/shaders/voxelization.geom       |   3 +
 .../resources/shaders/voxelization.vert       |   2 +
 projects/voxelization/src/Voxelization.cpp    |  25 ++-
 projects/voxelization/src/Voxelization.hpp    |   9 +-
 projects/voxelization/src/main.cpp            | 156 +++++++++---------
 9 files changed, 123 insertions(+), 101 deletions(-)
 create mode 100644 projects/voxelization/resources/shaders/perMeshResources.inc

diff --git a/projects/voxelization/resources/shaders/perMeshResources.inc b/projects/voxelization/resources/shaders/perMeshResources.inc
new file mode 100644
index 00000000..95e4fb7c
--- /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 95f1b331..edafc8c0 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 20c56e31..5e829888 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 69e2052c..7ea161ce 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 23084853..19e31e2d 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 6914e951..7a43c08b 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 a5658a38..e9748aa3 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 db1f1d85..f0f88493 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 0a419ddd..b2d13030 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(
-- 
GitLab