diff --git a/projects/indirect_dispatch/resources/shaders/motionBlur.comp b/projects/indirect_dispatch/resources/shaders/motionBlur.comp index 62bae1308a023ae953322a3d99b76a06b3d524ed..5c1960162a00d4d2689e218641431c08565bc8fa 100644 --- a/projects/indirect_dispatch/resources/shaders/motionBlur.comp +++ b/projects/indirect_dispatch/resources/shaders/motionBlur.comp @@ -1,5 +1,6 @@ #version 440 #extension GL_GOOGLE_include_directive : enable +#include "motionBlurConfig.inc" layout(set=0, binding=0) uniform texture2D inColor; layout(set=0, binding=1) uniform texture2D inDepth; @@ -10,7 +11,7 @@ layout(set=0, binding=4, 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 motionFactor; // computed from delta time and shutter speed + float motionScaleFactor; // computed from delta time and shutter speed float minVelocity; // camera planes are needed to linearize depth float cameraNearPlane; @@ -64,11 +65,26 @@ float computeSampleWeigth(SampleData mainPixel, SampleData samplePixel){ return weight; } +// see "A Reconstruction Filter for Plausible Motion Blur", section 2.2 +vec2 rescaleMotion(vec2 motion){ + // every frame a pixel should blur over the distance it moves + // as we blur in two directions (where it was and where it will be) we must half the motion + vec2 motionHalf = motion * 0.5; + vec2 motionScaled = motionHalf * motionScaleFactor; // scale factor contains shutter speed and delta time + + // pixels are anisotropic so the smaller dimension is used, so the clamping is conservative + float pixelSize = 1.f / max(imageSize(outImage).x, imageSize(outImage).y); + float velocity = length(motionScaled); + float epsilon = 0.0001; + // this clamps the motion to not exceed the radius given by the motion tile size + return motionScaled * max(0.5 * pixelSize, min(velocity, motionTileSize * pixelSize)) / (velocity + epsilon); +} + SampleData loadSampleData(vec2 uv){ SampleData data; data.uv = uv; - data.motion = texture(sampler2D(inMotion, nearestSampler), uv).rg * motionFactor; + data.motion = rescaleMotion(texture(sampler2D(inMotion, nearestSampler), uv).rg); data.velocity = length(data.motion); data.depthLinear = texture(sampler2D(inDepth, nearestSampler), uv).r; data.depthLinear = linearizeDepth(data.depthLinear, cameraNearPlane, cameraFarPlane); @@ -105,12 +121,6 @@ void main(){ imageStore(outImage, coord, vec4(color, 0.f)); return; } - - // TODO: check if a max velocity is necessary - // // TODO: should be configurable by user or computed by velocity tile sizes - // const float maxBlurDistance = 0.075; - // if(mainPixel.velocity > maxBlurDistance) - // motion *= maxBlurDistance / velocity; vec3 color = vec3(0); float weightSum = 0; diff --git a/projects/indirect_dispatch/resources/shaders/motionBlurConfig.inc b/projects/indirect_dispatch/resources/shaders/motionBlurConfig.inc new file mode 100644 index 0000000000000000000000000000000000000000..fdd915c8aa857ee3bf91fe31d8f6a224bfe85612 --- /dev/null +++ b/projects/indirect_dispatch/resources/shaders/motionBlurConfig.inc @@ -0,0 +1 @@ +const int motionTileSize = 20; \ No newline at end of file diff --git a/projects/indirect_dispatch/resources/shaders/motionVectorMax.comp b/projects/indirect_dispatch/resources/shaders/motionVectorMax.comp index 725fc3f4abd8fb2c07b3a0643f603ea9929bcbcb..65a6186c1b3af7804f9639fbe28655202b57c1ba 100644 --- a/projects/indirect_dispatch/resources/shaders/motionVectorMax.comp +++ b/projects/indirect_dispatch/resources/shaders/motionVectorMax.comp @@ -1,5 +1,6 @@ #version 440 #extension GL_GOOGLE_include_directive : enable +#include "motionBlurConfig.inc" layout(set=0, binding=0) uniform texture2D inMotion; layout(set=0, binding=1) uniform sampler textureSampler; @@ -7,8 +8,6 @@ layout(set=0, binding=2, rgba8) uniform image2D outMotionMax; layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; -const int motionTileSize = 20; - void main(){ ivec2 outImageRes = imageSize(outMotionMax); diff --git a/projects/indirect_dispatch/src/App.cpp b/projects/indirect_dispatch/src/App.cpp index 88fdca590a770f3ebb09e357716ad860dc5cc662..3b9992ed467145bfa203859c16b05a4f25c69391 100644 --- a/projects/indirect_dispatch/src/App.cpp +++ b/projects/indirect_dispatch/src/App.cpp @@ -89,7 +89,7 @@ void App::run() { float objectVerticalSpeed = 5; float motionBlurMinVelocity = 0.001; - int cameraShutterSpeedInverse = 30; + int cameraShutterSpeedInverse = 24; float motionVectorVisualisationRange = 0.008; glm::mat4 mvpPrevious = glm::mat4(1.f);