From f59d2c33f5bcce1df0fd8bd2d90f727f8edfaefa Mon Sep 17 00:00:00 2001
From: Alexander Gauggel <agauggel@uni-koblenz.de>
Date: Thu, 12 Aug 2021 16:37:46 +0200
Subject: [PATCH] [#106] Better motion vector visualisation

---
 .../resources/shaders/gammaCorrection.comp    |  3 -
 .../shaders/motionVectorVisualisation.comp    | 29 ++++++++
 projects/indirect_dispatch/src/App.cpp        | 71 ++++++++++++++-----
 projects/indirect_dispatch/src/App.hpp        |  1 +
 4 files changed, 83 insertions(+), 21 deletions(-)
 create mode 100644 projects/indirect_dispatch/resources/shaders/motionVectorVisualisation.comp

diff --git a/projects/indirect_dispatch/resources/shaders/gammaCorrection.comp b/projects/indirect_dispatch/resources/shaders/gammaCorrection.comp
index d1c3c049..7a6e129d 100644
--- a/projects/indirect_dispatch/resources/shaders/gammaCorrection.comp
+++ b/projects/indirect_dispatch/resources/shaders/gammaCorrection.comp
@@ -18,9 +18,6 @@ void main(){
     vec2 uv             = vec2(coord) / outImageRes;
     vec3 linearColor    = texture(sampler2D(inTexture, textureSampler), uv).rgb;
     
-    // in case of motion vector visualisation negative values are possible
-    linearColor         = abs(linearColor); 
-    
     vec3 gammaCorrected = pow(linearColor, vec3(1 / 2.2));
 
     imageStore(outImage, coord, vec4(gammaCorrected, 0.f));
diff --git a/projects/indirect_dispatch/resources/shaders/motionVectorVisualisation.comp b/projects/indirect_dispatch/resources/shaders/motionVectorVisualisation.comp
new file mode 100644
index 00000000..0fac2389
--- /dev/null
+++ b/projects/indirect_dispatch/resources/shaders/motionVectorVisualisation.comp
@@ -0,0 +1,29 @@
+#version 440
+#extension GL_GOOGLE_include_directive : enable
+
+layout(set=0, binding=0)                    uniform texture2D   inMotion;
+layout(set=0, binding=1)                    uniform sampler     textureSampler;
+layout(set=0, binding=2, r11f_g11f_b10f)    uniform image2D     outImage;
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+layout( push_constant ) uniform constants{
+    float range;
+};
+
+void main(){
+
+    ivec2 outImageRes = imageSize(outImage);
+    ivec2 coord       = ivec2(gl_GlobalInvocationID.xy);
+
+    if(any(greaterThanEqual(coord, outImageRes)))
+        return;
+   
+    vec2 uv                     = vec2(coord) / outImageRes;
+    vec2 motionVector           = texture(sampler2D(inMotion, textureSampler), uv).rg;
+    vec2 motionVectorNormalized = clamp(motionVector / range, -1, 1);
+    
+    vec2 color  = motionVectorNormalized * 0.5 + 0.5;
+
+    imageStore(outImage, coord, vec4(color, 0.5, 0));
+}
\ No newline at end of file
diff --git a/projects/indirect_dispatch/src/App.cpp b/projects/indirect_dispatch/src/App.cpp
index 68ff0060..d3afc681 100644
--- a/projects/indirect_dispatch/src/App.cpp
+++ b/projects/indirect_dispatch/src/App.cpp
@@ -47,6 +47,9 @@ bool App::initialize() {
 	if (!loadComputePass(m_core, "resources/shaders/motionVectorMaxNeighbourhood.comp", &m_motionVectorMaxNeighbourhoodPass))
 		return false;
 
+	if (!loadComputePass(m_core, "resources/shaders/motionVectorVisualisation.comp", &m_motionVectorVisualisationPass))
+		return false;
+
 	if (!loadMesh(m_core, "resources/models/sphere.gltf", & m_sphereMesh))
 		return false;
 
@@ -103,9 +106,10 @@ void App::run() {
 	eDebugView          debugView       = eDebugView::None;
 	eMotionBlurInput    motionBlurInput = eMotionBlurInput::MotionVectorMaxTileNeighbourhood;
 
-	float   objectVerticalSpeed         = 0.005;
-	float   motionBlurMinVelocity       = 0.001;
-	int     cameraShutterSpeedInverse   = 30;
+	float   objectVerticalSpeed             = 0.005;
+	float   motionBlurMinVelocity           = 0.001;
+	int     cameraShutterSpeedInverse       = 30;
+	float   motionVectorVisualisationRange  = 0.008;
 
 	glm::mat4 mvpPrevious               = glm::mat4(1.f);
 	glm::mat4 viewProjectionPrevious    = m_cameraManager.getActiveCamera().getMVP();
@@ -301,24 +305,51 @@ void App::run() {
 			{ vkcv::DescriptorSetUsage(0, m_core.getDescriptorSet(m_motionBlurDummyPass.descriptorSet).vulkanHandle) },
 			motionBlurPushConstants);
 
-		// gamma correction
-		vkcv::ImageHandle gammaCorrectionInput;
-		if (debugView == eDebugView::None)
-			gammaCorrectionInput = m_renderTargets.motionBlurOutput;
-		else if (debugView == eDebugView::MotionVector)
-			gammaCorrectionInput = m_renderTargets.motionBuffer;
-		else if (debugView == eDebugView::MotionVectorMaxTile)
-			gammaCorrectionInput = m_renderTargets.motionMax;
-		else if (debugView == eDebugView::MotionVectorMaxTileNeighbourhood)
-			gammaCorrectionInput = m_renderTargets.motionMaxNeighbourhood;
-		else {
-			vkcv_log(vkcv::LogLevel::ERROR, "Unknown eDebugView enum value");
-			gammaCorrectionInput = m_renderTargets.motionBlurOutput;
+		// motion vector debug visualisation
+		// writes to motion blur output
+		if (debugView != eDebugView::None) {
+			vkcv::ImageHandle visualisationInput;
+			if (debugView == eDebugView::MotionVector)
+				visualisationInput = m_renderTargets.motionBuffer;
+			else if (debugView == eDebugView::MotionVectorMaxTile)
+				visualisationInput = m_renderTargets.motionMax;
+			else if (debugView == eDebugView::MotionVectorMaxTileNeighbourhood)
+				visualisationInput = m_renderTargets.motionMaxNeighbourhood;
+			else {
+				vkcv_log(vkcv::LogLevel::ERROR, "Unknown eDebugView enum value");
+				visualisationInput = m_renderTargets.motionBlurOutput;
+			}
+
+			vkcv::DescriptorWrites motionVectorVisualisationDescriptorWrites;
+			motionVectorVisualisationDescriptorWrites.sampledImageWrites = {
+				vkcv::SampledImageDescriptorWrite(0, visualisationInput) };
+			motionVectorVisualisationDescriptorWrites.samplerWrites = {
+				vkcv::SamplerDescriptorWrite(1, m_linearSampler) };
+			motionVectorVisualisationDescriptorWrites.storageImageWrites = {
+				vkcv::StorageImageDescriptorWrite(2, m_renderTargets.motionBlurOutput) };
+
+			m_core.writeDescriptorSet(
+				m_motionVectorVisualisationPass.descriptorSet, 
+				motionVectorVisualisationDescriptorWrites);
+
+			m_core.prepareImageForSampling(cmdStream, visualisationInput);
+			m_core.prepareImageForStorage(cmdStream, m_renderTargets.motionBlurOutput);
+
+			vkcv::PushConstants motionVectorVisualisationPushConstants(sizeof(float));
+			motionVectorVisualisationPushConstants.appendDrawcall(motionVectorVisualisationRange);
+
+			m_core.recordComputeDispatchToCmdStream(
+				cmdStream,
+				m_motionVectorVisualisationPass.pipeline,
+				fullScreenImageDispatch,
+				{ vkcv::DescriptorSetUsage(0, m_core.getDescriptorSet(m_motionVectorVisualisationPass.descriptorSet).vulkanHandle) },
+				motionVectorVisualisationPushConstants);
 		}
 
+		// gamma correction
 		vkcv::DescriptorWrites gammaCorrectionDescriptorWrites;
 		gammaCorrectionDescriptorWrites.sampledImageWrites = {
-			vkcv::SampledImageDescriptorWrite(0, gammaCorrectionInput) };
+			vkcv::SampledImageDescriptorWrite(0, m_renderTargets.motionBlurOutput) };
 		gammaCorrectionDescriptorWrites.samplerWrites = {
 			vkcv::SamplerDescriptorWrite(1, m_linearSampler) };
 		gammaCorrectionDescriptorWrites.storageImageWrites = {
@@ -326,7 +357,7 @@ void App::run() {
 
 		m_core.writeDescriptorSet(m_gammaCorrectionPass.descriptorSet, gammaCorrectionDescriptorWrites);
 
-		m_core.prepareImageForSampling(cmdStream, gammaCorrectionInput);
+		m_core.prepareImageForSampling(cmdStream, m_renderTargets.motionBlurOutput);
 		m_core.prepareImageForStorage (cmdStream, swapchainInput);
 
 		m_core.recordComputeDispatchToCmdStream(
@@ -348,6 +379,10 @@ void App::run() {
 			debugViewLabels,
 			static_cast<int>(eDebugView::OptionCount));
 
+		if (debugView != eDebugView::None) {
+			ImGui::InputFloat("Motion vector visualisation range", &motionVectorVisualisationRange);
+		}
+
 		ImGui::Combo(
 			"Motion blur input",
 			reinterpret_cast<int*>(&motionBlurInput),
diff --git a/projects/indirect_dispatch/src/App.hpp b/projects/indirect_dispatch/src/App.hpp
index 9bbdde94..5f4fd7eb 100644
--- a/projects/indirect_dispatch/src/App.hpp
+++ b/projects/indirect_dispatch/src/App.hpp
@@ -30,6 +30,7 @@ private:
 	ComputePassHandles m_motionBlurDummyPass;
 	ComputePassHandles m_motionVectorMaxPass;
 	ComputePassHandles m_motionVectorMaxNeighbourhoodPass;
+	ComputePassHandles m_motionVectorVisualisationPass;
 
 	RenderTargets       m_renderTargets;
 	vkcv::SamplerHandle m_linearSampler;
-- 
GitLab