From 8ca8074bf0baeb3f04ec29f9eb6aa74580c6dd76 Mon Sep 17 00:00:00 2001
From: Alexander Gauggel <agauggel@uni-koblenz.de>
Date: Thu, 24 Jun 2021 00:40:59 +0200
Subject: [PATCH] [#82] Shadow blur, but wrong

---
 .../resources/shaders/depthToMoments.comp     |  6 +--
 .../resources/shaders/lightInfo.inc           |  1 -
 .../resources/shaders/shadowBlur.comp         | 42 +++++++++++++++++++
 projects/voxelization/src/ShadowMapping.cpp   | 40 +++++++++++++++---
 projects/voxelization/src/ShadowMapping.hpp   |  8 ++--
 projects/voxelization/src/main.cpp            |  6 ---
 6 files changed, 83 insertions(+), 20 deletions(-)
 create mode 100644 projects/voxelization/resources/shaders/shadowBlur.comp

diff --git a/projects/voxelization/resources/shaders/depthToMoments.comp b/projects/voxelization/resources/shaders/depthToMoments.comp
index 5d327f54..401f399f 100644
--- a/projects/voxelization/resources/shaders/depthToMoments.comp
+++ b/projects/voxelization/resources/shaders/depthToMoments.comp
@@ -6,9 +6,9 @@
 
 layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
 
-layout(set=0, binding=0)                    uniform texture2DMS     srcTexture;
-layout(set=0, binding=1)                    uniform sampler         depthSampler;                
-layout(set=0, binding=2, r11f_g11f_b10f)    uniform image2D         outImage;
+layout(set=0, binding=0)                    uniform texture2DMS srcTexture;
+layout(set=0, binding=1)                    uniform sampler     depthSampler;                
+layout(set=0, binding=2, rgba16)            uniform image2D     outImage;
 
 layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
 
diff --git a/projects/voxelization/resources/shaders/lightInfo.inc b/projects/voxelization/resources/shaders/lightInfo.inc
index c0df6551..7cbf605e 100644
--- a/projects/voxelization/resources/shaders/lightInfo.inc
+++ b/projects/voxelization/resources/shaders/lightInfo.inc
@@ -6,7 +6,6 @@ struct LightInfo{
     vec3 sunColor;      
     float sunStrength;
     mat4 lightMatrix;
-    vec2 warps;
 };
 
 #endif // #ifndef LIGHT_INFO_INC
\ No newline at end of file
diff --git a/projects/voxelization/resources/shaders/shadowBlur.comp b/projects/voxelization/resources/shaders/shadowBlur.comp
new file mode 100644
index 00000000..5daf72c6
--- /dev/null
+++ b/projects/voxelization/resources/shaders/shadowBlur.comp
@@ -0,0 +1,42 @@
+#version 450
+#extension GL_GOOGLE_include_directive : enable
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+layout(set=0, binding=0)                    uniform texture2D   srcTexture;
+layout(set=0, binding=1)                    uniform sampler     depthSampler;                
+layout(set=0, binding=2, rgba16)    uniform image2D     outImage;
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+void main(){
+
+    if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(outImage)))){
+        return;
+    }
+    ivec2 coord = ivec2(gl_GlobalInvocationID.xy);
+    
+    int blurRadius  = 0;
+    int minOffset   = -(blurRadius-1) / 2;
+    int maxOffset   = -minOffset;
+    
+    vec2 pixelSize = vec2(1) / textureSize(sampler2D(srcTexture, depthSampler), 0);
+    
+    float wTotal = 0;
+    vec4 moments = vec4(0);
+    
+    float weights1D[3] = { 0.5, 0.25, 0.125 };    // gaussian
+    
+    for(int x = minOffset; x <= maxOffset; x++){
+        for(int y = minOffset; y <= maxOffset; y++){
+            vec2 uv = (coord + ivec2(x, y)) * pixelSize;
+            uv      += 0.5 * pixelSize * sign(vec2(x, y)); // half pixel shift to take advantage of bilinear filtering
+            float w = weights1D[abs(x)] * weights1D[abs(y)];
+            moments += w * texture(sampler2D(srcTexture, depthSampler), uv);
+            wTotal  += w;
+        }
+    }
+    moments /= wTotal;
+    
+    imageStore(outImage, coord, moments);
+}
\ No newline at end of file
diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp
index 72add6d5..8b5a51fb 100644
--- a/projects/voxelization/src/ShadowMapping.cpp
+++ b/projects/voxelization/src/ShadowMapping.cpp
@@ -25,6 +25,16 @@ vkcv::ShaderProgram loadDepthToMomentsShader() {
 	return shader;
 }
 
+vkcv::ShaderProgram loadShadowBlurShader() {
+	vkcv::ShaderProgram shader;
+	vkcv::shader::GLSLCompiler compiler;
+	compiler.compile(vkcv::ShaderStage::COMPUTE, "resources/shaders/shadowBlur.comp",
+		[&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
+		shader.addShader(shaderStage, path);
+	});
+	return shader;
+}
+
 glm::mat4 computeShadowViewProjectionMatrix(
 	const glm::vec3&            lightDirection, 
 	const vkcv::camera::Camera& camera, 
@@ -121,6 +131,7 @@ const vkcv::Multisampling   msaa                    = vkcv::Multisampling::MSAA4
 ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vertexLayout) : 
 	m_corePtr(corePtr),
 	m_shadowMap(corePtr->createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution, 1, false, true)),
+	m_shadowMapIntermediate(corePtr->createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution, 1, false, true)),
 	m_shadowMapDepth(corePtr->createImage(shadowMapDepthFormat, shadowMapResolution, shadowMapResolution, 1, false, false, false, msaa)),
 	m_lightInfoBuffer(corePtr->createBuffer<LightInfo>(vkcv::BufferType::UNIFORM, sizeof(glm::vec3))){
 
@@ -162,8 +173,19 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert
 	vkcv::DescriptorWrites depthToMomentDescriptorWrites;
 	depthToMomentDescriptorWrites.sampledImageWrites    = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapDepth.getHandle()) };
 	depthToMomentDescriptorWrites.samplerWrites         = { vkcv::SamplerDescriptorWrite(1, m_shadowSampler) };
-	depthToMomentDescriptorWrites.storageImageWrites    = { vkcv::StorageImageDescriptorWrite(2, m_shadowMap.getHandle()) };
+	depthToMomentDescriptorWrites.storageImageWrites    = { vkcv::StorageImageDescriptorWrite(2, m_shadowMapIntermediate.getHandle()) };
 	corePtr->writeDescriptorSet(m_depthToMomentsDescriptorSet, depthToMomentDescriptorWrites);
+
+	// shadow blur
+	vkcv::ShaderProgram shadowBlurShader    = loadShadowBlurShader();
+	m_shadowBlurDescriptorSet               = corePtr->createDescriptorSet(shadowBlurShader.getReflectedDescriptors()[0]);
+	m_shadowBlurPipe                        = corePtr->createComputePipeline(shadowBlurShader, { corePtr->getDescriptorSet(m_shadowBlurDescriptorSet).layout });
+
+	vkcv::DescriptorWrites shadowBlurDescriptorWrites;
+	shadowBlurDescriptorWrites.sampledImageWrites   = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapIntermediate.getHandle()) };
+	shadowBlurDescriptorWrites.samplerWrites        = { vkcv::SamplerDescriptorWrite(1, m_shadowSampler) };
+	shadowBlurDescriptorWrites.storageImageWrites   = { vkcv::StorageImageDescriptorWrite(2, m_shadowMap.getHandle()) };
+	corePtr->writeDescriptorSet(m_shadowBlurDescriptorSet, shadowBlurDescriptorWrites);
 }
 
 void ShadowMapping::recordShadowMapRendering(
@@ -172,8 +194,6 @@ void ShadowMapping::recordShadowMapRendering(
 	const glm::vec3&                    lightColor,
 	float                               lightStrength,
 	float                               maxShadowDistance,
-	float                               exponentialWarpPositive,
-	float                               exponentialWarpNegative,
 	const std::vector<vkcv::Mesh>&      meshes,
 	const std::vector<glm::mat4>&       modelMatrices,
 	const vkcv::camera::Camera&         camera,
@@ -187,8 +207,6 @@ void ShadowMapping::recordShadowMapRendering(
 		std::cos(lightAngleRadian.x) * std::cos(lightAngleRadian.y),
 		std::sin(lightAngleRadian.x),
 		std::cos(lightAngleRadian.x) * std::sin(lightAngleRadian.y)));
-	lightInfo.exponentialWarpPositive = exponentialWarpPositive;
-	lightInfo.exponentialWarpNegative = exponentialWarpNegative;
 
 	lightInfo.lightMatrix = computeShadowViewProjectionMatrix(
 		lightInfo.direction,
@@ -226,13 +244,23 @@ void ShadowMapping::recordShadowMapRendering(
 
 	const uint32_t msaaSampleCount = msaaToSampleCount(msaa);
 
-	m_corePtr->prepareImageForStorage(cmdStream, m_shadowMap.getHandle());
+	m_corePtr->prepareImageForStorage(cmdStream, m_shadowMapIntermediate.getHandle());
 	m_corePtr->recordComputeDispatchToCmdStream(
 		cmdStream,
 		m_depthToMomentsPipe,
 		dispatchCount,
 		{ vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_depthToMomentsDescriptorSet).vulkanHandle) },
 		vkcv::PushConstantData((void*)&msaaSampleCount, sizeof(msaaSampleCount)));
+	m_corePtr->prepareImageForSampling(cmdStream, m_shadowMapIntermediate.getHandle());
+
+	// blur
+	m_corePtr->prepareImageForStorage(cmdStream, m_shadowMap.getHandle());
+	m_corePtr->recordComputeDispatchToCmdStream(
+		cmdStream,
+		m_shadowBlurPipe,
+		dispatchCount,
+		{ vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_shadowBlurDescriptorSet).vulkanHandle) },
+		vkcv::PushConstantData(nullptr, 0));
 	m_corePtr->prepareImageForSampling(cmdStream, m_shadowMap.getHandle());
 }
 
diff --git a/projects/voxelization/src/ShadowMapping.hpp b/projects/voxelization/src/ShadowMapping.hpp
index e9ad792c..2b25220b 100644
--- a/projects/voxelization/src/ShadowMapping.hpp
+++ b/projects/voxelization/src/ShadowMapping.hpp
@@ -13,8 +13,6 @@ struct LightInfo {
 	glm::vec3   sunColor;
 	float       sunStrength;
 	glm::mat4   lightMatrix;
-	float       exponentialWarpPositive;
-	float       exponentialWarpNegative;
 };
 
 class ShadowMapping {
@@ -27,8 +25,6 @@ public:
 		const glm::vec3&                    lightColor,
 		float                               lightStrength,
 		float                               maxShadowDistance,
-		float                               exponentialWarp,
-		float                               exponentialWarpNegative,
 		const std::vector<vkcv::Mesh>&      meshes,
 		const std::vector<glm::mat4>&       modelMatrices,
 		const vkcv::camera::Camera&         camera,
@@ -43,6 +39,7 @@ private:
 	vkcv::Core* m_corePtr;
 
 	vkcv::Image                 m_shadowMap;
+	vkcv::Image                 m_shadowMapIntermediate;
 	vkcv::Image                 m_shadowMapDepth;
 	vkcv::SamplerHandle         m_shadowSampler;
 	vkcv::Buffer<LightInfo>     m_lightInfoBuffer;
@@ -52,4 +49,7 @@ private:
 
 	vkcv::PipelineHandle        m_depthToMomentsPipe;
 	vkcv::DescriptorSetHandle   m_depthToMomentsDescriptorSet;
+
+	vkcv::PipelineHandle        m_shadowBlurPipe;
+	vkcv::DescriptorSetHandle   m_shadowBlurDescriptorSet;
 };
\ No newline at end of file
diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp
index 6c116738..a5395bac 100644
--- a/projects/voxelization/src/main.cpp
+++ b/projects/voxelization/src/main.cpp
@@ -361,8 +361,6 @@ int main(int argc, const char** argv) {
 	glm::vec3   lightColor                      = glm::vec3(1);
 	float       lightStrength                   = 25.f;
 	float       maxShadowDistance               = 30.f;
-	float       shadowExponentialWarpPositive   = 60.f;
-	float       shadowExponentialWarpNegative   = 60.f;
 
 	int     voxelVisualisationMip   = 0;
 	float   voxelizationExtent      = 30.f;
@@ -427,8 +425,6 @@ int main(int argc, const char** argv) {
 			lightColor,
 			lightStrength,
 			maxShadowDistance,
-			shadowExponentialWarpPositive,
-			shadowExponentialWarpNegative,
 			meshes,
 			modelMatrices,
 			cameraManager.getActiveCamera(),
@@ -520,8 +516,6 @@ int main(int argc, const char** argv) {
 		ImGui::DragFloat("Sun strength",            &lightStrength);
 		ImGui::DragFloat("Max shadow distance",     &maxShadowDistance);
 		maxShadowDistance = std::max(maxShadowDistance, 1.f);
-		ImGui::DragFloat("Shadow exponential warp positive", &shadowExponentialWarpPositive);
-		ImGui::DragFloat("Shadow exponential warp negative", &shadowExponentialWarpNegative);
 
 		ImGui::Checkbox("Draw voxel visualisation", &renderVoxelVis);
 		ImGui::SliderInt("Visualisation mip",       &voxelVisualisationMip, 0, 7);
-- 
GitLab