diff --git a/Include/NRD.h b/Include/NRD.h index 3c2573d8..8f08e97c 100644 --- a/Include/NRD.h +++ b/Include/NRD.h @@ -29,8 +29,8 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #define NRD_VERSION_MAJOR 3 #define NRD_VERSION_MINOR 4 -#define NRD_VERSION_BUILD 2 -#define NRD_VERSION_DATE "18 August 2022" +#define NRD_VERSION_BUILD 3 +#define NRD_VERSION_DATE "19 August 2022" #if defined(_MSC_VER) #define NRD_CALL __fastcall diff --git a/README.md b/README.md index 55544fcd..a3168086 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# NVIDIA Real-time Denoisers v3.4.2 (NRD) +# NVIDIA Real-time Denoisers v3.4.3 (NRD) ## SAMPLE APP diff --git a/Resources/Version.h b/Resources/Version.h index 847364b2..242585c1 100644 --- a/Resources/Version.h +++ b/Resources/Version.h @@ -23,7 +23,7 @@ Versioning rules: #define VERSION_MAJOR 3 #define VERSION_MINOR 4 -#define VERSION_BUILD 2 +#define VERSION_BUILD 3 #define VERSION_REVISION 0 #define VERSION_STRING STR(VERSION_MAJOR.VERSION_MINOR.VERSION_BUILD.VERSION_REVISION) diff --git a/Shaders/Include/REBLUR/REBLUR_Common.hlsli b/Shaders/Include/REBLUR/REBLUR_Common.hlsli index 6f816744..4ffdcc54 100644 --- a/Shaders/Include/REBLUR/REBLUR_Common.hlsli +++ b/Shaders/Include/REBLUR/REBLUR_Common.hlsli @@ -157,14 +157,6 @@ float GetSpecAccumulatedFrameNum( float roughness, float powerScale ) return REBLUR_MAX_ACCUM_FRAME_NUM * GetSpecMagicCurve( roughness, REBLUR_SPEC_ACCUM_BASE_POWER * powerScale ); } -float AdvanceAccumSpeed( float4 prevAccumSpeed, float4 weights ) -{ - float4 accumSpeeds = prevAccumSpeed + 1.0; - float accumSpeed = STL::Filtering::ApplyBilinearCustomWeights( accumSpeeds.x, accumSpeeds.y, accumSpeeds.z, accumSpeeds.w, weights ); - - return min( accumSpeed, gMaxAccumulatedFrameNum ); -} - float GetSpecAccumSpeed( float maxAccumSpeed, float roughness, float NoV, float parallax, float curvature, float viewZ ) { // Artificially increase roughness if parallax is low to get a few frames of accumulation // TODO: is there a better way? @@ -191,7 +183,7 @@ float GetSpecAccumSpeed( float maxAccumSpeed, float roughness, float NoV, float accumSpeed = min( accumSpeed, maxAccumSpeed ); - return accumSpeed * float( gResetHistory == 0 ); + return accumSpeed; } // Misc @@ -239,10 +231,7 @@ float InterpolateAccumSpeeds( float surfaceFrameNum, float virtualFrameNum, floa float GetFadeBasedOnAccumulatedFrames( float accumSpeed ) { - float fade = 1.0; // previously was "saturate( ( 1.0 - nonLinearAccumSpeed ) / 0.95 )" - - // Ignore reconstructed frames - fade *= STL::Math::LinearStep( REBLUR_FIXED_FRAME_NUM - 1, REBLUR_FIXED_FRAME_NUM + 1, accumSpeed ); + float fade = STL::Math::LinearStep( REBLUR_FIXED_FRAME_NUM - 1, REBLUR_FIXED_FRAME_NUM + 1, accumSpeed ); return fade; } @@ -335,12 +324,13 @@ float GetFadeBasedOnAccumulatedFrames( float accumSpeed ) float2 GetSensitivityToDarkness( float roughness ) { // Artificially increase sensitivity to darkness for low roughness, because specular can be very hot + // TODO: should depend on curvature for low roughness? float sensitivityToDarknessScale = lerp( 3.0, 1.0, roughness ); #ifdef REBLUR_SH - return gSensitivityToDarkness * float2( 0.282095, 1.0 ); + return gSensitivityToDarkness * sensitivityToDarknessScale * float2( 0.282095, 1.0 ); #else - return gSensitivityToDarkness; + return gSensitivityToDarkness * sensitivityToDarknessScale; #endif } @@ -397,9 +387,6 @@ float ComputeAntilagScale( float2 s = float2( GetLuma( sigma ), sigma.w ); #endif - // TODO: if roughness is close to 0, hitDist can be very divergent, antilag potentially can break accumulation - // on bumpy surfaces, "sensitivityToDarknessScale" can be increased in this case based on curvature - float2 delta = abs( h - c ) - s * antilagSigmaScale; delta /= max( h, c ) + GetSensitivityToDarkness( roughness ); @@ -526,7 +513,6 @@ float2 GetTemporalAccumulationParams( float isInScreenMulFootprintQuality, float // TODO: should weight depend on "sigma / signal" ratio to avoid stabilization where it's not needed? float w = normAccumSpeed * normAccumSpeed; w *= isInScreenMulFootprintQuality; - w *= float( gResetHistory == 0 ); // TODO: disocclusion regions on stable bumpy surfaces with super low roughness look better with s = 0 float s = normAccumSpeed; diff --git a/Shaders/Include/REBLUR/REBLUR_Config.hlsli b/Shaders/Include/REBLUR/REBLUR_Config.hlsli index 1010687c..47e2177d 100644 --- a/Shaders/Include/REBLUR/REBLUR_Config.hlsli +++ b/Shaders/Include/REBLUR/REBLUR_Config.hlsli @@ -120,7 +120,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. NRD_CONSTANT( float, gSpecPrepassBlurRadius ) \ NRD_CONSTANT( uint, gIsWorldSpaceMotionEnabled ) \ NRD_CONSTANT( uint, gFrameIndex ) \ - NRD_CONSTANT( uint, gResetHistory ) \ + NRD_CONSTANT( uint, gUnused1 ) \ NRD_CONSTANT( uint, gDiffMaterialMask ) \ NRD_CONSTANT( uint, gSpecMaterialMask ) diff --git a/Shaders/Include/REBLUR/REBLUR_DiffuseSpecular_PostBlur.hlsli b/Shaders/Include/REBLUR/REBLUR_DiffuseSpecular_PostBlur.hlsli index 13469581..abf6e366 100644 --- a/Shaders/Include/REBLUR/REBLUR_DiffuseSpecular_PostBlur.hlsli +++ b/Shaders/Include/REBLUR/REBLUR_DiffuseSpecular_PostBlur.hlsli @@ -52,7 +52,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Output gOut_Normal_Roughness[ pixelPos ] = PackNormalRoughness( normalAndRoughness ); #ifdef REBLUR_NO_TEMPORAL_STABILIZATION - gOut_AccumSpeeds_MaterialID[ pixelPos ] = PackAccumSpeedsMaterialID( internalData1.x, internalData1.z, materialID ); + gOut_AccumSpeeds_MaterialID[ pixelPos ] = PackAccumSpeedsMaterialID( internalData1.x + 1.0, internalData1.z + 1.0, materialID ); // increment history length #endif // Shared data diff --git a/Shaders/Include/REBLUR/REBLUR_DiffuseSpecular_TemporalAccumulation.hlsli b/Shaders/Include/REBLUR/REBLUR_DiffuseSpecular_TemporalAccumulation.hlsli index 0ebf8714..d9cc23d6 100644 --- a/Shaders/Include/REBLUR/REBLUR_DiffuseSpecular_TemporalAccumulation.hlsli +++ b/Shaders/Include/REBLUR/REBLUR_DiffuseSpecular_TemporalAccumulation.hlsli @@ -179,14 +179,14 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Previous accum speed and materialID // TODO: 4x4 materialID footprint is reduced to 2x2 only uint4 smbPackedAccumSpeedMaterialID = gIn_Prev_AccumSpeeds_MaterialID.GatherRed( gNearestClamp, smbBilinearGatherUv ).wzxy; - float3 prevAccumSpeedMaterialID00 = UnpackAccumSpeedsMaterialID( smbPackedAccumSpeedMaterialID.x ); - float3 prevAccumSpeedMaterialID10 = UnpackAccumSpeedsMaterialID( smbPackedAccumSpeedMaterialID.y ); - float3 prevAccumSpeedMaterialID01 = UnpackAccumSpeedsMaterialID( smbPackedAccumSpeedMaterialID.z ); - float3 prevAccumSpeedMaterialID11 = UnpackAccumSpeedsMaterialID( smbPackedAccumSpeedMaterialID.w ); + float3 accumSpeedMaterialID00 = UnpackAccumSpeedsMaterialID( smbPackedAccumSpeedMaterialID.x ); + float3 accumSpeedMaterialID10 = UnpackAccumSpeedsMaterialID( smbPackedAccumSpeedMaterialID.y ); + float3 accumSpeedMaterialID01 = UnpackAccumSpeedsMaterialID( smbPackedAccumSpeedMaterialID.z ); + float3 accumSpeedMaterialID11 = UnpackAccumSpeedsMaterialID( smbPackedAccumSpeedMaterialID.w ); - float4 prevDiffAccumSpeeds = float4( prevAccumSpeedMaterialID00.x, prevAccumSpeedMaterialID10.x, prevAccumSpeedMaterialID01.x, prevAccumSpeedMaterialID11.x ); - float4 prevSpecAccumSpeeds = float4( prevAccumSpeedMaterialID00.y, prevAccumSpeedMaterialID10.y, prevAccumSpeedMaterialID01.y, prevAccumSpeedMaterialID11.y ); - float4 prevMaterialIDs = float4( prevAccumSpeedMaterialID00.z, prevAccumSpeedMaterialID10.z, prevAccumSpeedMaterialID01.z, prevAccumSpeedMaterialID11.z ); + float4 diffAccumSpeeds = float4( accumSpeedMaterialID00.x, accumSpeedMaterialID10.x, accumSpeedMaterialID01.x, accumSpeedMaterialID11.x ); + float4 specAccumSpeeds = float4( accumSpeedMaterialID00.y, accumSpeedMaterialID10.y, accumSpeedMaterialID01.y, accumSpeedMaterialID11.y ); + float4 prevMaterialIDs = float4( accumSpeedMaterialID00.z, accumSpeedMaterialID10.z, accumSpeedMaterialID01.z, accumSpeedMaterialID11.z ); // Parallax float smbParallax = ComputeParallax( Xprev - gCameraDelta.xyz, gOrthoMode == 0.0 ? pixelUv : smbPixelUv, gWorldToClip, gRectSize, gUnproject, gOrthoMode ); @@ -213,7 +213,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float3 smbOcclusion3 = step( planeDist3, disocclusionThreshold ); float4 smbOcclusionWeights = STL::Filtering::GetBilinearCustomWeights( smbBilinearFilter, float4( smbOcclusion0.z, smbOcclusion1.y, smbOcclusion2.y, smbOcclusion3.x ) ); - bool smbIsCatromAllowed = dot( smbOcclusion0 + smbOcclusion1 + smbOcclusion2 + smbOcclusion3, 1.0 ) > 11.5 && REBLUR_USE_CATROM_FOR_SURFACE_MOTION_IN_TA; + bool smbAllowCatRom = dot( smbOcclusion0 + smbOcclusion1 + smbOcclusion2 + smbOcclusion3, 1.0 ) > 11.5 && REBLUR_USE_CATROM_FOR_SURFACE_MOTION_IN_TA; float footprintQuality = STL::Filtering::ApplyBilinearFilter( smbOcclusion0.z, smbOcclusion1.y, smbOcclusion2.y, smbOcclusion3.x, smbBilinearFilter ); footprintQuality = STL::Math::Sqrt01( footprintQuality ); @@ -226,7 +226,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : smbOcclusion3.x *= materialCmps.w; float4 smbOcclusionWeightsWithMaterialID = STL::Filtering::GetBilinearCustomWeights( smbBilinearFilter, float4( smbOcclusion0.z, smbOcclusion1.y, smbOcclusion2.y, smbOcclusion3.x ) ); - bool smbIsCatromAllowedWithMaterialID = dot( smbOcclusion0 + smbOcclusion1 + smbOcclusion2 + smbOcclusion3, 1.0 ) > 11.5 && REBLUR_USE_CATROM_FOR_SURFACE_MOTION_IN_TA; + bool smbAllowCatRomWithMaterialID = smbAllowCatRom && dot( materialCmps, 1.0 ) > 3.5 && REBLUR_USE_CATROM_FOR_SURFACE_MOTION_IN_TA; float footprintQualityWithMaterialID = STL::Filtering::ApplyBilinearFilter( smbOcclusion0.z, smbOcclusion1.y, smbOcclusion2.y, smbOcclusion3.x, smbBilinearFilter ); footprintQualityWithMaterialID = STL::Math::Sqrt01( footprintQualityWithMaterialID ); @@ -241,28 +241,36 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : footprintQualityWithMaterialID *= sizeQuality; // Bits - float fbits = smbIsCatromAllowed * 2.0; + float fbits = smbAllowCatRom * 2.0; fbits += smbOcclusion0.z * 4.0 + smbOcclusion1.y * 8.0 + smbOcclusion2.y * 16.0 + smbOcclusion3.x * 32.0; // Update accumulation speeds #ifdef REBLUR_DIFFUSE - float diffAccumSpeed = AdvanceAccumSpeed( prevDiffAccumSpeeds, gDiffMaterialMask ? smbOcclusionWeightsWithMaterialID : smbOcclusionWeights ); - diffAccumSpeed *= lerp( gDiffMaterialMask ? footprintQualityWithMaterialID : footprintQuality, 1.0, 1.0 / ( 1.0 + diffAccumSpeed ) ); + float4 diffOcclusionWeights = gDiffMaterialMask ? smbOcclusionWeightsWithMaterialID : smbOcclusionWeights; + float diffHistoryConfidence = gDiffMaterialMask ? footprintQualityWithMaterialID : footprintQuality; + float diffAllowCatRom = gDiffMaterialMask ? smbAllowCatRomWithMaterialID : smbAllowCatRom; #ifdef REBLUR_HAS_CONFIDENCE - float diffConfidence = gIn_Diff_Confidence[ pixelPosUser ]; - diffAccumSpeed *= lerp( diffConfidence, 1.0, 1.0 / ( 1.0 + diffAccumSpeed ) ); + diffHistoryConfidence *= gIn_Diff_Confidence[ pixelPosUser ]; #endif + + float diffAccumSpeed = STL::Filtering::ApplyBilinearCustomWeights( diffAccumSpeeds.x, diffAccumSpeeds.y, diffAccumSpeeds.z, diffAccumSpeeds.w, diffOcclusionWeights ); + diffAccumSpeed *= lerp( diffHistoryConfidence, 1.0, 1.0 / ( 1.0 + diffAccumSpeed ) ); + diffAccumSpeed = min( diffAccumSpeed, gMaxAccumulatedFrameNum ); #endif #ifdef REBLUR_SPECULAR - float specAccumSpeed = AdvanceAccumSpeed( prevSpecAccumSpeeds, gSpecMaterialMask ? smbOcclusionWeightsWithMaterialID : smbOcclusionWeights ); - specAccumSpeed *= lerp( gSpecMaterialMask ? footprintQualityWithMaterialID : footprintQuality, 1.0, 1.0 / ( 1.0 + specAccumSpeed ) ); + float4 specOcclusionWeights = gSpecMaterialMask ? smbOcclusionWeightsWithMaterialID : smbOcclusionWeights; + float specHistoryConfidence = gSpecMaterialMask ? footprintQualityWithMaterialID : footprintQuality; + float specAllowCatRom = gSpecMaterialMask ? smbAllowCatRomWithMaterialID : smbAllowCatRom; #ifdef REBLUR_HAS_CONFIDENCE - float specConfidence = gIn_Spec_Confidence[ pixelPosUser ]; - specAccumSpeed *= lerp( specConfidence, 1.0, 1.0 / ( 1.0 + specAccumSpeed ) ); + specHistoryConfidence *= gIn_Spec_Confidence[ pixelPosUser ]; #endif + + float specAccumSpeed = STL::Filtering::ApplyBilinearCustomWeights( specAccumSpeeds.x, specAccumSpeeds.y, specAccumSpeeds.z, specAccumSpeeds.w, specOcclusionWeights ); + specAccumSpeed *= lerp( specHistoryConfidence, 1.0, 1.0 / ( 1.0 + specAccumSpeed ) ); + specAccumSpeed = min( specAccumSpeed, gMaxAccumulatedFrameNum ); #endif uint checkerboard = STL::Sequence::CheckerBoard( pixelPos, gFrameIndex ); @@ -295,7 +303,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float smbDiffFastHistory; BicubicFilterNoCornersWithFallbackToBilinearFilterWithCustomWeights( saturate( smbPixelUv ) * gRectSizePrev, gInvScreenSize, - gDiffMaterialMask ? smbOcclusionWeightsWithMaterialID : smbOcclusionWeights, gDiffMaterialMask ? smbIsCatromAllowedWithMaterialID : smbIsCatromAllowed, + diffOcclusionWeights, diffAllowCatRom, gIn_Diff_History, smbDiffHistory #ifdef REBLUR_SH , gIn_DiffSh_History, smbDiffShHistory @@ -320,9 +328,9 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : } #endif - float diffAccumSpeedNonLinear = 1.0 / ( min( diffAccumSpeed, gMaxAccumulatedFrameNum ) + 1.0 ); + float diffAccumSpeedNonLinear = 1.0 / ( 1.0 + diffAccumSpeed ); if( !diffHasData ) - diffAccumSpeedNonLinear *= 1.0 - gCheckerboardResolveAccumSpeed * diffAccumSpeed / ( 1.0 + diffAccumSpeed ); + diffAccumSpeedNonLinear *= lerp( 1.0 - gCheckerboardResolveAccumSpeed, 1.0, diffAccumSpeedNonLinear ); REBLUR_TYPE diffResult = MixHistoryAndCurrent( smbDiffHistory, diff, diffAccumSpeedNonLinear ); #ifdef REBLUR_SH @@ -345,9 +353,9 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Fast history #if( REBLUR_USE_FAST_HISTORY == 1 && !defined( REBLUR_OCCLUSION ) ) float diffFastAccumSpeed = min( diffAccumSpeed, gMaxFastAccumulatedFrameNum ); - float diffFastAccumSpeedNonLinear = 1.0 / ( diffFastAccumSpeed + 1.0 ); + float diffFastAccumSpeedNonLinear = 1.0 / ( 1.0 + diffFastAccumSpeed ); if( !diffHasData ) - diffFastAccumSpeedNonLinear *= 1.0 - gCheckerboardResolveAccumSpeed * diffAccumSpeed / ( 1.0 + diffAccumSpeed ); + diffFastAccumSpeedNonLinear *= lerp( 0.5, 1.0, diffAccumSpeedNonLinear ); smbDiffFastHistory = diffAccumSpeed < gMaxFastAccumulatedFrameNum ? GetLuma( smbDiffHistory ) : smbDiffFastHistory; @@ -446,13 +454,13 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float virtualMotionRoughnessWeight = GetEncodingAwareRoughnessWeights( roughness, vmbRoughness, roughnessFraction ); virtualHistoryAmount *= virtualMotionRoughnessWeight; - // Sample history surface motion + // Sample history - surface motion REBLUR_TYPE smbSpecHistory; float4 smbSpecShHistory; float smbSpecFastHistory; BicubicFilterNoCornersWithFallbackToBilinearFilterWithCustomWeights( saturate( smbPixelUv ) * gRectSizePrev, gInvScreenSize, - gSpecMaterialMask ? smbOcclusionWeightsWithMaterialID : smbOcclusionWeights, gSpecMaterialMask ? smbIsCatromAllowedWithMaterialID : smbIsCatromAllowed, + specOcclusionWeights, specAllowCatRom, gIn_Spec_History, smbSpecHistory #ifdef REBLUR_SH , gIn_SpecSh_History, smbSpecShHistory @@ -465,16 +473,16 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Sample history - virtual motion float4 vmbOcclusionWeights = STL::Filtering::GetBilinearCustomWeights( vmbBilinearFilter, vmbOcclusion ); - bool vmbIsCatromAllowed = dot( vmbOcclusion, 1.0 ) > 3.5; - vmbIsCatromAllowed = vmbIsCatromAllowed & smbIsCatromAllowed; - vmbIsCatromAllowed = vmbIsCatromAllowed & REBLUR_USE_CATROM_FOR_VIRTUAL_MOTION_IN_TA; + bool vmbAllowCatRom = dot( vmbOcclusion, 1.0 ) > 3.5; + vmbAllowCatRom = vmbAllowCatRom && smbAllowCatRom; + vmbAllowCatRom = vmbAllowCatRom && REBLUR_USE_CATROM_FOR_VIRTUAL_MOTION_IN_TA; REBLUR_TYPE vmbSpecHistory; float4 vmbSpecShHistory; float vmbSpecFastHistory; BicubicFilterNoCornersWithFallbackToBilinearFilterWithCustomWeights( saturate( vmbPixelUv ) * gRectSizePrev, gInvScreenSize, - vmbOcclusionWeights, vmbIsCatromAllowed, + vmbOcclusionWeights, vmbAllowCatRom, gIn_Spec_History, vmbSpecHistory #ifdef REBLUR_SH , gIn_SpecSh_History, vmbSpecShHistory @@ -554,9 +562,9 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Accumulation with checkerboard resolve // TODO: materialID support? specAccumSpeed = InterpolateAccumSpeeds( smbSpecAccumSpeed, vmbSpecAccumSpeed, virtualHistoryAmount ); - float specAccumSpeedNonLinear = 1.0 / ( min( specAccumSpeed, gMaxAccumulatedFrameNum ) + 1.0 ); + float specAccumSpeedNonLinear = 1.0 / ( 1.0 + specAccumSpeed ); if( !specHasData ) - specAccumSpeedNonLinear *= 1.0 - gCheckerboardResolveAccumSpeed * specAccumSpeed / ( 1.0 + specAccumSpeed ); + specAccumSpeedNonLinear *= lerp( 1.0 - gCheckerboardResolveAccumSpeed, 1.0, specAccumSpeedNonLinear ); REBLUR_TYPE specHistory = lerp( smbSpecHistory, vmbSpecHistory, virtualHistoryAmount ); REBLUR_TYPE specResult = MixHistoryAndCurrent( specHistory, spec, specAccumSpeedNonLinear, roughnessModified ); @@ -602,9 +610,9 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Fast history #if( REBLUR_USE_FAST_HISTORY == 1 && !defined( REBLUR_OCCLUSION ) ) float specFastAccumSpeed = min( specAccumSpeed, gMaxFastAccumulatedFrameNum ); - float specFastAccumSpeedNonLinear = 1.0 / ( specFastAccumSpeed + 1.0 ); + float specFastAccumSpeedNonLinear = 1.0 / ( 1.0 + specFastAccumSpeed ); if( !specHasData ) - specFastAccumSpeedNonLinear *= 1.0 - gCheckerboardResolveAccumSpeed * specAccumSpeed / ( 1.0 + specAccumSpeed ); + specFastAccumSpeedNonLinear *= lerp( 0.5, 1.0, specAccumSpeedNonLinear ); float specFastHistory = lerp( smbSpecFastHistory, vmbSpecFastHistory, virtualHistoryAmount ); specFastHistory = specAccumSpeed < gMaxFastAccumulatedFrameNum ? GetLuma( specHistory ) : specFastHistory; diff --git a/Shaders/Include/REBLUR/REBLUR_DiffuseSpecular_TemporalStabilization.hlsli b/Shaders/Include/REBLUR/REBLUR_DiffuseSpecular_TemporalStabilization.hlsli index c987d1bc..1ce7b2e0 100644 --- a/Shaders/Include/REBLUR/REBLUR_DiffuseSpecular_TemporalStabilization.hlsli +++ b/Shaders/Include/REBLUR/REBLUR_DiffuseSpecular_TemporalStabilization.hlsli @@ -72,29 +72,32 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float4 diff = s_Diff[ smemPos.y ][ smemPos.x ]; float4 diffM1 = diff; float4 diffM2 = diff * diff; - float diffMin = NRD_INF; - float diffMax = -NRD_INF; #ifdef REBLUR_SH float4 diffSh = s_DiffSh[ smemPos.y ][ smemPos.x ]; float4 diffShM1 = diffSh; float4 diffShM2 = diffSh * diffSh; #endif + + float2 diffMin = NRD_INF; + float2 diffMax = -NRD_INF; #endif #ifdef REBLUR_SPECULAR float4 spec = s_Spec[ smemPos.y ][ smemPos.x ]; float4 specM1 = spec; float4 specM2 = spec * spec; - float specMin = NRD_INF; - float specMax = -NRD_INF; - float hitDistForTracking = spec.w; #ifdef REBLUR_SH float4 specSh = s_SpecSh[ smemPos.y ][ smemPos.x ]; float4 specShM1 = specSh; float4 specShM2 = specSh * specSh; #endif + + float2 specMin = NRD_INF; + float2 specMax = -NRD_INF; + + float hitDistForTracking = spec.w; #endif [unroll] @@ -109,37 +112,42 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : int2 pos = threadPos + int2( dx, dy ); #ifdef REBLUR_DIFFUSE + // Accumulate moments float4 d = s_Diff[ pos.y ][ pos.x ]; diffM1 += d; diffM2 += d * d; - float diffLuma = GetLuma( d ); - diffMin = min( diffMin, diffLuma ); - diffMax = max( diffMax, diffLuma ); - #ifdef REBLUR_SH float4 dh = s_DiffSh[ pos.y ][ pos.x ]; diffShM1 += dh; diffShM2 += dh * dh; #endif + + // RCRS + float diffLuma = GetLuma( d ); + diffMin = min( diffMin, float2( diffLuma, d.w ) ); + diffMax = max( diffMax, float2( diffLuma, d.w ) ); #endif #ifdef REBLUR_SPECULAR + // Accumulate moments float4 s = s_Spec[ pos.y ][ pos.x ]; specM1 += s; specM2 += s * s; - float specLuma = GetLuma( s ); - specMin = min( specMin, specLuma ); - specMax = max( specMax, specLuma ); - - hitDistForTracking = min( ExtractHitDist( s ), hitDistForTracking ); - #ifdef REBLUR_SH float4 sh = s_SpecSh[ pos.y ][ pos.x ]; specShM1 += sh; specShM2 += sh * sh; #endif + + // RCRS + float specLuma = GetLuma( s ); + specMin = min( specMin, float2( specLuma, s.w ) ); + specMax = max( specMax, float2( specLuma, s.w ) ); + + // Find optimal hitDist for tracking + hitDistForTracking = min( ExtractHitDist( s ), hitDistForTracking ); #endif } } @@ -147,37 +155,51 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float invSum = 1.0 / ( ( BORDER * 2 + 1 ) * ( BORDER * 2 + 1 ) ); #ifdef REBLUR_DIFFUSE + // Compute sigma diffM1 *= invSum; diffM2 *= invSum; float4 diffSigma = GetStdDev( diffM1, diffM2 ); - float diffLuma = GetLuma( diff ); - float diffLumaClamped = clamp( diffLuma, diffMin.x, diffMax.x ); - diffLumaClamped = lerp( diffLuma, diffLumaClamped, gStabilizationStrength * float( gBlurRadius != 0 ) ); - diff = ChangeLuma( diff, diffLumaClamped ); - #ifdef REBLUR_SH diffShM1 *= invSum; diffShM2 *= invSum; float4 diffShSigma = GetStdDev( diffShM1, diffShM2 ); #endif + + // RCRS + float diffLuma = GetLuma( diff ); + float diffLumaClamped = clamp( diffLuma, diffMin.x, diffMax.x ); + + [flatten] + if( gBlurRadius != 0 ) + { + diff = ChangeLuma( diff, diffLumaClamped ); + diff.w = clamp( diff.w, diffMin.y, diffMax.y ); + } #endif #ifdef REBLUR_SPECULAR + // Compute sigma specM1 *= invSum; specM2 *= invSum; float4 specSigma = GetStdDev( specM1, specM2 ); - float specLuma = GetLuma( spec ); - float specLumaClamped = clamp( specLuma, specMin.x, specMax.x ); - specLumaClamped = lerp( specLuma, specLumaClamped, gStabilizationStrength * float( gBlurRadius != 0 ) ); - spec = ChangeLuma( spec, specLumaClamped ); - #ifdef REBLUR_SH specShM1 *= invSum; specShM2 *= invSum; float4 specShSigma = GetStdDev( specShM1, specShM2 ); #endif + + // RCRS + float specLuma = GetLuma( spec ); + float specLumaClamped = clamp( specLuma, specMin.x, specMax.x ); + + [flatten] + if( gBlurRadius != 0 ) + { + spec = ChangeLuma( spec, specLumaClamped ); + spec.w = clamp( spec.w, specMin.y, specMax.y ); + } #endif // Compute previous pixel position @@ -194,15 +216,18 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float virtualHistoryAmount = internalData2.x; float hitDistScaleForTracking = internalData2.y; float curvature = internalData2.z; - float4 occlusion = float4( ( bits & uint4( 4, 8, 16, 32 ) ) != 0 ); + float4 smbOcclusion = float4( ( bits & uint4( 4, 8, 16, 32 ) ) != 0 ); float pixelSize = PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, viewZ ); STL::Filtering::Bilinear smbBilinearFilter = STL::Filtering::GetBilinearFilter( saturate( smbPixelUv ), gRectSizePrev ); - float4 smbOcclusionWeights = STL::Filtering::GetBilinearCustomWeights( smbBilinearFilter, occlusion ); // TODO: only for "WithMaterialID" even if test is disabled + float4 smbOcclusionWeights = STL::Filtering::GetBilinearCustomWeights( smbBilinearFilter, smbOcclusion ); // TODO: only for "WithMaterialID" even if test is disabled bool smbIsCatromAllowed = ( bits & 2 ) != 0 && REBLUR_USE_CATROM_FOR_SURFACE_MOTION_IN_TS; // TODO: only for "WithMaterialID" even if test is disabled + float footprintQuality = STL::Filtering::ApplyBilinearFilter( smbOcclusion.x, smbOcclusion.y, smbOcclusion.z, smbOcclusion.w, smbBilinearFilter ); + footprintQuality = STL::Math::Sqrt01( footprintQuality ); + // Diffuse #ifdef REBLUR_DIFFUSE // Sample history - surface motion @@ -220,19 +245,15 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Avoid negative values smbDiffHistory = ClampNegativeToZero( smbDiffHistory ); - // Antilag + // Compute antilag float diffAntilag = ComputeAntilagScale( smbDiffHistory, diff, diffM1, diffSigma, gAntilagMinMaxThreshold, gAntilagSigmaScale, gStabilizationStrength, curvature * pixelSize, internalData1.xy ); - float diffMinAccumSpeed = min( internalData1.x, REBLUR_FIXED_FRAME_NUM * REBLUR_USE_ANTILAG_NOT_INVOKING_HISTORY_FIX ); - internalData1.x = lerp( diffMinAccumSpeed, internalData1.x, diffAntilag ); - // Clamp history and combine with the current frame float2 diffTemporalAccumulationParams = GetTemporalAccumulationParams( isInScreen, internalData1.x ); - diffTemporalAccumulationParams.x *= diffAntilag; smbDiffHistory = STL::Color::Clamp( diffM1, diffSigma * diffTemporalAccumulationParams.y, smbDiffHistory ); #ifdef REBLUR_SH @@ -241,6 +262,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float diffHistoryWeight = REBLUR_TS_ACCUM_TIME / ( 1.0 + REBLUR_TS_ACCUM_TIME ); diffHistoryWeight *= diffTemporalAccumulationParams.x; + diffHistoryWeight *= footprintQuality; + diffHistoryWeight *= diffAntilag; diffHistoryWeight *= gStabilizationStrength; diffHistoryWeight = 1.0 - diffHistoryWeight; @@ -253,10 +276,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : #if( REBLUR_DEBUG != 0 ) uint diffMode = REBLUR_DEBUG; if( diffMode == 1 ) // Accumulated frame num - diffResult.w = 1.0 - saturate( internalData1.x / ( gMaxAccumulatedFrameNum + 1.0 ) ); // map history reset to red - else if( diffMode == 2 ) // Antilag - diffResult.w = diffAntilag; - else if( diffMode == 3 ) // Error + diffResult.w = 1.0 - saturate( internalData1.x / ( 1.0 + gMaxAccumulatedFrameNum ) ); // map history reset to red + else if( diffMode == 2 ) // Error diffResult.w = internalData1.y; // Show how colorization represents 0-1 range on the bottom @@ -273,6 +294,13 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : #ifdef REBLUR_SH gOut_DiffSh[ pixelPos ] = diffShResult; #endif + + // Increment history length + internalData1.x += 1.0; + + // Apply anti-lag + float diffMinAccumSpeed = min( internalData1.x, REBLUR_FIXED_FRAME_NUM ) * REBLUR_USE_ANTILAG_NOT_INVOKING_HISTORY_FIX; + internalData1.x = lerp( diffMinAccumSpeed, internalData1.x, diffAntilag ); #endif // Specular @@ -326,18 +354,14 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float4 specShHistory = lerp( smbSpecShHistory, vmbSpecShHistory, virtualHistoryAmount ); #endif - // Antilag + // Compute antilag float specAntilag = ComputeAntilagScale( specHistory, spec, specM1, specSigma, gAntilagMinMaxThreshold, gAntilagSigmaScale, gStabilizationStrength, curvature * pixelSize, internalData1.zw, roughness ); - float specMinAccumSpeed = min( internalData1.z, REBLUR_FIXED_FRAME_NUM * REBLUR_USE_ANTILAG_NOT_INVOKING_HISTORY_FIX ); - internalData1.z = lerp( specMinAccumSpeed, internalData1.z, specAntilag ); - // Clamp history and combine with the current frame float2 specTemporalAccumulationParams = GetTemporalAccumulationParams( isInScreen, internalData1.z ); - specTemporalAccumulationParams.x *= specAntilag; specHistory = STL::Color::Clamp( specM1, specSigma * specTemporalAccumulationParams.y, specHistory ); #ifdef REBLUR_SH @@ -346,6 +370,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float specHistoryWeight = REBLUR_TS_ACCUM_TIME / ( 1.0 + REBLUR_TS_ACCUM_TIME ); specHistoryWeight *= specTemporalAccumulationParams.x; + specHistoryWeight *= footprintQuality; + specHistoryWeight *= specAntilag; // this is important specHistoryWeight *= gStabilizationStrength; specHistoryWeight = 1.0 - specHistoryWeight; @@ -358,20 +384,18 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : #if( REBLUR_DEBUG != 0 ) uint specMode = REBLUR_DEBUG; if( specMode == 1 ) // Accumulated frame num - specResult.w = 1.0 - saturate( internalData1.z / ( gMaxAccumulatedFrameNum + 1.0 ) ); // map history reset to red - else if( specMode == 2 ) // Antilag - specResult.w = specAntilag; - else if( specMode == 3 ) // Error + specResult.w = 1.0 - saturate( internalData1.z / ( 1.0 + gMaxAccumulatedFrameNum ) ); // map history reset to red + else if( specMode == 2 ) // Error specResult.w = internalData1.w; // can be > 1.0 - else if( specMode == 4 ) // Curvature magnitude + else if( specMode == 3 ) // Curvature magnitude specResult.w = abs( curvature * pixelSize ); - else if( specMode == 5 ) // Curvature sign + else if( specMode == 4 ) // Curvature sign specResult.w = curvature * pixelSize < 0 ? 1 : 0; - else if( specMode == 6 ) // Virtual history amount + else if( specMode == 5 ) // Virtual history amount specResult.w = virtualHistoryAmount; - else if( specMode == 7 ) // Hit dist scale for tracking + else if( specMode == 6 ) // Hit dist scale for tracking specResult.w = hitDistScaleForTracking; - else if( specMode == 8 ) // Parallax + else if( specMode == 7 ) // Parallax { // or specResult.w = ComputeParallax( Xprev - gCameraDelta.xyz, gOrthoMode == 0.0 ? pixelUv : smbPixelUv, gWorldToClip, gRectSize, gUnproject, gOrthoMode ); @@ -394,6 +418,13 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : #ifdef REBLUR_SH gOut_SpecSh[ pixelPos ] = specShResult; #endif + + // Increment history length + internalData1.z += 1.0; + + // Apply anti-lag + float specMinAccumSpeed = min( internalData1.z, REBLUR_FIXED_FRAME_NUM ) * REBLUR_USE_ANTILAG_NOT_INVOKING_HISTORY_FIX; + internalData1.z = lerp( specMinAccumSpeed, internalData1.z, specAntilag ); #endif gOut_AccumSpeeds_MaterialID[ pixelPos ] = PackAccumSpeedsMaterialID( internalData1.x, internalData1.z, materialID ); diff --git a/Source/Methods/Reblur_Diffuse.hpp b/Source/Methods/Reblur_Diffuse.hpp index 944d4fa3..20659cf4 100644 --- a/Source/Methods/Reblur_Diffuse.hpp +++ b/Source/Methods/Reblur_Diffuse.hpp @@ -545,8 +545,8 @@ void nrd::DenoiserImpl::AddSharedConstants_Reblur(const MethodData& methodData, AddFloat(data, m_FrameRateScale); AddFloat(data, settings.enableReferenceAccumulation ? 0.0f : settings.blurRadius); - AddFloat(data, float(maxAccumulatedFrameNum)); - AddFloat(data, float(settings.maxFastAccumulatedFrameNum)); + AddFloat(data, m_CommonSettings.accumulationMode != AccumulationMode::CONTINUE ? 0 : float(maxAccumulatedFrameNum)); + AddFloat(data, m_CommonSettings.accumulationMode != AccumulationMode::CONTINUE ? 0 : float(settings.maxFastAccumulatedFrameNum)); AddFloat(data, settings.enableAntiFirefly ? 1.0f : 0.0f); AddFloat(data, settings.minConvergedStateBaseRadiusScale); @@ -559,7 +559,7 @@ void nrd::DenoiserImpl::AddSharedConstants_Reblur(const MethodData& methodData, AddUint(data, m_CommonSettings.isMotionVectorInWorldSpace ? 1 : 0); AddUint(data, m_CommonSettings.frameIndex); - AddUint(data, m_CommonSettings.accumulationMode != AccumulationMode::CONTINUE ? 1 : 0); + AddUint(data, 0); // TODO: unused AddUint(data, settings.enableMaterialTestForDiffuse ? 1 : 0); AddUint(data, settings.enableMaterialTestForSpecular ? 1 : 0); }