From 47c794626fb0f8a5f1d424e9e9b55803a060d4c9 Mon Sep 17 00:00:00 2001 From: Alexander Gauggel <agauggel@uni-koblenz.de> Date: Wed, 18 Aug 2021 17:12:31 +0200 Subject: [PATCH] [#106] Add jitter to motion tile lookup in motion blur to replace hard edges in blur with noise --- .../resources/shaders/motionBlur.comp | 21 ++++++++++++++++++- projects/indirect_dispatch/src/App.cpp | 7 +++++-- projects/indirect_dispatch/src/MotionBlur.cpp | 11 ++++++---- projects/indirect_dispatch/src/MotionBlur.hpp | 3 ++- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/projects/indirect_dispatch/resources/shaders/motionBlur.comp b/projects/indirect_dispatch/resources/shaders/motionBlur.comp index 43981689..d340d4d4 100644 --- a/projects/indirect_dispatch/resources/shaders/motionBlur.comp +++ b/projects/indirect_dispatch/resources/shaders/motionBlur.comp @@ -17,6 +17,7 @@ layout( push_constant ) uniform constants{ // camera planes are needed to linearize depth float cameraNearPlane; float cameraFarPlane; + float motionTileOffsetLength; }; float linearizeDepth(float depth, float near, float far){ @@ -111,6 +112,22 @@ float dither(ivec2 coord){ return x ^^ y ? 1 : 0; } +// from https://www.shadertoy.com/view/ttc3zr +uvec2 murmurHash22(uvec2 src) { + const uint M = 0x5bd1e995u; + uvec2 h = uvec2(1190494759u, 2147483647u); + 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; +} + +vec2 hash22(vec2 src) { + uvec2 h = murmurHash22(floatBitsToUint(src)); + return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0; +} + + void main(){ if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(outImage)))) @@ -120,7 +137,9 @@ void main(){ ivec2 coord = ivec2(gl_GlobalInvocationID.xy); vec2 uv = vec2(coord + 0.5) / textureRes; // + 0.5 to shift uv into pixel center - vec2 motionNeighbourhoodMax = processMotionVector(texture(sampler2D(inMotionNeighbourhoodMax, nearestSampler), uv).rg); + // the motion tile lookup is jittered, so the hard edges in the blur are replaced by noise + vec2 motionOffset = motionTileOffsetLength * (hash22(coord) * 2 - 1) / textureRes; + vec2 motionNeighbourhoodMax = processMotionVector(texture(sampler2D(inMotionNeighbourhoodMax, nearestSampler), uv + motionOffset).rg); SampleData mainPixel = loadSampleData(uv); diff --git a/projects/indirect_dispatch/src/App.cpp b/projects/indirect_dispatch/src/App.cpp index db97d57c..ecdbd50e 100644 --- a/projects/indirect_dispatch/src/App.cpp +++ b/projects/indirect_dispatch/src/App.cpp @@ -96,7 +96,8 @@ void App::run() { eMotionVectorVisualisationMode motionVectorVisualisationMode = eMotionVectorVisualisationMode::None; eMotionVectorMode motionBlurMotionMode = eMotionVectorMode::MaxTileNeighbourhood; - bool freezeFrame = false; + bool freezeFrame = false; + float motionBlurTileOffsetLength = 10; float objectVerticalSpeed = 5; float objectAmplitude = 0; float objectMeanHeight = 1; @@ -276,7 +277,8 @@ void App::run() { cameraNear, cameraFar, fDeltaTimeSeconds, - cameraShutterSpeedInverse); + cameraShutterSpeedInverse, + motionBlurTileOffsetLength); } else { eMotionVectorMode debugViewMode; @@ -331,6 +333,7 @@ void App::run() { ImGui::Begin("Settings"); ImGui::Checkbox("Freeze frame", &freezeFrame); + ImGui::InputFloat("Motion tile offset length", &motionBlurTileOffsetLength); ImGui::Combo( "Debug view", diff --git a/projects/indirect_dispatch/src/MotionBlur.cpp b/projects/indirect_dispatch/src/MotionBlur.cpp index a731b8b9..49e8b288 100644 --- a/projects/indirect_dispatch/src/MotionBlur.cpp +++ b/projects/indirect_dispatch/src/MotionBlur.cpp @@ -58,7 +58,8 @@ vkcv::ImageHandle MotionBlur::render( const float cameraNear, const float cameraFar, const float deltaTimeSeconds, - const float cameraShutterSpeedInverse) { + const float cameraShutterSpeedInverse, + const float motionTileOffsetLength) { computeMotionTiles(cmdStream, motionBufferFullRes); @@ -93,14 +94,16 @@ vkcv::ImageHandle MotionBlur::render( float motionFactor; float cameraNearPlane; float cameraFarPlane; + float motionTileOffsetLength; }; MotionBlurConstantData motionBlurConstantData; const float deltaTimeMotionBlur = deltaTimeSeconds; - motionBlurConstantData.motionFactor = 1 / (deltaTimeMotionBlur * cameraShutterSpeedInverse); - motionBlurConstantData.cameraNearPlane = cameraNear; - motionBlurConstantData.cameraFarPlane = cameraFar; + motionBlurConstantData.motionFactor = 1 / (deltaTimeMotionBlur * cameraShutterSpeedInverse); + motionBlurConstantData.cameraNearPlane = cameraNear; + motionBlurConstantData.cameraFarPlane = cameraFar; + motionBlurConstantData.motionTileOffsetLength = motionTileOffsetLength; vkcv::PushConstants motionBlurPushConstants(sizeof(motionBlurConstantData)); motionBlurPushConstants.appendDrawcall(motionBlurConstantData); diff --git a/projects/indirect_dispatch/src/MotionBlur.hpp b/projects/indirect_dispatch/src/MotionBlur.hpp index a6232125..b90cdfa4 100644 --- a/projects/indirect_dispatch/src/MotionBlur.hpp +++ b/projects/indirect_dispatch/src/MotionBlur.hpp @@ -31,7 +31,8 @@ public: const float cameraNear, const float cameraFar, const float deltaTimeSeconds, - const float cameraShutterSpeedInverse); + const float cameraShutterSpeedInverse, + const float motionTileOffsetLength); vkcv::ImageHandle renderMotionVectorVisualisation( const vkcv::CommandStreamHandle cmdStream, -- GitLab