From c55976040cf1909e1cb086d992e2f03a1cbaf004 Mon Sep 17 00:00:00 2001 From: dzhdan Date: Tue, 21 Jan 2025 18:51:18 +0800 Subject: [PATCH] v4.11.4: HIGHLIGHTS: - improved robustness DETAILS: - NRD: GLSL-related replacements come into play if not already defined - NRD: improved robustness - RELAX: fixed touching of pixels outside of denoising range (can be garbage) in "HistoryClamping" pass - RELAX/REBLUR: fixed touching of wrong data (can be garbage) in "checkerboard" mode on the left side of the screen - REBLUR: pedantic IQ changes in "TemporalStabilization" pass if "split screen" mode is active - Integration: NRI updated to v1.161 - updated docs --- External/MathLib | 2 +- Include/NRD.h | 4 +- Include/NRDSettings.h | 1 + Integration/NRDIntegration.hpp | 8 +- README.md | 26 ++--- Resources/Version.h | 2 +- Shaders/Include/Common.hlsli | 3 +- Shaders/Include/NRD.hlsli | 40 +++++-- .../REBLUR_Common_DiffuseSpatialFilter.hlsli | 6 +- .../REBLUR_Common_SpecularSpatialFilter.hlsli | 6 +- Shaders/Include/REBLUR_Config.hlsli | 1 + .../REBLUR_TemporalStabilization.hlsli | 6 +- Shaders/Include/RELAX_HistoryClamping.hlsli | 108 +++++++++++------- .../RELAX_HistoryClamping.resources.hlsli | 49 ++++---- Source/Denoisers/Relax_Diffuse.hpp | 1 + Source/Denoisers/Relax_DiffuseSh.hpp | 1 + Source/Denoisers/Relax_DiffuseSpecular.hpp | 1 + Source/Denoisers/Relax_DiffuseSpecularSh.hpp | 1 + Source/Denoisers/Relax_Specular.hpp | 1 + Source/Denoisers/Relax_SpecularSh.hpp | 1 + Source/InstanceImpl.cpp | 79 ++++++++----- Source/InstanceImpl.h | 1 + Source/Reblur.cpp | 3 +- Source/Relax.cpp | 11 +- 24 files changed, 222 insertions(+), 140 deletions(-) diff --git a/External/MathLib b/External/MathLib index 0ed690f8..63fab5b0 160000 --- a/External/MathLib +++ b/External/MathLib @@ -1 +1 @@ -Subproject commit 0ed690f8f8fff969104be299b3f0691439153d28 +Subproject commit 63fab5b00a1277962fb6bf3d316002f5d6d3f885 diff --git a/Include/NRD.h b/Include/NRD.h index e18f8183..4b97eb94 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 4 #define NRD_VERSION_MINOR 11 -#define NRD_VERSION_BUILD 3 -#define NRD_VERSION_DATE "3 January 2024" +#define NRD_VERSION_BUILD 4 +#define NRD_VERSION_DATE "20 January 2025" #if defined(_WIN32) #define NRD_CALL __stdcall diff --git a/Include/NRDSettings.h b/Include/NRDSettings.h index 3ae3e160..28f40de9 100644 --- a/Include/NRDSettings.h +++ b/Include/NRDSettings.h @@ -134,6 +134,7 @@ namespace nrd float timeDeltaBetweenFrames = 0.0f; // (units > 0) - use TLAS or tracing range + // It's highly recommended to use "viewZ > denoisingRange" for INF (sky) pixels float denoisingRange = 500000.0f; // [0.01; 0.02] - two samples considered occluded if relative distance difference is greater than this slope-scaled threshold diff --git a/Integration/NRDIntegration.hpp b/Integration/NRDIntegration.hpp index b5767806..19f37994 100644 --- a/Integration/NRDIntegration.hpp +++ b/Integration/NRDIntegration.hpp @@ -17,8 +17,8 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #include #endif -static_assert(NRD_VERSION_MAJOR >= 4 && NRD_VERSION_MINOR >= 10, "Unsupported NRD version!"); -static_assert(NRI_VERSION_MAJOR >= 1 && NRI_VERSION_MINOR >= 158, "Unsupported NRI version!"); +static_assert(NRD_VERSION_MAJOR >= 4 && NRD_VERSION_MINOR >= 11, "Unsupported NRD version!"); +static_assert(NRI_VERSION_MAJOR >= 1 && NRI_VERSION_MINOR >= 161, "Unsupported NRI version!"); namespace nrd { @@ -341,7 +341,7 @@ void Integration::CreateResources(uint16_t resourceWidth, uint16_t resourceHeigh snprintf(name, sizeof(name), "%s::P(%u)", m_Name, i); else snprintf(name, sizeof(name), "%s::T(%u)", m_Name, i - instanceDesc.permanentPoolSize); - m_NRI->SetTextureDebugName(*texture, name); + m_NRI->SetDebugName(texture, name); // Construct NRD texture nri::TextureBarrierDesc& nrdTexture = m_TexturePool[i]; @@ -349,7 +349,7 @@ void Integration::CreateResources(uint16_t resourceWidth, uint16_t resourceHeigh // Adjust memory usage nri::MemoryDesc memoryDesc = {}; - m_NRI->GetTextureMemoryDesc(*m_Device, textureDesc, nri::MemoryLocation::DEVICE, memoryDesc); + m_NRI->GetTextureMemoryDesc(*texture, nri::MemoryLocation::DEVICE, memoryDesc); if (i < instanceDesc.permanentPoolSize) m_PermanentPoolSize += memoryDesc.size; diff --git a/README.md b/README.md index 3eb96478..8393baa2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# NVIDIA REAL-TIME DENOISERS v4.11.3 (NRD) +# NVIDIA REAL-TIME DENOISERS v4.11.4 (NRD) [![Build NRD SDK](https://github.com/NVIDIAGameWorks/RayTracingDenoiser/actions/workflows/build.yml/badge.svg)](https://github.com/NVIDIAGameWorks/RayTracingDenoiser/actions/workflows/build.yml) @@ -98,8 +98,6 @@ NRD sample has *TESTS* section in the bottom of the UI, a new test can be added - If nothing helps - describe the issue, attach a video and steps to reproduce -Additionally, for any information, suggestions or general requests please feel free to contact us at NRD-SDK-Support@nvidia.com - # API Terminology: @@ -154,8 +152,6 @@ Commons inputs for primary hits (if *PSR* is not used, common use case) or for s - project on screen using matrices passed to NRD - `.w` component is positive view Z (or just transform world-space position to main view space and take `.z` component) -All textures should be *NaN* free at each pixel, even at pixels outside of denoising range. - The illustration below shows expected inputs for primary hits: ![Input without PSR](Images/InputsWithoutPsr.png) @@ -208,6 +204,17 @@ Distance to occluder (*SIGMA*): See `NRDDescs.h` and `NRD.hlsli` for more details and descriptions of other inputs and outputs. +# NOISY & NON-NOISY DATA REQUIREMENTS + +Noisy inputs: + - garbage values are allowed outside of active viewport, i.e. `>= CommonSettings::rectSize` + - garbage values are allowed outside of denoising range, i.e. `>= CommonSettings::denoisingRange` + +Non-noisy inputs (guides): + - must not contain garbage + +Where "garbage" is `NAN/INF` or undesired value. + # IMPROVING OUTPUT QUALITY The temporal part of *NRD* naturally suppresses jitter, which is essential for upscaling techniques. If an *SH* denoiser is in use, a high quality resolve can be applied to the final output to regain back macro details, micro details and per-pixel jittering. As an example, the image below demonstrates the results *after* and *before* resolve with active *DLSS* (quality mode). @@ -665,13 +672,6 @@ IN_NORMAL_ROUGHNESS = GetVirtualSpaceNormalAndRoughnessAt( B ); IN_MV = GetMotionAt( B ); ``` -## INTERACTION WITH `INFs` AND `NANs` - -- *NRD* doesn't touch pixels outside of viewport: `INFs / NANs` are allowed -- *NRD* doesn't touch pixels outside of denoising range: `INFs / NANs` are allowed -- `INFs / NANs` are not allowed for pixels inside the viewport and denoising range - - `INFs` can be used in `IN_VIEWZ`, but not recommended - ## INTERACTION WITH FRAME GENERATION TECHNIQUES Frame generation (FG) techniques boost FPS by interpolating between 2 last available frames. *NRD* works better when frame rate increases, because it gets more data per second. It's not the case for FG, because all rendering pipeline underlying passes (like, denoising) continue to work on the original non-boosted framerate. `GetMaxAccumulatedFrameNum` helper should get a real FPS, not a fake one. @@ -708,7 +708,7 @@ Hair strands tangent vectors *can't* be used as "normals guide" for *NRD* due to **[NRD]** When upgrading to the latest version keep an eye on `ResourceType` enumeration. The order of the input slots can be changed or something can be added, you need to adjust the inputs accordingly to match the mapping. Or use *NRD integration* to simplify the process. -**[NRD]** All pixels in floating point textures should be INF / NAN free to avoid propagation, because such values are used in weight calculations and accumulation of a weighted sum. Functions `XXX_FrontEnd_PackRadianceAndHitDist` perform optional NAN / INF clearing of the input signal. There is a boolean to skip these checks. +**[NRD]** Functions `XXX_FrontEnd_PackRadianceAndHitDist` perform optional `NAN/INF` clearing of the input signal. There is a boolean to skip these checks. **[NRD]** All denoisers work with positive RGB inputs (some denoisers can change color space in *front end* functions). For better image quality, HDR color inputs need to be in a sane range [0; 250], because the internal pipeline uses FP16 and *RELAX* tracks second moments of the input signal, i.e. `x^2` must fit into FP16 range. If the color input is in a wider range, any form of non-aggressive color compression can be applied (linear scaling, pow-based or log-based methods). *REBLUR* supports wider HDR ranges, because it doesn't track second moments. Passing pre-exposured colors (i.e. `color * exposure`) is not recommended, because a significant momentary change in exposure is hard to react to in this case. diff --git a/Resources/Version.h b/Resources/Version.h index 3a025c79..93b8ffa1 100644 --- a/Resources/Version.h +++ b/Resources/Version.h @@ -23,6 +23,6 @@ Versioning rules: #define VERSION_MAJOR 4 #define VERSION_MINOR 11 -#define VERSION_BUILD 3 +#define VERSION_BUILD 4 #define VERSION_STRING STR(VERSION_MAJOR.VERSION_MINOR.VERSION_BUILD encoding=NRD_NORMAL_ENCODING.NRD_ROUGHNESS_ENCODING) diff --git a/Shaders/Include/Common.hlsli b/Shaders/Include/Common.hlsli index 94bc9d50..d82dbee5 100644 --- a/Shaders/Include/Common.hlsli +++ b/Shaders/Include/Common.hlsli @@ -278,7 +278,7 @@ float4 GetBlurKernelRotation( compiletime const uint mode, uint2 pixelPos, float float IsInScreenNearest( float2 uv ) { - return float( all( uv >= 0.0 ) && all( uv < 1.0 ) ); + return float( all( uv > 0.0 ) && all( uv < 1.0 ) ); } // x y @@ -296,6 +296,7 @@ float4 IsInScreenBilinear( float2 footprintOrigin, float2 rectSize ) float2 ApplyCheckerboardShift( float2 pos, uint mode, uint counter, uint frameIndex ) { // IMPORTANT: "pos" must be snapped to the pixel center + pos += 16384.0; // apply pattern-neutral bias, to make "pos" non-negative uint checkerboard = Sequence::CheckerBoard( uint2( pos ), frameIndex ); float shift = ( ( counter & 0x1 ) == 0 ) ? -1.0 : 1.0; diff --git a/Shaders/Include/NRD.hlsli b/Shaders/Include/NRD.hlsli index a670a4ab..5e7f5815 100644 --- a/Shaders/Include/NRD.hlsli +++ b/Shaders/Include/NRD.hlsli @@ -236,16 +236,36 @@ NOISY INPUTS: //================================================================================================================================= #ifdef NRD_GLSL - #define float4 vec4 - #define float3 vec3 - #define float2 vec2 - #define float2x2 mat2x2 - #define float2x3 mat2x3 - #define float3x3 mat3x3 - #define rsqrt inversesqrt - #define saturate( x ) clamp( x, 0.0, 1.0 ) - #define lerp mix - #define mul( x, y ) ( x * y ) + #ifndef float4 + #define float4 vec4 + #endif + #ifndef float3 + #define float3 vec3 + #endif + #ifndef float2 + #define float2 vec2 + #endif + #ifndef float2x2 + #define float2x2 mat2x2 + #endif + #ifndef float2x3 + #define float2x3 mat2x3 + #endif + #ifndef float3x3 + #define float3x3 mat3x3 + #endif + #ifndef rsqrt + #define rsqrt inversesqrt + #endif + #ifndef saturate + #define saturate( x ) clamp( x, 0.0, 1.0 ) + #endif + #ifndef lerp + #define lerp mix + #endif + #ifndef mul + #define mul( x, y ) ( x * y ) + #endif #endif //================================================================================================================================= diff --git a/Shaders/Include/REBLUR_Common_DiffuseSpatialFilter.hlsli b/Shaders/Include/REBLUR_Common_DiffuseSpatialFilter.hlsli index b2dfbcaa..0b5c8ebd 100644 --- a/Shaders/Include/REBLUR_Common_DiffuseSpatialFilter.hlsli +++ b/Shaders/Include/REBLUR_Common_DiffuseSpatialFilter.hlsli @@ -106,14 +106,16 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #endif // Snap to the pixel center! - uv = ( floor( uv * gRectSize ) + 0.5 ) * gRectSizeInv; + uv = floor( uv * gRectSize ) + 0.5; // Apply checkerboard shift #if( REBLUR_SPATIAL_MODE == REBLUR_PRE_BLUR ) - uv = ApplyCheckerboardShift( uv * gRectSize, gDiffCheckerboard, n, gFrameIndex ) * gRectSizeInv; + uv = ApplyCheckerboardShift( uv, gDiffCheckerboard, n, gFrameIndex ); #endif // Texture coordinates + uv *= gRectSizeInv; + float2 uvScaled = ClampUvToViewport( uv ); float2 checkerboardUvScaled = uvScaled; #if( REBLUR_SPATIAL_MODE == REBLUR_PRE_BLUR ) diff --git a/Shaders/Include/REBLUR_Common_SpecularSpatialFilter.hlsli b/Shaders/Include/REBLUR_Common_SpecularSpatialFilter.hlsli index ab5db36a..6a33cb8c 100644 --- a/Shaders/Include/REBLUR_Common_SpecularSpatialFilter.hlsli +++ b/Shaders/Include/REBLUR_Common_SpecularSpatialFilter.hlsli @@ -130,14 +130,16 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #endif // Snap to the pixel center! - uv = ( floor( uv * gRectSize ) + 0.5 ) * gRectSizeInv; + uv = floor( uv * gRectSize ) + 0.5; // Apply checkerboard shift #if( REBLUR_SPATIAL_MODE == REBLUR_PRE_BLUR ) - uv = ApplyCheckerboardShift( uv * gRectSize, gSpecCheckerboard, n, gFrameIndex ) * gRectSizeInv; + uv = ApplyCheckerboardShift( uv, gSpecCheckerboard, n, gFrameIndex ); #endif // Texture coordinates + uv *= gRectSizeInv; + float2 uvScaled = ClampUvToViewport( uv ); float2 checkerboardUvScaled = uvScaled; #if( REBLUR_SPATIAL_MODE == REBLUR_PRE_BLUR ) diff --git a/Shaders/Include/REBLUR_Config.hlsli b/Shaders/Include/REBLUR_Config.hlsli index e6363199..3925dfe4 100644 --- a/Shaders/Include/REBLUR_Config.hlsli +++ b/Shaders/Include/REBLUR_Config.hlsli @@ -170,6 +170,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. NRD_CONSTANT( float, gMinRectDimMulUnproject ) \ NRD_CONSTANT( float, gUsePrepassNotOnlyForSpecularMotionEstimation ) \ NRD_CONSTANT( float, gSplitScreen ) \ + NRD_CONSTANT( float, gSplitScreenPrev ) \ NRD_CONSTANT( float, gCheckerboardResolveAccumSpeed ) \ NRD_CONSTANT( float, gViewZScale ) \ NRD_CONSTANT( float, gFireflySuppressorMinRelativeScale ) \ diff --git a/Shaders/Include/REBLUR_TemporalStabilization.hlsli b/Shaders/Include/REBLUR_TemporalStabilization.hlsli index 51987d2a..2adba801 100644 --- a/Shaders/Include/REBLUR_TemporalStabilization.hlsli +++ b/Shaders/Include/REBLUR_TemporalStabilization.hlsli @@ -262,7 +262,7 @@ NRD_EXPORT void NRD_CS_MAIN( NRD_CS_MAIN_ARGS ) float diffHistoryWeight = diffTemporalAccumulationParams.x; diffHistoryWeight *= diffAntilag; // this is important diffHistoryWeight *= float( pixelUv.x >= gSplitScreen ); - diffHistoryWeight *= float( smbPixelUv.x >= gSplitScreen ); + diffHistoryWeight *= float( smbPixelUv.x >= gSplitScreenPrev ); smbDiffHistory = Color::Clamp( diffM1, diffSigma * diffTemporalAccumulationParams.y, smbDiffHistory ); @@ -407,8 +407,8 @@ NRD_EXPORT void NRD_CS_MAIN( NRD_CS_MAIN_ARGS ) float specHistoryWeight = specTemporalAccumulationParams.x; specHistoryWeight *= specAntilag; // this is important specHistoryWeight *= float( pixelUv.x >= gSplitScreen ); - specHistoryWeight *= virtualHistoryAmount != 1.0 ? float( smbPixelUv.x >= gSplitScreen ) : 1.0; - specHistoryWeight *= virtualHistoryAmount != 0.0 ? float( vmbPixelUv.x >= gSplitScreen ) : 1.0; + specHistoryWeight *= virtualHistoryAmount != 1.0 ? float( smbPixelUv.x >= gSplitScreenPrev ) : 1.0; + specHistoryWeight *= virtualHistoryAmount != 0.0 ? float( vmbPixelUv.x >= gSplitScreenPrev ) : 1.0; float responsiveFactor = RemapRoughnessToResponsiveFactor( roughness ); float smc = GetSpecMagicCurve( roughness ); diff --git a/Shaders/Include/RELAX_HistoryClamping.hlsli b/Shaders/Include/RELAX_HistoryClamping.hlsli index 49039b0a..c7d4273c 100644 --- a/Shaders/Include/RELAX_HistoryClamping.hlsli +++ b/Shaders/Include/RELAX_HistoryClamping.hlsli @@ -10,35 +10,35 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #ifdef RELAX_SPECULAR groupshared float4 s_SpecResponsiveYCoCg[BUFFER_Y][BUFFER_X]; - groupshared float4 s_SpecNoisy_M2[BUFFER_Y][BUFFER_X]; + groupshared float4 s_SpecNoisy_IsValid[BUFFER_Y][BUFFER_X]; #endif #ifdef RELAX_DIFFUSE - groupshared float4 s_DiffNoisy_M2[BUFFER_Y][BUFFER_X]; groupshared float4 s_DiffResponsiveYCoCg[BUFFER_Y][BUFFER_X]; + groupshared float4 s_DiffNoisy_IsValid[BUFFER_Y][BUFFER_X]; #endif void Preload(uint2 sharedPos, int2 globalPos) { globalPos = clamp(globalPos, 0, gRectSize - 1.0); + float viewZ = gIn_ViewZ[globalPos]; + float isValid = float(viewZ < gDenoisingRange); + #ifdef RELAX_SPECULAR float4 specularResponsive = gIn_SpecFast[globalPos]; s_SpecResponsiveYCoCg[sharedPos.y][sharedPos.x] = float4(Color::RgbToYCoCg(specularResponsive.rgb), specularResponsive.a); - float4 specularNoisy = gIn_SpecNoisy[globalPos]; - float specularNoisyLuminance = Color::Luminance(specularNoisy.rgb); - s_SpecNoisy_M2[sharedPos.y][sharedPos.x] = float4(specularNoisy.rgb, specularNoisyLuminance * specularNoisyLuminance); - + float3 specularNoisy = gIn_SpecNoisy[globalPos].xyz; + s_SpecNoisy_IsValid[sharedPos.y][sharedPos.x] = float4(specularNoisy, isValid); #endif #ifdef RELAX_DIFFUSE float4 diffuseResponsive = gIn_DiffFast[globalPos]; s_DiffResponsiveYCoCg[sharedPos.y][sharedPos.x] = float4(Color::RgbToYCoCg(diffuseResponsive.rgb), diffuseResponsive.a); - float4 diffuseNoisy = gIn_DiffNoisy[globalPos]; - float diffuseNoisyLuminance = Color::Luminance(diffuseNoisy.rgb); - s_DiffNoisy_M2[sharedPos.y][sharedPos.x] = float4(diffuseNoisy.rgb, diffuseNoisyLuminance * diffuseNoisyLuminance); + float3 diffuseNoisy = gIn_DiffNoisy[globalPos].xyz; + s_DiffNoisy_IsValid[sharedPos.y][sharedPos.x] = float4(diffuseNoisy, isValid); #endif } @@ -62,6 +62,16 @@ NRD_EXPORT void NRD_CS_MAIN( NRD_CS_MAIN_ARGS ) if (isSky != 0.0 || pixelPos.x >= gRectSize.x || pixelPos.y >= gRectSize.y) return; + // Early out + uint2 sharedMemoryIndex = threadPos.xy + int2(BORDER, BORDER); +#ifdef RELAX_SPECULAR + if (s_SpecNoisy_IsValid[sharedMemoryIndex.y][sharedMemoryIndex.x].w == 0.0) + return; +#else + if (s_DiffNoisy_IsValid[sharedMemoryIndex.y][sharedMemoryIndex.x].w == 0.0) + return; +#endif + // Reading history length float historyLength = 255.0 * gIn_HistoryLength[pixelPos]; @@ -81,7 +91,7 @@ NRD_EXPORT void NRD_CS_MAIN( NRD_CS_MAIN_ARGS ) #endif // Running history clamping - uint2 sharedMemoryIndex = threadPos.xy + int2(BORDER, BORDER); + float sum = 0.0; [unroll] for (int dx = -2; dx <= 2; dx++) { @@ -90,34 +100,48 @@ NRD_EXPORT void NRD_CS_MAIN( NRD_CS_MAIN_ARGS ) { uint2 sharedMemoryIndexP = sharedMemoryIndex + int2(dx, dy); -#ifdef RELAX_SPECULAR - float3 specularSampleYCoCg = s_SpecResponsiveYCoCg[sharedMemoryIndexP.y][sharedMemoryIndexP.x].rgb; - specularResponsiveFirstMomentYCoCg += specularSampleYCoCg; - specularResponsiveSecondMomentYCoCg += specularSampleYCoCg * specularSampleYCoCg; - - float4 specularNoisySample = s_SpecNoisy_M2[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; - specularNoisyFirstMoment += specularNoisySample.rgb; - specularNoisySecondMoment += specularNoisySample.a; -#endif - -#ifdef RELAX_DIFFUSE - float3 diffuseSampleYCoCg = s_DiffResponsiveYCoCg[sharedMemoryIndexP.y][sharedMemoryIndexP.x].rgb; - diffuseResponsiveFirstMomentYCoCg += diffuseSampleYCoCg; - diffuseResponsiveSecondMomentYCoCg += diffuseSampleYCoCg * diffuseSampleYCoCg; - - float4 diffuseNoisySample = s_DiffNoisy_M2[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; - diffuseNoisyFirstMoment += diffuseNoisySample.rgb; - diffuseNoisySecondMoment += diffuseNoisySample.a; -#endif + float w; + #ifdef RELAX_SPECULAR + float4 specularNoisySample = s_SpecNoisy_IsValid[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; + w = specularNoisySample.w; + #endif + #ifdef RELAX_DIFFUSE + float4 diffuseNoisySample = s_DiffNoisy_IsValid[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; + w = diffuseNoisySample.w; // yes, overwrite to the same value + #endif + + if( w != 0.0 ) + { + #ifdef RELAX_SPECULAR + float3 specularSampleYCoCg = s_SpecResponsiveYCoCg[sharedMemoryIndexP.y][sharedMemoryIndexP.x].rgb; + specularResponsiveFirstMomentYCoCg += specularSampleYCoCg; + specularResponsiveSecondMomentYCoCg += specularSampleYCoCg * specularSampleYCoCg; + + float specularNoisyLuminance = Color::Luminance(specularNoisySample.rgb); + specularNoisyFirstMoment += specularNoisySample.rgb; + specularNoisySecondMoment += specularNoisyLuminance * specularNoisyLuminance; + #endif + #ifdef RELAX_DIFFUSE + float3 diffuseSampleYCoCg = s_DiffResponsiveYCoCg[sharedMemoryIndexP.y][sharedMemoryIndexP.x].rgb; + diffuseResponsiveFirstMomentYCoCg += diffuseSampleYCoCg; + diffuseResponsiveSecondMomentYCoCg += diffuseSampleYCoCg * diffuseSampleYCoCg; + + float diffuseNoisyLuminance = Color::Luminance(diffuseNoisySample.rgb); + diffuseNoisyFirstMoment += diffuseNoisySample.rgb; + diffuseNoisySecondMoment += diffuseNoisyLuminance * diffuseNoisyLuminance; + #endif + + sum += w; + } } } #ifdef RELAX_SPECULAR // Calculating color box - specularResponsiveFirstMomentYCoCg /= 25.0; - specularResponsiveSecondMomentYCoCg /= 25.0; - specularNoisyFirstMoment /= 25.0; - specularNoisySecondMoment /= 25.0; + specularResponsiveFirstMomentYCoCg /= sum; + specularResponsiveSecondMomentYCoCg /= sum; + specularNoisyFirstMoment /= sum; + specularNoisySecondMoment /= sum; float3 specularResponsiveSigmaYCoCg = sqrt(max(0.0f, specularResponsiveSecondMomentYCoCg - specularResponsiveFirstMomentYCoCg * specularResponsiveFirstMomentYCoCg)); float3 specularResponsiveColorMinYCoCg = specularResponsiveFirstMomentYCoCg - gColorBoxSigmaScale * specularResponsiveSigmaYCoCg; float3 specularResponsiveColorMaxYCoCg = specularResponsiveFirstMomentYCoCg + gColorBoxSigmaScale * specularResponsiveSigmaYCoCg; @@ -199,8 +223,9 @@ NRD_EXPORT void NRD_CS_MAIN( NRD_CS_MAIN_ARGS ) specularHistoryResetAmount = saturate(specularHistoryResetAmount); // Resetting history - outSpecular.rgb = lerp(outSpecular.rgb, s_SpecNoisy_M2[sharedMemoryIndex.y][sharedMemoryIndex.x].rgb, specularHistoryResetAmount); - outSpecularResponsive.rgb = lerp(outSpecularResponsive.rgb, s_SpecNoisy_M2[sharedMemoryIndex.y][sharedMemoryIndex.x].rgb, specularHistoryResetAmount); + float3 specNoisy = s_SpecNoisy_IsValid[sharedMemoryIndex.y][sharedMemoryIndex.x].rgb; + outSpecular.rgb = lerp(outSpecular.rgb, specNoisy, specularHistoryResetAmount); + outSpecularResponsive.rgb = lerp(outSpecularResponsive.rgb, specNoisy, specularHistoryResetAmount); // 2nd moment correction float outSpecularL = Color::Luminance(outSpecular.rgb); @@ -225,10 +250,10 @@ NRD_EXPORT void NRD_CS_MAIN( NRD_CS_MAIN_ARGS ) #ifdef RELAX_DIFFUSE // Calculating color box - diffuseResponsiveFirstMomentYCoCg /= 25.0; - diffuseResponsiveSecondMomentYCoCg /= 25.0; - diffuseNoisyFirstMoment /= 25.0; - diffuseNoisySecondMoment /= 25.0; + diffuseResponsiveFirstMomentYCoCg /= sum; + diffuseResponsiveSecondMomentYCoCg /= sum; + diffuseNoisyFirstMoment /= sum; + diffuseNoisySecondMoment /= sum; float3 diffuseResponsiveSigmaYCoCg = sqrt(max(0.0f, diffuseResponsiveSecondMomentYCoCg - diffuseResponsiveFirstMomentYCoCg * diffuseResponsiveFirstMomentYCoCg)); float3 diffuseResponsiveColorMinYCoCg = diffuseResponsiveFirstMomentYCoCg - gColorBoxSigmaScale * diffuseResponsiveSigmaYCoCg; float3 diffuseResponsiveColorMaxYCoCg = diffuseResponsiveFirstMomentYCoCg + gColorBoxSigmaScale * diffuseResponsiveSigmaYCoCg; @@ -309,8 +334,9 @@ NRD_EXPORT void NRD_CS_MAIN( NRD_CS_MAIN_ARGS ) float diffuseHistoryResetAmount = gHistoryResetAmount * max(0, abs(diffuseL - diffuseNoisyInputL) - noisydiffuseSpatialSigma - noisydiffuseTemporalSigma) / (1.0e-6 + max(diffuseL, diffuseNoisyInputL) + noisydiffuseSpatialSigma + noisydiffuseTemporalSigma); diffuseHistoryResetAmount = saturate(diffuseHistoryResetAmount); // Resetting history - outDiffuse.rgb = lerp(outDiffuse.rgb, s_DiffNoisy_M2[sharedMemoryIndex.y][sharedMemoryIndex.x].rgb, diffuseHistoryResetAmount); - outDiffuseResponsive.rgb = lerp(outDiffuseResponsive.rgb, s_DiffNoisy_M2[sharedMemoryIndex.y][sharedMemoryIndex.x].rgb, diffuseHistoryResetAmount); + float3 diffNoisy = s_DiffNoisy_IsValid[sharedMemoryIndex.y][sharedMemoryIndex.x].rgb; + outDiffuse.rgb = lerp(outDiffuse.rgb, diffNoisy, diffuseHistoryResetAmount); + outDiffuseResponsive.rgb = lerp(outDiffuseResponsive.rgb, diffNoisy, diffuseHistoryResetAmount); // 2nd moment correction float outDiffuseL = Color::Luminance(outDiffuse.rgb); diff --git a/Shaders/Resources/RELAX_HistoryClamping.resources.hlsli b/Shaders/Resources/RELAX_HistoryClamping.resources.hlsli index ac0c88a7..6463bc08 100644 --- a/Shaders/Resources/RELAX_HistoryClamping.resources.hlsli +++ b/Shaders/Resources/RELAX_HistoryClamping.resources.hlsli @@ -21,18 +21,19 @@ NRD_SAMPLERS_END NRD_INPUTS_START NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) - NRD_INPUT( Texture2D, gIn_SpecNoisy, t, 1 ) - NRD_INPUT( Texture2D, gIn_DiffNoisy, t, 2 ) - NRD_INPUT( Texture2D, gIn_Spec, t, 3 ) - NRD_INPUT( Texture2D, gIn_Diff, t, 4 ) - NRD_INPUT( Texture2D, gIn_SpecFast, t, 5 ) - NRD_INPUT( Texture2D, gIn_DiffFast, t, 6 ) - NRD_INPUT( Texture2D, gIn_HistoryLength, t, 7 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 1 ) + NRD_INPUT( Texture2D, gIn_SpecNoisy, t, 2 ) + NRD_INPUT( Texture2D, gIn_DiffNoisy, t, 3 ) + NRD_INPUT( Texture2D, gIn_Spec, t, 4 ) + NRD_INPUT( Texture2D, gIn_Diff, t, 5 ) + NRD_INPUT( Texture2D, gIn_SpecFast, t, 6 ) + NRD_INPUT( Texture2D, gIn_DiffFast, t, 7 ) + NRD_INPUT( Texture2D, gIn_HistoryLength, t, 8 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gIn_SpecSh, t, 8 ) - NRD_INPUT( Texture2D, gIn_DiffSh, t, 9 ) - NRD_INPUT( Texture2D, gIn_SpecShFast, t, 10 ) - NRD_INPUT( Texture2D, gIn_DiffShFast, t, 11 ) + NRD_INPUT( Texture2D, gIn_SpecSh, t, 9 ) + NRD_INPUT( Texture2D, gIn_DiffSh, t, 10 ) + NRD_INPUT( Texture2D, gIn_SpecShFast, t, 11 ) + NRD_INPUT( Texture2D, gIn_DiffShFast, t, 12 ) #endif NRD_INPUTS_END @@ -54,13 +55,14 @@ NRD_SAMPLERS_END NRD_INPUTS_START NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) - NRD_INPUT( Texture2D, gIn_DiffNoisy, t, 1 ) - NRD_INPUT( Texture2D, gIn_Diff, t, 2 ) - NRD_INPUT( Texture2D, gIn_DiffFast, t, 3 ) - NRD_INPUT( Texture2D, gIn_HistoryLength, t, 4 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 1 ) + NRD_INPUT( Texture2D, gIn_DiffNoisy, t, 2 ) + NRD_INPUT( Texture2D, gIn_Diff, t, 3 ) + NRD_INPUT( Texture2D, gIn_DiffFast, t, 4 ) + NRD_INPUT( Texture2D, gIn_HistoryLength, t, 5 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gIn_DiffSh, t, 5 ) - NRD_INPUT( Texture2D, gIn_DiffShFast, t, 6 ) + NRD_INPUT( Texture2D, gIn_DiffSh, t, 6 ) + NRD_INPUT( Texture2D, gIn_DiffShFast, t, 7 ) #endif NRD_INPUTS_END @@ -78,13 +80,14 @@ NRD_SAMPLERS_END NRD_INPUTS_START NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) - NRD_INPUT( Texture2D, gIn_SpecNoisy, t, 1 ) - NRD_INPUT( Texture2D, gIn_Spec, t, 2 ) - NRD_INPUT( Texture2D, gIn_SpecFast, t, 3 ) - NRD_INPUT( Texture2D, gIn_HistoryLength, t, 4 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 1 ) + NRD_INPUT( Texture2D, gIn_SpecNoisy, t, 2 ) + NRD_INPUT( Texture2D, gIn_Spec, t, 3 ) + NRD_INPUT( Texture2D, gIn_SpecFast, t, 4 ) + NRD_INPUT( Texture2D, gIn_HistoryLength, t, 5 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gIn_SpecSh, t, 5 ) - NRD_INPUT( Texture2D, gIn_SpecShFast, t, 6 ) + NRD_INPUT( Texture2D, gIn_SpecSh, t, 6 ) + NRD_INPUT( Texture2D, gIn_SpecShFast, t, 7 ) #endif NRD_INPUTS_END diff --git a/Source/Denoisers/Relax_Diffuse.hpp b/Source/Denoisers/Relax_Diffuse.hpp index 495b08c5..8b51d1bc 100644 --- a/Source/Denoisers/Relax_Diffuse.hpp +++ b/Source/Denoisers/Relax_Diffuse.hpp @@ -152,6 +152,7 @@ void nrd::InstanceImpl::Add_RelaxDiffuse(DenoiserData& denoiserData) { // Inputs PushInput( AsUint(Transient::TILES) ); + PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::OUT_DIFF_RADIANCE_HITDIST) ); PushInput( AsUint(Transient::DIFF_ILLUM_PING) ); PushInput( AsUint(Transient::DIFF_ILLUM_PONG) ); diff --git a/Source/Denoisers/Relax_DiffuseSh.hpp b/Source/Denoisers/Relax_DiffuseSh.hpp index 83c9094b..c05d9f75 100644 --- a/Source/Denoisers/Relax_DiffuseSh.hpp +++ b/Source/Denoisers/Relax_DiffuseSh.hpp @@ -169,6 +169,7 @@ void nrd::InstanceImpl::Add_RelaxDiffuseSh(DenoiserData& denoiserData) { // Inputs PushInput( AsUint(Transient::TILES) ); + PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::OUT_DIFF_SH0) ); PushInput( AsUint(Transient::DIFF_ILLUM_PING) ); PushInput( AsUint(Transient::DIFF_ILLUM_PONG) ); diff --git a/Source/Denoisers/Relax_DiffuseSpecular.hpp b/Source/Denoisers/Relax_DiffuseSpecular.hpp index cf6b74ef..9e264793 100644 --- a/Source/Denoisers/Relax_DiffuseSpecular.hpp +++ b/Source/Denoisers/Relax_DiffuseSpecular.hpp @@ -181,6 +181,7 @@ void nrd::InstanceImpl::Add_RelaxDiffuseSpecular(DenoiserData& denoiserData) { // Inputs PushInput( AsUint(Transient::TILES) ); + PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::OUT_SPEC_RADIANCE_HITDIST) ); // Noisy input with preblur applied PushInput( AsUint(ResourceType::OUT_DIFF_RADIANCE_HITDIST) ); PushInput( AsUint(Transient::SPEC_ILLUM_PING) ); // Normal history diff --git a/Source/Denoisers/Relax_DiffuseSpecularSh.hpp b/Source/Denoisers/Relax_DiffuseSpecularSh.hpp index 81a65744..bdd9d332 100644 --- a/Source/Denoisers/Relax_DiffuseSpecularSh.hpp +++ b/Source/Denoisers/Relax_DiffuseSpecularSh.hpp @@ -215,6 +215,7 @@ void nrd::InstanceImpl::Add_RelaxDiffuseSpecularSh(DenoiserData& denoiserData) { // Inputs PushInput( AsUint(Transient::TILES) ); + PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::OUT_SPEC_SH0) ); // Noisy input with preblur applied PushInput( AsUint(ResourceType::OUT_DIFF_SH0) ); PushInput( AsUint(Transient::SPEC_ILLUM_PING) ); // Normal history diff --git a/Source/Denoisers/Relax_Specular.hpp b/Source/Denoisers/Relax_Specular.hpp index 26b74c01..05775345 100644 --- a/Source/Denoisers/Relax_Specular.hpp +++ b/Source/Denoisers/Relax_Specular.hpp @@ -160,6 +160,7 @@ void nrd::InstanceImpl::Add_RelaxSpecular(DenoiserData& denoiserData) { // Inputs PushInput( AsUint(Transient::TILES) ); + PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::OUT_SPEC_RADIANCE_HITDIST) ); PushInput( AsUint(Transient::SPEC_ILLUM_PING) ); PushInput( AsUint(Transient::SPEC_ILLUM_PONG) ); diff --git a/Source/Denoisers/Relax_SpecularSh.hpp b/Source/Denoisers/Relax_SpecularSh.hpp index 12dbeca9..0d7d2b06 100644 --- a/Source/Denoisers/Relax_SpecularSh.hpp +++ b/Source/Denoisers/Relax_SpecularSh.hpp @@ -177,6 +177,7 @@ void nrd::InstanceImpl::Add_RelaxSpecularSh(DenoiserData& denoiserData) { // Inputs PushInput( AsUint(Transient::TILES) ); + PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::OUT_SPEC_SH0) ); // Noisy input with preblur applied PushInput( AsUint(Transient::SPEC_ILLUM_PING) ); // Normal history PushInput( AsUint(Transient::SPEC_ILLUM_PONG) ); // Responsive history diff --git a/Source/InstanceImpl.cpp b/Source/InstanceImpl.cpp index 5c4ff2fb..a2efd855 100644 --- a/Source/InstanceImpl.cpp +++ b/Source/InstanceImpl.cpp @@ -268,58 +268,84 @@ nrd::Result nrd::InstanceImpl::Create(const InstanceCreationDesc& instanceCreati nrd::Result nrd::InstanceImpl::SetCommonSettings(const CommonSettings& commonSettings) { + m_SplitScreenPrev = m_CommonSettings.splitScreen; + + memcpy(&m_CommonSettings, &commonSettings, sizeof(commonSettings)); + + // Silently fix settings for known cases + if (m_IsFirstUse) + { + m_CommonSettings.accumulationMode = AccumulationMode::CLEAR_AND_RESTART; + m_IsFirstUse = false; + } + + if (m_CommonSettings.accumulationMode != AccumulationMode::CONTINUE) + { + m_SplitScreenPrev = 0.0f; + + m_WorldToViewPrev = m_WorldToView; + m_ViewToClipPrev = m_ViewToClip; + + m_CommonSettings.resourceSizePrev[0] = m_CommonSettings.resourceSize[0]; + m_CommonSettings.resourceSizePrev[1] = m_CommonSettings.resourceSize[1]; + + m_CommonSettings.rectSizePrev[0] = m_CommonSettings.rectSize[0]; + m_CommonSettings.rectSizePrev[1] = m_CommonSettings.rectSize[1]; + + m_CommonSettings.cameraJitterPrev[0] = m_CommonSettings.cameraJitter[0]; + m_CommonSettings.cameraJitterPrev[1] = m_CommonSettings.cameraJitter[1]; + } + // TODO: matrix verifications? - bool isValid = commonSettings.viewZScale > 0.0f; + bool isValid = m_CommonSettings.viewZScale > 0.0f; assert("'viewZScale' can't be <= 0" && isValid); - isValid &= commonSettings.resourceSize[0] != 0 && commonSettings.resourceSize[1] != 0; + isValid &= m_CommonSettings.resourceSize[0] != 0 && m_CommonSettings.resourceSize[1] != 0; assert("'resourceSize' can't be 0" && isValid); - isValid &= commonSettings.resourceSizePrev[0] != 0 && commonSettings.resourceSizePrev[1] != 0; + isValid &= m_CommonSettings.resourceSizePrev[0] != 0 && m_CommonSettings.resourceSizePrev[1] != 0; assert("'resourceSizePrev' can't be 0" && isValid); - isValid &= commonSettings.rectSize[0] != 0 && commonSettings.rectSize[1] != 0; + isValid &= m_CommonSettings.rectSize[0] != 0 && m_CommonSettings.rectSize[1] != 0; assert("'rectSize' can't be 0" && isValid); - isValid &= commonSettings.rectSizePrev[0] != 0 && commonSettings.rectSizePrev[1] != 0; + isValid &= m_CommonSettings.rectSizePrev[0] != 0 && m_CommonSettings.rectSizePrev[1] != 0; assert("'rectSizePrev' can't be 0" && isValid); - isValid &= ((commonSettings.motionVectorScale[0] != 0.0f && commonSettings.motionVectorScale[1] != 0.0f) || commonSettings.isMotionVectorInWorldSpace); + isValid &= ((m_CommonSettings.motionVectorScale[0] != 0.0f && m_CommonSettings.motionVectorScale[1] != 0.0f) || m_CommonSettings.isMotionVectorInWorldSpace); assert("'mvScale.xy' can't be 0" && isValid); - isValid &= commonSettings.cameraJitter[0] >= -0.5f && commonSettings.cameraJitter[0] <= 0.5f && commonSettings.cameraJitter[1] >= -0.5f && commonSettings.cameraJitter[1] <= 0.5f; + isValid &= m_CommonSettings.cameraJitter[0] >= -0.5f && m_CommonSettings.cameraJitter[0] <= 0.5f && m_CommonSettings.cameraJitter[1] >= -0.5f && m_CommonSettings.cameraJitter[1] <= 0.5f; assert("'cameraJitter' must be in range [-0.5; 0.5]" && isValid); - isValid &= commonSettings.cameraJitterPrev[0] >= -0.5f && commonSettings.cameraJitterPrev[0] <= 0.5f && commonSettings.cameraJitterPrev[1] >= -0.5f && commonSettings.cameraJitterPrev[1] <= 0.5f; + isValid &= m_CommonSettings.cameraJitterPrev[0] >= -0.5f && m_CommonSettings.cameraJitterPrev[0] <= 0.5f && m_CommonSettings.cameraJitterPrev[1] >= -0.5f && m_CommonSettings.cameraJitterPrev[1] <= 0.5f; assert("'cameraJitterPrev' must be in range [-0.5; 0.5]" && isValid); - isValid &= commonSettings.denoisingRange > 0.0f; + isValid &= m_CommonSettings.denoisingRange > 0.0f; assert("'denoisingRange' must be >= 0" && isValid); - isValid &= commonSettings.disocclusionThreshold > 0.0f; + isValid &= m_CommonSettings.disocclusionThreshold > 0.0f; assert("'disocclusionThreshold' must be > 0" && isValid); - isValid &= commonSettings.disocclusionThresholdAlternate > 0.0f; + isValid &= m_CommonSettings.disocclusionThresholdAlternate > 0.0f; assert("'disocclusionThresholdAlternate' must be > 0" && isValid); - isValid &= commonSettings.strandMaterialID != 0.0f || GetLibraryDesc().normalEncoding == NormalEncoding::R10_G10_B10_A2_UNORM; + isValid &= m_CommonSettings.strandMaterialID != 0.0f || GetLibraryDesc().normalEncoding == NormalEncoding::R10_G10_B10_A2_UNORM; assert("'strandMaterialID' can't be 0 if material ID is not supported by encoding" && isValid); - isValid &= commonSettings.cameraAttachedReflectionMaterialID != 0.0f || GetLibraryDesc().normalEncoding == NormalEncoding::R10_G10_B10_A2_UNORM; + isValid &= m_CommonSettings.cameraAttachedReflectionMaterialID != 0.0f || GetLibraryDesc().normalEncoding == NormalEncoding::R10_G10_B10_A2_UNORM; assert("'cameraAttachedReflectionMaterialID' can't be 0 if material ID is not supported by encoding" && isValid); - memcpy(&m_CommonSettings, &commonSettings, sizeof(commonSettings)); - // Rotators (respecting sample patterns symmetry) - float angle1 = Sequence::Weyl1D(0.5f, commonSettings.frameIndex) * radians(90.0f); + float angle1 = Sequence::Weyl1D(0.5f, m_CommonSettings.frameIndex) * radians(90.0f); m_RotatorPre = Geometry::GetRotator(angle1); - float a0 = Sequence::Weyl1D(0.0f, commonSettings.frameIndex * 2) * radians(90.0f); - float a1 = Sequence::Bayer4x4(uint2(0, 0), commonSettings.frameIndex * 2) * radians(360.0f); + float a0 = Sequence::Weyl1D(0.0f, m_CommonSettings.frameIndex * 2) * radians(90.0f); + float a1 = Sequence::Bayer4x4(uint2(0, 0), m_CommonSettings.frameIndex * 2) * radians(360.0f); m_Rotator = Geometry::CombineRotators(Geometry::GetRotator(a0), Geometry::GetRotator(a1)); - float a2 = Sequence::Weyl1D(0.0f, commonSettings.frameIndex * 2 + 1) * radians(90.0f); - float a3 = Sequence::Bayer4x4(uint2(0, 0), commonSettings.frameIndex * 2 + 1) * radians(360.0f); + float a2 = Sequence::Weyl1D(0.0f, m_CommonSettings.frameIndex * 2 + 1) * radians(90.0f); + float a3 = Sequence::Bayer4x4(uint2(0, 0), m_CommonSettings.frameIndex * 2 + 1) * radians(360.0f); m_RotatorPost = Geometry::CombineRotators(Geometry::GetRotator(a2), Geometry::GetRotator(a3)); // Main matrices @@ -363,15 +389,6 @@ nrd::Result nrd::InstanceImpl::SetCommonSettings(const CommonSettings& commonSet float4(m_CommonSettings.worldPrevToWorldMatrix + 12) ); - // There are many cases, where history buffers contain garbage - handle at least one of them internally - if (m_IsFirstUse) - { - m_CommonSettings.accumulationMode = AccumulationMode::CLEAR_AND_RESTART; - m_WorldToViewPrev = m_WorldToView; - m_ViewToClipPrev = m_ViewToClip; - m_IsFirstUse = false; - } - // Convert to LH uint32_t flags = 0; DecomposeProjection(STYLE_D3D, STYLE_D3D, m_ViewToClip, &flags, nullptr, nullptr, m_Frustum.a, nullptr, nullptr); @@ -426,8 +443,8 @@ nrd::Result nrd::InstanceImpl::SetCommonSettings(const CommonSettings& commonSet m_ClipToWorld.Invert(); float project[3]; - float settings[PROJ_NUM]; - DecomposeProjection(STYLE_D3D, STYLE_D3D, m_ViewToClip, &flags, settings, nullptr, m_Frustum.a, project, nullptr); + DecomposeProjection(STYLE_D3D, STYLE_D3D, m_ViewToClip, &flags, nullptr, nullptr, m_Frustum.a, project, nullptr); + m_ProjectY = project[1]; m_OrthoMode = (flags & PROJ_ORTHO) ? -1.0f : 0.0f; diff --git a/Source/InstanceImpl.h b/Source/InstanceImpl.h index a5348692..cda5154a 100644 --- a/Source/InstanceImpl.h +++ b/Source/InstanceImpl.h @@ -331,6 +331,7 @@ namespace nrd float3 m_CameraDelta = float3::Zero(); float3 m_ViewDirection = float3::Zero(); float3 m_ViewDirectionPrev = float3::Zero(); + float m_SplitScreenPrev = 0.0f; const char* m_PassName = nullptr; uint8_t* m_ConstantDataUnaligned = nullptr; uint8_t* m_ConstantData = nullptr; diff --git a/Source/Reblur.cpp b/Source/Reblur.cpp index 6abfc5d8..df10c5e0 100644 --- a/Source/Reblur.cpp +++ b/Source/Reblur.cpp @@ -387,7 +387,7 @@ void nrd::InstanceImpl::AddSharedConstants_Reblur(const ReblurSettings& settings consts->gDiffPrepassBlurRadius = diffusePrepassBlurRadius; consts->gSpecPrepassBlurRadius = specularPrepassBlurRadius; consts->gMaxAccumulatedFrameNum = isHistoryReset ? 0 : float(maxAccumulatedFrameNum); - consts->gMaxFastAccumulatedFrameNum = float(settings.maxFastAccumulatedFrameNum); + consts->gMaxFastAccumulatedFrameNum = isHistoryReset ? 0 : float(settings.maxFastAccumulatedFrameNum); consts->gAntiFirefly = settings.enableAntiFirefly ? 1.0f : 0.0f; consts->gLobeAngleFraction = settings.lobeAngleFraction * settings.lobeAngleFraction; // TODO: GetSpecularLobeTanHalfAngle has been fixed, but we want to use existing settings consts->gRoughnessFraction = settings.roughnessFraction; @@ -396,6 +396,7 @@ void nrd::InstanceImpl::AddSharedConstants_Reblur(const ReblurSettings& settings consts->gMinRectDimMulUnproject = (float)min(rectW, rectH) * unproject; consts->gUsePrepassNotOnlyForSpecularMotionEstimation = settings.usePrepassOnlyForSpecularMotionEstimation ? 0.0f : 1.0f; consts->gSplitScreen = m_CommonSettings.splitScreen; + consts->gSplitScreenPrev = m_SplitScreenPrev; consts->gCheckerboardResolveAccumSpeed = m_CheckerboardResolveAccumSpeed; consts->gViewZScale = m_CommonSettings.viewZScale; consts->gFireflySuppressorMinRelativeScale = settings.fireflySuppressorMinRelativeScale; diff --git a/Source/Relax.cpp b/Source/Relax.cpp index 587e8317..6a662678 100644 --- a/Source/Relax.cpp +++ b/Source/Relax.cpp @@ -81,6 +81,7 @@ void nrd::InstanceImpl::AddSharedConstants_Relax(const RelaxSettings& settings, float maxDiffuseLuminanceRelativeDifference = -log( saturate(settings.diffuseMinLuminanceWeight) ); float maxSpecularLuminanceRelativeDifference = -log( saturate(settings.specularMinLuminanceWeight) ); float disocclusionThresholdBonus = (1.0f + m_JitterDelta) / float(rectH); + bool isHistoryReset = m_CommonSettings.accumulationMode != AccumulationMode::CONTINUE; // Checkerboard logic uint32_t specCheckerboard = 2; @@ -122,10 +123,10 @@ void nrd::InstanceImpl::AddSharedConstants_Relax(const RelaxSettings& settings, consts->gPrintfAt = uint2(m_CommonSettings.printfAt[0], m_CommonSettings.printfAt[1]); consts->gRectOrigin = uint2(m_CommonSettings.rectOrigin[0], m_CommonSettings.rectOrigin[1]); consts->gRectSize = int2(rectW, rectH); - consts->gSpecMaxAccumulatedFrameNum = (float)min(settings.specularMaxAccumulatedFrameNum, RELAX_MAX_HISTORY_FRAME_NUM); - consts->gSpecMaxFastAccumulatedFrameNum = (float)min(settings.specularMaxFastAccumulatedFrameNum, RELAX_MAX_HISTORY_FRAME_NUM); - consts->gDiffMaxAccumulatedFrameNum = (float)min(settings.diffuseMaxAccumulatedFrameNum, RELAX_MAX_HISTORY_FRAME_NUM); - consts->gDiffMaxFastAccumulatedFrameNum = (float)min(settings.diffuseMaxFastAccumulatedFrameNum, RELAX_MAX_HISTORY_FRAME_NUM); + consts->gSpecMaxAccumulatedFrameNum = isHistoryReset ? 0.0f : (float)min(settings.specularMaxAccumulatedFrameNum, RELAX_MAX_HISTORY_FRAME_NUM); + consts->gSpecMaxFastAccumulatedFrameNum = isHistoryReset ? 0.0f : (float)min(settings.specularMaxFastAccumulatedFrameNum, RELAX_MAX_HISTORY_FRAME_NUM); + consts->gDiffMaxAccumulatedFrameNum = isHistoryReset ? 0.0f : (float)min(settings.diffuseMaxAccumulatedFrameNum, RELAX_MAX_HISTORY_FRAME_NUM); + consts->gDiffMaxFastAccumulatedFrameNum = isHistoryReset ? 0.0f : (float)min(settings.diffuseMaxFastAccumulatedFrameNum, RELAX_MAX_HISTORY_FRAME_NUM); consts->gDisocclusionThreshold = m_CommonSettings.disocclusionThreshold + disocclusionThresholdBonus; consts->gDisocclusionThresholdAlternate = m_CommonSettings.disocclusionThresholdAlternate + disocclusionThresholdBonus; consts->gCameraAttachedReflectionMaterialID = m_CommonSettings.cameraAttachedReflectionMaterialID; @@ -173,7 +174,7 @@ void nrd::InstanceImpl::AddSharedConstants_Relax(const RelaxSettings& settings, consts->gHasDisocclusionThresholdMix = m_CommonSettings.isDisocclusionThresholdMixAvailable ? 1 : 0; consts->gDiffMaterialMask = settings.enableMaterialTestForDiffuse ? 1 : 0; consts->gSpecMaterialMask = settings.enableMaterialTestForSpecular ? 1 : 0; - consts->gResetHistory = m_CommonSettings.accumulationMode != AccumulationMode::CONTINUE ? 1 : 0; + consts->gResetHistory = isHistoryReset ? 1 : 0; } void nrd::InstanceImpl::Update_Relax(const DenoiserData& denoiserData)