From b5f2879871b32cc098fa0dfa9794d82afe74506a Mon Sep 17 00:00:00 2001
From: Alexander Gauggel <agauggel@uni-koblenz.de>
Date: Mon, 16 Aug 2021 23:14:16 +0200
Subject: [PATCH] [#106] Replaced motion blur noise with dither to reduce
 visible noise

---
 .../resources/shaders/motionBlur.comp         | 28 +++++++++----------
 .../shaders/motionVectorMaxNeighbourhood.comp |  2 --
 projects/indirect_dispatch/src/App.cpp        |  2 --
 3 files changed, 13 insertions(+), 19 deletions(-)

diff --git a/projects/indirect_dispatch/resources/shaders/motionBlur.comp b/projects/indirect_dispatch/resources/shaders/motionBlur.comp
index 233947d1..62bae130 100644
--- a/projects/indirect_dispatch/resources/shaders/motionBlur.comp
+++ b/projects/indirect_dispatch/resources/shaders/motionBlur.comp
@@ -15,7 +15,6 @@ layout( push_constant ) uniform constants{
     // camera planes are needed to linearize depth
     float cameraNearPlane;
     float cameraFarPlane;
-    float time;
 };
 
 float linearizeDepth(float depth, float near, float far){
@@ -77,19 +76,16 @@ SampleData loadSampleData(vec2 uv){
     return data;
 }
 
-// simple hash/noise function from: https://www.shadertoy.com/view/ttc3zr
-uint murmurHash12(uvec2 src) {
-    const uint M = 0x5bd1e995u;
-    uint h = 1190494759u;
-    src *= M; src ^= src>>24u; src *= M;
-    h *= M; h ^= src.x; h *= M; h ^= src.y;
-    h ^= h>>13u; h *= M; h ^= h>>15u;
-    return h;
-}
-
-float hash12(vec2 src) {
-    uint h = murmurHash12(floatBitsToUint(src));
-    return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0;
+// simple binary dither pattern
+// could be optimized to avoid modulo and branch
+float dither(ivec2 coord){
+    
+    int ditherSize = 4;
+    
+    bool x = coord.x % ditherSize < (ditherSize / 2);
+    bool y = coord.y % ditherSize < (ditherSize / 2);
+    
+    return x ^^ y ? 1 : 0;
 }
 
 void main(){
@@ -126,7 +122,9 @@ void main(){
     vec2 uvEnd      = clamp(uv + mainPixel.motion, 0, 1);
     
     // samples are placed evenly, but the entire filter is jittered
-    float random = hash12(uv + time) - 0.5; // in range [-0.5, 0.5]
+    // dither returns either 0 or 1
+    // the sampleUV code expects an offset in range [-0.5, 0.5], so the dither is rescaled to a binary -0.25/0.25
+    float random = dither(coord) * 0.5 - 0.25;
     
     for(int i = 0; i < sampleCount; i++){
         vec2    sampleUV    = mix(uvStart, uvEnd, (i + random + 1) / float(sampleCount + 1));
diff --git a/projects/indirect_dispatch/resources/shaders/motionVectorMaxNeighbourhood.comp b/projects/indirect_dispatch/resources/shaders/motionVectorMaxNeighbourhood.comp
index 85d45235..90f9acce 100644
--- a/projects/indirect_dispatch/resources/shaders/motionVectorMaxNeighbourhood.comp
+++ b/projects/indirect_dispatch/resources/shaders/motionVectorMaxNeighbourhood.comp
@@ -7,8 +7,6 @@ layout(set=0, binding=2, rgba8) uniform image2D     outMotionMaxNeighbourhood;
 
 layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
 
-const int motionTileSize = 8;
-
 void main(){
     
     ivec2 outImageRes       = imageSize(outMotionMaxNeighbourhood);
diff --git a/projects/indirect_dispatch/src/App.cpp b/projects/indirect_dispatch/src/App.cpp
index 0856173a..02442423 100644
--- a/projects/indirect_dispatch/src/App.cpp
+++ b/projects/indirect_dispatch/src/App.cpp
@@ -305,7 +305,6 @@ void App::run() {
 			float minVelocity;
 			float cameraNearPlane;
 			float cameraFarPlane;
-			float time;
 		};
 		MotionBlurConstantData motionBlurConstantData;
 
@@ -323,7 +322,6 @@ void App::run() {
 		m_cameraManager.getActiveCamera().getNearFar(cameraNear, cameraFar);
 		motionBlurConstantData.cameraNearPlane  = cameraNear;
 		motionBlurConstantData.cameraFarPlane   = cameraFar;
-		motionBlurConstantData.time             = fCurrentTime;
 
 		vkcv::PushConstants motionBlurPushConstants(sizeof(motionBlurConstantData));
 		motionBlurPushConstants.appendDrawcall(motionBlurConstantData);
-- 
GitLab