From ec9375f2567966db05159e9821e5729650b1c7c8 Mon Sep 17 00:00:00 2001 From: Anis Benyoub Date: Fri, 8 Jan 2021 10:28:35 +0100 Subject: [PATCH] Fixed the condition on temporal accumulation in the reflection denoiser (case 1303504). --- .../CHANGELOG.md | 1 + .../ScreenSpaceLighting/SSGIDenoiser.compute | 10 ++-------- .../Shaders/Denoising/DenoisingUtils.hlsl | 16 ++++++++++++++++ .../Shaders/Denoising/DenoisingUtils.hlsl.meta | 10 ++++++++++ .../Shaders/Denoising/DiffuseDenoiser.compute | 7 ++----- .../Shaders/Denoising/ReflectionDenoiser.compute | 6 +++++- .../Shaders/Denoising/TemporalFilter.compute | 11 ++--------- 7 files changed, 38 insertions(+), 23 deletions(-) create mode 100644 com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/DenoisingUtils.hlsl create mode 100644 com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/DenoisingUtils.hlsl.meta diff --git a/com.unity.render-pipelines.high-definition/CHANGELOG.md b/com.unity.render-pipelines.high-definition/CHANGELOG.md index 797b99b9e93..d04e50fb560 100644 --- a/com.unity.render-pipelines.high-definition/CHANGELOG.md +++ b/com.unity.render-pipelines.high-definition/CHANGELOG.md @@ -33,6 +33,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Fixed an issue with half res ssgi upscale. - Fixed Clearcoat on Stacklit or Lit breaks when URP is imported into the project (case 1297806) - Fixed timing issues with accumulation motion blur +- Fixed the condition on temporal accumulation in the reflection denoiser (case 1303504). ### Changed - Removed the material pass probe volumes evaluation mode. diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/SSGIDenoiser.compute b/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/SSGIDenoiser.compute index 97c7167676d..a5409ebf515 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/SSGIDenoiser.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/SSGIDenoiser.compute @@ -16,6 +16,7 @@ #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Builtin/BuiltinData.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/TemporalAntialiasing.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/BilateralFilter.hlsl" +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/DenoisingUtils.hlsl" // #pragma only_renderers d3d11 // #pragma enable_d3d11_debug_symbols @@ -43,10 +44,6 @@ RW_TEXTURE2D_X(float4, _OutputFilteredBuffer1); #define SPATIAL_FILTER_SIGMA_RATIO 0.9 #define DEPTH_WEIGHT_MULTIPLIER 100.0f #define NORMAL_WEIGHT_MULTIPLIER 5.0 -// The maximal world space distance for temporal reprojection -#define MAX_WORLD_SPACE_DISTANCE 0.1 -// The maximal pixel reprojection distance -#define PIXEL_RADIUS_TOLERANCE_THRESHOLD 4 // Number of samples to compelte the accumulation loop #define NUM_SAMPLE_LOOP 8.0 @@ -234,10 +231,7 @@ void TEMPORAL_FILTER(uint3 dispatchThreadId : SV_DispatchThreadID DecodeFromNormalBuffer(centerCoord, normalData); // Compute the max reprojection distance. This is evaluated as the max between a fixed radius value and an approximation of the footprint of the pixel. - const float3 viewWS = GetWorldSpaceNormalizeViewDir(posInputs.positionWS); - float parallelPixelFootPrint = _PixelSpreadAngleTangent * length(posInputs.positionWS); - float realPixelFootPrint = parallelPixelFootPrint / abs(dot(normalData.normalWS, viewWS)); - float maxRadius = max(MAX_WORLD_SPACE_DISTANCE, realPixelFootPrint * PIXEL_RADIUS_TOLERANCE_THRESHOLD); + float maxRadius = ComputeMaxReprojectionWorldRadius(posInputs.positionWS, normalData.normalWS, _PixelSpreadAngleTangent); // Is it too far from the current position? if (length(historyPositionWS - posInputs.positionWS) > maxRadius) diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/DenoisingUtils.hlsl b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/DenoisingUtils.hlsl new file mode 100644 index 00000000000..f9acfbac2b9 --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/DenoisingUtils.hlsl @@ -0,0 +1,16 @@ + +#define MAX_REPROJECTION_DISTANCE 0.1 +#define MAX_PIXEL_TOLERANCE 4 + +float ComputeMaxReprojectionWorldRadius(float3 positionWS, float3 normalWS, float pixelSpreadAngleTangent, float maxDistance, float pixelTolerance) +{ + const float3 viewWS = GetWorldSpaceNormalizeViewDir(positionWS); + float parallelPixelFootPrint = pixelSpreadAngleTangent * length(positionWS); + float realPixelFootPrint = parallelPixelFootPrint / abs(dot(normalWS, viewWS)); + return max(maxDistance, realPixelFootPrint * pixelTolerance); +} + +float ComputeMaxReprojectionWorldRadius(float3 positionWS, float3 normalWS, float pixelSpreadAngleTangent) +{ + return ComputeMaxReprojectionWorldRadius(positionWS, normalWS, pixelSpreadAngleTangent, MAX_REPROJECTION_DISTANCE, MAX_PIXEL_TOLERANCE); +} diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/DenoisingUtils.hlsl.meta b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/DenoisingUtils.hlsl.meta new file mode 100644 index 00000000000..b0a88caffee --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/DenoisingUtils.hlsl.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 07e251d6348c2124fa304daa26ea9a26 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + preprocessorOverride: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/DiffuseDenoiser.compute b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/DiffuseDenoiser.compute index b53383d5a9c..3f20dc6f44e 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/DiffuseDenoiser.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/DiffuseDenoiser.compute @@ -22,6 +22,7 @@ #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingSampling.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracing.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/BilateralFilter.hlsl" +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/DenoisingUtils.hlsl" // Tile size of this compute shaders #define DIFFUSE_DENOISER_TILE_SIZE 8 @@ -80,11 +81,7 @@ void BILATERAL_FILTER(uint3 dispatchThreadId : SV_DispatchThreadID, uint2 groupT #endif // Compute the radius of the filter. This is evaluated as the max between a fixed radius value and an approximation of the footprint of the pixel - const float parallelPixelFootPrint = _PixelSpreadAngleTangent * length(center.position); - // Compute the view in world space - const float3 viewWS = GetWorldSpaceNormalizeViewDir(center.position); - const float realPixelFootPrint = parallelPixelFootPrint / abs(dot(center.normal, viewWS)); - const float denoisingRadius = max(_DenoiserFilterRadius, realPixelFootPrint * PIXEL_RADIUS_TOLERANCE_THRESHOLD); + const float denoisingRadius = ComputeMaxReprojectionWorldRadius(center.position, center.normal, _PixelSpreadAngleTangent, _DenoiserFilterRadius, PIXEL_RADIUS_TOLERANCE_THRESHOLD); // Compute the sigma value const float sigma = 0.9 * denoisingRadius; diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/ReflectionDenoiser.compute b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/ReflectionDenoiser.compute index 5f35c1bd5f2..3651b024774 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/ReflectionDenoiser.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/ReflectionDenoiser.compute @@ -17,6 +17,7 @@ #include "Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/TemporalAntialiasing.hlsl" #define BILATERAL_ROUGHNESS #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/BilateralFilter.hlsl" +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/DenoisingUtils.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracing.cs.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl" @@ -126,8 +127,11 @@ void TEMPORAL_ACCUMULATION(uint3 dispatchThreadId : SV_DispatchThreadID, uint2 g // Compute the world space position (from previous frame) float3 historyPositionWS = ComputeWorldSpacePosition(posInput.positionNDC - velocity, historyDepth, UNITY_MATRIX_PREV_I_VP); + // Compute the max world radius that we consider acceptable for history reprojection + float maxRadius = ComputeMaxReprojectionWorldRadius(posInput.positionWS, normalData.normalWS, _PixelSpreadAngleTangent); + // Is it too far from the current position? - if (length(historyPositionWS - posInput.positionWS) > 0.1) + if (length(historyPositionWS - posInput.positionWS) > maxRadius) canBeReprojected = false; if (canBeReprojected && sampleCount != 0.0) diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/TemporalFilter.compute b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/TemporalFilter.compute index cd472cdabd0..3aaddc280f3 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/TemporalFilter.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/TemporalFilter.compute @@ -23,6 +23,7 @@ #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/NormalBuffer.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Builtin/BuiltinData.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/TemporalAntialiasing.hlsl" +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Denoising/DenoisingUtils.hlsl" #pragma only_renderers d3d11 // #pragma enable_d3d11_debug_symbols @@ -45,10 +46,6 @@ float _PixelSpreadAngleTangent; // Value that tells us if the current history should be discarded based on scene-level data float _HistoryValidity; -// The maximal world space distance for temporal reprojection -#define MAX_WORLD_SPACE_DISTANCE 0.1 -// The maximal pixel reprojection distance -#define PIXEL_RADIUS_TOLERANCE_THRESHOLD 4 // The maximal normal difference threshold #define MAX_NORMAL_DIFFERENCE 0.65 // The minimal motion distance @@ -95,7 +92,6 @@ void ValidateHistory(uint3 dispatchThreadId : SV_DispatchThreadID, uint2 groupTh return; } - // Real the normal data for this pixel NormalData normalData; DecodeFromNormalBuffer(centerCoord, normalData); @@ -104,10 +100,7 @@ void ValidateHistory(uint3 dispatchThreadId : SV_DispatchThreadID, uint2 groupTh float3 historyPositionWS = ComputeWorldSpacePosition(posInputs.positionNDC - velocity, historyDepth, UNITY_MATRIX_PREV_I_VP); // Compute the max reprojection distance. This is evaluated as the max between a fixed radius value and an approximation of the footprint of the pixel. - const float3 viewWS = GetWorldSpaceNormalizeViewDir(posInputs.positionWS); - float parallelPixelFootPrint = _PixelSpreadAngleTangent * length(posInputs.positionWS); - float realPixelFootPrint = parallelPixelFootPrint / abs(dot(normalData.normalWS, viewWS)); - float maxRadius = max(MAX_WORLD_SPACE_DISTANCE, realPixelFootPrint * PIXEL_RADIUS_TOLERANCE_THRESHOLD); + float maxRadius = ComputeMaxReprojectionWorldRadius(posInputs.positionWS, normalData.normalWS, _PixelSpreadAngleTangent); // Is it too far from the current position? if (length(historyPositionWS - posInputs.positionWS) > maxRadius)