From dc0ba40f4405080ae43a0bf68d5ebc1186dfa7c1 Mon Sep 17 00:00:00 2001 From: dzhdan Date: Tue, 5 Nov 2024 12:43:58 +0800 Subject: [PATCH] v4.11.0: HIGHLIGHTS: - NRD: added "GetMaxAccumulatedFrameNum" helper, emphasizing the importance of time-based accumulation, also added "DEFAULT_ACCUMULATION_TIME" constants for all denoisers - NRD: added "cameraAttachedReflectionMaterialID" to "CommonSettings" (currently used by REBLUR only), helping to deal with mirror reflections of objects attached to the camera. It's a suboptimal solution, future releases will address this problem better - REBLUR/SIGMA: "stabilizationStrength" replaced with "maxStabilizedFrameNum" for consistency with other accumulation related settings and "GetMaxAccumulatedFrameNum" helper. The progression "0, 1, 2, 3... 9" is more understandable than "1.00, 0.50, 0.33, 0.25... 0.10" BREAKING CHANGES: - settings related (please, read UPDATE.md) - "NRD_FrontEnd_UnpackNormalAndRoughness" returns "materialID" in the same range, it was passed to "NRD_FrontEnd_PackNormalAndRoughness" DETAILS: - NRD: added "GetMaxAccumulatedFrameNum" helper to the main header - NRD: added "cameraAttachedReflectionMaterialID" to "CommonSettings" (currently used by REBLUR only, WIP longer term) - NRD: "NRD_FrontEnd_UnpackNormalAndRoughness" returns "materialID" in the same range, it was passed to "NRD_FrontEnd_PackNormalAndRoughness" - NRD: improved code reuse between REBLUR and RELAX, reduced divergence - NRD: improved per frame rotators (better noise properties) - NRD: interface polishing (no functional changes) - RELAX: added clamping to user provided "max accumulated frame num" values - RELAX: reduced memory usage of DIFFUSE denoiser (had a dummy allocation) - RELAX: diff-spec lobe fraction replaced with one shared fraction (simplified settings) - RELAX: partial refactoring to match overall NRD style - REBLUR/RELAX: hot/cold branch sorting - REBLUR/RELAX: improved parallax computations, affecting many aspects of specular tracking - REBLUR/RELAX: improved curvature computations - REBLUR/RELAX: added forgotten initialization of "gStrandThickness" constant (oops!) - REBLUR: minor performance opts - REBLUR: fixed minor regressions related to migration to stochastic bilinear filter for RGBA1010102 oct-packed normals (since prev data repacking is gone) - REBLUR: stochastic bilinear gets replaced with native bilinear if normals are interpolate-able - REBLUR: slightly decreased hit distance sensitivity in case of 0 roughness - REBLUR: slightly reduced "lobeAngleFraction" default value to squeeze more normal details (using the old default is OK) - REBLUR: "lobeHalfAngle" uses code from "GetNormalWeightParam" (reduced code entropy) - REBLUR: adjusted virtual parallax based confidence to be a bit more aggressive - REBLUR: improved screen space sampling (now used in more shaders without IQ loss, improves perf, WIP) - REBLUR: "GetGeometryWeightParams" should not become more strict if history is long (the rest is handled by normal weights) - REBLUR: minimized deprecated "GetBilateralWeight" usage - REBLUR: relaxed maximum value of slope scaling for disocclusion threshold - REBLUR: improved antilag (which didn't do much last year), also made almost FPS independent, tuned to "not hurt" - REBLUR: finally fixed ancient and ugly issue leading to "bright lighting crawling", caused by unbiased (bright) fast history selectively accelerating the biased (fireflies suppressed) main history - REBLUR/SIGMA: "stabilization strength" settings replaced with "max stabilized frame num" - SIGMA: removed unnecessary checks in spatial filters - SIGMA: "closest viewZ" replaced with "longest MV" logic in the temporal stabilization pass - SIGMA: history copying decoupled into a separate pass - SIGMA: added disocclusion tracking to get rid of ghosting - SIGMA: fixed ugly white outlines (suboptimal weighting scheme between dense and sparse passes) - SIGMA: tuned defaults settings - SIGMA: introduced screen space sampling to better respect low-discrepancy based per frame rotators - updated docs - updated dependencies - refactoring --- External/MathLib | 2 +- Include/NRD.h | 10 +- Include/NRDDescs.h | 18 +- Include/NRDSettings.h | 146 +++++--- Integration/NRDIntegration.hpp | 21 +- README.md | 38 +- Resources/Version.h | 2 +- Shaders.cfg | 13 +- Shaders/Include/Common.hlsli | 93 +++-- Shaders/Include/NRD.hlsli | 4 +- Shaders/Include/REBLUR_Blur.hlsli | 4 +- Shaders/Include/REBLUR_Common.hlsli | 67 ++-- .../REBLUR_Common_DiffuseSpatialFilter.hlsli | 35 +- .../REBLUR_Common_SpecularSpatialFilter.hlsli | 32 +- Shaders/Include/REBLUR_Config.hlsli | 25 +- Shaders/Include/REBLUR_Copy.hlsli | 2 +- Shaders/Include/REBLUR_HistoryFix.hlsli | 33 +- .../REBLUR_HitDistReconstruction.hlsli | 27 +- Shaders/Include/REBLUR_PostBlur.hlsli | 4 +- Shaders/Include/REBLUR_PrePass.hlsli | 34 +- .../Include/REBLUR_TemporalAccumulation.hlsli | 218 +++++++----- .../REBLUR_TemporalStabilization.hlsli | 112 +++--- Shaders/Include/RELAX_AntiFirefly.hlsli | 38 +- Shaders/Include/RELAX_Atrous.hlsli | 60 ++-- Shaders/Include/RELAX_AtrousSmem.hlsli | 124 +++---- Shaders/Include/RELAX_Common.hlsli | 27 +- Shaders/Include/RELAX_Config.hlsli | 4 +- Shaders/Include/RELAX_Copy.hlsli | 5 +- Shaders/Include/RELAX_HistoryClamping.hlsli | 85 +++-- Shaders/Include/RELAX_HistoryFix.hlsli | 44 +-- .../Include/RELAX_HitDistReconstruction.hlsli | 46 +-- Shaders/Include/RELAX_PrePass.hlsli | 94 ++--- .../Include/RELAX_TemporalAccumulation.hlsli | 333 +++++++++--------- Shaders/Include/SIGMA_Blur.hlsli | 165 ++++----- Shaders/Include/SIGMA_ClassifyTiles.hlsli | 4 +- Shaders/Include/SIGMA_Common.hlsli | 23 +- Shaders/Include/SIGMA_Config.hlsli | 23 +- Shaders/Include/SIGMA_Copy.hlsli | 22 ++ .../SIGMA_SmoothTiles.hlsli} | 9 - Shaders/Include/SIGMA_SplitScreen.hlsli | 2 +- .../Include/SIGMA_TemporalStabilization.hlsli | 181 ++++++---- .../Resources/REBLUR_PrePass.resources.hlsli | 4 +- ...EBLUR_TemporalAccumulation.resources.hlsli | 62 ++-- ...BLUR_TemporalStabilization.resources.hlsli | 20 +- .../RELAX_AntiFirefly.resources.hlsli | 34 +- .../Resources/RELAX_Atrous.resources.hlsli | 68 ++-- .../RELAX_AtrousSmem.resources.hlsli | 86 ++--- Shaders/Resources/RELAX_Copy.resources.hlsli | 16 +- .../RELAX_HistoryClamping.resources.hlsli | 90 ++--- .../RELAX_HistoryFix.resources.hlsli | 56 +-- ...ELAX_HitDistReconstruction.resources.hlsli | 34 +- .../Resources/RELAX_PrePass.resources.hlsli | 50 +-- ...RELAX_TemporalAccumulation.resources.hlsli | 160 ++++----- Shaders/Resources/SIGMA_Blur.resources.hlsli | 10 +- Shaders/Resources/SIGMA_Copy.resources.hlsli | 34 ++ ...IGMA_TemporalStabilization.resources.hlsli | 4 +- Shaders/Source/SIGMA_Copy.cs.hlsl | 18 + Shaders/Source/SIGMA_SmoothTiles.cs.hlsl | 19 + Source/Denoisers/Reference.hpp | 16 +- Source/Denoisers/Relax_Diffuse.hpp | 1 - Source/Denoisers/Sigma_Shadow.hpp | 48 ++- Source/Denoisers/Sigma_ShadowTranslucency.hpp | 50 ++- Source/InstanceImpl.cpp | 10 +- Source/Reblur.cpp | 23 +- Source/Relax.cpp | 18 +- Source/Sigma.cpp | 45 ++- UPDATE.md | 18 + 67 files changed, 1822 insertions(+), 1401 deletions(-) create mode 100644 Shaders/Include/SIGMA_Copy.hlsli rename Shaders/{Source/SIGMA_Shadow_SmoothTiles.cs.hlsl => Include/SIGMA_SmoothTiles.hlsli} (88%) create mode 100644 Shaders/Resources/SIGMA_Copy.resources.hlsli create mode 100644 Shaders/Source/SIGMA_Copy.cs.hlsl create mode 100644 Shaders/Source/SIGMA_SmoothTiles.cs.hlsl diff --git a/External/MathLib b/External/MathLib index 1e43e5f1..368dd254 160000 --- a/External/MathLib +++ b/External/MathLib @@ -1 +1 @@ -Subproject commit 1e43e5f1e98f9dd36bd2b8ceb0d331ffde752ba1 +Subproject commit 368dd2547aa62e4bff38ae923a846b13f7fed68e diff --git a/Include/NRD.h b/Include/NRD.h index 2a3cfe9e..d4087dbc 100644 --- a/Include/NRD.h +++ b/Include/NRD.h @@ -28,14 +28,12 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #include #define NRD_VERSION_MAJOR 4 -#define NRD_VERSION_MINOR 10 +#define NRD_VERSION_MINOR 11 #define NRD_VERSION_BUILD 0 -#define NRD_VERSION_DATE "9 October 2024" +#define NRD_VERSION_DATE "5 November 2024" -#if defined(_MSC_VER) - #define NRD_CALL __fastcall -#elif !defined(__aarch64__) && !defined(__x86_64) && (defined(__GNUC__) || defined (__clang__)) - #define NRD_CALL __attribute__((fastcall)) +#if defined(_WIN32) + #define NRD_CALL __stdcall #else #define NRD_CALL #endif diff --git a/Include/NRDDescs.h b/Include/NRDDescs.h index 41f8e907..512c9db0 100644 --- a/Include/NRDDescs.h +++ b/Include/NRDDescs.h @@ -11,7 +11,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #pragma once #define NRD_DESCS_VERSION_MAJOR 4 -#define NRD_DESCS_VERSION_MINOR 10 +#define NRD_DESCS_VERSION_MINOR 11 static_assert(NRD_VERSION_MAJOR == NRD_DESCS_VERSION_MAJOR && NRD_VERSION_MINOR == NRD_DESCS_VERSION_MINOR, "Please, update all NRD SDK files"); @@ -167,9 +167,9 @@ namespace nrd - Optional inputs are in () */ - // ============================================================================================================================= + //============================================================================================================================= // REBLUR - // ============================================================================================================================= + //============================================================================================================================= // INPUTS - IN_DIFF_RADIANCE_HITDIST (IN_DIFF_CONFIDENCE, IN_DISOCCLUSION_THRESHOLD_MIX) // OUTPUTS - OUT_DIFF_RADIANCE_HITDIST @@ -211,9 +211,9 @@ namespace nrd // OUTPUTS - OUT_DIFF_DIRECTION_HITDIST REBLUR_DIFFUSE_DIRECTIONAL_OCCLUSION, - // ============================================================================================================================= + //============================================================================================================================= // RELAX - // ============================================================================================================================= + //============================================================================================================================= // INPUTS - IN_DIFF_RADIANCE_HITDIST (IN_DIFF_CONFIDENCE, IN_DISOCCLUSION_THRESHOLD_MIX) // OUTPUTS - OUT_DIFF_RADIANCE_HITDIST @@ -239,9 +239,9 @@ namespace nrd // OUTPUTS - OUT_DIFF_SH0, OUT_DIFF_SH1, OUT_SPEC_SH0, OUT_SPEC_SH1 RELAX_DIFFUSE_SPECULAR_SH, - // ============================================================================================================================= + //============================================================================================================================= // SIGMA - // ============================================================================================================================= + //============================================================================================================================= // INPUTS - IN_PENUMBRA, OUT_SHADOW_TRANSLUCENCY // OUTPUTS - OUT_SHADOW_TRANSLUCENCY @@ -251,9 +251,9 @@ namespace nrd // OUTPUTS - OUT_SHADOW_TRANSLUCENCY SIGMA_SHADOW_TRANSLUCENCY, - // ============================================================================================================================= + //============================================================================================================================= // REFERENCE - // ============================================================================================================================= + //============================================================================================================================= // INPUTS - IN_SIGNAL // OUTPUTS - OUT_SIGNAL diff --git a/Include/NRDSettings.h b/Include/NRDSettings.h index 59e9e99f..6f3e377d 100644 --- a/Include/NRDSettings.h +++ b/Include/NRDSettings.h @@ -11,12 +11,25 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #pragma once #define NRD_SETTINGS_VERSION_MAJOR 4 -#define NRD_SETTINGS_VERSION_MINOR 10 +#define NRD_SETTINGS_VERSION_MINOR 11 static_assert(NRD_VERSION_MAJOR == NRD_SETTINGS_VERSION_MAJOR && NRD_VERSION_MINOR == NRD_SETTINGS_VERSION_MINOR, "Please, update all NRD SDK files"); namespace nrd { + //==================================================================================================================================================== + // COMMON + //==================================================================================================================================================== + + // IMPORTANT: despite that all NRD accumulation related settings are measured in "frames" (for simplicity), it's recommended to recalculate the + // number of accumulated frames from the accumulation time (in seconds). It allows to minimize lags if FPS is low and maximize IQ if FPS is high. + // All default values provided for 60 FPS. Each denoiser has a recommended accumulation time constant and absolute maximum of accumulated frames + // to clamp to: + inline uint32_t GetMaxAccumulatedFrameNum(float accumulationTime, float fps) + { + return (uint32_t)(accumulationTime * fps); + } + // Internally, NRD uses the following sequence based on "CommonSettings::frameIndex": // Even frame (0) Odd frame (1) ... // B W W B @@ -88,7 +101,7 @@ namespace nrd // If coordinate system moves with the camera, camera delta must be included to reflect camera motion float worldToViewMatrixPrev[16] = {}; - // (Optional) Previous world-space to current world-space matrix. It is for virtual normals, where a coordinate + // (Optional) previous world-space to current world-space matrix. It is for virtual normals, where a coordinate // system of the virtual space changes frame to frame, such as in a case of animated intermediary reflecting // surfaces when primary surface replacement is used for them. float worldPrevToWorldMatrix[16] = { @@ -114,13 +127,13 @@ namespace nrd // (>0) - viewZ = IN_VIEWZ * viewZScale (mostly for FP16 viewZ) float viewZScale = 1.0f; - // (ms) - user provided if > 0, otherwise - tracked internally + // (Optional) (ms) - user provided if > 0, otherwise - tracked internally float timeDeltaBetweenFrames = 0.0f; // (units > 0) - use TLAS or tracing range float denoisingRange = 500000.0f; - // [0.01; 0.02] - if relative distance difference is greater than the threshold (slope scaled), the accumulation process gets restarted + // [0.01; 0.02] - two samples considered occluded if relative distance difference is greater than this slope-scaled threshold float disocclusionThreshold = 0.01f; // [0.02; 0.2] - an alternative disocclusion threshold, which is mixed to based on: @@ -128,23 +141,27 @@ namespace nrd // - IN_DISOCCLUSION_THRESHOLD_MIX texture, if "isDisocclusionThresholdMixAvailable = true" (has higher priority and ignores "strandMaterialID") float disocclusionThresholdAlternate = 0.05f; - // [0; 1] - Enables "under-the-hood" tweaks for hair (and grass) denoising (requires "NormalEncoding::R10_G10_B10_A2_UNORM") - // Must respect material ID encoding + // (Optional) (>=0) - marks reflections of camera attached objects (requires "NormalEncoding::R10_G10_B10_A2_UNORM") + // This material ID marks reflections of objects attached to the camera, not objects themselves. Unfortunately, this is only an improvement + // for critical cases, but not a generic solution. A generic solution requires reflection MVs, which NRD currently doesn't ask for + float cameraAttachedReflectionMaterialID = 999.0f; + + // (Optional) (>=0) - marks hair (grass) geometry to enable "under-the-hood" tweaks (requires "NormalEncoding::R10_G10_B10_A2_UNORM") float strandMaterialID = 999.0f; - // (units > 0) Defines how "disocclusionThreshold" blends into "disocclusionThresholdAlternate" = pixelSize / (pixelSize + strandThickness) + // (units > 0) - defines how "disocclusionThreshold" blends into "disocclusionThresholdAlternate" = pixelSize / (pixelSize + strandThickness) float strandThickness = 80e-6f; // [0; 1] - enables "noisy input / denoised output" comparison float splitScreen = 0.0f; - // For internal needs + // (Optional) for internal needs uint16_t printfAt[2] = {9999, 9999}; // thread (pixel) position float debug = 0.0f; - // (pixels) - viewport origin - // IMPORTANT: gets applied only to non-noisy guides (aka g-buffer), including IN_DIFF_CONFIDENCE, IN_SPEC_CONFIDENCE, IN_DISOCCLUSION_THRESHOLD_MIX and IN_BASECOLOR_METALNESS - // Must be manually enabled via NRD_USE_VIEWPORT_OFFSET macro switch + // (Optional) (pixels) - viewport origin + // IMPORTANT: gets applied only to non-noisy guides (aka g-buffer), including IN_DIFF_CONFIDENCE, IN_SPEC_CONFIDENCE, + // IN_DISOCCLUSION_THRESHOLD_MIX and IN_BASECOLOR_METALNESS. Must be manually enabled via NRD_USE_VIEWPORT_OFFSET macro switch uint32_t rectOrigin[2] = {}; // A consecutive number @@ -170,9 +187,12 @@ namespace nrd bool enableValidation = false; }; + //==================================================================================================================================================== // REBLUR + //==================================================================================================================================================== const uint32_t REBLUR_MAX_HISTORY_FRAME_NUM = 63; + const float REBLUR_DEFAULT_ACCUMULATION_TIME = 0.5f; // sec // "Normalized hit distance" = saturate( "hit distance" / f ), where: // f = ( A + viewZ * B ) * lerp( 1.0, C, exp2( D * roughness ^ 2 ) ), see "NRD.hlsl/REBLUR_FrontEnd_GetNormHitDist" @@ -194,12 +214,12 @@ namespace nrd struct ReblurAntilagSettings { // [1; 3] - delta is reduced by local variance multiplied by this value - float luminanceSigmaScale = 2.0f; - float hitDistanceSigmaScale = 2.0f; + float luminanceSigmaScale = 3.0f; + float hitDistanceSigmaScale = 3.0f; - // (0; 1] - antilag = pow( antilag, power ) - float luminanceAntilagPower = 0.5f; - float hitDistanceAntilagPower = 1.0f; + // [1; 3] - antilag sensitivity (smaller values increase sensitivity) + float luminanceSensitivity = 2.0f; + float hitDistanceSensitivity = 2.0f; }; struct ReblurSettings @@ -207,12 +227,23 @@ namespace nrd HitDistanceParameters hitDistanceParameters = {}; ReblurAntilagSettings antilagSettings = {}; - // [0; REBLUR_MAX_HISTORY_FRAME_NUM] - maximum number of linearly accumulated frames (= FPS * "time of accumulation") + // [0; REBLUR_MAX_HISTORY_FRAME_NUM] - maximum number of linearly accumulated frames uint32_t maxAccumulatedFrameNum = 30; - // [0; REBLUR_MAX_HISTORY_FRAME_NUM] - maximum number of linearly accumulated frames in fast history (less than "maxAccumulatedFrameNum") + // [0; maxAccumulatedFrameNum) - maximum number of linearly accumulated frames for fast history + // Values ">= maxAccumulatedFrameNum" disable fast history + // Usually 5x times shorter than the main history uint32_t maxFastAccumulatedFrameNum = 6; + // [0; maxAccumulatedFrameNum] - maximum number of linearly accumulated frames for stabilized radiance + // "0" disables the stabilization pass + // Values ">= maxAccumulatedFrameNum" get clamped to "maxAccumulatedFrameNum" + uint32_t maxStabilizedFrameNum = REBLUR_MAX_HISTORY_FRAME_NUM; + + // [0; maxAccumulatedFrameNum] - maximum number of linearly accumulated frames for stabilized hit distance + // 0 - allows to reach parity with "REBLUR_OCCLUSION" + uint32_t maxStabilizedFrameNumForHitDistance = REBLUR_MAX_HISTORY_FRAME_NUM; + // [0; 3] - number of reconstructed frames after history reset (less than "maxFastAccumulatedFrameNum") uint32_t historyFixFrameNum = 3; @@ -227,7 +258,7 @@ namespace nrd float maxBlurRadius = 30.0f; // (normalized %) - base fraction of diffuse or specular lobe angle used to drive normal based rejection - float lobeAngleFraction = 0.2f; + float lobeAngleFraction = 0.15f; // (normalized %) - base fraction of center roughness used to drive roughness based rejection float roughnessFraction = 0.15f; @@ -235,17 +266,8 @@ namespace nrd // [0; 1] - if roughness < this, temporal accumulation becomes responsive and driven by roughness (useful for animated water) float responsiveAccumulationRoughnessThreshold = 0.0f; - // (normalized %) - stabilizes output, but adds temporal lag, at the same time more stabilization improves antilag (clean signals can use lower values) - // = N / (1 + N), where N is the number of accumulated frames - // 0 - disables the stabilization pass - float stabilizationStrength = 1.0f; // TODO: replace with number of accumulated frames - - // (normalized %) - same as "stabilizationStrength", but for hit distance (can't be > "stabilizationStrength", 0 - allows to reach parity with REBLUR_OCCLUSION) - // = N / (1 + N), where N is the number of accumulated frames - float hitDistanceStabilizationStrength = 1.0f; // TODO: replace with number of accumulated frames - - // (normalized %) - represents maximum allowed deviation from local tangent plane - float planeDistanceSensitivity = 0.005f; + // (normalized %) - represents maximum allowed deviation from the local tangent plane + float planeDistanceSensitivity = 0.02f; // IN_MV = lerp(IN_MV, specularMotion, smoothstep(this[0], this[1], specularProbability)) float specularProbabilityThresholdsForMvModification[2] = {0.5f, 0.9f}; @@ -265,7 +287,7 @@ namespace nrd // Boosts performance by sacrificing IQ bool enablePerformanceMode = false; - // Optional material index comparison: enableMaterialTest ? materialID[x] == materialID[y] : 1 (requires "NormalEncoding::R10_G10_B10_A2_UNORM") + // (Optional) material ID comparison: enableMaterialTest ? materialID[x] == materialID[y] : 1 (requires "NormalEncoding::R10_G10_B10_A2_UNORM") bool enableMaterialTestForDiffuse = false; bool enableMaterialTestForSpecular = false; @@ -278,22 +300,20 @@ namespace nrd bool usePrepassOnlyForSpecularMotionEstimation = false; }; + //==================================================================================================================================================== // RELAX + //==================================================================================================================================================== const uint32_t RELAX_MAX_HISTORY_FRAME_NUM = 255; + const float RELAX_DEFAULT_ACCUMULATION_TIME = 0.5f; // sec struct RelaxAntilagSettings { - // IMPORTANT: History acceleration and reset amounts for specular are made 2x-3x weaker than values for diffuse below - // due to specific specular logic that does additional history acceleration and reset - // [0; 1] - amount of history acceleration if history clamping happened in pixel float accelerationAmount = 0.3f; // (> 0) - history is being reset if delta between history and raw input is larger than spatial sigma + temporal sigma float spatialSigmaScale = 4.5f; - - // (> 0) - history is being reset if delta between history and raw input is larger than spatial sigma + temporal sigma float temporalSigmaScale = 0.5f; // [0; 1] - amount of history reset, 0.0 - no reset, 1.0 - full reset @@ -304,28 +324,36 @@ namespace nrd { RelaxAntilagSettings antilagSettings = {}; - // (pixels) - pre-accumulation spatial reuse pass blur radius (0 = disabled, must be used in case of probabilistic sampling) - float diffusePrepassBlurRadius = 30.0f; - float specularPrepassBlurRadius = 50.0f; - - // [0; RELAX_MAX_HISTORY_FRAME_NUM] - maximum number of linearly accumulated frames ( = FPS * "time of accumulation") + // [0; RELAX_MAX_HISTORY_FRAME_NUM] - maximum number of linearly accumulated frames uint32_t diffuseMaxAccumulatedFrameNum = 30; uint32_t specularMaxAccumulatedFrameNum = 30; - // [0; RELAX_MAX_HISTORY_FRAME_NUM] - maximum number of linearly accumulated frames in fast history (less than "maxAccumulatedFrameNum") + // [0; diffuseMaxAccumulatedFrameNum) - maximum number of linearly accumulated frames for diffuse fast history + // Values ">= diffuseMaxAccumulatedFrameNum" disable diffuse fast history + // Usually 5x times shorter than the main history uint32_t diffuseMaxFastAccumulatedFrameNum = 6; + + // [0; specularMaxAccumulatedFrameNum) - maximum number of linearly accumulated frames for specular fast history + // Values ">= specularMaxAccumulatedFrameNum" disable specular fast history + // Usually 5x times shorter than the main history uint32_t specularMaxFastAccumulatedFrameNum = 6; // [0; 3] - number of reconstructed frames after history reset (less than "maxFastAccumulatedFrameNum") uint32_t historyFixFrameNum = 3; + // (>= 0) - history length threshold below which spatial variance estimation will be executed + uint32_t spatialVarianceEstimationHistoryThreshold = 3; + + // (pixels) - pre-accumulation spatial reuse pass blur radius (0 = disabled, must be used in case of probabilistic sampling) + float diffusePrepassBlurRadius = 30.0f; + float specularPrepassBlurRadius = 50.0f; + // A-trous edge stopping Luminance sensitivity float diffusePhiLuminance = 2.0f; float specularPhiLuminance = 1.0f; // (normalized %) - base fraction of diffuse or specular lobe angle used to drive normal based rejection - float diffuseLobeAngleFraction = 0.5f; - float specularLobeAngleFraction = 0.5f; + float lobeAngleFraction = 0.5f; // (normalized %) - base fraction of center roughness used to drive roughness based rejection float roughnessFraction = 0.15f; @@ -342,9 +370,6 @@ namespace nrd // [1; 3] - standard deviation scale of color box for clamping main "slow" history to responsive "fast" history float historyClampingColorBoxSigmaScale = 2.0f; - // (>= 0) - history length threshold below which spatial variance estimation will be executed - uint32_t spatialVarianceEstimationHistoryThreshold = 3; - // [2; 8] - number of iterations for A-Trous wavelet transform uint32_t atrousIterationNum = 5; @@ -379,12 +404,17 @@ namespace nrd // Roughness based rejection bool enableRoughnessEdgeStopping = true; - // Optional material index comparison: enableMaterialTest ? materialID[x] == materialID[y] : 1 (requires "NormalEncoding::R10_G10_B10_A2_UNORM") + // (Optional) material ID comparison: enableMaterialTest ? materialID[x] == materialID[y] : 1 (requires "NormalEncoding::R10_G10_B10_A2_UNORM") bool enableMaterialTestForDiffuse = false; bool enableMaterialTestForSpecular = false; }; + //==================================================================================================================================================== // SIGMA + //==================================================================================================================================================== + + const uint32_t SIGMA_MAX_HISTORY_FRAME_NUM = 7; + const float SIGMA_DEFAULT_ACCUMULATION_TIME = 0.084f; // sec struct SigmaSettings { @@ -392,20 +422,24 @@ namespace nrd // IMPORTANT: it is needed only for directional light sources (sun) float lightDirection[3] = {0.0f, 0.0f, 0.0f}; - // (normalized %) - represents maximum allowed deviation from local tangent plane - float planeDistanceSensitivity = 0.005f; + // (normalized %) - represents maximum allowed deviation from the local tangent plane + float planeDistanceSensitivity = 0.02f; - // (normalized %) - stabilizes output, more stabilization improves antilag (clean signals can use lower values) - // 0 - disables the stabilization pass and makes denoising spatial only (no history) - // = N / (1 + N), where N is the number of accumulated frames - float stabilizationStrength = 1.0f; // TODO: replace with number of accumulated frames + // [0; SIGMA_MAX_HISTORY_FRAME_NUM] - maximum number of linearly accumulated frames + // 0 - disables the stabilization pass + uint32_t maxStabilizedFrameNum = 5; }; + //==================================================================================================================================================== // REFERENCE + //==================================================================================================================================================== + + const uint32_t REFERENCE_MAX_HISTORY_FRAME_NUM = 4095; + const float REFERENCE_DEFAULT_ACCUMULATION_TIME = 17.0f; // sec struct ReferenceSettings { - // (>= 0) - maximum number of linearly accumulated frames ( = FPS * "time of accumulation") - uint32_t maxAccumulatedFrameNum = 1024; + // (>= 0) - maximum number of linearly accumulated frames + uint32_t maxAccumulatedFrameNum = 1020; }; } diff --git a/Integration/NRDIntegration.hpp b/Integration/NRDIntegration.hpp index df3f13ae..7bb28169 100644 --- a/Integration/NRDIntegration.hpp +++ b/Integration/NRDIntegration.hpp @@ -567,6 +567,7 @@ void Integration::Dispatch(nri::CommandBuffer& commandBuffer, nri::DescriptorPoo { const ResourceDesc& nrdResource = dispatchDesc.resources[n]; + // Get texture nri::TextureBarrierDesc* nrdTexture = nullptr; if (nrdResource.type == ResourceType::TRANSIENT_POOL) nrdTexture = &m_TexturePool[nrdResource.indexInPool + instanceDesc.permanentPoolSize]; @@ -578,13 +579,19 @@ void Integration::Dispatch(nri::CommandBuffer& commandBuffer, nri::DescriptorPoo NRD_INTEGRATION_ASSERT(nrdTexture && nrdTexture->texture, "'userPool' entry can't be NULL if it's in use!"); } - const nri::AccessBits nextAccess = nrdResource.descriptorType == DescriptorType::TEXTURE ? nri::AccessBits::SHADER_RESOURCE : nri::AccessBits::SHADER_RESOURCE_STORAGE; - const nri::Layout nextLayout = nrdResource.descriptorType == DescriptorType::TEXTURE ? nri::Layout::SHADER_RESOURCE : nri::Layout::SHADER_RESOURCE_STORAGE; - bool isStateChanged = nextAccess != nrdTexture->after.access || nextLayout != nrdTexture->after.layout; - bool isStorageBarrier = nextAccess == nri::AccessBits::SHADER_RESOURCE_STORAGE && nrdTexture->after.access == nri::AccessBits::SHADER_RESOURCE_STORAGE; + // Prepare barrier + nri::AccessLayoutStage next = {}; + if (nrdResource.descriptorType == DescriptorType::TEXTURE) + next = {nri::AccessBits::SHADER_RESOURCE, nri::Layout::SHADER_RESOURCE, nri::StageBits::COMPUTE_SHADER}; + else + next = {nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::Layout::SHADER_RESOURCE_STORAGE, nri::StageBits::COMPUTE_SHADER}; + + bool isStateChanged = next.access != nrdTexture->after.access || next.layout != nrdTexture->after.layout; + bool isStorageBarrier = next.access == nri::AccessBits::SHADER_RESOURCE_STORAGE && nrdTexture->after.access == nri::AccessBits::SHADER_RESOURCE_STORAGE; if (isStateChanged || isStorageBarrier) - transitions[transitionBarriers.textureNum++] = nri::TextureBarrierFromState(*nrdTexture, {nextAccess, nextLayout}, 0, 1); + transitions[transitionBarriers.textureNum++] = nri::TextureBarrierFromState(*nrdTexture, next); + // Create descriptor uint64_t resource = m_NRI->GetTextureNativeObject(*nrdTexture->texture); uint64_t key = CreateDescriptorKey(resource, isStorage); const auto& entry = m_CachedDescriptors.find(key); @@ -607,6 +614,9 @@ void Integration::Dispatch(nri::CommandBuffer& commandBuffer, nri::DescriptorPoo } } + // Barriers + m_NRI->CmdBarrier(commandBuffer, transitionBarriers); + // Allocating descriptor sets uint32_t descriptorSetSamplersIndex = instanceDesc.constantBufferSpaceIndex == instanceDesc.samplersSpaceIndex ? 0 : 1; uint32_t descriptorSetResourcesIndex = instanceDesc.resourcesSpaceIndex == instanceDesc.constantBufferSpaceIndex ? 0 : (instanceDesc.resourcesSpaceIndex == instanceDesc.samplersSpaceIndex ? descriptorSetSamplersIndex : descriptorSetSamplersIndex + 1); @@ -664,7 +674,6 @@ void Integration::Dispatch(nri::CommandBuffer& commandBuffer, nri::DescriptorPoo m_NRI->UpdateDescriptorRanges(*descriptorSets[descriptorSetResourcesIndex], instanceDesc.samplersSpaceIndex == instanceDesc.resourcesSpaceIndex ? 1 : 0, pipelineDesc.resourceRangesNum, resourceRanges); // Rendering - m_NRI->CmdBarrier(commandBuffer, transitionBarriers); m_NRI->CmdSetPipelineLayout(commandBuffer, *pipelineLayout); nri::Pipeline* pipeline = m_Pipelines[dispatchDesc.pipelineIndex]; diff --git a/README.md b/README.md index 87cd8ce0..7a0b9ca3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# NVIDIA REAL-TIME DENOISERS v4.10.0 (NRD) +# NVIDIA REAL-TIME DENOISERS v4.11.0 (NRD) [![Build NRD SDK](https://github.com/NVIDIAGameWorks/RayTracingDenoiser/actions/workflows/build.yml/badge.svg)](https://github.com/NVIDIAGameWorks/RayTracingDenoiser/actions/workflows/build.yml) @@ -15,11 +15,11 @@ For quick starting see *[NRD sample](https://github.com/NVIDIAGameWorks/NRDSampl - *RELAX* - A-trous based denoiser, has been designed for *[RTXDI (RTX Direct Illumination)](https://developer.nvidia.com/rtxdi)* - *SIGMA* - shadow-only denoiser -Performance on RTX 4080 @ 1440p (native resolution, default denoiser settings): -- `REBLUR_DIFFUSE_SPECULAR` - 2.45 ms -- `RELAX_DIFFUSE_SPECULAR` - 2.90 ms -- `SIGMA_SHADOW` - 0.35 ms (0.25 ms if temporal stabilization is off) -- `SIGMA_SHADOW_TRANSLUCENCY` - 0.45 ms (0.32 ms if temporal stabilization is off) +Performance on RTX 4080 @ 1440p (native resolution, default denoiser settings, `NormalEncoding::R10_G10_B10_A2_UNORM`): +- `REBLUR_DIFFUSE_SPECULAR` - 2.40 ms (2.15 in performance mode) +- `RELAX_DIFFUSE_SPECULAR` - 2.95 ms +- `SIGMA_SHADOW` - 0.40 ms +- `SIGMA_SHADOW_TRANSLUCENCY` - 0.50 ms Supported signal types: - *RELAX*: @@ -322,14 +322,14 @@ The *Persistent* column (matches *NRD Permanent pool*) indicates how much of the | | REBLUR_DIFFUSE_SPECULAR_OCCLUSION | 67.94 | 38.12 | 29.81 | | | REBLUR_DIFFUSE_SPECULAR_SH | 266.12 | 105.62 | 160.50 | | | REBLUR_DIFFUSE_DIRECTIONAL_OCCLUSION | 84.56 | 42.25 | 42.31 | -| | RELAX_DIFFUSE | 99.25 | 63.31 | 35.94 | +| | RELAX_DIFFUSE | 90.81 | 54.88 | 35.94 | | | RELAX_DIFFUSE_SH | 158.31 | 88.62 | 69.69 | | | RELAX_SPECULAR | 101.44 | 63.38 | 38.06 | | | RELAX_SPECULAR_SH | 168.94 | 97.12 | 71.81 | | | RELAX_DIFFUSE_SPECULAR | 168.94 | 97.12 | 71.81 | | | RELAX_DIFFUSE_SPECULAR_SH | 303.94 | 164.62 | 139.31 | -| | SIGMA_SHADOW | 15.00 | 0.00 | 15.00 | -| | SIGMA_SHADOW_TRANSLUCENCY | 33.94 | 0.00 | 33.94 | +| | SIGMA_SHADOW | 31.88 | 8.44 | 23.44 | +| | SIGMA_SHADOW_TRANSLUCENCY | 50.81 | 8.44 | 42.38 | | | REFERENCE | 33.75 | 33.75 | 0.00 | | | | | | | | 1440p | REBLUR_DIFFUSE | 150.06 | 75.00 | 75.06 | @@ -342,14 +342,14 @@ The *Persistent* column (matches *NRD Permanent pool*) indicates how much of the | | REBLUR_DIFFUSE_SPECULAR_OCCLUSION | 120.06 | 67.50 | 52.56 | | | REBLUR_DIFFUSE_SPECULAR_SH | 472.56 | 187.50 | 285.06 | | | REBLUR_DIFFUSE_DIRECTIONAL_OCCLUSION | 150.06 | 75.00 | 75.06 | -| | RELAX_DIFFUSE | 176.31 | 112.50 | 63.81 | +| | RELAX_DIFFUSE | 161.31 | 97.50 | 63.81 | | | RELAX_DIFFUSE_SH | 281.31 | 157.50 | 123.81 | | | RELAX_SPECULAR | 180.06 | 112.50 | 67.56 | | | RELAX_SPECULAR_SH | 300.06 | 172.50 | 127.56 | | | RELAX_DIFFUSE_SPECULAR | 300.06 | 172.50 | 127.56 | | | RELAX_DIFFUSE_SPECULAR_SH | 540.06 | 292.50 | 247.56 | -| | SIGMA_SHADOW | 26.38 | 0.00 | 26.38 | -| | SIGMA_SHADOW_TRANSLUCENCY | 60.12 | 0.00 | 60.12 | +| | SIGMA_SHADOW | 56.38 | 15.00 | 41.38 | +| | SIGMA_SHADOW_TRANSLUCENCY | 90.12 | 15.00 | 75.12 | | | REFERENCE | 60.00 | 60.00 | 0.00 | | | | | | | | 2160p | REBLUR_DIFFUSE | 318.88 | 159.38 | 159.50 | @@ -362,14 +362,14 @@ The *Persistent* column (matches *NRD Permanent pool*) indicates how much of the | | REBLUR_DIFFUSE_SPECULAR_OCCLUSION | 255.06 | 143.44 | 111.62 | | | REBLUR_DIFFUSE_SPECULAR_SH | 1004.12 | 398.44 | 605.69 | | | REBLUR_DIFFUSE_DIRECTIONAL_OCCLUSION | 318.88 | 159.38 | 159.50 | -| | RELAX_DIFFUSE | 374.69 | 239.12 | 135.56 | +| | RELAX_DIFFUSE | 342.81 | 207.25 | 135.56 | | | RELAX_DIFFUSE_SH | 597.81 | 334.75 | 263.06 | | | RELAX_SPECULAR | 382.69 | 239.12 | 143.56 | | | RELAX_SPECULAR_SH | 637.69 | 366.62 | 271.06 | | | RELAX_DIFFUSE_SPECULAR | 637.69 | 366.62 | 271.06 | | | RELAX_DIFFUSE_SPECULAR_SH | 1147.69 | 621.62 | 526.06 | -| | SIGMA_SHADOW | 56.19 | 0.00 | 56.19 | -| | SIGMA_SHADOW_TRANSLUCENCY | 127.81 | 0.00 | 127.81 | +| | SIGMA_SHADOW | 119.94 | 31.88 | 88.06 | +| | SIGMA_SHADOW_TRANSLUCENCY | 191.56 | 31.88 | 159.69 | | | REFERENCE | 127.50 | 127.50 | 0.00 | # INTEGRATION VARIANTS @@ -636,7 +636,7 @@ When denoising reflections in pure mirrors, some advantages can be reached if *N Notes, requirements and restrictions: - the primary hit (0th bounce) gets replaced with the first "non-pure mirror" hit in the bounce chain - this hit becomes *PSR* - all associated data in the g-buffer gets replaced by *PSR* data -- the camera "sees" PSR like the mirror surface in-between don't exist. This space is called virtual world space +- the camera "sees" PSR like the mirror surface in-between doesn't exist. This space is called virtual world space - virtual space position lies on the same view vector as the primary hit position, but the position is elongated. Elongation depends on `hitT` and curvature at hits, starting from the primary hit - virtual space normal is the normal at *PSR* hit mirrored several times in the reversed order until the primary hit is reached - *PSR* data is NOT always data at the *PSR* hit! @@ -674,7 +674,7 @@ IN_MV = GetMotionAt( B ); ## INTERACTION WITH FRAME GENERATION TECHNIQUES -Frame generation (FG) techniques boost FPS by interpolating between 2 last available frames. *NRD* works better when framerate 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. +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. ## HAIR DENOISING TIPS @@ -704,7 +704,7 @@ Hair strands tangent vectors *can't* be used as "normals guide" for *NRD* due to **[NRD]** *NRD* requires non-jittered matrices. -**[NRD]** Most of denoisers do not write into output pixels outside of `CommonSettings::denoisingRange`. +**[NRD]** Most denoisers do not write into output pixels outside of `CommonSettings::denoisingRange`. **[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. @@ -771,7 +771,7 @@ maxAccumulatedFrameNum > maxFastAccumulatedFrameNum > historyFixFrameNum **[SIGMA]** Using "blue" noise helps to minimize shadow shimmering and flickering. It works best if the pattern has limited number of animated frames (4-8) or it is static on the screen. -**[SIGMA]** *SIGMA* can be used for multi-light shadow denoising if applied "per light". `SigmaSettings::stabilizationStrength` can be set to `0` to disable temporal history. It provides the followinmg benefits: +**[SIGMA]** *SIGMA* can be used for multi-light shadow denoising if applied "per light". `SigmaSettings::stabilizationStrength` can be set to `0` to disable temporal history. It provides the following benefits: - light count independent memory usage - no need to manage history buffers for lights diff --git a/Resources/Version.h b/Resources/Version.h index 376edbad..65034ecf 100644 --- a/Resources/Version.h +++ b/Resources/Version.h @@ -22,7 +22,7 @@ Versioning rules: */ #define VERSION_MAJOR 4 -#define VERSION_MINOR 10 +#define VERSION_MINOR 11 #define VERSION_BUILD 0 #define VERSION_STRING STR(VERSION_MAJOR.VERSION_MINOR.VERSION_BUILD encoding=NRD_NORMAL_ENCODING.NRD_ROUGHNESS_ENCODING) diff --git a/Shaders.cfg b/Shaders.cfg index 950ae21a..841ee6d7 100644 --- a/Shaders.cfg +++ b/Shaders.cfg @@ -230,14 +230,15 @@ RELAX_DiffuseSpecularSh_PrePass.cs.hlsl -T cs RELAX_DiffuseSpecularSh_SplitScreen.cs.hlsl -T cs RELAX_DiffuseSpecularSh_TemporalAccumulation.cs.hlsl -T cs RELAX_Validation.cs.hlsl -T cs -SIGMA_ShadowTranslucency_Blur.cs.hlsl -T cs -SIGMA_ShadowTranslucency_ClassifyTiles.cs.hlsl -T cs -SIGMA_ShadowTranslucency_PostBlur.cs.hlsl -T cs -SIGMA_ShadowTranslucency_SplitScreen.cs.hlsl -T cs -SIGMA_ShadowTranslucency_TemporalStabilization.cs.hlsl -T cs +SIGMA_Copy.cs.hlsl -T cs +SIGMA_SmoothTiles.cs.hlsl -T cs SIGMA_Shadow_Blur.cs.hlsl -T cs SIGMA_Shadow_ClassifyTiles.cs.hlsl -T cs SIGMA_Shadow_PostBlur.cs.hlsl -T cs -SIGMA_Shadow_SmoothTiles.cs.hlsl -T cs SIGMA_Shadow_SplitScreen.cs.hlsl -T cs SIGMA_Shadow_TemporalStabilization.cs.hlsl -T cs +SIGMA_ShadowTranslucency_Blur.cs.hlsl -T cs +SIGMA_ShadowTranslucency_ClassifyTiles.cs.hlsl -T cs +SIGMA_ShadowTranslucency_PostBlur.cs.hlsl -T cs +SIGMA_ShadowTranslucency_SplitScreen.cs.hlsl -T cs +SIGMA_ShadowTranslucency_TemporalStabilization.cs.hlsl -T cs diff --git a/Shaders/Include/Common.hlsli b/Shaders/Include/Common.hlsli index 2a2c6ccb..4ebdf00a 100644 --- a/Shaders/Include/Common.hlsli +++ b/Shaders/Include/Common.hlsli @@ -8,6 +8,19 @@ distribution of this software and related documentation without an express license agreement from NVIDIA CORPORATION is strictly prohibited. */ +//================================================================================================================== +// Naming convention +//================================================================================================================== +// g[In/Prev/History/Out]_[A]_[B] +// gIn_ - an input +// gPrev_ - an input from the previous frame ( looks better than "gInPrev_" ) +// gHistory_ - an input from the previous frame, which is a history buffer ( looks better than "gInHistory_" ) +// gOut_ - an output +// _ - means "and" ( when used in-between A and B ) +// s_ - shared memory +// Fast - fast history +// Noisy - noisy input, where an emphasis needed + #include "Poisson.hlsli" // Constants @@ -50,20 +63,24 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #define NRD_USE_VIEWPORT_OFFSET 0 // enable if "CommonSettings::rectOrigin" is used // Settings -#define NRD_BILATERAL_WEIGHT_CUTOFF 0.03 +#define NRD_DISOCCLUSION_THRESHOLD 0.02 // normalized % // TODO: use CommonSettings::disocclusionThreshold? #define NRD_CATROM_SHARPNESS 0.5 // [ 0; 1 ], 0.5 matches Catmull-Rom #define NRD_RADIANCE_COMPRESSION_MODE 3 // 0-4, specular color compression for spatial passes #define NRD_EXP_WEIGHT_DEFAULT_SCALE 3.0 #define NRD_ROUGHNESS_SENSITIVITY 0.01 // smaller => more sensitive #define NRD_CURVATURE_Z_THRESHOLD 0.1 // normalized % #define NRD_MAX_ALLOWED_VIRTUAL_MOTION_ACCELERATION 15.0 // keep relatively high to avoid ruining concave mirrors +#define NRD_MAX_PERCENT_OF_LOBE_VOLUME 0.75 // normalized % #if( NRD_NORMAL_ENCODING < NRD_NORMAL_ENCODING_R10G10B10A2_UNORM ) #define NRD_NORMAL_ENCODING_ERROR ( 1.50 / 255.0 ) + #define STOCHASTIC_BILINEAR_FILTER gLinearClamp #elif( NRD_NORMAL_ENCODING == NRD_NORMAL_ENCODING_R10G10B10A2_UNORM ) #define NRD_NORMAL_ENCODING_ERROR ( 0.75 / 255.0 ) + #define STOCHASTIC_BILINEAR_FILTER gNearestClamp #else #define NRD_NORMAL_ENCODING_ERROR ( 0.50 / 255.0 ) + #define STOCHASTIC_BILINEAR_FILTER gLinearClamp #endif //================================================================================================================== @@ -281,9 +298,11 @@ float GetSpecMagicCurve( float roughness, float power = 0.25 ) float ComputeParallaxInPixels( float3 X, float2 uvForZeroParallax, float4x4 mWorldToClip, float2 rectSize ) { - // Produce same results: - // - ComputeParallaxInPixels( Xprev - gCameraDelta, gOrthoMode == 0.0 ? pixelUv : smbPixelUv, gWorldToClip, gRectSize ); - // - ComputeParallaxInPixels( Xprev + gCameraDelta, gOrthoMode == 0.0 ? smbPixelUv : pixelUv, gWorldToClipPrev, gRectSize ); + // Both produce same results, but behavior is different on objects attached to the camera: + // non-0 parallax on pure translations, 0 parallax on pure rotations + // ComputeParallaxInPixels( Xprev + gCameraDelta, gOrthoMode == 0.0 ? smbPixelUv : pixelUv, gWorldToClipPrev, gRectSize ); + // 0 parallax on translations, non-0 parallax on pure rotations + // ComputeParallaxInPixels( Xprev - gCameraDelta, gOrthoMode == 0.0 ? pixelUv : smbPixelUv, gWorldToClip, gRectSize ); float2 uv = Geometry::GetScreenUv( mWorldToClip, X ); float2 parallaxInUv = uv - uvForZeroParallax; @@ -317,19 +336,9 @@ float GetColorCompressionExposureForSpatialPasses( float roughness ) #endif } -float GetSpecLobeTanHalfAngle( float roughness, float percentOfVolume = 0.75 ) -{ - // TODO: ideally should migrate to fixed "ImportanceSampling::GetSpecularLobeTanHalfAngle", but since - // denoisers behavior have been tuned for the old version, let's continue to use it in critical places - roughness = saturate( roughness ); - percentOfVolume = saturate( percentOfVolume ); - - return roughness * roughness * percentOfVolume / ( 1.0 - percentOfVolume + NRD_EPS ); -} - float2 StochasticBilinear( float2 uv, float2 texSize ) { -#if( REBLUR_USE_STF == 1 ) +#if( REBLUR_USE_STF == 1 && NRD_NORMAL_ENCODING == NRD_NORMAL_ENCODING_R10G10B10A2_UNORM ) // Requires: Rng::Hash::Initialize( pixelPos, gFrameIndex ) Filtering::Bilinear f = Filtering::GetBilinearFilter( uv, texSize ); @@ -397,7 +406,7 @@ float2 GetKernelSampleCoordinates( float4x4 mToClip, float3 offset, float3 X, fl offset.xy *= offset.z; #endif - // We can't rotate T and B instead, because T is skewed + // We can't rotate T and B instead, because they can be skewed offset.xy = Geometry::RotateVector( rotator, offset.xy ); float3 p = X + T * offset.x + B * offset.y; @@ -412,13 +421,24 @@ float2 GetKernelSampleCoordinates( float4x4 mToClip, float3 offset, float3 X, fl // Weight parameters +float GetNormalWeightParam( float nonLinearAccumSpeed, float lobeAngleFraction, float roughness = 1.0 ) +{ + float percentOfVolume = NRD_MAX_PERCENT_OF_LOBE_VOLUME * lerp( lobeAngleFraction, 1.0, nonLinearAccumSpeed ); + float tanHalfAngle = ImportanceSampling::GetSpecularLobeTanHalfAngle( roughness, percentOfVolume ); + + float angle = atan( tanHalfAngle ); + angle = max( angle, NRD_NORMAL_ENCODING_ERROR ); + + return 1.0 / angle; +} + float2 GetGeometryWeightParams( float planeDistSensitivity, float frustumSize, float3 Xv, float3 Nv, float nonLinearAccumSpeed ) { - float relaxation = lerp( 1.0, 0.25, nonLinearAccumSpeed ); - float a = relaxation / ( planeDistSensitivity * frustumSize ); - float b = -dot( Nv, Xv ) * a; + float norm = planeDistSensitivity * frustumSize; + float a = 1.0 / norm; + float b = dot( Nv, Xv ) * a; - return float2( a, b ); + return float2( a, -b ); } float2 GetHitDistanceWeightParams( float hitDist, float nonLinearAccumSpeed, float roughness = 1.0 ) @@ -426,7 +446,7 @@ float2 GetHitDistanceWeightParams( float hitDist, float nonLinearAccumSpeed, flo // IMPORTANT: since this weight is exponential, 3% can lead to leaks from bright objects in reflections. // Even 1% is not enough in some cases, but using a lower value makes things even more fragile float smc = GetSpecMagicCurve( roughness ); - float norm = lerp( NRD_EPS, 1.0, min( nonLinearAccumSpeed, smc ) ); + float norm = lerp( 0.0005, 1.0, min( nonLinearAccumSpeed, smc ) ); float a = 1.0 / norm; float b = hitDist * a; @@ -468,12 +488,12 @@ float2 GetRelaxedRoughnessWeightParams( float m, float fraction = 1.0, float sen ExpApprox( -NRD_EXP_WEIGHT_DEFAULT_SCALE * abs( ( x ) * px + py ) ) // A good choice for non noisy data -// IMPORTANT: cutoffs are needed to minimize floating point precision drifting +// Previously "Math::SmoothStep( 0.999, 0.001" was used, but it seems to be not needed anymore #define ComputeNonExponentialWeight( x, px, py ) \ - Math::SmoothStep( 0.999, 0.001, abs( ( x ) * px + py ) ) + Math::SmoothStep( 1.0, 0.0, abs( ( x ) * px + py ) ) #define ComputeNonExponentialWeightWithSigma( x, px, py, sigma ) \ - Math::SmoothStep( 0.999, 0.001, abs( ( x ) * px + py ) - sigma * px ) + Math::SmoothStep( 1.0, 0.0, abs( ( x ) * px + py ) - sigma * px ) #if( NRD_USE_EXPONENTIAL_WEIGHTS == 1 ) #define ComputeWeight( x, px, py ) ComputeExponentialWeight( x, px, py ) @@ -488,28 +508,27 @@ float GetGaussianWeight( float r ) // Encoding precision aware weight functions ( for reprojection ) -float GetEncodingAwareNormalWeight( float3 Ncurr, float3 Nprev, float maxAngle, float curvatureAngle, float thresholdAngle ) +float GetEncodingAwareNormalWeight( float3 Ncurr, float3 Nprev, float maxAngle, float curvatureAngle, float thresholdAngle, bool remap = false ) { - // Anything below "thresholdAngle" is ignored - curvatureAngle += thresholdAngle; - float cosa = dot( Ncurr, Nprev ); - - float a = 1.0 / maxAngle; - float d = Math::AcosApprox( cosa ); - - float w = Math::SmoothStep01( 1.0 - ( d - curvatureAngle ) * a ); + float angle = Math::AcosApprox( cosa ); + float w = Math::SmoothStep01( 1.0 - ( angle - curvatureAngle - thresholdAngle ) / maxAngle ); // Needed to mitigate imprecision issues because prev normals are RGBA8 ( test 3, 43 if roughness is low ) - w = Math::SmoothStep( 0.05, 0.95, w ); + if( remap ) // TODO: needed only for RELAX + w = Math::SmoothStep( 0.05, 0.95, w ); return w; } -// Only for checkerboard resolve and some "lazy" comparisons +// Only for viewZ comparisons for close to each other pixels ( not sparse filters! ) + +float GetDisocclusionThreshold( float disocclusionThreshold, float frustumSize, float NoV ) +{ + return frustumSize * saturate( disocclusionThreshold / max( 0.01, NoV ) ); +} -#define GetBilateralWeight( z, zc ) \ - Math::LinearStep( NRD_BILATERAL_WEIGHT_CUTOFF, 0.0, abs( z - zc ) * rcp( max( z, zc ) ) ) +#define GetDisocclusionWeight( z, z0, disocclusionThreshold ) step( abs( z - z0 ), disocclusionThreshold ) // Upsampling diff --git a/Shaders/Include/NRD.hlsli b/Shaders/Include/NRD.hlsli index 792488e7..9c97aa3e 100644 --- a/Shaders/Include/NRD.hlsli +++ b/Shaders/Include/NRD.hlsli @@ -541,7 +541,7 @@ float4 NRD_FrontEnd_UnpackNormalAndRoughness( float4 p, out float materialID ) r.xyz = _NRD_DecodeUnitVector( p.xy, false, false ); r.w = p.z; - materialID = p.w; + materialID = p.w * 3.0; #else #if( NRD_NORMAL_ENCODING == NRD_NORMAL_ENCODING_RGBA8_UNORM || NRD_NORMAL_ENCODING == NRD_NORMAL_ENCODING_RGBA16_UNORM ) p.xyz = p.xyz * 2.0 - 1.0; @@ -550,7 +550,7 @@ float4 NRD_FrontEnd_UnpackNormalAndRoughness( float4 p, out float materialID ) r.xyz = p.xyz; r.w = p.w; - materialID = 0; + materialID = 0.0; #endif r.xyz = _NRD_SafeNormalize( r.xyz ); diff --git a/Shaders/Include/REBLUR_Blur.hlsli b/Shaders/Include/REBLUR_Blur.hlsli index 5595dea5..9764d154 100644 --- a/Shaders/Include/REBLUR_Blur.hlsli +++ b/Shaders/Include/REBLUR_Blur.hlsli @@ -36,11 +36,13 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float2 pixelUv = float2( pixelPos + 0.5 ) * gRectSizeInv; float3 Xv = Geometry::ReconstructViewPosition( pixelUv, gFrustum, viewZ, gOrthoMode ); - float4 rotator = GetBlurKernelRotation( REBLUR_BLUR_ROTATOR_MODE, pixelPos, gRotator, gFrameIndex ); float3 Vv = GetViewVector( Xv, true ); float NoV = abs( dot( Nv, Vv ) ); + const float frustumSize = GetFrustumSize( gMinRectDimMulUnproject, gOrthoMode, viewZ ); + const float4 rotator = GetBlurKernelRotation( REBLUR_BLUR_ROTATOR_MODE, pixelPos, gRotator, gFrameIndex ); + // Spatial filtering #define REBLUR_SPATIAL_MODE REBLUR_BLUR diff --git a/Shaders/Include/REBLUR_Common.hlsli b/Shaders/Include/REBLUR_Common.hlsli index 75928046..59e46687 100644 --- a/Shaders/Include/REBLUR_Common.hlsli +++ b/Shaders/Include/REBLUR_Common.hlsli @@ -8,24 +8,13 @@ distribution of this software and related documentation without an express license agreement from NVIDIA CORPORATION is strictly prohibited. */ -// Spatial filtering - -#define REBLUR_PRE_BLUR 0 -#define REBLUR_BLUR 1 -#define REBLUR_POST_BLUR 2 - -// Storage - -#define REBLUR_MAX_ACCUM_FRAME_NUM 63.0 -#define REBLUR_ACCUMSPEED_BITS 7 // "( 1 << REBLUR_ACCUMSPEED_BITS ) - 1" must be >= REBLUR_MAX_ACCUM_FRAME_NUM -#define REBLUR_MATERIALID_BITS ( 16 - REBLUR_ACCUMSPEED_BITS - REBLUR_ACCUMSPEED_BITS ) - // Internal data ( from the previous frame ) uint PackInternalData( float diffAccumSpeed, float specAccumSpeed, float materialID ) { - float3 t = float3( diffAccumSpeed, specAccumSpeed, materialID ); - t.xy /= REBLUR_MAX_ACCUM_FRAME_NUM; + float3 t; + t.xy = float2( diffAccumSpeed, specAccumSpeed ) / REBLUR_MAX_ACCUM_FRAME_NUM; + t.z = materialID / REBLUR_MAX_MATERIALID_NUM; uint p = Packing::RgbaToUint( t.xyzz, REBLUR_ACCUMSPEED_BITS, REBLUR_ACCUMSPEED_BITS, REBLUR_MATERIALID_BITS, 0 ); @@ -36,6 +25,7 @@ float3 UnpackInternalData( uint p ) { float3 t = Packing::UintToRgba( p, REBLUR_ACCUMSPEED_BITS, REBLUR_ACCUMSPEED_BITS, REBLUR_MATERIALID_BITS, 0 ).xyz; t.xy *= REBLUR_MAX_ACCUM_FRAME_NUM; + t.z *= REBLUR_MAX_MATERIALID_NUM; return t; } @@ -251,21 +241,34 @@ float GetLumaScale( float currLuma, float newLuma ) #endif -float ComputeAntilag( REBLUR_TYPE history, REBLUR_TYPE signal, REBLUR_TYPE sigma, float4 antilagParams, float accumSpeed ) +float ComputeAntilag( REBLUR_TYPE history, REBLUR_TYPE avg, REBLUR_TYPE sigma, float accumSpeed ) { - float2 slow = float2( GetLuma( history ), ExtractHitDist( history ) ); - float2 fast = float2( GetLuma( signal ), ExtractHitDist( signal ) ); - float2 s = float2( GetLuma( sigma ), ExtractHitDist( sigma ) ); - - float2 a = abs( slow - fast ) - antilagParams.xy * s - NRD_EPS; - float2 b = max( slow, fast ) + antilagParams.xy * s + NRD_EPS; - float2 d = a / b; - - d = Math::SmoothStep01( 1.0 - d ); - d = Math::Pow01( d, antilagParams.zw ); + // Tests 4, 36, 44, 47, 95 ( no SHARC, stop animation ) + float2 h = float2( GetLuma( history ), ExtractHitDist( history ) ); + float2 a = float2( GetLuma( avg ), ExtractHitDist( avg ) ); + float2 s = float2( GetLuma( sigma ), ExtractHitDist( sigma ) ) * gAntilagParams.xy; + float2 magic = gAntilagParams.zw * gFramerateScale * gFramerateScale; + + #if( REBLUR_ANTILAG_MODE == 0 ) + // Old mode, but uses better threshold ( not bad ) + float2 x = abs( h - a ) - s - NRD_EPS; + float2 y = max( h, a ) + s + NRD_EPS; + float2 d = x / y; + + d = Math::LinearStep( magic / ( 1.0 + accumSpeed ), 0.0, d ); + #elif( REBLUR_ANTILAG_MODE == 1 ) + // New mode, but overly reactive at low FPS ( undesired ) + float2 hc = Color::Clamp( a, s, h ); + float2 d = abs( h - hc ) / ( max( h, hc ) + NRD_EPS ); + + d = Math::LinearStep( magic / ( 1.0 + accumSpeed ), 0.0, d ); + #else + // New mode, pretends to respect "no harm" idiom ( best? ) + float2 hc = Color::Clamp( a, s, h ); + float2 d = abs( h - hc ) / ( max( h, hc ) + NRD_EPS ); - // Needed at least for test 156, especially when motion is accelerated - d = lerp( 1.0, d, GetFadeBasedOnAccumulatedFrames( accumSpeed ) ); + d = 1.0 / ( 1.0 + d * accumSpeed / magic ); + #endif return REBLUR_SHOW == 0 ? min( d.x, d.y ) : 1.0; } @@ -297,14 +300,6 @@ float2x3 GetKernelBasis( float3 D, float3 N, float NoD, float roughness = 1.0, f // Weight parameters -float GetNormalWeightParams( float nonLinearAccumSpeed, float roughness = 1.0 ) -{ - float percentOfVolume = REBLUR_MAX_PERCENT_OF_LOBE_VOLUME * lerp( gLobeAngleFraction, 1.0, nonLinearAccumSpeed ); - float angle = atan( ImportanceSampling::GetSpecularLobeTanHalfAngle( roughness, percentOfVolume ) ); - - return 1.0 / max( angle, REBLUR_NORMAL_ULP ); -} - float2 GetTemporalAccumulationParams( float isInScreenMulFootprintQuality, float accumSpeed ) { accumSpeed *= REBLUR_SAMPLES_PER_FRAME; @@ -316,7 +311,7 @@ float2 GetTemporalAccumulationParams( float isInScreenMulFootprintQuality, float return float2( w, 1.0 + 3.0 * gFramerateScale * w ); } -// Weights +// Filtering void BicubicFilterNoCornersWithFallbackToBilinearFilterWithCustomWeights( float2 samplePos, float2 invResourceSize, diff --git a/Shaders/Include/REBLUR_Common_DiffuseSpatialFilter.hlsli b/Shaders/Include/REBLUR_Common_DiffuseSpatialFilter.hlsli index 1a86a92a..835037fd 100644 --- a/Shaders/Include/REBLUR_Common_DiffuseSpatialFilter.hlsli +++ b/Shaders/Include/REBLUR_Common_DiffuseSpatialFilter.hlsli @@ -41,7 +41,6 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. // Hit distance factor ( tests 53, 76, 95, 120 ) float hitDistScale = _REBLUR_GetHitDistanceNormalization( viewZ, gHitDistParams, 1.0 ); float hitDist = ExtractHitDist( diff ) * hitDistScale; - float frustumSize = GetFrustumSize( gMinRectDimMulUnproject, gOrthoMode, viewZ ); float hitDistFactor = GetHitDistFactor( hitDist, frustumSize ); // Blur radius @@ -68,19 +67,29 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. // Weights float2 geometryWeightParams = GetGeometryWeightParams( gPlaneDistSensitivity, frustumSize, Xv, Nv, diffNonLinearAccumSpeed ); - float normalWeightParams = GetNormalWeightParams( diffNonLinearAccumSpeed ) / fractionScale; - float2 px = float2( geometryWeightParams.x, normalWeightParams ); - float2 py = float2( geometryWeightParams.y, 0.0 ); + float normalWeightParam = GetNormalWeightParam( diffNonLinearAccumSpeed, gLobeAngleFraction ) / fractionScale; float2 hitDistanceWeightParams = GetHitDistanceWeightParams( ExtractHitDist( diff ), diffNonLinearAccumSpeed ); float minHitDistWeight = REBLUR_HIT_DIST_MIN_WEIGHT( 1.0 ) * fractionScale; // Sampling + #if( REBLUR_USE_SCREEN_SPACE_SAMPLING == 1 || REBLUR_SPATIAL_MODE == REBLUR_PRE_BLUR || REBLUR_USE_SCREEN_SPACE_SAMPLING_FOR_DIFFUSE == 1 ) + #if( REBLUR_SPATIAL_MODE == REBLUR_PRE_BLUR ) + float2 skew = 1.0; // seems that uniform screen space sampling in pre-pass breaks residual boiling better + #else + float2 skew = lerp( 1.0 - abs( Nv.xy ), 1.0, NoV ); + skew /= max( skew.x, skew.y ); + #endif + skew *= gRectSizeInv * blurRadius; + + float4 scaledRotator = Geometry::ScaleRotator( rotator, skew ); + #else float2x3 TvBv = GetKernelBasis( Nv, Nv, 1.0 ); // D = N float worldRadius = PixelRadiusToWorld( gUnproject, gOrthoMode, blurRadius, viewZ ); TvBv[ 0 ] *= worldRadius; TvBv[ 1 ] *= worldRadius; + #endif [unroll] for( uint n = 0; n < POISSON_SAMPLE_NUM; n++ ) @@ -88,8 +97,8 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. float3 offset = POISSON_SAMPLES( n ); // Sample coordinates - #if( REBLUR_USE_SCREEN_SPACE_SAMPLING == 1 || REBLUR_SPATIAL_MODE == REBLUR_PRE_BLUR ) - float2 uv = pixelUv + Geometry::RotateVector( rotator, offset.xy ) * gRectSizeInv * blurRadius; + #if( REBLUR_USE_SCREEN_SPACE_SAMPLING == 1 || REBLUR_SPATIAL_MODE == REBLUR_PRE_BLUR || REBLUR_USE_SCREEN_SPACE_SAMPLING_FOR_DIFFUSE == 1 ) + float2 uv = pixelUv + Geometry::RotateVector( scaledRotator, offset.xy ); #else float2 uv = GetKernelSampleCoordinates( gViewToClip, offset, Xv, TvBv[ 0 ], TvBv[ 1 ], rotator ); #endif @@ -117,22 +126,18 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. float zs = UnpackViewZ( gIn_ViewZ.SampleLevel( gNearestClamp, WithRectOffset( uvScaled ), 0 ) ); #endif - float3 Xvs = Geometry::ReconstructViewPosition( uv, gFrustum, zs, gOrthoMode ); - float materialIDs; float4 Ns = gIn_Normal_Roughness.SampleLevel( gNearestClamp, WithRectOffset( uvScaled ), 0 ); Ns = NRD_FrontEnd_UnpackNormalAndRoughness( Ns, materialIDs ); // Weight + float angle = Math::AcosApprox( dot( N, Ns.xyz ) ); + float3 Xvs = Geometry::ReconstructViewPosition( uv, gFrustum, zs, gOrthoMode ); + float w = IsInScreenNearest( uv ); - w *= float( zs < gDenoisingRange ); + w *= ComputeWeight( dot( Nv, Xvs ), geometryWeightParams.x, geometryWeightParams.y ); w *= CompareMaterials( materialID, materialIDs, gDiffMaterialMask ); - - float2 x; - x.x = dot( Nv, Xvs ); - x.y = Math::AcosApprox( dot( N, Ns.xyz ) ); - x = ComputeWeight( x, px, py ); - w *= x.x * x.y; + w *= ComputeWeight( angle, normalWeightParam, 0.0 ); REBLUR_TYPE s = gIn_Diff.SampleLevel( gNearestClamp, checkerboardUvScaled, 0 ); s = Denanify( w, s ); diff --git a/Shaders/Include/REBLUR_Common_SpecularSpatialFilter.hlsli b/Shaders/Include/REBLUR_Common_SpecularSpatialFilter.hlsli index 849ef272..064da077 100644 --- a/Shaders/Include/REBLUR_Common_SpecularSpatialFilter.hlsli +++ b/Shaders/Include/REBLUR_Common_SpecularSpatialFilter.hlsli @@ -47,7 +47,6 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. float NoD = abs( dot( Nv, Dv.xyz ) ); float hitDistScale = _REBLUR_GetHitDistanceNormalization( viewZ, gHitDistParams, roughness ); float hitDist = ExtractHitDist( spec ) * hitDistScale; - float frustumSize = GetFrustumSize( gMinRectDimMulUnproject, gOrthoMode, viewZ ); float hitDistFactor = GetHitDistFactor( hitDist * NoD, frustumSize ); // Blur radius @@ -78,20 +77,25 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. // Weights float roughnessFractionScaled = saturate( gRoughnessFraction * fractionScale ); float2 geometryWeightParams = GetGeometryWeightParams( gPlaneDistSensitivity, frustumSize, Xv, Nv, specNonLinearAccumSpeed ); - float normalWeightParams = GetNormalWeightParams( specNonLinearAccumSpeed, roughness ) / fractionScale; + float normalWeightParam = GetNormalWeightParam( specNonLinearAccumSpeed, gLobeAngleFraction, roughness ) / fractionScale; float2 roughnessWeightParams = GetRoughnessWeightParams( roughness, roughnessFractionScaled ); - float3 px = float3( geometryWeightParams.x, normalWeightParams, roughnessWeightParams.x ); - float3 py = float3( geometryWeightParams.y, 0.0, roughnessWeightParams.y ); float2 hitDistanceWeightParams = GetHitDistanceWeightParams( ExtractHitDist( spec ), specNonLinearAccumSpeed, roughness ); float minHitDistWeight = REBLUR_HIT_DIST_MIN_WEIGHT( smc ) * fractionScale; // Sampling + #if( REBLUR_USE_SCREEN_SPACE_SAMPLING == 1 || REBLUR_SPATIAL_MODE == REBLUR_PRE_BLUR ) + float2 skew = 1.0; // TODO: even for rough specular diffuse-like behavior is undesired ( especially visible in performance mode ) + skew *= gRectSizeInv * blurRadius; + + float4 scaledRotator = Geometry::ScaleRotator( rotator, skew ); + #else float2x3 TvBv = GetKernelBasis( Dv.xyz, Nv, NoD, roughness, specNonLinearAccumSpeed ); float worldRadius = PixelRadiusToWorld( gUnproject, gOrthoMode, blurRadius, viewZ ); TvBv[ 0 ] *= worldRadius; TvBv[ 1 ] *= worldRadius; + #endif [unroll] for( uint n = 0; n < POISSON_SAMPLE_NUM; n++ ) @@ -100,7 +104,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. // Sample coordinates #if( REBLUR_USE_SCREEN_SPACE_SAMPLING == 1 || REBLUR_SPATIAL_MODE == REBLUR_PRE_BLUR ) - float2 uv = pixelUv + Geometry::RotateVector( rotator, offset.xy ) * gRectSizeInv * blurRadius; + float2 uv = pixelUv + Geometry::RotateVector( scaledRotator, offset.xy ); #else float2 uv = GetKernelSampleCoordinates( gViewToClip, offset, Xv, TvBv[ 0 ], TvBv[ 1 ], rotator ); #endif @@ -128,23 +132,19 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. float zs = UnpackViewZ( gIn_ViewZ.SampleLevel( gNearestClamp, WithRectOffset( uvScaled ), 0 ) ); #endif - float3 Xvs = Geometry::ReconstructViewPosition( uv, gFrustum, zs, gOrthoMode ); - float materialIDs; float4 Ns = gIn_Normal_Roughness.SampleLevel( gNearestClamp, WithRectOffset( uvScaled ), 0 ); Ns = NRD_FrontEnd_UnpackNormalAndRoughness( Ns, materialIDs ); // Weight + float angle = Math::AcosApprox( dot( N, Ns.xyz ) ); + float3 Xvs = Geometry::ReconstructViewPosition( uv, gFrustum, zs, gOrthoMode ); + float w = IsInScreenNearest( uv ); - w *= float( zs < gDenoisingRange ); + w *= ComputeWeight( dot( Nv, Xvs ), geometryWeightParams.x, geometryWeightParams.y ); w *= CompareMaterials( materialID, materialIDs, gSpecMaterialMask ); - - float3 x; - x.x = dot( Nv, Xvs ); - x.y = Math::AcosApprox( dot( N, Ns.xyz ) ); - x.z = Ns.w; - x = ComputeWeight( x, px, py ); - w *= x.x * x.y * x.z; + w *= ComputeWeight( angle, normalWeightParam, 0.0 ); + w *= ComputeWeight( Ns.w, roughnessWeightParams.x, roughnessWeightParams.y ); REBLUR_TYPE s = gIn_Spec.SampleLevel( gNearestClamp, checkerboardUvScaled, 0 ); s = Denanify( w, s ); @@ -191,7 +191,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #if( REBLUR_SPATIAL_MODE == REBLUR_PRE_BLUR ) // Output - gOut_Spec_HitDistForTracking[ pixelPos ] = minHitDist == NRD_INF ? 0.0 : minHitDist; // TODO: lerp to hitT at center based on NoV or NoD? + gOut_SpecHitDistForTracking[ pixelPos ] = minHitDist == NRD_INF ? 0.0 : minHitDist; // TODO: lerp to hitT at center based on NoV or NoD? } // Checkerboard resolve ( if pre-pass failed ) diff --git a/Shaders/Include/REBLUR_Config.hlsli b/Shaders/Include/REBLUR_Config.hlsli index f1932c69..75e03a45 100644 --- a/Shaders/Include/REBLUR_Config.hlsli +++ b/Shaders/Include/REBLUR_Config.hlsli @@ -20,10 +20,11 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #define REBLUR_USE_ANTIFIREFLY 1 #define REBLUR_USE_CONFIDENCE_NON_LINEARLY 1 #define REBLUR_USE_STF 1 // gives very minor IQ boost visible only in debug visualization +#define REBLUR_USE_ANTILAG_NOT_INVOKING_HISTORY_FIX 1 // TODO: for now full history reset is undesired +#define REBLUR_USE_SCREEN_SPACE_SAMPLING_FOR_DIFFUSE 1 // almost matches world-space sampling but simpler code // Switches ( default 0 ) #define REBLUR_USE_SCREEN_SPACE_SAMPLING 0 -#define REBLUR_USE_ANTILAG_NOT_INVOKING_HISTORY_FIX 0 #define REBLUR_USE_DECOMPRESSED_HIT_DIST_IN_RECONSTRUCTION 0 // compression helps to preserve "lobe important" values #if( defined REBLUR_OCCLUSION || defined REBLUR_DIRECTIONAL_OCCLUSION ) @@ -45,7 +46,18 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #define REBLUR_SHOW_VIRTUAL_HISTORY_PARALLAX_CONFIDENCE 8 #define REBLUR_SHOW_HIT_DIST_FOR_TRACKING 9 -#define REBLUR_SHOW 0 // 0 or "REBLUR_SHOW_X" +#define REBLUR_SHOW 0 // 0 or REBLUR_SHOW_X + +// Constants +#define REBLUR_PRE_BLUR 0 +#define REBLUR_BLUR 1 +#define REBLUR_POST_BLUR 2 + +// Storage +#define REBLUR_ACCUMSPEED_BITS 6 +#define REBLUR_MATERIALID_BITS ( 16 - REBLUR_ACCUMSPEED_BITS - REBLUR_ACCUMSPEED_BITS ) +#define REBLUR_MAX_ACCUM_FRAME_NUM ( ( 1 << REBLUR_ACCUMSPEED_BITS ) - 1 ) +#define REBLUR_MAX_MATERIALID_NUM ( ( 1 << REBLUR_MATERIALID_BITS ) - 1 ) // Settings #define REBLUR_PRE_BLUR_POISSON_SAMPLE_NUM 8 @@ -69,13 +81,14 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #define REBLUR_NORMAL_ULP NRD_NORMAL_ENCODING_ERROR // was 1.5 / 255.0 ( too much for 0 roughness ) #define REBLUR_ALMOST_ZERO_ANGLE cos( Math::DegToRad( 89.0 ) ) -#define REBLUR_MAX_PERCENT_OF_LOBE_VOLUME 0.75 #define REBLUR_VIRTUAL_MOTION_PREV_PREV_WEIGHT_ITERATION_NUM 1 #define REBLUR_FIREFLY_SUPPRESSOR_MAX_RELATIVE_INTENSITY 38.0 #define REBLUR_FIREFLY_SUPPRESSOR_RADIUS_SCALE 0.1 +#define REBLUR_FIREFLY_SUPPRESSOR_FAST_RELATIVE_INTENSITY 4.0 // TODO: needed only for high FPS. Why? #define REBLUR_ANTI_FIREFLY_FILTER_RADIUS 4 // pixels #define REBLUR_ANTI_FIREFLY_SIGMA_SCALE 2.0 #define REBLUR_ROUGHNESS_SENSITIVITY_IN_TA ( NRD_ROUGHNESS_SENSITIVITY * 0.3 ) +#define REBLUR_ANTILAG_MODE 2 // 0 - modernized old, 1 - overly reactive @ low FPS, 2 - best? #define REBLUR_SAMPLES_PER_FRAME 1.0 // TODO: expose in settings, it will become useful with very clean signals, when max number of accumulated frames is low #if( defined REBLUR_OCCLUSION || defined REBLUR_DIRECTIONAL_OCCLUSION ) @@ -97,6 +110,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. // Shared constants #define REBLUR_SHARED_CONSTANTS \ + NRD_CONSTANT( float4x4, gWorldToClip ) \ NRD_CONSTANT( float4x4, gViewToClip ) \ NRD_CONSTANT( float4x4, gViewToWorld ) \ NRD_CONSTANT( float4x4, gWorldToViewPrev ) \ @@ -126,6 +140,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. NRD_CONSTANT( int2, gRectSizeMinusOne ) \ NRD_CONSTANT( float, gDisocclusionThreshold ) \ NRD_CONSTANT( float, gDisocclusionThresholdAlternate ) \ + NRD_CONSTANT( float, gCameraAttachedReflectionMaterialID ) \ NRD_CONSTANT( float, gStrandMaterialID ) \ NRD_CONSTANT( float, gStrandThickness ) \ NRD_CONSTANT( float, gStabilizationStrength ) \ @@ -171,7 +186,6 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #define REBLUR_USE_CATROM_FOR_VIRTUAL_MOTION_IN_TA 0 #endif -// PERFORMANCE MODE: x1.25 perf boost by sacrificing IQ ( DIFFUSE_SPECULAR on RTX 3090 @ 1440p 2.05 vs 2.55 ms ) #ifdef REBLUR_PERFORMANCE_MODE #undef REBLUR_USE_CATROM_FOR_SURFACE_MOTION_IN_TA #define REBLUR_USE_CATROM_FOR_SURFACE_MOTION_IN_TA 0 @@ -188,9 +202,6 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #undef REBLUR_USE_SCREEN_SPACE_SAMPLING #define REBLUR_USE_SCREEN_SPACE_SAMPLING 1 - #undef REBLUR_USE_STF - #define REBLUR_USE_STF 0 - #undef REBLUR_POISSON_SAMPLE_NUM #define REBLUR_POISSON_SAMPLE_NUM 6 diff --git a/Shaders/Include/REBLUR_Copy.hlsli b/Shaders/Include/REBLUR_Copy.hlsli index 187f11c1..696eb46e 100644 --- a/Shaders/Include/REBLUR_Copy.hlsli +++ b/Shaders/Include/REBLUR_Copy.hlsli @@ -16,7 +16,7 @@ NRD_EXPORT void NRD_CS_MAIN( uint2 pixelPos : SV_DispatchThreadId ) if( isSky != 0.0 && !gIsRectChanged ) return; - // TODO: is it possible to introduce "CopyResource" in NRD API? + // TODO: introduce "CopyResource" in NRD API? #ifdef REBLUR_DIFFUSE gOut_Diff[ pixelPos ] = gIn_Diff[ pixelPos ]; #ifdef REBLUR_SH diff --git a/Shaders/Include/REBLUR_HistoryFix.hlsli b/Shaders/Include/REBLUR_HistoryFix.hlsli index 854022de..666379c8 100644 --- a/Shaders/Include/REBLUR_HistoryFix.hlsli +++ b/Shaders/Include/REBLUR_HistoryFix.hlsli @@ -58,7 +58,6 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float3 Nv = Geometry::RotateVectorInverse( gViewToWorld, N ); float3 Vv = GetViewVector( Xv, true ); float NoV = abs( dot( Nv, Vv ) ); - float slopeScale = 1.0 / max( NoV, 0.2 ); // TODO: bigger scale introduces ghosting // Smooth number of accumulated frames int2 smemPos = threadPos + BORDER; @@ -118,8 +117,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Parameters float diffNonLinearAccumSpeed = 1.0 / ( 1.0 + frameNum.x ); - float diffNormalWeightParam = GetNormalWeightParams( diffNonLinearAccumSpeed ); - float2 diffGeometryWeightParams = GetGeometryWeightParams( gPlaneDistSensitivity * slopeScale, frustumSize, Xv, Nv, diffNonLinearAccumSpeed ); + float normalWeightParam = GetNormalWeightParam( diffNonLinearAccumSpeed, gLobeAngleFraction ); + float2 geometryWeightParams = GetGeometryWeightParams( gPlaneDistSensitivity, frustumSize, Xv, Nv, diffNonLinearAccumSpeed ); float sumd = 1.0 + frameNum.x; #ifdef REBLUR_PERFORMANCE_MODE @@ -152,23 +151,20 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : pos = clamp( pos, 0, gRectSizeMinusOne ); // Fetch data - float z = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( pos ) ] ); + float zs = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( pos ) ] ); float materialIDs; float4 Ns = gIn_Normal_Roughness[ WithRectOrigin( pos ) ]; Ns = NRD_FrontEnd_UnpackNormalAndRoughness( Ns, materialIDs ); - float3 Xvs = Geometry::ReconstructViewPosition( uv, gFrustum, z, gOrthoMode ); - float NoX = dot( Nv, Xvs ); - + // Weight float angle = Math::AcosApprox( dot( Ns.xyz, N ) ); + float3 Xvs = Geometry::ReconstructViewPosition( uv, gFrustum, zs, gOrthoMode ); - // Weight float w = IsInScreenNearest( uv ); - w *= float( z < gDenoisingRange ); + w *= ComputeWeight( dot( Nv, Xvs ), geometryWeightParams.x, geometryWeightParams.y ); w *= CompareMaterials( materialID, materialIDs, gDiffMaterialMask ); - w *= ComputeWeight( NoX, diffGeometryWeightParams.x, diffGeometryWeightParams.y ); - w *= ComputeExponentialWeight( angle, diffNormalWeightParam, 0.0 ); + w *= ComputeExponentialWeight( angle, normalWeightParam, 0.0 ); #ifndef REBLUR_PERFORMANCE_MODE w *= 1.0 + UnpackData1( gIn_Data1[ pos ] ).x; @@ -305,8 +301,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float specNonLinearAccumSpeed = 1.0 / ( 1.0 + frameNum.y ); float hitDistNormAtCenter = ExtractHitDist( spec ); - float specNormalWeightParam = GetNormalWeightParams( specNonLinearAccumSpeed, roughness ); - float2 specGeometryWeightParams = GetGeometryWeightParams( gPlaneDistSensitivity * slopeScale, frustumSize, Xv, Nv, specNonLinearAccumSpeed ); + float normalWeightParam = GetNormalWeightParam( specNonLinearAccumSpeed, gLobeAngleFraction, roughness ); + float2 geometryWeightParams = GetGeometryWeightParams( gPlaneDistSensitivity, frustumSize, Xv, Nv, specNonLinearAccumSpeed ); float2 relaxedRoughnessWeightParams = GetRelaxedRoughnessWeightParams( roughness * roughness, sqrt( gRoughnessFraction ) ); float2 hitDistanceWeightParams = GetHitDistanceWeightParams( hitDistNormAtCenter, specNonLinearAccumSpeed, roughness ); @@ -341,23 +337,20 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : pos = clamp( pos, 0, gRectSizeMinusOne ); // Fetch data - float z = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( pos ) ] ); + float zs = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( pos ) ] ); float materialIDs; float4 Ns = gIn_Normal_Roughness[ WithRectOrigin( pos ) ]; Ns = NRD_FrontEnd_UnpackNormalAndRoughness( Ns, materialIDs ); - float3 Xvs = Geometry::ReconstructViewPosition( uv, gFrustum, z, gOrthoMode ); - float NoX = dot( Nv, Xvs ); - float angle = Math::AcosApprox( dot( Ns.xyz, N ) ); + float3 Xvs = Geometry::ReconstructViewPosition( uv, gFrustum, zs, gOrthoMode ); // Weight float w = IsInScreenNearest( uv ); - w *= float( z < gDenoisingRange ); + w *= ComputeWeight( dot( Nv, Xvs ), geometryWeightParams.x, geometryWeightParams.y ); w *= CompareMaterials( materialID, materialIDs, gSpecMaterialMask ); - w *= ComputeWeight( NoX, specGeometryWeightParams.x, specGeometryWeightParams.y ); - w *= ComputeExponentialWeight( angle, specNormalWeightParam, 0.0 ); + w *= ComputeExponentialWeight( angle, normalWeightParam, 0.0 ); w *= ComputeExponentialWeight( Ns.w * Ns.w, relaxedRoughnessWeightParams.x, relaxedRoughnessWeightParams.y ); #ifndef REBLUR_PERFORMANCE_MODE diff --git a/Shaders/Include/REBLUR_HitDistReconstruction.hlsli b/Shaders/Include/REBLUR_HitDistReconstruction.hlsli index 0dcb3f79..a222b84a 100644 --- a/Shaders/Include/REBLUR_HitDistReconstruction.hlsli +++ b/Shaders/Include/REBLUR_HitDistReconstruction.hlsli @@ -62,15 +62,17 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float3 N = normalAndRoughness.xyz; float roughness = normalAndRoughness.w; - float frustumSize = GetFrustumSize( gMinRectDimMulUnproject, gOrthoMode, center.z ); float2 pixelUv = float2( pixelPos + 0.5 ) * gRectSizeInv; float3 Xv = Geometry::ReconstructViewPosition( pixelUv, gFrustum, center.z, gOrthoMode ); float3 Nv = Geometry::RotateVectorInverse( gViewToWorld, N ); - float2 geometryWeightParams = GetGeometryWeightParams( gPlaneDistSensitivity, frustumSize, Xv, Nv, 1.0 ); + float3 Vv = GetViewVector( Xv, true ); + float frustumSize = GetFrustumSize( gMinRectDimMulUnproject, gOrthoMode, center.z ); + + float2 geometryWeightParams = GetGeometryWeightParams( gPlaneDistSensitivity, frustumSize, Xv, Nv, 1.0 ); float2 relaxedRoughnessWeightParams = GetRelaxedRoughnessWeightParams( roughness * roughness ); - float diffNormalWeightParam = GetNormalWeightParams( 1.0 ); - float specNormalWeightParam = GetNormalWeightParams( 1.0, roughness ); + float diffNormalWeightParam = GetNormalWeightParam( 1.0, 1.0 ); + float specNormalWeightParam = GetNormalWeightParam( 1.0, 1.0, roughness ); // Hit distance reconstruction float2 sum = 1000.0 * float2( center.xy != 0.0 ); @@ -87,17 +89,16 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : continue; int2 pos = threadPos + int2( i, j ); - float3 temp = s_HitDist_ViewZ[ pos.y ][ pos.x ]; + float3 data = s_HitDist_ViewZ[ pos.y ][ pos.x ]; // Weight float w = IsInScreenNearest( pixelUv + o * gRectSizeInv ); - w *= float( temp.z < gDenoisingRange ); w *= GetGaussianWeight( length( o ) * 0.5 ); // This weight is strict ( non exponential ) because we need to avoid accessing data from other surfaces - float3 Xvs = Geometry::ReconstructViewPosition( pixelUv + o * gRectSizeInv, gFrustum, temp.z, gOrthoMode ); - float NoX = dot( Nv, Xvs ); - w *= ComputeWeight( NoX, geometryWeightParams.x, geometryWeightParams.y ); + float2 uv = pixelUv + o * gRectSizeInv; + float3 Xvs = Geometry::ReconstructViewPosition( uv, gFrustum, data.z, gOrthoMode ); + w *= ComputeWeight( dot( Nv, Xvs ), geometryWeightParams.x, geometryWeightParams.y ); float2 ww = w; #ifndef REBLUR_PERFORMANCE_MODE @@ -112,12 +113,12 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : ww.y *= ComputeExponentialWeight( normalAndRoughness.w * normalAndRoughness.w, relaxedRoughnessWeightParams.x, relaxedRoughnessWeightParams.y ); #endif - temp.x = Denanify( ww.x, temp.x ); - temp.y = Denanify( ww.y, temp.y ); - ww *= float2( temp.xy != 0.0 ); + data.x = Denanify( ww.x, data.x ); + data.y = Denanify( ww.y, data.y ); + ww *= float2( data.xy != 0.0 ); // Accumulate - center.xy += temp.xy * ww; + center.xy += data.xy * ww; sum += ww; } } diff --git a/Shaders/Include/REBLUR_PostBlur.hlsli b/Shaders/Include/REBLUR_PostBlur.hlsli index 70467474..6f732a75 100644 --- a/Shaders/Include/REBLUR_PostBlur.hlsli +++ b/Shaders/Include/REBLUR_PostBlur.hlsli @@ -34,11 +34,13 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float2 pixelUv = float2( pixelPos + 0.5 ) * gRectSizeInv; float3 Xv = Geometry::ReconstructViewPosition( pixelUv, gFrustum, viewZ, gOrthoMode ); - float4 rotator = GetBlurKernelRotation( REBLUR_POST_BLUR_ROTATOR_MODE, pixelPos, gRotator, gFrameIndex ); float3 Vv = GetViewVector( Xv, true ); float NoV = abs( dot( Nv, Vv ) ); + const float frustumSize = GetFrustumSize( gMinRectDimMulUnproject, gOrthoMode, viewZ ); + const float4 rotator = GetBlurKernelRotation( REBLUR_POST_BLUR_ROTATOR_MODE, pixelPos, gRotator, gFrameIndex ); + // Output gOut_Normal_Roughness[ pixelPos ] = normalAndRoughnessPacked; #ifdef REBLUR_NO_TEMPORAL_STABILIZATION diff --git a/Shaders/Include/REBLUR_PrePass.hlsli b/Shaders/Include/REBLUR_PrePass.hlsli index 3678f686..179b8e34 100644 --- a/Shaders/Include/REBLUR_PrePass.hlsli +++ b/Shaders/Include/REBLUR_PrePass.hlsli @@ -21,20 +21,6 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : if( viewZ > gDenoisingRange ) return; - // Checkerboard resolve - uint checkerboard = Sequence::CheckerBoard( pixelPos, gFrameIndex ); - - int3 checkerboardPos = pixelPos.xxy + int3( -1, 1, 0 ); - checkerboardPos.x = max( checkerboardPos.x, 0 ); - checkerboardPos.y = min( checkerboardPos.y, gRectSizeMinusOne.x ); - float viewZ0 = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( checkerboardPos.xz ) ] ); - float viewZ1 = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( checkerboardPos.yz ) ] ); - float2 wc = GetBilateralWeight( float2( viewZ0, viewZ1 ), viewZ ); - wc.x = ( viewZ0 > gDenoisingRange || pixelPos.x < 1 ) ? 0.0 : wc.x; - wc.y = ( viewZ1 > gDenoisingRange || pixelPos.x >= gRectSizeMinusOne.x ) ? 0.0 : wc.y; - wc *= Math::PositiveRcp( wc.x + wc.y ); - checkerboardPos.xy >>= 1; - // Normal and roughness float materialID; float4 normalAndRoughness = NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Normal_Roughness[ WithRectOrigin( pixelPos ) ], materialID ); @@ -45,11 +31,29 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Shared data float2 pixelUv = float2( pixelPos + 0.5 ) * gRectSizeInv; float3 Xv = Geometry::ReconstructViewPosition( pixelUv, gFrustum, viewZ, gOrthoMode ); - float4 rotator = GetBlurKernelRotation( REBLUR_PRE_BLUR_ROTATOR_MODE, pixelPos, gRotator, gFrameIndex ); float3 Vv = GetViewVector( Xv, true ); float NoV = abs( dot( Nv, Vv ) ); + const float frustumSize = GetFrustumSize( gMinRectDimMulUnproject, gOrthoMode, viewZ ); + const float4 rotator = GetBlurKernelRotation( REBLUR_PRE_BLUR_ROTATOR_MODE, pixelPos, gRotator, gFrameIndex ); + + // Checkerboard resolve + uint checkerboard = Sequence::CheckerBoard( pixelPos, gFrameIndex ); + + int3 checkerboardPos = pixelPos.xxy + int3( -1, 1, 0 ); + checkerboardPos.x = max( checkerboardPos.x, 0 ); + checkerboardPos.y = min( checkerboardPos.y, gRectSizeMinusOne.x ); + float viewZ0 = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( checkerboardPos.xz ) ] ); + float viewZ1 = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( checkerboardPos.yz ) ] ); + float disocclusionThresholdCheckerboard = GetDisocclusionThreshold( NRD_DISOCCLUSION_THRESHOLD, frustumSize, NoV ); + float2 wc = GetDisocclusionWeight( float2( viewZ0, viewZ1 ), viewZ, disocclusionThresholdCheckerboard ); + wc.x = ( viewZ0 > gDenoisingRange || pixelPos.x < 1 ) ? 0.0 : wc.x; + wc.y = ( viewZ1 > gDenoisingRange || pixelPos.x >= gRectSizeMinusOne.x ) ? 0.0 : wc.y; + wc *= Math::PositiveRcp( wc.x + wc.y ); + checkerboardPos.xy >>= 1; + + // Spatial filtering #define REBLUR_SPATIAL_MODE REBLUR_PRE_BLUR #ifdef REBLUR_DIFFUSE diff --git a/Shaders/Include/REBLUR_TemporalAccumulation.hlsli b/Shaders/Include/REBLUR_TemporalAccumulation.hlsli index abab886f..be6f6ae0 100644 --- a/Shaders/Include/REBLUR_TemporalAccumulation.hlsli +++ b/Shaders/Include/REBLUR_TemporalAccumulation.hlsli @@ -30,7 +30,7 @@ void Preload( uint2 sharedPos, int2 globalPos ) #ifdef REBLUR_OCCLUSION float hitDist = ExtractHitDist( spec ); #else - float hitDist = gSpecPrepassBlurRadius == 0.0 ? ExtractHitDist( spec ) : gIn_Spec_HitDistForTracking[ globalPos ]; + float hitDist = gSpecPrepassBlurRadius == 0.0 ? ExtractHitDist( spec ) : gIn_SpecHitDistForTracking[ globalPos ]; #endif s_HitDistForTracking[ sharedPos.y ][ sharedPos.x ] = hitDist; @@ -111,7 +111,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Hit distance for tracking ( tests 8, 110, 139, e3, e9 without normal map, e24 ) #ifdef REBLUR_SPECULAR - #if( REBLUR_USE_STF == 1 ) + #if( REBLUR_USE_STF == 1 && NRD_NORMAL_ENCODING == NRD_NORMAL_ENCODING_R10G10B10A2_UNORM ) Rng::Hash::Initialize( pixelPos, gFrameIndex ); #endif @@ -124,7 +124,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : hitDistForTracking *= gSpecPrepassBlurRadius == 0.0 ? hitDistNormalization : 1.0; #endif - gOut_Spec_HitDistForTracking[ pixelPos ] = hitDistForTracking; + gOut_SpecHitDistForTracking[ pixelPos ] = hitDistForTracking; #endif // Previous position and surface motion uv @@ -132,12 +132,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float3 Xprev = X; float2 smbPixelUv = pixelUv + mv.xy; - if( gMvScale.w != 0.0 ) - { - Xprev += mv; - smbPixelUv = Geometry::GetScreenUv( gWorldToClipPrev, Xprev ); - } - else + if( gMvScale.w == 0.0 ) { if( gMvScale.z == 0.0 ) mv.z = Geometry::AffineTransform( gWorldToViewPrev, X ).z - viewZ; @@ -147,9 +142,11 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : Xprev = Geometry::RotateVectorInverse( gWorldToViewPrev, Xvprevlocal ) + gCameraDelta.xyz; } - - // Parallax - float smbParallaxInPixels = ComputeParallaxInPixels( Xprev + gCameraDelta.xyz, gOrthoMode == 0.0 ? smbPixelUv : pixelUv, gWorldToClipPrev, gRectSize ); + else + { + Xprev += mv; + smbPixelUv = Geometry::GetScreenUv( gWorldToClipPrev, Xprev ); + } // Previous viewZ ( 4x4, surface motion ) /* @@ -167,10 +164,10 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : */ Filtering::CatmullRom smbCatromFilter = Filtering::GetCatmullRomFilter( smbPixelUv, gRectSizePrev ); float2 smbCatromGatherUv = smbCatromFilter.origin * gResourceSizeInvPrev; - float4 smbViewZ0 = gIn_Prev_ViewZ.GatherRed( gNearestClamp, smbCatromGatherUv, float2( 1, 1 ) ).wzxy; - float4 smbViewZ1 = gIn_Prev_ViewZ.GatherRed( gNearestClamp, smbCatromGatherUv, float2( 3, 1 ) ).wzxy; - float4 smbViewZ2 = gIn_Prev_ViewZ.GatherRed( gNearestClamp, smbCatromGatherUv, float2( 1, 3 ) ).wzxy; - float4 smbViewZ3 = gIn_Prev_ViewZ.GatherRed( gNearestClamp, smbCatromGatherUv, float2( 3, 3 ) ).wzxy; + float4 smbViewZ0 = gPrev_ViewZ.GatherRed( gNearestClamp, smbCatromGatherUv, float2( 1, 1 ) ).wzxy; + float4 smbViewZ1 = gPrev_ViewZ.GatherRed( gNearestClamp, smbCatromGatherUv, float2( 3, 1 ) ).wzxy; + float4 smbViewZ2 = gPrev_ViewZ.GatherRed( gNearestClamp, smbCatromGatherUv, float2( 1, 3 ) ).wzxy; + float4 smbViewZ3 = gPrev_ViewZ.GatherRed( gNearestClamp, smbCatromGatherUv, float2( 3, 3 ) ).wzxy; float3 prevViewZ0 = UnpackViewZ( smbViewZ0.yzw ); float3 prevViewZ1 = UnpackViewZ( smbViewZ1.xzw ); @@ -186,25 +183,32 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float sum = 0.0; float w = float( prevViewZ0.z < gDenoisingRange ); - smbNavg = NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Prev_Normal_Roughness[ p ] ).xyz * w; + smbNavg = NRD_FrontEnd_UnpackNormalAndRoughness( gPrev_Normal_Roughness[ p ] ).xyz * w; sum += w; w = float( prevViewZ1.y < gDenoisingRange ); - smbNavg += NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Prev_Normal_Roughness[ p + uint2( 1, 0 ) ] ).xyz * w; + smbNavg += NRD_FrontEnd_UnpackNormalAndRoughness( gPrev_Normal_Roughness[ p + uint2( 1, 0 ) ] ).xyz * w; sum += w; w = float( prevViewZ2.y < gDenoisingRange ); - smbNavg += NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Prev_Normal_Roughness[ p + uint2( 0, 1 ) ] ).xyz * w; + smbNavg += NRD_FrontEnd_UnpackNormalAndRoughness( gPrev_Normal_Roughness[ p + uint2( 0, 1 ) ] ).xyz * w; sum += w; w = float( prevViewZ3.x < gDenoisingRange ); - smbNavg += NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Prev_Normal_Roughness[ p + uint2( 1, 1 ) ] ).xyz * w; + smbNavg += NRD_FrontEnd_UnpackNormalAndRoughness( gPrev_Normal_Roughness[ p + uint2( 1, 1 ) ] ).xyz * w; sum += w; smbNavg /= sum == 0.0 ? 1.0 : sum; } smbNavg = Geometry::RotateVector( gWorldPrevToWorld, smbNavg ); + // Parallax + float smbParallaxInPixels1 = ComputeParallaxInPixels( Xprev + gCameraDelta.xyz, gOrthoMode == 0.0 ? smbPixelUv : pixelUv, gWorldToClipPrev, gRectSize ); + float smbParallaxInPixels2 = ComputeParallaxInPixels( Xprev - gCameraDelta.xyz, gOrthoMode == 0.0 ? pixelUv : smbPixelUv, gWorldToClip, gRectSize ); + + float smbParallaxInPixelsMax = max( smbParallaxInPixels1, smbParallaxInPixels2 ); + float smbParallaxInPixelsMin = min( smbParallaxInPixels1, smbParallaxInPixels2 ); + // Disocclusion: threshold float pixelSize = PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, viewZ ); float frustumSize = GetFrustumSize( gMinRectDimMulUnproject, gOrthoMode, viewZ ); @@ -219,8 +223,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float3 V = GetViewVector( X ); float NoV = abs( dot( N, V ) ); - float disocclusionThresholdSlopeScale = 1.0 / lerp( lerp( 0.05, 1.0, NoV ), 1.0, saturate( smbParallaxInPixels / 30.0 ) ); - float4 smbDisocclusionThreshold = saturate( disocclusionThreshold * disocclusionThresholdSlopeScale ) * frustumSize; + float NoVstrict = lerp( NoV, 1.0, saturate( smbParallaxInPixelsMax / 30.0 ) ); + float4 smbDisocclusionThreshold = GetDisocclusionThreshold( disocclusionThreshold, frustumSize, NoVstrict ); smbDisocclusionThreshold *= float( dot( smbNavg, Navg ) > REBLUR_ALMOST_ZERO_ANGLE ); // good for smb smbDisocclusionThreshold *= IsInScreenBilinear( smbBilinearFilter.origin, gRectSizePrev ); smbDisocclusionThreshold -= NRD_EPS; @@ -238,10 +242,10 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Disocclusion: materialID #if( NRD_NORMAL_ENCODING == NRD_NORMAL_ENCODING_R10G10B10A2_UNORM ) - uint4 smbInternalData0 = gIn_Prev_InternalData.GatherRed( gNearestClamp, smbCatromGatherUv, float2( 1, 1 ) ).wzxy; - uint4 smbInternalData1 = gIn_Prev_InternalData.GatherRed( gNearestClamp, smbCatromGatherUv, float2( 3, 1 ) ).wzxy; - uint4 smbInternalData2 = gIn_Prev_InternalData.GatherRed( gNearestClamp, smbCatromGatherUv, float2( 1, 3 ) ).wzxy; - uint4 smbInternalData3 = gIn_Prev_InternalData.GatherRed( gNearestClamp, smbCatromGatherUv, float2( 3, 3 ) ).wzxy; + uint4 smbInternalData0 = gPrev_InternalData.GatherRed( gNearestClamp, smbCatromGatherUv, float2( 1, 1 ) ).wzxy; + uint4 smbInternalData1 = gPrev_InternalData.GatherRed( gNearestClamp, smbCatromGatherUv, float2( 3, 1 ) ).wzxy; + uint4 smbInternalData2 = gPrev_InternalData.GatherRed( gNearestClamp, smbCatromGatherUv, float2( 1, 3 ) ).wzxy; + uint4 smbInternalData3 = gPrev_InternalData.GatherRed( gNearestClamp, smbCatromGatherUv, float2( 3, 3 ) ).wzxy; float3 smbMaterialID0 = float3( UnpackInternalData( smbInternalData0.y ).z, UnpackInternalData( smbInternalData0.z ).z, UnpackInternalData( smbInternalData0.w ).z ); float3 smbMaterialID1 = float3( UnpackInternalData( smbInternalData1.x ).z, UnpackInternalData( smbInternalData1.z ).z, UnpackInternalData( smbInternalData1.w ).z ); @@ -257,7 +261,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : uint4 smbInternalData = uint4( smbInternalData0.w, smbInternalData1.z, smbInternalData2.y, smbInternalData3.x ); #else float2 smbBilinearGatherUv = ( smbBilinearFilter.origin + 1.0 ) * gResourceSizeInvPrev; - uint4 smbInternalData = gIn_Prev_InternalData.GatherRed( gNearestClamp, smbBilinearGatherUv ).wzxy; + uint4 smbInternalData = gPrev_InternalData.GatherRed( gNearestClamp, smbBilinearGatherUv ).wzxy; #endif // 2x2 occlusion weights @@ -304,7 +308,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : checkerboardPos.y = min( checkerboardPos.y, gRectSizeMinusOne.x ); float viewZ0 = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( checkerboardPos.xz ) ] ); float viewZ1 = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( checkerboardPos.yz ) ] ); - float2 wc = GetBilateralWeight( float2( viewZ0, viewZ1 ), viewZ ); + float disocclusionThresholdCheckerboard = GetDisocclusionThreshold( NRD_DISOCCLUSION_THRESHOLD, frustumSize, NoV ); + float2 wc = GetDisocclusionWeight( float2( viewZ0, viewZ1 ), viewZ, disocclusionThresholdCheckerboard ); wc.x = ( viewZ0 > gDenoisingRange || pixelPos.x < 1 ) ? 0.0 : wc.x; wc.y = ( viewZ1 > gDenoisingRange || pixelPos.x >= gRectSizeMinusOne.x ) ? 0.0 : wc.y; wc *= Math::PositiveRcp( wc.x + wc.y ); @@ -316,7 +321,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Accumulation speed float specHistoryConfidence = smbFootprintQuality; if( gHasHistoryConfidence && NRD_USE_HISTORY_CONFIDENCE ) - specHistoryConfidence *= gIn_Spec_Confidence[ WithRectOrigin( pixelPos ) ]; + specHistoryConfidence *= gIn_SpecConfidence[ WithRectOrigin( pixelPos ) ]; smbSpecAccumSpeed *= lerp( specHistoryConfidence, 1.0, 1.0 / ( 1.0 + smbSpecAccumSpeed ) ); smbSpecAccumSpeed = min( smbSpecAccumSpeed, gMaxAccumulatedFrameNum ); @@ -356,52 +361,65 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : */ float curvature = 0.0; { - // IMPORTANT: this code allows to get non-zero parallax on objects attached to the camera + // IMPORTANT: non-zero parallax on objects attached to the camera is needed + // IMPORTANT: the direction of "deltaUv" is important ( test 1 ) float2 uvForZeroParallax = gOrthoMode == 0.0 ? smbPixelUv : pixelUv; - float2 deltaUv = Geometry::GetScreenUv( gWorldToClipPrev, Xprev - gCameraDelta.xyz ) - uvForZeroParallax; + float2 deltaUv = uvForZeroParallax - Geometry::GetScreenUv( gWorldToClipPrev, Xprev + gCameraDelta.xyz ); // TODO: repeats code for "smbParallaxInPixels1" with "-" sign deltaUv *= gRectSize; - float deltaUvLen = length( deltaUv ); - deltaUv /= max( deltaUvLen, 1.0 / 256.0 ); - float2 motionUv = pixelUv + 0.99 * deltaUv * gRectSizeInv; // stay in SMEM + deltaUv /= max( smbParallaxInPixels1, 1.0 / 256.0 ); + + // 10 edge + float3 n10, x10; + { + float3 xv = Geometry::ReconstructViewPosition( pixelUv + float2( 1, 0 ) * gRectSizeInv, gFrustum, 1.0, gOrthoMode ); + float3 x = Geometry::RotateVector( gViewToWorld, xv ); + float3 v = GetViewVector( x ); + float3 o = gOrthoMode == 0.0 ? 0 : x; - // Construct the other edge point "x" - float z = UnpackViewZ( gIn_ViewZ.SampleLevel( gLinearClamp, WithRectOffset( motionUv * gResolutionScale ), 0 ) ); - float3 x = Geometry::ReconstructViewPosition( motionUv, gFrustum, z, gOrthoMode ); - x = Geometry::RotateVector( gViewToWorld, x ); + x10 = o + v * dot( X - o, N ) / dot( N, v ); // line-plane intersection + n10 = s_Normal_Roughness[ threadPos.y + BORDER ][ threadPos.x + BORDER + 1 ].xyz; + } - // Interpolate normal at "x" - Filtering::Bilinear f = Filtering::GetBilinearFilter( motionUv, gRectSize ); + // 01 edge + float3 n01, x01; + { + float3 xv = Geometry::ReconstructViewPosition( pixelUv + float2( 0, 1 ) * gRectSizeInv, gFrustum, 1.0, gOrthoMode ); + float3 x = Geometry::RotateVector( gViewToWorld, xv ); + float3 v = GetViewVector( x ); + float3 o = gOrthoMode == 0.0 ? 0 : x; - int2 pos = threadPos + BORDER + int2( f.origin ) - pixelPos; - pos = clamp( pos, 0, int2( BUFFER_X, BUFFER_Y ) - 2 ); // just in case? + x01 = o + v * dot( X - o, N ) / dot( N, v ); // line-plane intersection + n01 = s_Normal_Roughness[ threadPos.y + BORDER + 1 ][ threadPos.x + BORDER ].xyz; + } - float3 n00 = s_Normal_Roughness[ pos.y ][ pos.x ].xyz; - float3 n10 = s_Normal_Roughness[ pos.y ][ pos.x + 1 ].xyz; - float3 n01 = s_Normal_Roughness[ pos.y + 1 ][ pos.x ].xyz; - float3 n11 = s_Normal_Roughness[ pos.y + 1 ][ pos.x + 1 ].xyz; + // Mix + float2 w = abs( deltaUv ) + 1.0 / 256.0; + w /= w.x + w.y; - float3 n = _NRD_SafeNormalize( Filtering::ApplyBilinearFilter( n00, n10, n01, n11, f ) ); + float3 x = x10 * w.x + x01 * w.y; + float3 n = normalize( n10 * w.x + n01 * w.y ); // ( Optional ) High parallax - flattens surface on high motion ( test 132, e9 ) // IMPORTANT: a must for 8-bit and 10-bit normals ( tests b7, b10, b33 ) - float deltaUvLenFixed = deltaUvLen * ( NRD_USE_HIGH_PARALLAX_CURVATURE_SILHOUETTE_FIX ? NoV : 1.0 ); // it fixes silhouettes, but leads to less flattening + float deltaUvLenFixed = smbParallaxInPixelsMin; // not needed for objects attached to the camera! + deltaUvLenFixed *= NRD_USE_HIGH_PARALLAX_CURVATURE_SILHOUETTE_FIX ? NoV : 1.0; // it fixes silhouettes, but leads to less flattening + float2 motionUvHigh = pixelUv + deltaUvLenFixed * deltaUv * gRectSizeInv; + motionUvHigh = ( floor( motionUvHigh * gRectSize ) + 0.5 ) * gRectSizeInv; // Snap to the pixel center! + if( NRD_USE_HIGH_PARALLAX_CURVATURE && deltaUvLenFixed > 1.0 && IsInScreenNearest( motionUvHigh ) ) { - float2 pos = StochasticBilinear( motionUvHigh, gRectSize ); - pos = WithRectOffset( pos * gResolutionScale ); + float2 uvScaled = WithRectOffset( ClampUvToViewport( motionUvHigh ) ); - // Construct the other edge point "xHigh" - float zHigh = UnpackViewZ( gIn_ViewZ.SampleLevel( gNearestClamp, pos, 0 ) ); - float3 xHigh = Geometry::ReconstructViewPosition( pos, gFrustum, zHigh, gOrthoMode ); + float zHigh = UnpackViewZ( gIn_ViewZ.SampleLevel( gNearestClamp, uvScaled, 0 ) ); + float3 xHigh = Geometry::ReconstructViewPosition( motionUvHigh, gFrustum, zHigh, gOrthoMode ); xHigh = Geometry::RotateVector( gViewToWorld, xHigh ); - // Interpolate normal at "xHigh" - float3 nHigh = NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Normal_Roughness.SampleLevel( gNearestClamp, pos, 0 ) ).xyz; + float3 nHigh = NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Normal_Roughness.SampleLevel( gNearestClamp, uvScaled, 0 ) ).xyz; // Replace if same surface float zError = abs( zHigh - viewZ ) * rcp( max( zHigh, viewZ ) ); - bool cmp = zError < NRD_CURVATURE_Z_THRESHOLD; + bool cmp = zError < NRD_CURVATURE_Z_THRESHOLD; // TODO: use common disocclusion logic? n = cmp ? nHigh : n; x = cmp ? xHigh : x; @@ -420,32 +438,34 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float2 uv1 = Geometry::GetScreenUv( gWorldToClipPrev, X - V * ApplyThinLensEquation( hitDistForTracking, curvature ) ); float2 uv2 = Geometry::GetScreenUv( gWorldToClipPrev, X ); float a = length( ( uv1 - uv2 ) * gRectSize ); - curvature *= float( a < NRD_MAX_ALLOWED_VIRTUAL_MOTION_ACCELERATION * deltaUvLen + gRectSizeInv.x ); + curvature *= float( a < NRD_MAX_ALLOWED_VIRTUAL_MOTION_ACCELERATION * smbParallaxInPixelsMax + gRectSizeInv.x ); } // Virtual motion - coordinates float3 Xvirtual = GetXvirtual( hitDistForTracking, curvature, X, Xprev, V, Dfactor ); + float XvirtualLength = length( Xvirtual ); + float2 vmbPixelUv = Geometry::GetScreenUv( gWorldToClipPrev, Xvirtual ); - float2 vmbDelta = vmbPixelUv - smbPixelUv; + vmbPixelUv = materialID == gCameraAttachedReflectionMaterialID ? pixelUv : vmbPixelUv; + float2 vmbDelta = vmbPixelUv - smbPixelUv; float vmbPixelsTraveled = length( vmbDelta * gRectSize ); - float XvirtualLength = length( Xvirtual ); // Virtual motion - roughness Filtering::Bilinear vmbBilinearFilter = Filtering::GetBilinearFilter( vmbPixelUv, gRectSizePrev ); float2 vmbBilinearGatherUv = ( vmbBilinearFilter.origin + 1.0 ) * gResourceSizeInvPrev; float2 relaxedRoughnessWeightParams = GetRelaxedRoughnessWeightParams( roughness * roughness, gRoughnessFraction, REBLUR_ROUGHNESS_SENSITIVITY_IN_TA ); #if( NRD_NORMAL_ENCODING == NRD_NORMAL_ENCODING_R10G10B10A2_UNORM ) - float4 vmbRoughness = gIn_Prev_Normal_Roughness.GatherBlue( gNearestClamp, vmbBilinearGatherUv ).wzxy; + float4 vmbRoughness = gPrev_Normal_Roughness.GatherBlue( gNearestClamp, vmbBilinearGatherUv ).wzxy; #else - float4 vmbRoughness = gIn_Prev_Normal_Roughness.GatherAlpha( gNearestClamp, vmbBilinearGatherUv ).wzxy; + float4 vmbRoughness = gPrev_Normal_Roughness.GatherAlpha( gNearestClamp, vmbBilinearGatherUv ).wzxy; #endif float4 roughnessWeight = ComputeNonExponentialWeightWithSigma( vmbRoughness * vmbRoughness, relaxedRoughnessWeightParams.x, relaxedRoughnessWeightParams.y, roughnessSigma ); - roughnessWeight = lerp( Math::SmoothStep( 1.0, 0.0, smbParallaxInPixels ), 1.0, roughnessWeight ); // jitter friendly + roughnessWeight = lerp( Math::SmoothStep( 1.0, 0.0, smbParallaxInPixelsMax ), 1.0, roughnessWeight ); // jitter friendly float virtualHistoryRoughnessBasedConfidence = Filtering::ApplyBilinearFilter( roughnessWeight.x, roughnessWeight.y, roughnessWeight.z, roughnessWeight.w, vmbBilinearFilter ); // Virtual motion - normal: parallax ( test 132 ) - float4 vmbNormalAndRoughness = NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Prev_Normal_Roughness.SampleLevel( gNearestClamp, StochasticBilinear( vmbPixelUv, gRectSizePrev ) * gResolutionScalePrev, 0 ) ); + float4 vmbNormalAndRoughness = NRD_FrontEnd_UnpackNormalAndRoughness( gPrev_Normal_Roughness.SampleLevel( STOCHASTIC_BILINEAR_FILTER, StochasticBilinear( vmbPixelUv, gRectSizePrev ) * gResolutionScalePrev, 0 ) ); float3 vmbN = Geometry::RotateVector( gWorldPrevToWorld, vmbNormalAndRoughness.xyz ); float virtualHistoryNormalBasedConfidence = 1.0 / ( 1.0 + 0.5 * Dfactor * saturate( length( N - vmbN ) - REBLUR_NORMAL_ULP ) * vmbPixelsTraveled ); @@ -459,7 +479,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : vmbOcclusionThreshold *= IsInScreenBilinear( vmbBilinearFilter.origin, gRectSizePrev ); vmbOcclusionThreshold -= NRD_EPS; - float4 vmbViewZ = UnpackViewZ( gIn_Prev_ViewZ.GatherRed( gNearestClamp, vmbBilinearGatherUv ).wzxy ); + float4 vmbViewZ = UnpackViewZ( gPrev_ViewZ.GatherRed( gNearestClamp, vmbBilinearGatherUv ).wzxy ); float3 vmbVv = Geometry::ReconstructViewPosition( vmbPixelUv, gFrustumPrev, 1.0 ); // unnormalized, orthoMode = 0 float3 vmbV = Geometry::RotateVectorInverse( gWorldToViewPrev, vmbVv ); float NoXcurr = dot( N, Xprev - gCameraDelta.xyz ); @@ -471,7 +491,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : } // Virtual motion - disocclusion: materialID - uint4 vmbInternalData = gIn_Prev_InternalData.GatherRed( gNearestClamp, vmbBilinearGatherUv ).wzxy; + uint4 vmbInternalData = gPrev_InternalData.GatherRed( gNearestClamp, vmbBilinearGatherUv ).wzxy; float3 vmbInternalData00 = UnpackInternalData( vmbInternalData.x ); float3 vmbInternalData10 = UnpackInternalData( vmbInternalData.y ); @@ -508,10 +528,12 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : curvatureAngleTan *= 2.0; // TODO: why it's here? it's needed to allow REBLUR_NORMAL_ULP values < "1.5 / 255.0" float curvatureAngle = atan( curvatureAngleTan ); - float lobeTanHalfAngle = ImportanceSampling::GetSpecularLobeTanHalfAngle( roughnessModified, REBLUR_MAX_PERCENT_OF_LOBE_VOLUME ); - lobeTanHalfAngle *= 1.0 / ( 1.0 + vmbSpecAccumSpeed ); // make more strict if history is long, modifying "tan" works better + // Copied from "GetNormalWeightParam" but doesn't use "lobeAngleFraction" + float percentOfVolume = NRD_MAX_PERCENT_OF_LOBE_VOLUME / ( 1.0 + vmbSpecAccumSpeed ); + float lobeTanHalfAngle = ImportanceSampling::GetSpecularLobeTanHalfAngle( roughnessModified, percentOfVolume ); + float lobeHalfAngle = atan( lobeTanHalfAngle ); - lobeHalfAngle = max( lobeHalfAngle, REBLUR_NORMAL_ULP ); + lobeHalfAngle = max( lobeHalfAngle, NRD_NORMAL_ENCODING_ERROR ); // Virtual motion - normal: lobe overlapping ( test 107 ) float normalWeight = GetEncodingAwareNormalWeight( N, vmbN, lobeHalfAngle, curvatureAngle, REBLUR_NORMAL_ULP ); @@ -526,17 +548,18 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Tests 3, 6, 8, 11, 14, 100, 103, 104, 106, 109, 110, 114, 120, 127, 130, 131, 132, 138, 139 and 9e float virtualHistoryParallaxBasedConfidence; { - float hitDistForTrackingPrev = gIn_Prev_Spec_HitDistForTracking.SampleLevel( gLinearClamp, vmbPixelUv * gResolutionScalePrev, 0 ); + float hitDistForTrackingPrev = gPrev_SpecHitDistForTracking.SampleLevel( gLinearClamp, vmbPixelUv * gResolutionScalePrev, 0 ); float3 XvirtualPrev = GetXvirtual( hitDistForTrackingPrev, curvature, X, Xprev, V, Dfactor ); - float XvirtualLengthPrev = length( XvirtualPrev ); + float2 vmbPixelUvPrev = Geometry::GetScreenUv( gWorldToClipPrev, XvirtualPrev ); + vmbPixelUvPrev = materialID == gCameraAttachedReflectionMaterialID ? pixelUv : vmbPixelUvPrev; - float unproj1 = hitDistForTracking / PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, XvirtualLength ); - float unproj2 = hitDistForTrackingPrev / PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, XvirtualLengthPrev ); - float lobeRadiusInPixels = lobeTanHalfAngle * min( unproj1, unproj2 ); + float pixelSizeAtXvirtual = PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, XvirtualLength ); + float r = ( lobeTanHalfAngle + curvatureAngle ) * min( hitDistForTracking, hitDistForTrackingPrev ) / pixelSizeAtXvirtual; // "pixelSize" at "XvirtualPrev" seems to be not needed + float d = length( ( vmbPixelUvPrev - vmbPixelUv ) * gRectSize ); - float deltaParallaxInPixels = length( ( vmbPixelUvPrev - vmbPixelUv ) * gRectSize ); - virtualHistoryParallaxBasedConfidence = Math::SmoothStep( lobeRadiusInPixels + 0.25, 0.0, deltaParallaxInPixels ); + r = max( r, 0.1 ); // important, especially if "curvatureAngle" is not used + virtualHistoryParallaxBasedConfidence = Math::LinearStep( r, 0.0, d ); } // Virtual motion - normal & roughness prev-prev tests @@ -553,12 +576,17 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : for( i = 1; i <= REBLUR_VIRTUAL_MOTION_PREV_PREV_WEIGHT_ITERATION_NUM; i++ ) { float2 vmbPixelUvPrev = vmbPixelUv + vmbDelta * i * stepBetweenTaps; - float4 vmbNormalAndRoughnessPrev = NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Prev_Normal_Roughness.SampleLevel( gNearestClamp, StochasticBilinear( vmbPixelUvPrev, gRectSizePrev ) * gResolutionScalePrev, 0 ) ); + float4 vmbNormalAndRoughnessPrev = NRD_FrontEnd_UnpackNormalAndRoughness( gPrev_Normal_Roughness.SampleLevel( STOCHASTIC_BILINEAR_FILTER, StochasticBilinear( vmbPixelUvPrev, gRectSizePrev ) * gResolutionScalePrev, 0 ) ); float2 w; w.x = GetEncodingAwareNormalWeight( vmbNormalAndRoughness.xyz, vmbNormalAndRoughnessPrev.xyz, lobeHalfAngle, curvatureAngle * ( 1.0 + i * stepBetweenTaps ), REBLUR_NORMAL_ULP ); w.y = ComputeNonExponentialWeightWithSigma( vmbNormalAndRoughnessPrev.w * vmbNormalAndRoughnessPrev.w, relaxedRoughnessWeightParams.x, relaxedRoughnessWeightParams.y, roughnessSigma ); + #if( REBLUR_USE_STF == 1 && NRD_NORMAL_ENCODING == NRD_NORMAL_ENCODING_R10G10B10A2_UNORM ) + // Cures issues of "StochasticBilinear", produces closer look to the linear filter + w = lerp( 1.0, w, saturate( stepBetweenTaps ) ); + #endif + w = IsInScreenNearest( vmbPixelUvPrev ) ? w : 1.0; virtualHistoryNormalBasedConfidence = min( virtualHistoryNormalBasedConfidence, w.x ); @@ -577,10 +605,10 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : BicubicFilterNoCornersWithFallbackToBilinearFilterWithCustomWeights( saturate( smbPixelUv ) * gRectSizePrev, gResourceSizeInvPrev, smbOcclusionWeights, smbAllowCatRom, - gIn_Spec_History, smbSpecHistory, - gIn_SpecFast_History, smbSpecFastHistory + gHistory_Spec, smbSpecHistory, + gHistory_SpecFast, smbSpecFastHistory #ifdef REBLUR_SH - , gIn_SpecSh_History, smbSpecShHistory + , gHistory_SpecSh, smbSpecShHistory #endif ); @@ -590,20 +618,21 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // - curvature is so high that "vmb" regresses to "smb" and starts to lag float surfaceHistoryConfidence = 1.0; { - float a = atan( smbParallaxInPixels * pixelSize / length( X ) ); + float a = atan( smbParallaxInPixelsMax * pixelSize / length( X ) ); //a = acos( saturate( dot( V, smbVprev ) ) ); // numerically unstable float nonLinearAccumSpeed = 1.0 / ( 1.0 + smbSpecAccumSpeed ); float h = lerp( ExtractHitDist( smbSpecHistory ), ExtractHitDist( spec ), nonLinearAccumSpeed ) * hitDistNormalization; float hdf = GetHitDistFactor( h, frustumSize ); - float a0 = ImportanceSampling::GetSpecularLobeTanHalfAngle( roughnessModified, REBLUR_MAX_PERCENT_OF_LOBE_VOLUME ); // base lobe angle + float a0 = ImportanceSampling::GetSpecularLobeTanHalfAngle( roughnessModified, NRD_MAX_PERCENT_OF_LOBE_VOLUME ); // base lobe angle a0 *= lerp( NoV, 1.0, roughnessModified ); // make more strict if NoV is low and lobe is very V-dependent a0 *= nonLinearAccumSpeed; // make more strict if history is long a0 /= hdf + NRD_EPS; // make relaxed "in corners", where reflection is close to the surface a0 = atan( a0 ); + a0 = max( a0, NRD_NORMAL_ENCODING_ERROR ); - float f = Math::LinearStep( a0 + NRD_EPS, 0.0, a ); + float f = Math::LinearStep( a0, 0.0, a ); surfaceHistoryConfidence = Math::Pow01( f, 4.0 ); } @@ -664,10 +693,10 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : BicubicFilterNoCornersWithFallbackToBilinearFilterWithCustomWeights( saturate( vmbPixelUv ) * gRectSizePrev, gResourceSizeInvPrev, vmbOcclusionWeights, vmbAllowCatRom, - gIn_Spec_History, vmbSpecHistory, - gIn_SpecFast_History, vmbSpecFastHistory + gHistory_Spec, vmbSpecHistory, + gHistory_SpecFast, vmbSpecFastHistory #ifdef REBLUR_SH - , gIn_SpecSh_History, vmbSpecShHistory + , gHistory_SpecSh, vmbSpecShHistory #endif ); @@ -736,6 +765,12 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float specFastResult = lerp( smbSpecFast, vmbSpecFast, virtualHistoryAmount ); + #if( !defined REBLUR_OCCLUSION && !defined REBLUR_DIRECTIONAL_OCCLUSION ) + // Firefly suppressor ( fixes heavy crawling under camera rotation: test 95, 120 ) + float specFastClamped = min( specFastResult, GetLuma( specHistory ) * specMaxRelativeIntensity * REBLUR_FIREFLY_SUPPRESSOR_FAST_RELATIVE_INTENSITY ); + specFastResult = lerp( specFastResult, specFastClamped, specAntifireflyFactor ); + #endif + gOut_SpecFast[ pixelPos ] = specFastResult; // Debug @@ -773,7 +808,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Accumulation speed float diffHistoryConfidence = smbFootprintQuality; if( gHasHistoryConfidence && NRD_USE_HISTORY_CONFIDENCE ) - diffHistoryConfidence *= gIn_Diff_Confidence[ WithRectOrigin( pixelPos ) ]; + diffHistoryConfidence *= gIn_DiffConfidence[ WithRectOrigin( pixelPos ) ]; diffAccumSpeed *= lerp( diffHistoryConfidence, 1.0, 1.0 / ( 1.0 + diffAccumSpeed ) ); diffAccumSpeed = min( diffAccumSpeed, gMaxAccumulatedFrameNum ); @@ -809,10 +844,10 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : BicubicFilterNoCornersWithFallbackToBilinearFilterWithCustomWeights( saturate( smbPixelUv ) * gRectSizePrev, gResourceSizeInvPrev, smbOcclusionWeights, smbAllowCatRom, - gIn_Diff_History, smbDiffHistory, - gIn_DiffFast_History, smbDiffFastHistory + gHistory_Diff, smbDiffHistory, + gHistory_DiffFast, smbDiffFastHistory #ifdef REBLUR_SH - , gIn_DiffSh_History, smbDiffShHistory + , gHistory_DiffSh, smbDiffShHistory #endif ); @@ -860,6 +895,11 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : diffFastNonLinearAccumSpeed *= lerp( 1.0 - gCheckerboardResolveAccumSpeed, 1.0, diffFastNonLinearAccumSpeed ); float diffFastResult = lerp( smbDiffFastHistory.x, GetLuma( diff ), diffFastNonLinearAccumSpeed ); + #if( !defined REBLUR_OCCLUSION && !defined REBLUR_DIRECTIONAL_OCCLUSION ) + // Firefly suppressor ( fixes heavy crawling under camera rotation, test 99 ) + float diffFastClamped = min( diffFastResult, GetLuma( smbDiffHistory ) * diffMaxRelativeIntensity * REBLUR_FIREFLY_SUPPRESSOR_FAST_RELATIVE_INTENSITY ); + diffFastResult = lerp( diffFastResult, diffFastClamped, diffAntifireflyFactor ); + #endif gOut_DiffFast[ pixelPos ] = diffFastResult; #else diff --git a/Shaders/Include/REBLUR_TemporalStabilization.hlsli b/Shaders/Include/REBLUR_TemporalStabilization.hlsli index b467981a..08c3d775 100644 --- a/Shaders/Include/REBLUR_TemporalStabilization.hlsli +++ b/Shaders/Include/REBLUR_TemporalStabilization.hlsli @@ -51,17 +51,6 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : if( viewZ > gDenoisingRange ) return; // IMPORTANT: no data output, must be rejected by the "viewZ" check! - // Normal and roughness - float materialID; - float4 normalAndRoughness = NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Normal_Roughness[ WithRectOrigin( pixelPos ) ], materialID ); - float3 N = normalAndRoughness.xyz; - float roughness = normalAndRoughness.w; - - // Position - float2 pixelUv = float2( pixelPos + 0.5 ) * gRectSizeInv; - float3 Xv = Geometry::ReconstructViewPosition( pixelUv, gFrustum, viewZ, gOrthoMode ); - float3 X = Geometry::RotateVector( gViewToWorld, Xv ); - // Local variance int2 smemPos = threadPos + BORDER; @@ -76,8 +65,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float3 diffShM2 = diffSh.xyz * diffSh.xyz; #endif - float2 diffMin = NRD_INF; - float2 diffMax = -NRD_INF; + float diffMin = NRD_INF; + float diffMax = -NRD_INF; #endif #ifdef REBLUR_SPECULAR @@ -91,8 +80,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float3 specShM2 = specSh.xyz * specSh.xyz; #endif - float2 specMin = NRD_INF; - float2 specMax = -NRD_INF; + float specMin = NRD_INF; + float specMax = -NRD_INF; #endif [unroll] @@ -120,8 +109,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // RCRS float diffLuma = GetLuma( d ); - diffMin = min( diffMin, float2( diffLuma, d.w ) ); - diffMax = max( diffMax, float2( diffLuma, d.w ) ); + diffMin = min( diffMin, diffLuma ); + diffMax = max( diffMax, diffLuma ); #endif #ifdef REBLUR_SPECULAR @@ -138,8 +127,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // RCRS float specLuma = GetLuma( s ); - specMin = min( specMin, float2( specLuma, s.w ) ); - specMax = max( specMax, float2( specLuma, s.w ) ); + specMin = min( specMin, specLuma ); + specMax = max( specMax, specLuma ); #endif } } @@ -159,14 +148,16 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : #endif // RCRS - float diffLuma = GetLuma( diff ); - float diffLumaClamped = clamp( diffLuma, diffMin.x, diffMax.x ); - [flatten] if( gMaxBlurRadius != 0 ) { + float diffLuma = GetLuma( diff ); + float diffLumaClamped = clamp( diffLuma, diffMin, diffMax ); + diff = ChangeLuma( diff, diffLumaClamped ); - diff.w = clamp( diff.w, diffMin.y, diffMax.y ); + #ifdef REBLUR_SH + diffSh.xyz *= GetLumaScale( length( diffSh.xyz ), diffLumaClamped ); + #endif } #endif @@ -183,29 +174,31 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : #endif // RCRS - float specLuma = GetLuma( spec ); - float specLumaClamped = clamp( specLuma, specMin.x, specMax.x ); - [flatten] if( gMaxBlurRadius != 0 ) { + float specLuma = GetLuma( spec ); + float specLumaClamped = clamp( specLuma, specMin, specMax ); + spec = ChangeLuma( spec, specLumaClamped ); - spec.w = clamp( spec.w, specMin.y, specMax.y ); + #ifdef REBLUR_SH + specSh.xyz *= GetLumaScale( length( specSh.xyz ), specLumaClamped ); + #endif } #endif + // Position + float2 pixelUv = float2( pixelPos + 0.5 ) * gRectSizeInv; + float3 Xv = Geometry::ReconstructViewPosition( pixelUv, gFrustum, viewZ, gOrthoMode ); + float3 X = Geometry::RotateVector( gViewToWorld, Xv ); + // Previous position and surface motion uv float4 inMv = gInOut_Mv[ WithRectOrigin( pixelPos ) ]; float3 mv = inMv.xyz * gMvScale.xyz; float3 Xprev = X; float2 smbPixelUv = pixelUv + mv.xy; - if( gMvScale.w != 0.0 ) - { - Xprev += mv; - smbPixelUv = Geometry::GetScreenUv( gWorldToClipPrev, Xprev ); - } - else + if( gMvScale.w == 0.0 ) { if( gMvScale.z == 0.0 ) mv.z = Geometry::AffineTransform( gWorldToViewPrev, X ).z - viewZ; @@ -215,6 +208,17 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : Xprev = Geometry::RotateVectorInverse( gWorldToViewPrev, Xvprevlocal ) + gCameraDelta.xyz; } + else + { + Xprev += mv; + smbPixelUv = Geometry::GetScreenUv( gWorldToClipPrev, Xprev ); + } + + // Normal and roughness + float materialID; + float4 normalAndRoughness = NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Normal_Roughness[ WithRectOrigin( pixelPos ) ], materialID ); + float3 N = normalAndRoughness.xyz; + float roughness = normalAndRoughness.w; // Shared data uint bits; @@ -238,9 +242,9 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : BicubicFilterNoCornersWithFallbackToBilinearFilterWithCustomWeights( saturate( smbPixelUv ) * gRectSizePrev, gResourceSizeInvPrev, smbOcclusionWeights, smbAllowCatRom, - gIn_Diff_StabilizedHistory, smbDiffHistory + gHistory_DiffStabilized, smbDiffHistory #ifdef REBLUR_SH - , gIn_DiffSh_StabilizedHistory, smbDiffShHistory + , gHistory_DiffShStabilized, smbDiffShHistory #endif ); @@ -248,21 +252,21 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : smbDiffHistory = ClampNegativeToZero( smbDiffHistory ); // Compute antilag - float diffStabilizationStrength = float( pixelUv.x >= gSplitScreen ) * float( smbPixelUv.x >= gSplitScreen ); - float diffAntilag = ComputeAntilag( smbDiffHistory, diff, diffSigma, gAntilagParams, smbFootprintQuality * data1.x ); + float diffAntilag = ComputeAntilag( smbDiffHistory, diffM1, diffSigma, smbFootprintQuality * data1.x ); // Clamp history and combine with the current frame float2 diffTemporalAccumulationParams = GetTemporalAccumulationParams( smbFootprintQuality, data1.x ); float diffHistoryWeight = diffTemporalAccumulationParams.x; diffHistoryWeight *= diffAntilag; // this is important - diffHistoryWeight *= diffStabilizationStrength; + diffHistoryWeight *= float( pixelUv.x >= gSplitScreen ); + diffHistoryWeight *= float( smbPixelUv.x >= gSplitScreen ); smbDiffHistory = Color::Clamp( diffM1, diffSigma * diffTemporalAccumulationParams.y, smbDiffHistory ); REBLUR_TYPE diffResult; - diffResult.xyz = lerp( diff.xyz, smbDiffHistory.xyz, diffHistoryWeight * gStabilizationStrength ); - diffResult.w = lerp( diff.w, smbDiffHistory.w, diffHistoryWeight * gHitDistStabilizationStrength ); + diffResult.xyz = lerp( diff.xyz, smbDiffHistory.xyz, min( diffHistoryWeight, gStabilizationStrength ) ); + diffResult.w = lerp( diff.w, smbDiffHistory.w, min( diffHistoryWeight, gHitDistStabilizationStrength ) ); #ifdef REBLUR_SH smbDiffShHistory.xyz = Color::Clamp( diffShM1, diffShSigma * diffTemporalAccumulationParams.y, smbDiffShHistory.xyz ); @@ -291,19 +295,21 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float curvature = data2.y; // Hit distance for tracking ( tests 6, 67, 155 ) - float hitDistForTracking = min( spec.w, specMin.y ) * _REBLUR_GetHitDistanceNormalization( viewZ, gHitDistParams, roughness ); + float hitDistForTracking = spec.w * _REBLUR_GetHitDistanceNormalization( viewZ, gHitDistParams, roughness ); // TODO: min in 3x3 seems to be not needed here // Needed to preserve contact ( test 3, 8 ), but adds pixelation in some cases ( test 160 ). More fun if lobe trimming is off. [flatten] if( gSpecPrepassBlurRadius != 0.0 ) - hitDistForTracking = min( hitDistForTracking, gIn_Spec_HitDistForTracking[ pixelPos ] ); + hitDistForTracking = min( hitDistForTracking, gIn_SpecHitDistForTracking[ pixelPos ] ); // Virtual motion float3 V = GetViewVector( X ); float NoV = abs( dot( N, V ) ); float dominantFactor = ImportanceSampling::GetSpecularDominantFactor( NoV, roughness, ML_SPECULAR_DOMINANT_DIRECTION_G2 ); float3 Xvirtual = GetXvirtual( hitDistForTracking, curvature, X, Xprev, V, dominantFactor ); + float2 vmbPixelUv = Geometry::GetScreenUv( gWorldToClipPrev, Xvirtual ); + vmbPixelUv = materialID == gCameraAttachedReflectionMaterialID ? pixelUv : vmbPixelUv; // Modify MVs if requested if( gSpecProbabilityThresholdsForMvModification.x < 1.0 && NRD_USE_BASECOLOR_METALNESS ) @@ -349,9 +355,9 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : BicubicFilterNoCornersWithFallbackToBilinearFilterWithCustomWeights( saturate( smbPixelUv ) * gRectSizePrev, gResourceSizeInvPrev, smbOcclusionWeights, smbAllowCatRom, - gIn_Spec_StabilizedHistory, smbSpecHistory + gHistory_SpecStabilized, smbSpecHistory #ifdef REBLUR_SH - , gIn_SpecSh_StabilizedHistory, smbSpecShHistory + , gHistory_SpecShStabilized, smbSpecShHistory #endif ); @@ -370,9 +376,9 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : BicubicFilterNoCornersWithFallbackToBilinearFilterWithCustomWeights( saturate( vmbPixelUv ) * gRectSizePrev, gResourceSizeInvPrev, vmbOcclusionWeights, vmbAllowCatRom, - gIn_Spec_StabilizedHistory, vmbSpecHistory + gHistory_SpecStabilized, vmbSpecHistory #ifdef REBLUR_SH - , gIn_SpecSh_StabilizedHistory, vmbSpecShHistory + , gHistory_SpecShStabilized, vmbSpecShHistory #endif ); @@ -387,12 +393,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : #endif // Compute antilag - float specStabilizationStrength = float( pixelUv.x >= gSplitScreen ); - specStabilizationStrength *= virtualHistoryAmount != 1.0 ? float( smbPixelUv.x >= gSplitScreen ) : 1.0; - specStabilizationStrength *= virtualHistoryAmount != 0.0 ? float( vmbPixelUv.x >= gSplitScreen ) : 0.0; - float footprintQuality = lerp( smbFootprintQuality, vmbFootprintQuality, virtualHistoryAmount ); - float specAntilag = ComputeAntilag( specHistory, spec, specSigma, gAntilagParams, footprintQuality * data1.y ); + float specAntilag = ComputeAntilag( specHistory, specM1, specSigma, footprintQuality * data1.y ); // Clamp history and combine with the current frame float2 specTemporalAccumulationParams = GetTemporalAccumulationParams( footprintQuality, data1.y ); @@ -402,7 +404,9 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // - compute moments for samples with similar roughness float specHistoryWeight = specTemporalAccumulationParams.x; specHistoryWeight *= specAntilag; // this is important - specHistoryWeight *= specStabilizationStrength; + 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; float responsiveFactor = RemapRoughnessToResponsiveFactor( roughness ); float smc = GetSpecMagicCurve( roughness ); @@ -412,8 +416,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : specHistory = Color::Clamp( specM1, specSigma * specTemporalAccumulationParams.y, specHistory ); REBLUR_TYPE specResult; - specResult.xyz = lerp( spec.xyz, specHistory.xyz, specHistoryWeight * gStabilizationStrength ); - specResult.w = lerp( spec.w, specHistory.w, specHistoryWeight * gHitDistStabilizationStrength ); + specResult.xyz = lerp( spec.xyz, specHistory.xyz, min( specHistoryWeight, gStabilizationStrength ) ); + specResult.w = lerp( spec.w, specHistory.w, min( specHistoryWeight, gHitDistStabilizationStrength ) ); #ifdef REBLUR_SH specShHistory.xyz = Color::Clamp( specShM1, specShSigma * specTemporalAccumulationParams.y, specShHistory.xyz ); diff --git a/Shaders/Include/RELAX_AntiFirefly.hlsli b/Shaders/Include/RELAX_AntiFirefly.hlsli index e1245526..b2c22616 100644 --- a/Shaders/Include/RELAX_AntiFirefly.hlsli +++ b/Shaders/Include/RELAX_AntiFirefly.hlsli @@ -9,14 +9,14 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. */ #ifdef RELAX_SPECULAR - groupshared float4 sharedSpecular[BUFFER_Y][BUFFER_X]; + groupshared float4 s_Spec[BUFFER_Y][BUFFER_X]; #endif #ifdef RELAX_DIFFUSE - groupshared float4 sharedDiffuse[BUFFER_Y][BUFFER_X]; + groupshared float4 s_Diff[BUFFER_Y][BUFFER_X]; #endif - groupshared float sharedMaterialID[BUFFER_Y][BUFFER_X]; +groupshared float s_MaterialID[BUFFER_Y][BUFFER_X]; // Helper functions void Preload(uint2 sharedPos, int2 globalPos) @@ -24,15 +24,15 @@ void Preload(uint2 sharedPos, int2 globalPos) globalPos = clamp(globalPos, 0, gRectSize - 1.0); float materialID; - NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness[globalPos], materialID); - sharedMaterialID[sharedPos.y][sharedPos.x] = materialID; + NRD_FrontEnd_UnpackNormalAndRoughness(gIn_Normal_Roughness[globalPos], materialID); + s_MaterialID[sharedPos.y][sharedPos.x] = materialID; #ifdef RELAX_SPECULAR - sharedSpecular[sharedPos.y][sharedPos.x] = gSpecIllumination[globalPos]; + s_Spec[sharedPos.y][sharedPos.x] = gIn_Spec[globalPos]; #endif #ifdef RELAX_DIFFUSE - sharedDiffuse[sharedPos.y][sharedPos.x] = gDiffIllumination[globalPos]; + s_Diff[sharedPos.y][sharedPos.x] = gIn_Diff[globalPos]; #endif } @@ -50,10 +50,10 @@ void runRCRS( { // Fetching center data uint2 sharedMemoryIndex = threadPos + int2(BORDER, BORDER); - float centerMaterialID = sharedMaterialID[sharedMemoryIndex.y][sharedMemoryIndex.x]; + float centerMaterialID = s_MaterialID[sharedMemoryIndex.y][sharedMemoryIndex.x]; #ifdef RELAX_SPECULAR - float4 s = sharedSpecular[sharedMemoryIndex.y][sharedMemoryIndex.x]; + float4 s = s_Spec[sharedMemoryIndex.y][sharedMemoryIndex.x]; float3 specularIlluminationCenter = s.rgb; float specular2ndMomentCenter = s.a; float specularLuminanceCenter = Color::Luminance(specularIlluminationCenter); @@ -65,7 +65,7 @@ void runRCRS( #endif #ifdef RELAX_DIFFUSE - float4 d = sharedDiffuse[sharedMemoryIndex.y][sharedMemoryIndex.x]; + float4 d = s_Diff[sharedMemoryIndex.y][sharedMemoryIndex.x]; float3 diffuseIlluminationCenter = d.rgb; float diffuse2ndMomentCenter = d.a; float diffuseLuminanceCenter = Color::Luminance(diffuseIlluminationCenter); @@ -93,16 +93,16 @@ void runRCRS( // Fetching sample data #ifdef RELAX_SPECULAR - float3 specularIlluminationSample = sharedSpecular[sharedMemoryIndexSample.y][sharedMemoryIndexSample.x].rgb; + float3 specularIlluminationSample = s_Spec[sharedMemoryIndexSample.y][sharedMemoryIndexSample.x].rgb; float specularLuminanceSample = Color::Luminance(specularIlluminationSample); #endif #ifdef RELAX_DIFFUSE - float3 diffuseIlluminationSample = sharedDiffuse[sharedMemoryIndexSample.y][sharedMemoryIndexSample.x].rgb; + float3 diffuseIlluminationSample = s_Diff[sharedMemoryIndexSample.y][sharedMemoryIndexSample.x].rgb; float diffuseLuminanceSample = Color::Luminance(diffuseIlluminationSample); #endif - float sampleMaterialID = sharedMaterialID[sharedMemoryIndexSample.y][sharedMemoryIndexSample.x]; + float sampleMaterialID = s_MaterialID[sharedMemoryIndexSample.y][sharedMemoryIndexSample.x]; #ifdef RELAX_SPECULAR if (CompareMaterials(sampleMaterialID, centerMaterialID, gSpecMaterialMask) > 0) @@ -146,7 +146,7 @@ void runRCRS( specularCoords = maxSpecularLuminanceCoords; if(specularLuminanceCenter < minSpecularLuminance) specularCoords = minSpecularLuminanceCoords; - outSpecular = float4(sharedSpecular[specularCoords.y][specularCoords.x].rgb, specular2ndMomentCenter); + outSpecular = float4(s_Spec[specularCoords.y][specularCoords.x].rgb, specular2ndMomentCenter); #endif #ifdef RELAX_DIFFUSE @@ -155,14 +155,14 @@ void runRCRS( diffuseCoords = maxDiffuseLuminanceCoords; if(diffuseLuminanceCenter < minDiffuseLuminance) diffuseCoords = minDiffuseLuminanceCoords; - outDiffuse = float4(sharedDiffuse[diffuseCoords.y][diffuseCoords.x].rgb, diffuse2ndMomentCenter); + outDiffuse = float4(s_Diff[diffuseCoords.y][diffuseCoords.x].rgb, diffuse2ndMomentCenter); #endif } [numthreads(GROUP_X, GROUP_Y, 1)] NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPos : SV_GroupThreadId, uint threadIndex : SV_GroupIndex) { - float isSky = gTiles[pixelPos >> 4]; + float isSky = gIn_Tiles[pixelPos >> 4]; PRELOAD_INTO_SMEM_WITH_TILE_CHECK; // Tile-based early out @@ -170,7 +170,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo return; // Early out if linearZ is beyond denoising range - float centerViewZ = UnpackViewZ(gViewZ[pixelPos]); + float centerViewZ = UnpackViewZ(gIn_ViewZ[pixelPos]); if (centerViewZ > gDenoisingRange) return; @@ -195,10 +195,10 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo ); #ifdef RELAX_SPECULAR - gOutSpecularIllumination[pixelPos.xy] = outSpecularIlluminationAnd2ndMoment; + gOut_Spec[pixelPos.xy] = outSpecularIlluminationAnd2ndMoment; #endif #ifdef RELAX_DIFFUSE - gOutDiffuseIllumination[pixelPos.xy] = outDiffuseIlluminationAnd2ndMoment; + gOut_Diff[pixelPos.xy] = outDiffuseIlluminationAnd2ndMoment; #endif } diff --git a/Shaders/Include/RELAX_Atrous.hlsli b/Shaders/Include/RELAX_Atrous.hlsli index e66acdc6..58986ee8 100644 --- a/Shaders/Include/RELAX_Atrous.hlsli +++ b/Shaders/Include/RELAX_Atrous.hlsli @@ -12,35 +12,35 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) { // Tile-based early out - float isSky = gTiles[pixelPos >> 4]; + float isSky = gIn_Tiles[pixelPos >> 4]; if (isSky != 0.0 || pixelPos.x >= gRectSize.x || pixelPos.y >= gRectSize.y) return; // Early out if linearZ is beyond denoising range - float centerViewZ = UnpackViewZ(gViewZ[pixelPos]); + float centerViewZ = UnpackViewZ(gIn_ViewZ[pixelPos]); if (centerViewZ > gDenoisingRange) return; float centerMaterialID; - float4 centerNormalRoughness = NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness[pixelPos], centerMaterialID); + float4 centerNormalRoughness = NRD_FrontEnd_UnpackNormalAndRoughness(gIn_Normal_Roughness[pixelPos], centerMaterialID); float3 centerNormal = centerNormalRoughness.rgb; float centerRoughness = centerNormalRoughness.a; - float historyLength = 255.0 * gHistoryLength[pixelPos]; + float historyLength = 255.0 * gIn_HistoryLength[pixelPos]; // Diffuse normal weight is used for diffuse and can be used for specular depending on settings. // Weight strictness is higher as the Atrous step size increases. - float diffuseLobeAngleFraction = gDiffLobeAngleFraction / sqrt(gStepSize); + float diffuseLobeAngleFraction = gLobeAngleFraction / sqrt(gStepSize); #ifdef RELAX_SH diffuseLobeAngleFraction = 1.0 / sqrt(gStepSize); #endif diffuseLobeAngleFraction = lerp(0.99, diffuseLobeAngleFraction, saturate(historyLength / 5.0)); #ifdef RELAX_SPECULAR - float4 centerSpecularIlluminationAndVariance = gSpecIlluminationAndVariance[pixelPos]; + float4 centerSpecularIlluminationAndVariance = gIn_Spec_Variance[pixelPos]; float centerSpecularLuminance = Color::Luminance(centerSpecularIlluminationAndVariance.rgb); float centerSpecularVar = centerSpecularIlluminationAndVariance.a; - float specularReprojectionConfidence = gSpecReprojectionConfidence[pixelPos]; + float specularReprojectionConfidence = gIn_SpecReprojectionConfidence[pixelPos]; float specularLuminanceWeightRelaxation = 1.0; if (gStepSize <= 4) specularLuminanceWeightRelaxation = lerp(1.0, specularReprojectionConfidence, gLuminanceEdgeStoppingRelaxation); @@ -50,11 +50,11 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) float2 roughnessWeightParams = GetRoughnessWeightParams(centerRoughness, gRoughnessFraction); float diffuseLobeAngleFractionForSimplifiedSpecularNormalWeight = diffuseLobeAngleFraction; - float specularLobeAngleFraction = gSpecLobeAngleFraction; + float specularLobeAngleFraction = gLobeAngleFraction; if (gHasHistoryConfidence && NRD_USE_HISTORY_CONFIDENCE) { - float specConfidenceDrivenRelaxation = saturate(gConfidenceDrivenRelaxationMultiplier * (1.0 - gSpecConfidence[WithRectOrigin(pixelPos)])); + float specConfidenceDrivenRelaxation = saturate(gConfidenceDrivenRelaxationMultiplier * (1.0 - gIn_SpecConfidence[WithRectOrigin(pixelPos)])); // Relaxing normal weights for specular float r = saturate(specConfidenceDrivenRelaxation * gConfidenceDrivenNormalEdgeStoppingRelaxation); @@ -66,7 +66,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) specularLuminanceWeightRelaxation *= 1.0 - r; } - float specularNormalWeightParamsSimplified = GetNormalWeightParams(1.0, diffuseLobeAngleFractionForSimplifiedSpecularNormalWeight); + float specularNormalWeightParamSimplified = GetNormalWeightParam2(1.0, diffuseLobeAngleFractionForSimplifiedSpecularNormalWeight); float2 specularNormalWeightParams = GetNormalWeightParams_ATrous( centerRoughness, @@ -79,14 +79,14 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) float sumWSpecular = 0.44198 * 0.44198; float4 sumSpecularIlluminationAndVariance = centerSpecularIlluminationAndVariance * float4(sumWSpecular.xxx, sumWSpecular * sumWSpecular); #ifdef RELAX_SH - float4 centerSpecularSH1 = gSpecSH1[pixelPos]; - float4 sumSpecularSH1 = centerSpecularSH1 * sumWSpecular; - float roughnessModified = centerSpecularSH1.w; + float4 centerSpecularSH = gIn_SpecSh[pixelPos]; + float4 sumSpecularSH = centerSpecularSH * sumWSpecular; + float roughnessModified = centerSpecularSH.w; #endif #endif #ifdef RELAX_DIFFUSE - float4 centerDiffuseIlluminationAndVariance = gDiffIlluminationAndVariance[pixelPos]; + float4 centerDiffuseIlluminationAndVariance = gIn_Diff_Variance[pixelPos]; float centerDiffuseLuminance = Color::Luminance(centerDiffuseIlluminationAndVariance.rgb); float centerDiffuseVar = centerDiffuseIlluminationAndVariance.a; float diffusePhiLIlluminationInv = 1.0 / max(1.0e-4, gDiffPhiLuminance * sqrt(centerDiffuseVar)); @@ -94,7 +94,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) float diffuseLuminanceWeightRelaxation = 1.0; if (gHasHistoryConfidence && NRD_USE_HISTORY_CONFIDENCE) { - float diffConfidenceDrivenRelaxation = saturate(gConfidenceDrivenRelaxationMultiplier * (1.0 - gDiffConfidence[WithRectOrigin(pixelPos)])); + float diffConfidenceDrivenRelaxation = saturate(gConfidenceDrivenRelaxationMultiplier * (1.0 - gIn_DiffConfidence[WithRectOrigin(pixelPos)])); // Relaxing normal weights for diffuse float r = saturate(diffConfidenceDrivenRelaxation * gConfidenceDrivenNormalEdgeStoppingRelaxation); @@ -104,13 +104,13 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) r = saturate(diffConfidenceDrivenRelaxation * gConfidenceDrivenLuminanceEdgeStoppingRelaxation); diffuseLuminanceWeightRelaxation = 1.0 - r; } - float diffuseNormalWeightParams = GetNormalWeightParams(1.0, diffuseLobeAngleFraction); + float diffuseNormalWeightParam = GetNormalWeightParam2(1.0, diffuseLobeAngleFraction); float sumWDiffuse = 0.44198 * 0.44198; float4 sumDiffuseIlluminationAndVariance = centerDiffuseIlluminationAndVariance * float4(sumWDiffuse.xxx, sumWDiffuse * sumWDiffuse); #ifdef RELAX_SH - float4 centerDiffuseSH1 = gDiffSH1[pixelPos]; - float4 sumDiffuseSH1 = centerDiffuseSH1 * sumWDiffuse; + float4 centerDiffuseSH = gIn_DiffSh[pixelPos]; + float4 sumDiffuseSH = centerDiffuseSH * sumWDiffuse; #endif #endif @@ -143,10 +143,10 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) // Fetching normal, roughness, linear Z float sampleMaterialID; - float4 sampleNormalRoughnes = NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness[p], sampleMaterialID); + float4 sampleNormalRoughnes = NRD_FrontEnd_UnpackNormalAndRoughness(gIn_Normal_Roughness[p], sampleMaterialID); float3 sampleNormal = sampleNormalRoughnes.rgb; float sampleRoughness = sampleNormalRoughnes.a; - float sampleViewZ = UnpackViewZ(gViewZ[p]); + float sampleViewZ = UnpackViewZ(gIn_ViewZ[p]); // Calculating sample world position float3 sampleWorldPos = GetCurrentWorldPosFromPixelPos(p, sampleViewZ); @@ -164,7 +164,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) // Calculating weights for specular float angles = Math::AcosApprox(dot(centerNormal, sampleNormal)); - float normalWSpecularSimplified = ComputeWeight(angles, specularNormalWeightParamsSimplified, 0.0); + float normalWSpecularSimplified = ComputeWeight(angles, specularNormalWeightParamSimplified, 0.0); float normalWSpecular = GetSpecularNormalWeight_ATrous(specularNormalWeightParams, centerNormal, sampleNormal, centerV, sampleV); float roughnessWSpecular = ComputeWeight(sampleRoughness, roughnessWeightParams.x, roughnessWeightParams.y); @@ -173,7 +173,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) wSpecular *= CompareMaterials(sampleMaterialID, centerMaterialID, gSpecMaterialMask); if (wSpecular > 1e-4) { - float4 sampleSpecularIlluminationAndVariance = gSpecIlluminationAndVariance[p]; + float4 sampleSpecularIlluminationAndVariance = gIn_Spec_Variance[p]; float sampleSpecularLuminance = Color::Luminance(sampleSpecularIlluminationAndVariance.rgb); float specularLuminanceW = abs(centerSpecularLuminance - sampleSpecularLuminance) * specularPhiLIlluminationInv; @@ -184,7 +184,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) sumWSpecular += wSpecular; sumSpecularIlluminationAndVariance += float4(wSpecular.xxx, wSpecular * wSpecular) * sampleSpecularIlluminationAndVariance; #ifdef RELAX_SH - sumSpecularSH1 += gSpecSH1[p] * wSpecular; + sumSpecularSH += gIn_SpecSh[p] * wSpecular; #endif } #endif @@ -192,14 +192,14 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) #ifdef RELAX_DIFFUSE // Calculating weights for diffuse float angled = Math::AcosApprox(dot(centerNormal, sampleNormal)); - float normalWDiffuse = ComputeWeight(angled, diffuseNormalWeightParams, 0.0); + float normalWDiffuse = ComputeWeight(angled, diffuseNormalWeightParam, 0.0); // Summing up diffuse float wDiffuse = geometryW * normalWDiffuse; wDiffuse *= CompareMaterials(sampleMaterialID, centerMaterialID, gDiffMaterialMask); if (wDiffuse > 1e-4) { - float4 sampleDiffuseIlluminationAndVariance = gDiffIlluminationAndVariance[p]; + float4 sampleDiffuseIlluminationAndVariance = gIn_Diff_Variance[p]; float sampleDiffuseLuminance = Color::Luminance(sampleDiffuseIlluminationAndVariance.rgb); float diffuseLuminanceW = abs(centerDiffuseLuminance - sampleDiffuseLuminance) * diffusePhiLIlluminationInv; @@ -211,7 +211,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) sumWDiffuse += wDiffuse; sumDiffuseIlluminationAndVariance += float4(wDiffuse.xxx, wDiffuse * wDiffuse) * sampleDiffuseIlluminationAndVariance; #ifdef RELAX_SH - sumDiffuseSH1 += gDiffSH1[p] * wDiffuse; + sumDiffuseSH += gIn_DiffSh[p] * wDiffuse; #endif } #endif @@ -224,9 +224,9 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) // Luminance output is expected in YCoCg color space in SH mode, converting to YCoCg in last A-Trous pass if (gIsLastPass == 1) filteredSpecularIlluminationAndVariance.rgb = _NRD_LinearToYCoCg(filteredSpecularIlluminationAndVariance.rgb); - gOutSpecularSH1[pixelPos] = float4(sumSpecularSH1.rgb / sumWSpecular, roughnessModified); + gOut_SpecSh[pixelPos] = float4(sumSpecularSH.rgb / sumWSpecular, roughnessModified); #endif - gOutSpecularIlluminationAndVariance[pixelPos] = filteredSpecularIlluminationAndVariance; + gOut_Spec_Variance[pixelPos] = filteredSpecularIlluminationAndVariance; #endif #ifdef RELAX_DIFFUSE @@ -235,8 +235,8 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) // Luminance output is expected in YCoCg color space in SH mode, converting to YCoCg in last A-Trous pass if (gIsLastPass == 1) filteredDiffuseIlluminationAndVariance.rgb = _NRD_LinearToYCoCg(filteredDiffuseIlluminationAndVariance.rgb); - gOutDiffuseSH1[pixelPos] = sumDiffuseSH1 / sumWDiffuse; + gOut_DiffSh[pixelPos] = sumDiffuseSH / sumWDiffuse; #endif - gOutDiffuseIlluminationAndVariance[pixelPos] = filteredDiffuseIlluminationAndVariance; + gOut_Diff_Variance[pixelPos] = filteredDiffuseIlluminationAndVariance; #endif } diff --git a/Shaders/Include/RELAX_AtrousSmem.hlsli b/Shaders/Include/RELAX_AtrousSmem.hlsli index 3e286a19..cb5b6f4f 100644 --- a/Shaders/Include/RELAX_AtrousSmem.hlsli +++ b/Shaders/Include/RELAX_AtrousSmem.hlsli @@ -9,21 +9,21 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. */ #ifdef RELAX_DIFFUSE - groupshared float4 sharedDiffuse[BUFFER_Y][BUFFER_X]; + groupshared float4 s_Diff[BUFFER_Y][BUFFER_X]; #ifdef RELAX_SH - groupshared float4 sharedDiffuseSH1[BUFFER_Y][BUFFER_X]; + groupshared float4 s_DiffSH[BUFFER_Y][BUFFER_X]; #endif #endif #ifdef RELAX_SPECULAR - groupshared float4 sharedSpecular[BUFFER_Y][BUFFER_X]; + groupshared float4 s_Spec[BUFFER_Y][BUFFER_X]; #ifdef RELAX_SH - groupshared float4 sharedSpecularSH1[BUFFER_Y][BUFFER_X]; + groupshared float4 s_SpecSH[BUFFER_Y][BUFFER_X]; #endif #endif -groupshared float4 sharedNormalRoughness[BUFFER_Y][BUFFER_X]; -groupshared float4 sharedWorldPosMaterialID[BUFFER_Y][BUFFER_X]; +groupshared float4 s_Normal_Roughness[BUFFER_Y][BUFFER_X]; +groupshared float4 s_WorldPos_MaterialID[BUFFER_Y][BUFFER_X]; // Helper functions @@ -62,11 +62,11 @@ void computeVariance( int2 sharedMemoryIndexP = sharedMemoryIndex + int2(dx,dy); float k = kernel[abs(dx)][abs(dy)]; #ifdef RELAX_SPECULAR - float4 specular = sharedSpecular[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; + float4 specular = s_Spec[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; specularSum += specular * k; #endif #ifdef RELAX_DIFFUSE - float4 diffuse = sharedDiffuse[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; + float4 diffuse = s_Diff[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; diffuseSum += diffuse * k; #endif } @@ -88,23 +88,23 @@ void Preload(uint2 sharedPos, int2 globalPos) globalPos = clamp(globalPos, 0, gRectSize - 1.0); #ifdef RELAX_SPECULAR - sharedSpecular[sharedPos.y][sharedPos.x] = gSpecIlluminationAnd2ndMoment[globalPos]; + s_Spec[sharedPos.y][sharedPos.x] = gIn_Spec_Variance[globalPos]; #ifdef RELAX_SH - sharedSpecularSH1[sharedPos.y][sharedPos.x] = gSpecSH1[globalPos]; + s_SpecSH[sharedPos.y][sharedPos.x] = gIn_SpecSh[globalPos]; #endif #endif #ifdef RELAX_DIFFUSE - sharedDiffuse[sharedPos.y][sharedPos.x] = gDiffIlluminationAnd2ndMoment[globalPos]; + s_Diff[sharedPos.y][sharedPos.x] = gIn_Diff_Variance[globalPos]; #ifdef RELAX_SH - sharedDiffuseSH1[sharedPos.y][sharedPos.x] = gDiffSH1[globalPos]; + s_DiffSH[sharedPos.y][sharedPos.x] = gIn_DiffSh[globalPos]; #endif #endif float materialID; - sharedNormalRoughness[sharedPos.y][sharedPos.x] = NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness[globalPos], materialID); + s_Normal_Roughness[sharedPos.y][sharedPos.x] = NRD_FrontEnd_UnpackNormalAndRoughness(gIn_Normal_Roughness[globalPos], materialID); - float viewZ = UnpackViewZ(gViewZ[globalPos]); - sharedWorldPosMaterialID[sharedPos.y][sharedPos.x] = float4(GetCurrentWorldPosFromPixelPos(globalPos, viewZ), materialID); + float viewZ = UnpackViewZ(gIn_ViewZ[globalPos]); + s_WorldPos_MaterialID[sharedPos.y][sharedPos.x] = float4(GetCurrentWorldPosFromPixelPos(globalPos, viewZ), materialID); } @@ -112,30 +112,30 @@ void Preload(uint2 sharedPos, int2 globalPos) NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos : SV_GroupThreadId, uint threadIndex : SV_GroupIndex) { // Preload - float isSky = gTiles[pixelPos >> 4]; + float isSky = gIn_Tiles[pixelPos >> 4]; PRELOAD_INTO_SMEM_WITH_TILE_CHECK; // Prev ViewZ - float viewZpacked = gViewZ[pixelPos]; - gOutViewZ[pixelPos] = viewZpacked; + float viewZpacked = gIn_ViewZ[pixelPos]; + gOut_ViewZ[pixelPos] = viewZpacked; // Prev normal and roughness int2 sharedMemoryIndex = threadPos.xy + int2(BORDER, BORDER); - float4 normalRoughness = sharedNormalRoughness[sharedMemoryIndex.y][sharedMemoryIndex.x]; + float4 normalRoughness = s_Normal_Roughness[sharedMemoryIndex.y][sharedMemoryIndex.x]; float centerViewZ = UnpackViewZ(viewZpacked); if (centerViewZ > gDenoisingRange) { // Setting normal and roughness to close to zero for out of range pixels normalRoughness = 1.0 / 255.0; } - gOutNormalRoughness[pixelPos] = PackPrevNormalRoughness(normalRoughness); + gOut_NormalRoughness[pixelPos] = PackPrevNormalRoughness(normalRoughness); - float4 centerWorldPosMaterialID = sharedWorldPosMaterialID[sharedMemoryIndex.y][sharedMemoryIndex.x]; + float4 centerWorldPosMaterialID = s_WorldPos_MaterialID[sharedMemoryIndex.y][sharedMemoryIndex.x]; float3 centerWorldPos = centerWorldPosMaterialID.xyz; float centerMaterialID = centerWorldPosMaterialID.w; #if( NRD_NORMAL_ENCODING == NRD_NORMAL_ENCODING_R10G10B10A2_UNORM ) - gOutMaterialID[pixelPos] = centerMaterialID; + gOut_MaterialID[pixelPos] = centerMaterialID / 255.0; #endif // Tile-based early out @@ -149,7 +149,7 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos float3 centerNormal = normalRoughness.rgb; float centerRoughness = normalRoughness.a; - float historyLength = 255.0 * gHistoryLength[pixelPos]; + float historyLength = 255.0 * gIn_HistoryLength[pixelPos]; [branch] if (historyLength >= gHistoryThreshold) // Running Atrous 3x3 @@ -172,22 +172,22 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos ); // Diffuse normal weight is used for diffuse and can be used for specular depending on settings. - float diffuseLobeAngleFraction = gDiffLobeAngleFraction; + float diffuseLobeAngleFraction = gLobeAngleFraction; #ifdef RELAX_SPECULAR - float specularReprojectionConfidence = gSpecReprojectionConfidence[pixelPos]; + float specularReprojectionConfidence = gIn_SpecReprojectionConfidence[pixelPos]; float specularLuminanceWeightRelaxation = lerp(1.0, specularReprojectionConfidence, gLuminanceEdgeStoppingRelaxation); - float centerSpecularLuminance = Color::Luminance(sharedSpecular[sharedMemoryIndex.y][sharedMemoryIndex.x].rgb); + float centerSpecularLuminance = Color::Luminance(s_Spec[sharedMemoryIndex.y][sharedMemoryIndex.x].rgb); float specularPhiLIlluminationInv = 1.0 / max(1.0e-4, gSpecPhiLuminance * sqrt(centerSpecularVar)); float2 roughnessWeightParams = GetRoughnessWeightParams(centerRoughness, gRoughnessFraction); float diffuseLobeAngleFractionForSimplifiedSpecularNormalWeight = diffuseLobeAngleFraction; - float specularLobeAngleFraction = gSpecLobeAngleFraction; + float specularLobeAngleFraction = gLobeAngleFraction; if (gHasHistoryConfidence && NRD_USE_HISTORY_CONFIDENCE) { - float specConfidenceDrivenRelaxation = saturate(gConfidenceDrivenRelaxationMultiplier * (1.0 - gSpecConfidence[WithRectOrigin(pixelPos)])); + float specConfidenceDrivenRelaxation = saturate(gConfidenceDrivenRelaxationMultiplier * (1.0 - gIn_SpecConfidence[WithRectOrigin(pixelPos)])); // Relaxing normal weights for specular float r = saturate(specConfidenceDrivenRelaxation * gConfidenceDrivenNormalEdgeStoppingRelaxation); @@ -199,7 +199,7 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos specularLuminanceWeightRelaxation *= 1.0 - r; } - float specularNormalWeightParamsSimplified = GetNormalWeightParams(1.0, diffuseLobeAngleFractionForSimplifiedSpecularNormalWeight); + float specularNormalWeightParamSimplified = GetNormalWeightParam2(1.0, diffuseLobeAngleFractionForSimplifiedSpecularNormalWeight); float2 specularNormalWeightParams = GetNormalWeightParams_ATrous( centerRoughness, @@ -212,20 +212,20 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos float sumWSpecular = 0; float4 sumSpecularIlluminationAnd2ndMoment = 0; #ifdef RELAX_SH - float4 sumSpecularSH1 = 0; - float roughnessModified = sharedSpecularSH1[sharedMemoryIndex.y][sharedMemoryIndex.x].w; + float4 sumSpecularSH = 0; + float roughnessModified = s_SpecSH[sharedMemoryIndex.y][sharedMemoryIndex.x].w; #endif float3 centerV = -normalize(centerWorldPos); #endif #ifdef RELAX_DIFFUSE - float centerDiffuseLuminance = Color::Luminance(sharedDiffuse[sharedMemoryIndex.y][sharedMemoryIndex.x].rgb); + float centerDiffuseLuminance = Color::Luminance(s_Diff[sharedMemoryIndex.y][sharedMemoryIndex.x].rgb); float diffusePhiLIlluminationInv = 1.0 / max(1.0e-4, gDiffPhiLuminance * sqrt(centerDiffuseVar)); float diffuseLuminanceWeightRelaxation = 1.0; if (gHasHistoryConfidence && NRD_USE_HISTORY_CONFIDENCE) { - float diffConfidenceDrivenRelaxation = saturate(gConfidenceDrivenRelaxationMultiplier * (1.0 - gDiffConfidence[WithRectOrigin(pixelPos)])); + float diffConfidenceDrivenRelaxation = saturate(gConfidenceDrivenRelaxationMultiplier * (1.0 - gIn_DiffConfidence[WithRectOrigin(pixelPos)])); // Relaxing normal weights for diffuse float r = saturate(diffConfidenceDrivenRelaxation * gConfidenceDrivenNormalEdgeStoppingRelaxation); @@ -235,12 +235,12 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos r = saturate(diffConfidenceDrivenRelaxation * gConfidenceDrivenLuminanceEdgeStoppingRelaxation); diffuseLuminanceWeightRelaxation = 1.0 - r; } - float diffuseNormalWeightParams = GetNormalWeightParams(1.0, diffuseLobeAngleFraction); + float diffuseNormalWeightParam = GetNormalWeightParam2(1.0, diffuseLobeAngleFraction); float sumWDiffuse = 0; float4 sumDiffuseIlluminationAnd2ndMoment = 0; #ifdef RELAX_SH - float4 sumDiffuseSH1 = 0; + float4 sumDiffuseSH = 0; #endif #endif @@ -260,10 +260,10 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos int2 sharedMemoryIndexP = sharedMemoryIndex + int2(cx, cy); - float4 sampleNormalRoughness = sharedNormalRoughness[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; + float4 sampleNormalRoughness = s_Normal_Roughness[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; float3 sampleNormal = sampleNormalRoughness.rgb; float sampleRoughness = sampleNormalRoughness.a; - float4 sampleWorldPosMaterialID = sharedWorldPosMaterialID[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; + float4 sampleWorldPosMaterialID = s_WorldPos_MaterialID[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; float3 sampleWorldPos = sampleWorldPosMaterialID.rgb; float sampleMaterialID = sampleWorldPosMaterialID.a; @@ -284,13 +284,13 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos // relaxes view direction based rejection float angles = Math::AcosApprox(dot(centerNormal, sampleNormal)); float3 sampleV = -normalize(sampleWorldPos + gRoughnessEdgeStoppingRelaxation * centerWorldPos); - float normalWSpecularSimplified = ComputeWeight(angles, specularNormalWeightParamsSimplified, 0.0); + float normalWSpecularSimplified = ComputeWeight(angles, specularNormalWeightParamSimplified, 0.0); float normalWSpecular = GetSpecularNormalWeight_ATrous(specularNormalWeightParams, centerNormal, sampleNormal, centerV, sampleV); float roughnessWSpecular = ComputeWeight(sampleRoughness, roughnessWeightParams.x, roughnessWeightParams.y); // Summing up specular - float4 sampleSpecularIlluminationAnd2ndMoment = sharedSpecular[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; + float4 sampleSpecularIlluminationAnd2ndMoment = s_Spec[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; float sampleSpecularLuminance = Color::Luminance(sampleSpecularIlluminationAnd2ndMoment.rgb); float specularLuminanceW = abs(centerSpecularLuminance - sampleSpecularLuminance) * specularPhiLIlluminationInv; @@ -305,16 +305,16 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos sumWSpecular += wSpecular; sumSpecularIlluminationAnd2ndMoment += wSpecular * sampleSpecularIlluminationAnd2ndMoment; #ifdef RELAX_SH - sumSpecularSH1 += wSpecular * sharedSpecularSH1[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; + sumSpecularSH += wSpecular * s_SpecSH[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; #endif #endif #ifdef RELAX_DIFFUSE // Calculating weights for diffuse float angled = Math::AcosApprox(dot(centerNormal, sampleNormal)); - float normalWDiffuse = ComputeWeight(angled, diffuseNormalWeightParams, 0.0); + float normalWDiffuse = ComputeWeight(angled, diffuseNormalWeightParam, 0.0); // Summing up diffuse - float4 sampleDiffuseIlluminationAnd2ndMoment = sharedDiffuse[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; + float4 sampleDiffuseIlluminationAnd2ndMoment = s_Diff[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; float sampleDiffuseLuminance = Color::Luminance(sampleDiffuseIlluminationAnd2ndMoment.rgb); float diffuseLuminanceW = abs(centerDiffuseLuminance - sampleDiffuseLuminance) * diffusePhiLIlluminationInv; @@ -329,7 +329,7 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos sumWDiffuse += wDiffuse; sumDiffuseIlluminationAnd2ndMoment += wDiffuse * sampleDiffuseIlluminationAnd2ndMoment; #ifdef RELAX_SH - sumDiffuseSH1 += wDiffuse * sharedDiffuseSH1[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; + sumDiffuseSH += wDiffuse * s_DiffSH[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; #endif #endif } @@ -341,9 +341,9 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos float specular2ndMoment = sumSpecularIlluminationAnd2ndMoment.a; float specularVariance = max(0, specular2ndMoment - specular1stMoment * specular1stMoment); float4 filteredSpecularIlluminationAndVariance = float4(sumSpecularIlluminationAnd2ndMoment.rgb, specularVariance); - gOutSpecularIlluminationAndVariance[pixelPos] = filteredSpecularIlluminationAndVariance; + gOut_Spec_Variance[pixelPos] = filteredSpecularIlluminationAndVariance; #ifdef RELAX_SH - gOutSpecularSH1[pixelPos] = float4(sumSpecularSH1.rgb / sumWSpecular, roughnessModified); + gOut_SpecSh[pixelPos] = float4(sumSpecularSH.rgb / sumWSpecular, roughnessModified); #endif #endif #ifdef RELAX_DIFFUSE @@ -353,9 +353,9 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos float diffuse2ndMoment = sumDiffuseIlluminationAnd2ndMoment.a; float diffuseVariance = max(0, diffuse2ndMoment - diffuse1stMoment * diffuse1stMoment); float4 filteredDiffuseIlluminationAndVariance = float4(sumDiffuseIlluminationAnd2ndMoment.rgb, diffuseVariance); - gOutDiffuseIlluminationAndVariance[pixelPos] = filteredDiffuseIlluminationAndVariance; + gOut_Diff_Variance[pixelPos] = filteredDiffuseIlluminationAndVariance; #ifdef RELAX_SH - gOutDiffuseSH1[pixelPos] = sumDiffuseSH1 / sumWDiffuse; + gOut_DiffSh[pixelPos] = sumDiffuseSH / sumWDiffuse; #endif #endif } @@ -368,7 +368,7 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos float sumSpecular1stMoment = 0; float sumSpecular2ndMoment = 0; #ifdef RELAX_SH - float4 sumSpecularSH1 = 0; + float4 sumSpecularSH = 0; #endif #endif @@ -378,12 +378,12 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos float sumDiffuse1stMoment = 0; float sumDiffuse2ndMoment = 0; #ifdef RELAX_SH - float4 sumDiffuseSH1 = 0; + float4 sumDiffuseSH = 0; #endif #endif // Normal weight is same for diffuse and specular during spatial variance estimation - float diffuseNormalWeightParams = GetNormalWeightParams(1.0, gDiffLobeAngleFraction); + float diffuseNormalWeightParam = GetNormalWeightParam2(1.0, gLobeAngleFraction); // Compute first and second moment spatially. This code also applies cross-bilateral // filtering on the input illumination. @@ -395,16 +395,16 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos { int2 sharedMemoryIndexP = sharedMemoryIndex + int2(cx, cy); - float3 sampleNormal = sharedNormalRoughness[sharedMemoryIndexP.y][sharedMemoryIndexP.x].rgb; - float sampleMaterialID = sharedWorldPosMaterialID[sharedMemoryIndexP.y][sharedMemoryIndexP.x].a; + float3 sampleNormal = s_Normal_Roughness[sharedMemoryIndexP.y][sharedMemoryIndexP.x].rgb; + float sampleMaterialID = s_WorldPos_MaterialID[sharedMemoryIndexP.y][sharedMemoryIndexP.x].a; // Calculating weights float depthW = 1.0;// TODO: should we take in account depth here? float angle = Math::AcosApprox(dot(centerNormal, sampleNormal)); - float normalW = ComputeWeight(angle, diffuseNormalWeightParams, 0.0); + float normalW = ComputeWeight(angle, diffuseNormalWeightParam, 0.0); #ifdef RELAX_SPECULAR - float4 sampleSpecular = sharedSpecular[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; + float4 sampleSpecular = s_Spec[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; float3 sampleSpecularIllumination = sampleSpecular.rgb; float sampleSpecular1stMoment = Color::Luminance(sampleSpecularIllumination); float sampleSpecular2ndMoment = sampleSpecular.a; @@ -416,12 +416,12 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos sumSpecular1stMoment += sampleSpecular1stMoment * specularW; sumSpecular2ndMoment += sampleSpecular2ndMoment * specularW; #ifdef RELAX_SH - sumSpecularSH1 += sharedSpecularSH1[sharedMemoryIndexP.y][sharedMemoryIndexP.x] * specularW; + sumSpecularSH += s_SpecSH[sharedMemoryIndexP.y][sharedMemoryIndexP.x] * specularW; #endif #endif #ifdef RELAX_DIFFUSE - float4 sampleDiffuse = sharedDiffuse[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; + float4 sampleDiffuse = s_Diff[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; float3 sampleDiffuseIllumination = sampleDiffuse.rgb; float sampleDiffuse1stMoment = Color::Luminance(sampleDiffuseIllumination); float sampleDiffuse2ndMoment = sampleDiffuse.a; @@ -433,7 +433,7 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos sumDiffuse1stMoment += sampleDiffuse1stMoment * diffuseW; sumDiffuse2ndMoment += sampleDiffuse2ndMoment * diffuseW; #ifdef RELAX_SH - sumDiffuseSH1 += sharedDiffuseSH1[sharedMemoryIndexP.y][sharedMemoryIndexP.x] * diffuseW; + sumDiffuseSH += s_DiffSH[sharedMemoryIndexP.y][sharedMemoryIndexP.x] * diffuseW; #endif #endif } @@ -448,10 +448,10 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos sumSpecular2ndMoment /= sumWSpecularIllumination; float specularVariance = max(0, sumSpecular2ndMoment - sumSpecular1stMoment * sumSpecular1stMoment); specularVariance *= boost; - gOutSpecularIlluminationAndVariance[pixelPos] = float4(sumSpecularIllumination, specularVariance); + gOut_Spec_Variance[pixelPos] = float4(sumSpecularIllumination, specularVariance); #ifdef RELAX_SH - float roughnessModified = sharedSpecularSH1[sharedMemoryIndex.y][sharedMemoryIndex.x].w; - gOutSpecularSH1[pixelPos] = float4(sumSpecularSH1.rgb / sumWSpecularIllumination, roughnessModified); + float roughnessModified = s_SpecSH[sharedMemoryIndex.y][sharedMemoryIndex.x].w; + gOut_SpecSh[pixelPos] = float4(sumSpecularSH.rgb / sumWSpecularIllumination, roughnessModified); #endif #endif @@ -462,9 +462,9 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos sumDiffuse2ndMoment /= sumWDiffuseIllumination; float diffuseVariance = max(0, sumDiffuse2ndMoment - sumDiffuse1stMoment * sumDiffuse1stMoment); diffuseVariance *= boost; - gOutDiffuseIlluminationAndVariance[pixelPos] = float4(sumDiffuseIllumination, diffuseVariance); + gOut_Diff_Variance[pixelPos] = float4(sumDiffuseIllumination, diffuseVariance); #ifdef RELAX_SH - gOutDiffuseSH1[pixelPos] = sumDiffuseSH1 / sumWDiffuseIllumination; + gOut_DiffSh[pixelPos] = sumDiffuseSH / sumWDiffuseIllumination; #endif #endif } diff --git a/Shaders/Include/RELAX_Common.hlsli b/Shaders/Include/RELAX_Common.hlsli index cd33d2c0..95438bd7 100644 --- a/Shaders/Include/RELAX_Common.hlsli +++ b/Shaders/Include/RELAX_Common.hlsli @@ -109,6 +109,16 @@ float GetPlaneDistanceWeight_Atrous(float3 centerWorldPos, float3 centerNormal, return distanceToCenterPointPlane < threshold ? 1.0 : 0.0; } +float GetSpecLobeTanHalfAngle( float roughness, float percentOfVolume = 0.75 ) +{ + // TODO: ideally should migrate to fixed "ImportanceSampling::GetSpecularLobeTanHalfAngle", but since + // denoisers behavior have been tuned for the old version, let's continue to use it in critical places + roughness = saturate( roughness ); + percentOfVolume = saturate( percentOfVolume ); + + return roughness * roughness * percentOfVolume / ( 1.0 - percentOfVolume + NRD_EPS ); +} + float2 GetNormalWeightParams_ATrous(float roughness, float numFramesInHistory, float specularReprojectionConfidence, float normalEdgeStoppingRelaxation, float specularLobeAngleFraction, float specularLobeAngleSlack) { // Relaxing normal weights if not enough frames in history @@ -141,7 +151,8 @@ float GetSpecularNormalWeight_ATrous(float2 params0, float3 n0, float3 n, float3 return saturate(1.0 - a * params0.y); } -float GetNormalWeightParams(float roughness, float angleFraction = 0.75) +// TODO: better use "GetNormalWeightParam" +float GetNormalWeightParam2(float roughness, float angleFraction) { float angle = atan(GetSpecLobeTanHalfAngle(roughness, angleFraction)); angle = 1.0 / max(angle, RELAX_NORMAL_ULP); @@ -149,17 +160,9 @@ float GetNormalWeightParams(float roughness, float angleFraction = 0.75) return angle; } -float GetNormalWeight(float3 Ncurr, float3 Nprev, float maxAngle) -{ - float cosa = dot(Ncurr, Nprev); - - float a = 1.0 / maxAngle; - float d = Math::AcosApprox(cosa); - - float w = Math::SmoothStep01(1.0 - (d * a)); - - return w; -} +// TODO: better use "GetDisocclusionWeight" +#define GetBilateralWeight( z, zc ) \ + Math::LinearStep( 0.03, 0.0, abs( z - zc ) * rcp( max( z, zc ) ) ) void BicubicFilterNoCornersWithFallbackToBilinearFilterWithCustomWeights( float2 samplePos, float2 invResourceSize, diff --git a/Shaders/Include/RELAX_Config.hlsli b/Shaders/Include/RELAX_Config.hlsli index 88f82a5a..276167ef 100644 --- a/Shaders/Include/RELAX_Config.hlsli +++ b/Shaders/Include/RELAX_Config.hlsli @@ -20,6 +20,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. // Shared constants #define RELAX_SHARED_CONSTANTS \ + NRD_CONSTANT( float4x4, gWorldToClip ) \ NRD_CONSTANT( float4x4, gWorldToClipPrev ) \ NRD_CONSTANT( float4x4, gWorldToViewPrev ) \ NRD_CONSTANT( float4x4, gWorldPrevToWorld ) \ @@ -56,8 +57,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. NRD_CONSTANT( float, gDiffBlurRadius ) \ NRD_CONSTANT( float, gSpecBlurRadius ) \ NRD_CONSTANT( float, gDepthThreshold ) \ - NRD_CONSTANT( float, gDiffLobeAngleFraction ) \ - NRD_CONSTANT( float, gSpecLobeAngleFraction ) \ + NRD_CONSTANT( float, gLobeAngleFraction ) \ NRD_CONSTANT( float, gSpecLobeAngleSlack ) \ NRD_CONSTANT( float, gHistoryFixEdgeStoppingNormalPower ) \ NRD_CONSTANT( float, gRoughnessEdgeStoppingRelaxation ) \ diff --git a/Shaders/Include/RELAX_Copy.hlsli b/Shaders/Include/RELAX_Copy.hlsli index 967858b7..4e4ff131 100644 --- a/Shaders/Include/RELAX_Copy.hlsli +++ b/Shaders/Include/RELAX_Copy.hlsli @@ -11,11 +11,12 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. [numthreads( GROUP_X, GROUP_Y, 1 )] NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) { + // TODO: introduce "CopyResource" in NRD API? #ifdef RELAX_SPECULAR - gOutSpecularIllumination[pixelPos.xy] = gSpecIllumination[pixelPos.xy]; + gOut_Spec[pixelPos.xy] = gIn_Spec[pixelPos.xy]; #endif #ifdef RELAX_DIFFUSE - gOutDiffuseIllumination[pixelPos.xy] = gDiffIllumination[pixelPos.xy]; + gOut_Diff[pixelPos.xy] = gIn_Diff[pixelPos.xy]; #endif } diff --git a/Shaders/Include/RELAX_HistoryClamping.hlsli b/Shaders/Include/RELAX_HistoryClamping.hlsli index d2df56c3..ae92cc51 100644 --- a/Shaders/Include/RELAX_HistoryClamping.hlsli +++ b/Shaders/Include/RELAX_HistoryClamping.hlsli @@ -9,13 +9,13 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. */ #ifdef RELAX_SPECULAR - groupshared float4 sharedSpecularResponsiveYCoCg[BUFFER_Y][BUFFER_X]; - groupshared float4 sharedSpecularNoisyAnd2ndMoment[BUFFER_Y][BUFFER_X]; + groupshared float4 s_SpecResponsiveYCoCg[BUFFER_Y][BUFFER_X]; + groupshared float4 s_SpecNoisy_M2[BUFFER_Y][BUFFER_X]; #endif #ifdef RELAX_DIFFUSE - groupshared float4 sharedDiffuseNoisyAnd2ndMoment[BUFFER_Y][BUFFER_X]; - groupshared float4 sharedDiffuseResponsiveYCoCg[BUFFER_Y][BUFFER_X]; + groupshared float4 s_DiffNoisy_M2[BUFFER_Y][BUFFER_X]; + groupshared float4 s_DiffResponsiveYCoCg[BUFFER_Y][BUFFER_X]; #endif void Preload(uint2 sharedPos, int2 globalPos) @@ -23,30 +23,37 @@ void Preload(uint2 sharedPos, int2 globalPos) globalPos = clamp(globalPos, 0, gRectSize - 1.0); #ifdef RELAX_SPECULAR - float4 specularResponsive = gSpecIlluminationResponsive[globalPos]; - sharedSpecularResponsiveYCoCg[sharedPos.y][sharedPos.x] = float4(Color::RgbToYCoCg(specularResponsive.rgb), specularResponsive.a); + float4 specularResponsive = gIn_SpecFast[globalPos]; + s_SpecResponsiveYCoCg[sharedPos.y][sharedPos.x] = float4(Color::RgbToYCoCg(specularResponsive.rgb), specularResponsive.a); - float4 specularNoisy = gNoisySpecularIllumination[globalPos]; + float4 specularNoisy = gIn_SpecNoisy[globalPos]; float specularNoisyLuminance = Color::Luminance(specularNoisy.rgb); - sharedSpecularNoisyAnd2ndMoment[sharedPos.y][sharedPos.x] = float4(specularNoisy.rgb, specularNoisyLuminance * specularNoisyLuminance); + s_SpecNoisy_M2[sharedPos.y][sharedPos.x] = float4(specularNoisy.rgb, specularNoisyLuminance * specularNoisyLuminance); #endif #ifdef RELAX_DIFFUSE - float4 diffuseResponsive = gDiffIlluminationResponsive[globalPos]; - sharedDiffuseResponsiveYCoCg[sharedPos.y][sharedPos.x] = float4(Color::RgbToYCoCg(diffuseResponsive.rgb), diffuseResponsive.a); + float4 diffuseResponsive = gIn_DiffFast[globalPos]; + s_DiffResponsiveYCoCg[sharedPos.y][sharedPos.x] = float4(Color::RgbToYCoCg(diffuseResponsive.rgb), diffuseResponsive.a); - float4 diffuseNoisy = gNoisyDiffuseIllumination[globalPos]; + float4 diffuseNoisy = gIn_DiffNoisy[globalPos]; float diffuseNoisyLuminance = Color::Luminance(diffuseNoisy.rgb); - sharedDiffuseNoisyAnd2ndMoment[sharedPos.y][sharedPos.x] = float4(diffuseNoisy.rgb, diffuseNoisyLuminance * diffuseNoisyLuminance); + s_DiffNoisy_M2[sharedPos.y][sharedPos.x] = float4(diffuseNoisy.rgb, diffuseNoisyLuminance * diffuseNoisyLuminance); #endif } +/* +// TODO: antilag code can be simplified to this: + float f = saturate( ( lumaSlowClamped - lumaSlow ) / ( lumaFast - lumaSlow ) * gAccelerationAmount ); + slow = lerp( slow, fast, f ); + fast = lerp( fast, noisyFirstMoment, f ); +*/ + [numthreads(GROUP_X, GROUP_Y, 1)] NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPos : SV_GroupThreadId, uint threadIndex : SV_GroupIndex) { // Preload - float isSky = gTiles[pixelPos >> 4]; + float isSky = gIn_Tiles[pixelPos >> 4]; PRELOAD_INTO_SMEM_WITH_TILE_CHECK; // Tile-based early out @@ -54,7 +61,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo return; // Reading history length - float historyLength = 255.0 * gHistoryLength[pixelPos]; + float historyLength = 255.0 * gIn_HistoryLength[pixelPos]; // Reading normal history #ifdef RELAX_SPECULAR @@ -82,21 +89,21 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo uint2 sharedMemoryIndexP = sharedMemoryIndex + int2(dx, dy); #ifdef RELAX_SPECULAR - float3 specularSampleYCoCg = sharedSpecularResponsiveYCoCg[sharedMemoryIndexP.y][sharedMemoryIndexP.x].rgb; + float3 specularSampleYCoCg = s_SpecResponsiveYCoCg[sharedMemoryIndexP.y][sharedMemoryIndexP.x].rgb; specularResponsiveFirstMomentYCoCg += specularSampleYCoCg; specularResponsiveSecondMomentYCoCg += specularSampleYCoCg * specularSampleYCoCg; - float4 specularNoisySample = sharedSpecularNoisyAnd2ndMoment[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; + float4 specularNoisySample = s_SpecNoisy_M2[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; specularNoisyFirstMoment += specularNoisySample.rgb; specularNoisySecondMoment += specularNoisySample.a; #endif #ifdef RELAX_DIFFUSE - float3 diffuseSampleYCoCg = sharedDiffuseResponsiveYCoCg[sharedMemoryIndexP.y][sharedMemoryIndexP.x].rgb; + float3 diffuseSampleYCoCg = s_DiffResponsiveYCoCg[sharedMemoryIndexP.y][sharedMemoryIndexP.x].rgb; diffuseResponsiveFirstMomentYCoCg += diffuseSampleYCoCg; diffuseResponsiveSecondMomentYCoCg += diffuseSampleYCoCg * diffuseSampleYCoCg; - float4 diffuseNoisySample = sharedDiffuseNoisyAnd2ndMoment[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; + float4 diffuseNoisySample = s_DiffNoisy_M2[sharedMemoryIndexP.y][sharedMemoryIndexP.x]; diffuseNoisyFirstMoment += diffuseNoisySample.rgb; diffuseNoisySecondMoment += diffuseNoisySample.a; #endif @@ -114,12 +121,12 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo float3 specularResponsiveColorMaxYCoCg = specularResponsiveFirstMomentYCoCg + gColorBoxSigmaScale * specularResponsiveSigmaYCoCg; // Expanding color box with color of the center pixel to minimize introduced bias - float4 specularResponsiveCenterYCoCg = sharedSpecularResponsiveYCoCg[sharedMemoryIndex.y][sharedMemoryIndex.x]; + float4 specularResponsiveCenterYCoCg = s_SpecResponsiveYCoCg[sharedMemoryIndex.y][sharedMemoryIndex.x]; specularResponsiveColorMinYCoCg = min(specularResponsiveColorMinYCoCg, specularResponsiveCenterYCoCg.rgb); specularResponsiveColorMaxYCoCg = max(specularResponsiveColorMaxYCoCg, specularResponsiveCenterYCoCg.rgb); // Clamping color with color box expansion - float4 specularIlluminationAnd2ndMoment = gSpecIllumination[pixelPos]; + float4 specularIlluminationAnd2ndMoment = gIn_Spec[pixelPos]; float3 specularYCoCg = Color::RgbToYCoCg(specularIlluminationAnd2ndMoment.rgb); float3 clampedSpecularYCoCg = specularYCoCg; if (gSpecMaxFastAccumulatedFrameNum < gSpecMaxAccumulatedFrameNum) @@ -190,8 +197,8 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo specularHistoryResetAmount = saturate(specularHistoryResetAmount); // Resetting history - outSpecular.rgb = lerp(outSpecular.rgb, sharedSpecularNoisyAnd2ndMoment[sharedMemoryIndex.y][sharedMemoryIndex.x].rgb, specularHistoryResetAmount); - outSpecularResponsive.rgb = lerp(outSpecularResponsive.rgb, sharedSpecularNoisyAnd2ndMoment[sharedMemoryIndex.y][sharedMemoryIndex.x].rgb, specularHistoryResetAmount); + 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); // 2nd moment correction float outSpecularL = Color::Luminance(outSpecular.rgb); @@ -201,15 +208,15 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo outSpecular.a = max(0, outSpecular.a); // Writing outputs - gOutSpecularIllumination[pixelPos.xy] = outSpecular; - gOutSpecularIlluminationResponsive[pixelPos.xy] = outSpecularResponsive; + gOut_Spec[pixelPos.xy] = outSpecular; + gOut_SpecFast[pixelPos.xy] = outSpecularResponsive; #ifdef RELAX_SH - float4 specularSH1 = gSpecSH1[pixelPos.xy]; - float4 specularResponsiveSH1 = gSpecResponsiveSH1[pixelPos.xy]; + float4 specularSH = gIn_SpecSh[pixelPos.xy]; + float4 specularResponsiveSH = gIn_SpecShFast[pixelPos.xy]; - gOutSpecularSH1[pixelPos.xy] = lerp(specularSH1, specularResponsiveSH1, specClampingFactor); - gOutSpecularResponsiveSH1[pixelPos.xy] = specularResponsiveSH1; + gOut_SpecSh[pixelPos.xy] = lerp(specularSH, specularResponsiveSH, specClampingFactor); + gOut_SpecShFast[pixelPos.xy] = specularResponsiveSH; #endif #endif @@ -225,13 +232,13 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo float3 diffuseResponsiveColorMaxYCoCg = diffuseResponsiveFirstMomentYCoCg + gColorBoxSigmaScale * diffuseResponsiveSigmaYCoCg; // Expanding color box with color of the center pixel to minimize introduced bias - float4 diffuseResponsiveCenterYCoCg = sharedDiffuseResponsiveYCoCg[sharedMemoryIndex.y][sharedMemoryIndex.x]; + float4 diffuseResponsiveCenterYCoCg = s_DiffResponsiveYCoCg[sharedMemoryIndex.y][sharedMemoryIndex.x]; diffuseResponsiveColorMinYCoCg = min(diffuseResponsiveColorMinYCoCg, diffuseResponsiveCenterYCoCg.rgb); diffuseResponsiveColorMaxYCoCg = max(diffuseResponsiveColorMaxYCoCg, diffuseResponsiveCenterYCoCg.rgb); // Clamping color with color box expansion - float4 diffuseIlluminationAnd2ndMoment = gDiffIllumination[pixelPos]; + float4 diffuseIlluminationAnd2ndMoment = gIn_Diff[pixelPos]; float3 diffuseYCoCg = Color::RgbToYCoCg(diffuseIlluminationAnd2ndMoment.rgb); float3 clampedDiffuseYCoCg = diffuseYCoCg; if (gDiffMaxFastAccumulatedFrameNum < gDiffMaxAccumulatedFrameNum) @@ -300,8 +307,8 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo 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, sharedDiffuseNoisyAnd2ndMoment[sharedMemoryIndex.y][sharedMemoryIndex.x].rgb, diffuseHistoryResetAmount); - outDiffuseResponsive.rgb = lerp(outDiffuseResponsive.rgb, sharedDiffuseNoisyAnd2ndMoment[sharedMemoryIndex.y][sharedMemoryIndex.x].rgb, diffuseHistoryResetAmount); + 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); // 2nd moment correction float outDiffuseL = Color::Luminance(outDiffuse.rgb); @@ -311,19 +318,19 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo outDiffuse.a = max(0, outDiffuse.a); // Writing outputs - gOutDiffuseIllumination[pixelPos.xy] = outDiffuse; - gOutDiffuseIlluminationResponsive[pixelPos.xy] = outDiffuseResponsive; + gOut_Diff[pixelPos.xy] = outDiffuse; + gOut_DiffFast[pixelPos.xy] = outDiffuseResponsive; #ifdef RELAX_SH - float4 diffuseSH1 = gDiffSH1[pixelPos.xy]; - float4 diffuseResponsiveSH1 = gDiffResponsiveSH1[pixelPos.xy]; + float4 diffuseSH = gIn_DiffSh[pixelPos.xy]; + float4 diffuseResponsiveSH = gIn_DiffShFast[pixelPos.xy]; - gOutDiffuseSH1[pixelPos.xy] = lerp(diffuseSH1, diffuseResponsiveSH1, diffClampingFactor); - gOutDiffuseResponsiveSH1[pixelPos.xy] = diffuseResponsiveSH1; + gOut_DiffSh[pixelPos.xy] = lerp(diffuseSH, diffuseResponsiveSH, diffClampingFactor); + gOut_DiffShFast[pixelPos.xy] = diffuseResponsiveSH; #endif #endif // Writing out history length for use in the next frame - gOutHistoryLength[pixelPos] = historyLength / 255.0; + gOut_HistoryLength[pixelPos] = historyLength / 255.0; } diff --git a/Shaders/Include/RELAX_HistoryFix.hlsli b/Shaders/Include/RELAX_HistoryFix.hlsli index b08fc3a8..7b462ef3 100644 --- a/Shaders/Include/RELAX_HistoryFix.hlsli +++ b/Shaders/Include/RELAX_HistoryFix.hlsli @@ -25,20 +25,20 @@ float getRadius(float historyLength) NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) { // Tile-based early out - float isSky = gTiles[pixelPos >> 4]; + float isSky = gIn_Tiles[pixelPos >> 4]; if (isSky != 0.0 || pixelPos.x >= gRectSize.x || pixelPos.y >= gRectSize.y) return; // Early out if linearZ is beyond denoising range // Early out if no disocclusion detected - float centerViewZ = UnpackViewZ(gViewZ[pixelPos]); - float historyLength = 255.0 * gHistoryLength[pixelPos]; + float centerViewZ = UnpackViewZ(gIn_ViewZ[pixelPos]); + float historyLength = 255.0 * gIn_HistoryLength[pixelPos]; if ((centerViewZ > gDenoisingRange) || (historyLength > gHistoryFixFrameNum || gHistoryFixFrameNum == 1.0)) return; // Loading center data float centerMaterialID; - float4 centerNormalRoughness = NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness[pixelPos], centerMaterialID); + float4 centerNormalRoughness = NRD_FrontEnd_UnpackNormalAndRoughness(gIn_Normal_Roughness[pixelPos], centerMaterialID); float3 centerNormal = centerNormalRoughness.rgb; float centerRoughness = centerNormalRoughness.a; float3 centerWorldPos = GetCurrentWorldPosFromPixelPos(pixelPos, centerViewZ); @@ -46,17 +46,17 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) float depthThreshold = gDepthThreshold * (gOrthoMode == 0 ? centerViewZ : 1.0); #ifdef RELAX_DIFFUSE - float4 diffuseIlluminationAnd2ndMomentSum = gDiffIllumination[pixelPos]; + float4 diffuseIlluminationAnd2ndMomentSum = gIn_Diff[pixelPos]; #ifdef RELAX_SH - float4 diffuseSumSH1 = gDiffSH1[pixelPos]; + float4 diffuseSumSH = gIn_DiffSh[pixelPos]; #endif float diffuseWSum = 1; #endif #ifdef RELAX_SPECULAR - float4 specularIlluminationAnd2ndMomentSum = gSpecIllumination[pixelPos]; + float4 specularIlluminationAnd2ndMomentSum = gIn_Spec[pixelPos]; #ifdef RELAX_SH - float4 specularSumSH1 = gSpecSH1[pixelPos]; - float roughnessModified = specularSumSH1.w; + float4 specularSumSH = gIn_SpecSh[pixelPos]; + float roughnessModified = specularSumSH.w; #endif float specularWSum = 1; float2 specularNormalWeightParams = @@ -65,7 +65,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) 5.0, // History length, 1.0, // Specular reprojection confidence 0.0, // Normal edge stopping relaxation - gSpecLobeAngleFraction, + gLobeAngleFraction, gSpecLobeAngleSlack); #endif @@ -87,9 +87,9 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) continue; float sampleMaterialID; - float3 sampleNormal = NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness[samplePosInt], sampleMaterialID).rgb; + float3 sampleNormal = NRD_FrontEnd_UnpackNormalAndRoughness(gIn_Normal_Roughness[samplePosInt], sampleMaterialID).rgb; - float sampleViewZ = UnpackViewZ(gViewZ[samplePosInt]); + float sampleViewZ = UnpackViewZ(gIn_ViewZ[samplePosInt]); float3 sampleWorldPos = GetCurrentWorldPosFromPixelPos(samplePosInt, sampleViewZ); float geometryWeight = GetPlaneDistanceWeight_Atrous( centerWorldPos, @@ -106,11 +106,11 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) if (diffuseW > 1e-4) { - float4 sampleDiffuseIlluminationAnd2ndMoment = gDiffIllumination[samplePosInt]; + float4 sampleDiffuseIlluminationAnd2ndMoment = gIn_Diff[samplePosInt]; diffuseIlluminationAnd2ndMomentSum += sampleDiffuseIlluminationAnd2ndMoment * diffuseW; #ifdef RELAX_SH - float4 sampleDiffuseSH1 = gDiffSH1[samplePosInt]; - diffuseSumSH1 += sampleDiffuseSH1 * diffuseW; + float4 sampleDiffuseSH = gIn_DiffSh[samplePosInt]; + diffuseSumSH += sampleDiffuseSH * diffuseW; #endif diffuseWSum += diffuseW; } @@ -130,11 +130,11 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) if (specularW > 1e-4) { - float4 sampleSpecularIlluminationAnd2ndMoment = gSpecIllumination[samplePosInt]; + float4 sampleSpecularIlluminationAnd2ndMoment = gIn_Spec[samplePosInt]; specularIlluminationAnd2ndMomentSum += sampleSpecularIlluminationAnd2ndMoment * specularW; #ifdef RELAX_SH - float4 sampleSpecularSH1 = gSpecSH1[samplePosInt]; - specularSumSH1 += sampleSpecularSH1 * specularW; + float4 sampleSpecularSH = gIn_SpecSh[samplePosInt]; + specularSumSH += sampleSpecularSH * specularW; #endif specularWSum += specularW; } @@ -146,17 +146,17 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) // The next shader will have to copy these areas to normal and responsive history buffers. #ifdef RELAX_DIFFUSE float4 outDiffuseIlluminationAnd2ndMoment = diffuseIlluminationAnd2ndMomentSum / diffuseWSum; - gOutDiffuseIllumination[pixelPos] = outDiffuseIlluminationAnd2ndMoment; + gOut_Diff[pixelPos] = outDiffuseIlluminationAnd2ndMoment; #ifdef RELAX_SH - gOutDiffuseSH1[pixelPos] = diffuseSumSH1 / diffuseWSum; + gOut_DiffSh[pixelPos] = diffuseSumSH / diffuseWSum; #endif #endif #ifdef RELAX_SPECULAR float4 outSpecularIlluminationAnd2ndMoment = specularIlluminationAnd2ndMomentSum / specularWSum; - gOutSpecularIllumination[pixelPos] = outSpecularIlluminationAnd2ndMoment; + gOut_Spec[pixelPos] = outSpecularIlluminationAnd2ndMoment; #ifdef RELAX_SH - gOutSpecularSH1[pixelPos] = float4(specularSumSH1.rgb / specularWSum, roughnessModified); + gOut_SpecSh[pixelPos] = float4(specularSumSH.rgb / specularWSum, roughnessModified); #endif #endif } diff --git a/Shaders/Include/RELAX_HitDistReconstruction.hlsli b/Shaders/Include/RELAX_HitDistReconstruction.hlsli index 18d16b6c..8be92cf4 100644 --- a/Shaders/Include/RELAX_HitDistReconstruction.hlsli +++ b/Shaders/Include/RELAX_HitDistReconstruction.hlsli @@ -8,36 +8,28 @@ distribution of this software and related documentation without an express license agreement from NVIDIA CORPORATION is strictly prohibited. */ -groupshared float4 sharedNormalRoughness[BUFFER_Y][BUFFER_X]; -groupshared float3 sharedHitdistViewZ[BUFFER_Y][BUFFER_X]; - -float GetNormalWeightParams(float nonLinearAccumSpeed, float fraction, float roughness = 1.0) -{ - float angle = atan(GetSpecLobeTanHalfAngle(roughness)); - angle *= lerp(saturate(fraction), 1.0, nonLinearAccumSpeed); // TODO: use as "percentOfVolume" instead? - - return 1.0 / max(angle, RELAX_NORMAL_ULP); -} +groupshared float4 s_Normal_Roughness[BUFFER_Y][BUFFER_X]; +groupshared float3 s_HitDist_ViewZ[BUFFER_Y][BUFFER_X]; void Preload(uint2 sharedPos, int2 globalPos) { globalPos = clamp(globalPos, 0, gRectSize - 1.0); // It's ok that we don't use materialID in Hitdist reconstruction - float4 normalRoughness = NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness[WithRectOrigin(globalPos)]); - float viewZ = UnpackViewZ(gViewZ[WithRectOrigin(globalPos)]); + float4 normalRoughness = NRD_FrontEnd_UnpackNormalAndRoughness(gIn_Normal_Roughness[WithRectOrigin(globalPos)]); + float viewZ = UnpackViewZ(gIn_ViewZ[WithRectOrigin(globalPos)]); float2 hitDist = gDenoisingRange; #ifdef RELAX_SPECULAR - hitDist.x = gSpecIllumination[globalPos].w; + hitDist.x = gIn_Spec[globalPos].w; #endif #ifdef RELAX_DIFFUSE - hitDist.y = gDiffIllumination[globalPos].w; + hitDist.y = gIn_Diff[globalPos].w; #endif - sharedNormalRoughness[sharedPos.y][sharedPos.x] = normalRoughness; - sharedHitdistViewZ[sharedPos.y][sharedPos.x] = float3(hitDist, viewZ); + s_Normal_Roughness[sharedPos.y][sharedPos.x] = normalRoughness; + s_HitDist_ViewZ[sharedPos.y][sharedPos.x] = float3(hitDist, viewZ); } [numthreads( GROUP_X, GROUP_Y, 1 )] @@ -46,7 +38,7 @@ NRD_EXPORT void NRD_CS_MAIN(int2 threadPos : SV_GroupThreadId, int2 pixelPos : S float2 pixelUv = float2(pixelPos + 0.5) * gRectSizeInv; // Preload - float isSky = gTiles[pixelPos >> 4]; + float isSky = gIn_Tiles[pixelPos >> 4]; PRELOAD_INTO_SMEM_WITH_TILE_CHECK; // Tile-based early out @@ -54,7 +46,7 @@ NRD_EXPORT void NRD_CS_MAIN(int2 threadPos : SV_GroupThreadId, int2 pixelPos : S return; int2 smemPos = threadPos + BORDER; - float3 centerHitdistViewZ = sharedHitdistViewZ[smemPos.y][smemPos.x]; + float3 centerHitdistViewZ = s_HitDist_ViewZ[smemPos.y][smemPos.x]; float centerViewZ = centerHitdistViewZ.z; // Early out @@ -62,25 +54,25 @@ NRD_EXPORT void NRD_CS_MAIN(int2 threadPos : SV_GroupThreadId, int2 pixelPos : S return; // Center data - float4 normalAndRoughness = NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness[WithRectOrigin( pixelPos )]); + float4 normalAndRoughness = NRD_FrontEnd_UnpackNormalAndRoughness(gIn_Normal_Roughness[WithRectOrigin( pixelPos )]); float3 centerNormal = normalAndRoughness.xyz; float centerRoughness = normalAndRoughness.w; // Hit distance reconstruction #ifdef RELAX_SPECULAR - float3 centerSpecularIllumination = gSpecIllumination[pixelPos].xyz; + float3 centerSpecularIllumination = gIn_Spec[pixelPos].xyz; float centerSpecularHitDist = centerHitdistViewZ.x; float2 relaxedRoughnessWeightParams = GetRelaxedRoughnessWeightParams(centerRoughness * centerRoughness); - float specularNormalWeightParam = GetNormalWeightParams(1.0, 1.0, centerRoughness); + float specularNormalWeightParam = GetNormalWeightParam(1.0, 1.0, centerRoughness); float sumSpecularWeight = 1000.0 * float(centerSpecularHitDist != 0.0); float sumSpecularHitDist = centerSpecularHitDist * sumSpecularWeight; #endif #ifdef RELAX_DIFFUSE - float3 centerDiffuseIllumination = gDiffIllumination[pixelPos].xyz; + float3 centerDiffuseIllumination = gIn_Diff[pixelPos].xyz; float centerDiffuseHitDist = centerHitdistViewZ.y; - float diffuseNormalWeightParam = GetNormalWeightParams(1.0, 1.0, 1.0); + float diffuseNormalWeightParam = GetNormalWeightParam(1.0, 1.0); float sumDiffuseWeight = 1000.0 * float(centerDiffuseHitDist != 0.0); float sumDiffuseHitDist = centerDiffuseHitDist * sumDiffuseWeight; @@ -98,10 +90,10 @@ NRD_EXPORT void NRD_CS_MAIN(int2 threadPos : SV_GroupThreadId, int2 pixelPos : S continue; int2 pos = threadPos + int2(dx, dy); - float4 sampleNormalRoughness = sharedNormalRoughness[pos.y][pos.x]; + float4 sampleNormalRoughness = s_Normal_Roughness[pos.y][pos.x]; float3 sampleNormal = sampleNormalRoughness.xyz; float3 sampleRoughness = sampleNormalRoughness.w; - float3 sampleHitdistViewZ = sharedHitdistViewZ[pos.y][pos.x]; + float3 sampleHitdistViewZ = s_HitDist_ViewZ[pos.y][pos.x]; float sampleViewZ = sampleHitdistViewZ.z; float cosa = dot(centerNormal, sampleNormal); float angle = Math::AcosApprox(cosa); @@ -143,12 +135,12 @@ NRD_EXPORT void NRD_CS_MAIN(int2 threadPos : SV_GroupThreadId, int2 pixelPos : S // Output #ifdef RELAX_SPECULAR sumSpecularHitDist /= max(sumSpecularWeight, 1e-6); - gOutSpecularIllumination[pixelPos] = float4(centerSpecularIllumination, sumSpecularHitDist); + gOut_Spec[pixelPos] = float4(centerSpecularIllumination, sumSpecularHitDist); #endif #ifdef RELAX_DIFFUSE sumDiffuseHitDist /= max(sumDiffuseWeight, 1e-6); - gOutDiffuseIllumination[pixelPos] = float4(centerDiffuseIllumination, sumDiffuseHitDist); + gOut_Diff[pixelPos] = float4(centerDiffuseIllumination, sumDiffuseHitDist); #endif } diff --git a/Shaders/Include/RELAX_PrePass.hlsli b/Shaders/Include/RELAX_PrePass.hlsli index 42b9e3e2..a2402eca 100644 --- a/Shaders/Include/RELAX_PrePass.hlsli +++ b/Shaders/Include/RELAX_PrePass.hlsli @@ -15,12 +15,12 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos : SV_GroupThreadId, uint threadIndex : SV_GroupIndex) { // Tile-based early out - float isSky = gTiles[pixelPos >> 4]; + float isSky = gIn_Tiles[pixelPos >> 4]; if (isSky != 0.0 || pixelPos.x >= (int)gRectSize.x || pixelPos.y >= (int)gRectSize.y) return; // Early out if linearZ is beyond denoising range - float centerViewZ = UnpackViewZ(gViewZ[WithRectOrigin(pixelPos)]); + float centerViewZ = UnpackViewZ(gIn_ViewZ[WithRectOrigin(pixelPos)]); if (centerViewZ > gDenoisingRange) return; @@ -42,12 +42,12 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos if (gSpecCheckerboard != 2) #endif { - float viewZ0 = UnpackViewZ(gViewZ[WithRectOrigin(checkerboardPos.xz)]); - float viewZ1 = UnpackViewZ(gViewZ[WithRectOrigin(checkerboardPos.yz)]); + float viewZ0 = UnpackViewZ(gIn_ViewZ[WithRectOrigin(checkerboardPos.xz)]); + float viewZ1 = UnpackViewZ(gIn_ViewZ[WithRectOrigin(checkerboardPos.yz)]); #if( NRD_NORMAL_ENCODING == NRD_NORMAL_ENCODING_R10G10B10A2_UNORM ) - NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness[WithRectOrigin(checkerboardPos.xz)], materialID0); - NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness[WithRectOrigin(checkerboardPos.yz)], materialID1); + NRD_FrontEnd_UnpackNormalAndRoughness(gIn_Normal_Roughness[WithRectOrigin(checkerboardPos.xz)], materialID0); + NRD_FrontEnd_UnpackNormalAndRoughness(gIn_Normal_Roughness[WithRectOrigin(checkerboardPos.yz)], materialID1); #endif checkerboardResolveWeights = GetBilateralWeight(float2(viewZ0, viewZ1), centerViewZ); @@ -58,7 +58,7 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos checkerboardPos.xy >>= 1; float centerMaterialID; - float4 centerNormalRoughness = NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness[WithRectOrigin(pixelPos)], centerMaterialID); + float4 centerNormalRoughness = NRD_FrontEnd_UnpackNormalAndRoughness(gIn_Normal_Roughness[WithRectOrigin(pixelPos)], centerMaterialID); float3 centerNormal = centerNormalRoughness.xyz; float centerRoughness = centerNormalRoughness.w; @@ -77,9 +77,9 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos } // Reading diffuse & resolving diffuse checkerboard - float4 diffuseIllumination = gDiffIllumination[diffPos]; + float4 diffuseIllumination = gIn_Diff[diffPos]; #ifdef RELAX_SH - float4 diffuseSH1 = gDiffSH1[diffPos]; + float4 diffuseSH = gIn_DiffSh[diffPos]; #endif if (!diffHasData) @@ -91,18 +91,18 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos #endif wc *= Math::PositiveRcp( wc.x + wc.y ); - float4 d0 = gDiffIllumination[checkerboardPos.xz]; - float4 d1 = gDiffIllumination[checkerboardPos.yz]; + float4 d0 = gIn_Diff[checkerboardPos.xz]; + float4 d1 = gIn_Diff[checkerboardPos.yz]; d0 = Denanify( wc.x, d0 ); d1 = Denanify( wc.y, d1 ); diffuseIllumination = d0 * wc.x + d1 * wc.y; #ifdef RELAX_SH - float4 d0SH1 = gDiffSH1[checkerboardPos.xz]; - float4 d1SH1 = gDiffSH1[checkerboardPos.yz]; - d0SH1 = Denanify( wc.x, d0SH1 ); - d1SH1 = Denanify( wc.y, d1SH1 ); - diffuseSH1 = d0SH1 * wc.x + d1SH1 * wc.y; + float4 d0SH = gIn_DiffSh[checkerboardPos.xz]; + float4 d1SH = gIn_DiffSh[checkerboardPos.yz]; + d0SH = Denanify( wc.x, d0SH ); + d1SH = Denanify( wc.y, d1SH ); + diffuseSH = d0SH * wc.x + d1SH * wc.y; #endif } @@ -119,7 +119,7 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos blurRadius = max(blurRadius, 1.0); float worldBlurRadius = PixelRadiusToWorld(gUnproject, gOrthoMode, blurRadius, centerViewZ) * min(gResolutionScale.x, gResolutionScale.y); - float normalWeightParams = GetNormalWeightParams(1.0, 0.25 * gDiffLobeAngleFraction); + float normalWeightParam = GetNormalWeightParam2(1.0, 0.25 * gLobeAngleFraction); float2 hitDistanceWeightParams = GetHitDistanceWeightParams(diffuseIllumination.w, 1.0 / 9.0); float weightSum = 1.0; @@ -142,8 +142,8 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos // Fetch data float sampleMaterialID; - float3 sampleNormal = NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness.SampleLevel(gNearestClamp, WithRectOffset(uvScaled), 0), sampleMaterialID).rgb; - float sampleViewZ = UnpackViewZ(gViewZ.SampleLevel(gNearestClamp, WithRectOffset(uvScaled), 0)); + float3 sampleNormal = NRD_FrontEnd_UnpackNormalAndRoughness(gIn_Normal_Roughness.SampleLevel(gNearestClamp, WithRectOffset(uvScaled), 0), sampleMaterialID).rgb; + float sampleViewZ = UnpackViewZ(gIn_ViewZ.SampleLevel(gNearestClamp, WithRectOffset(uvScaled), 0)); float3 sampleWorldPos = GetCurrentWorldPosFromClipSpaceXY(uv * 2.0 - 1.0, sampleViewZ); // Sample weight @@ -159,9 +159,9 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos gDepthThreshold); float angle = Math::AcosApprox(dot(centerNormal, sampleNormal)); - sampleWeight *= ComputeWeight(angle, normalWeightParams, 0.0); + sampleWeight *= ComputeWeight(angle, normalWeightParam, 0.0); - float4 sampleDiffuseIllumination = gDiffIllumination.SampleLevel(gNearestClamp, checkerboardUvScaled, 0); + float4 sampleDiffuseIllumination = gIn_Diff.SampleLevel(gNearestClamp, checkerboardUvScaled, 0); sampleDiffuseIllumination = Denanify( sampleWeight, sampleDiffuseIllumination ); sampleWeight *= lerp(diffMinHitDistanceWeight, 1.0, ComputeExponentialWeight(sampleDiffuseIllumination.a, hitDistanceWeightParams.x, hitDistanceWeightParams.y)); @@ -172,21 +172,21 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos diffuseIllumination += sampleDiffuseIllumination * sampleWeight; #ifdef RELAX_SH - float4 sampleDiffuseSH1 = gDiffSH1.SampleLevel(gNearestClamp, checkerboardUvScaled, 0); - sampleDiffuseSH1 = Denanify( sampleWeight, sampleDiffuseSH1 ); - diffuseSH1 += sampleDiffuseSH1 * sampleWeight; + float4 sampleDiffuseSH = gIn_DiffSh.SampleLevel(gNearestClamp, checkerboardUvScaled, 0); + sampleDiffuseSH = Denanify( sampleWeight, sampleDiffuseSH ); + diffuseSH += sampleDiffuseSH * sampleWeight; #endif } diffuseIllumination /= weightSum; #ifdef RELAX_SH - diffuseSH1 /= weightSum; + diffuseSH /= weightSum; #endif } - gOutDiffuseIllumination[pixelPos] = clamp(diffuseIllumination, 0, NRD_FP16_MAX); + gOut_Diff[pixelPos] = clamp(diffuseIllumination, 0, NRD_FP16_MAX); #ifdef RELAX_SH - gOutDiffuseSH1[pixelPos] = clamp(diffuseSH1, -NRD_FP16_MAX, NRD_FP16_MAX); + gOut_DiffSh[pixelPos] = clamp(diffuseSH, -NRD_FP16_MAX, NRD_FP16_MAX); #endif #endif @@ -200,9 +200,9 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos } // Reading specular & resolving specular checkerboard - float4 specularIllumination = gSpecIllumination[specPos]; + float4 specularIllumination = gIn_Spec[specPos]; #ifdef RELAX_SH - float4 specularSH1 = gSpecSH1[specPos]; + float4 specularSH = gIn_SpecSh[specPos]; #endif if (!specHasData) @@ -214,18 +214,18 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos #endif wc *= Math::PositiveRcp( wc.x + wc.y ); - float4 s0 = gSpecIllumination[checkerboardPos.xz]; - float4 s1 = gSpecIllumination[checkerboardPos.yz]; + float4 s0 = gIn_Spec[checkerboardPos.xz]; + float4 s1 = gIn_Spec[checkerboardPos.yz]; s0 = Denanify( wc.x, s0 ); s1 = Denanify( wc.y, s1 ); specularIllumination = s0 * wc.x + s1 * wc.y; #ifdef RELAX_SH - float4 s0SH1 = gSpecSH1[checkerboardPos.xz]; - float4 s1SH1 = gSpecSH1[checkerboardPos.yz]; - s0SH1 = Denanify( wc.x, s0SH1 ); - s1SH1 = Denanify( wc.y, s1SH1 ); - specularSH1 = s0SH1 * wc.x + s1SH1 * wc.y; + float4 s0SH = gIn_SpecSh[checkerboardPos.xz]; + float4 s1SH = gIn_SpecSh[checkerboardPos.yz]; + s0SH = Denanify( wc.x, s0SH ); + s1SH = Denanify( wc.y, s1SH ); + specularSH = s0SH * wc.x + s1SH * wc.y; #endif } @@ -254,7 +254,7 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos if (specularIllumination.w == 0.0) blurRadius = max(blurRadius, 1.0); - float normalWeightParams = GetNormalWeightParams(centerRoughness, 0.5 * gSpecLobeAngleFraction); + float normalWeightParam = GetNormalWeightParam2(centerRoughness, 0.5 * gLobeAngleFraction); float2 hitDistanceWeightParams = GetHitDistanceWeightParams(specularIllumination.w, 1.0 / 9.0, centerRoughness); float2 roughnessWeightParams = GetRoughnessWeightParams(centerRoughness, gRoughnessFraction); @@ -283,10 +283,10 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos // Fetch data float sampleMaterialID; - float4 sampleNormalRoughness = NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness.SampleLevel(gNearestClamp, WithRectOffset(uvScaled), 0), sampleMaterialID); + float4 sampleNormalRoughness = NRD_FrontEnd_UnpackNormalAndRoughness(gIn_Normal_Roughness.SampleLevel(gNearestClamp, WithRectOffset(uvScaled), 0), sampleMaterialID); float3 sampleNormal = sampleNormalRoughness.rgb; float sampleRoughness = sampleNormalRoughness.a; - float sampleViewZ = UnpackViewZ(gViewZ.SampleLevel(gNearestClamp, WithRectOffset(uvScaled), 0)); + float sampleViewZ = UnpackViewZ(gIn_ViewZ.SampleLevel(gNearestClamp, WithRectOffset(uvScaled), 0)); // Sample weight float sampleWeight = IsInScreenNearest(uv); @@ -295,7 +295,7 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos sampleWeight *= ComputeWeight(sampleRoughness, roughnessWeightParams.x, roughnessWeightParams.y); float angle = Math::AcosApprox(dot(centerNormal, sampleNormal)); - sampleWeight *= ComputeWeight(angle, normalWeightParams, 0.0); + sampleWeight *= ComputeWeight(angle, normalWeightParam, 0.0); float3 sampleWorldPos = GetCurrentWorldPosFromClipSpaceXY(uv * 2.0 - 1.0, sampleViewZ); sampleWeight *= GetPlaneDistanceWeight( @@ -305,7 +305,7 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos sampleWorldPos, gDepthThreshold); - float4 sampleSpecularIllumination = gSpecIllumination.SampleLevel(gNearestClamp, checkerboardUvScaled, 0); + float4 sampleSpecularIllumination = gIn_Spec.SampleLevel(gNearestClamp, checkerboardUvScaled, 0); sampleSpecularIllumination = Denanify( sampleWeight, sampleSpecularIllumination ); sampleWeight *= lerp(specMinHitDistanceWeight, 1.0, ComputeExponentialWeight(sampleSpecularIllumination.a, hitDistanceWeightParams.x, hitDistanceWeightParams.y)); @@ -322,9 +322,9 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos specularIllumination.rgb += sampleSpecularIllumination.rgb * sampleWeight; #ifdef RELAX_SH - float4 sampleSpecularSH1 = gSpecSH1.SampleLevel(gNearestClamp, checkerboardUvScaled, 0); - sampleSpecularSH1 = Denanify( sampleWeight, sampleSpecularSH1 ); - specularSH1 += sampleSpecularSH1 * sampleWeight; + float4 sampleSpecularSH = gIn_SpecSh.SampleLevel(gNearestClamp, checkerboardUvScaled, 0); + sampleSpecularSH = Denanify( sampleWeight, sampleSpecularSH ); + specularSH += sampleSpecularSH * sampleWeight; #endif if (sampleWeight != 0.0) @@ -333,13 +333,13 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos specularIllumination.rgb /= weightSum; specularIllumination.a = minHitT == NRD_INF ? 0.0 : minHitT; #ifdef RELAX_SH - specularSH1 /= weightSum; + specularSH /= weightSum; #endif } - gOutSpecularIllumination[pixelPos] = clamp(specularIllumination, 0, NRD_FP16_MAX); + gOut_Spec[pixelPos] = clamp(specularIllumination, 0, NRD_FP16_MAX); #ifdef RELAX_SH - gOutSpecularSH1[pixelPos] = clamp(specularSH1, -NRD_FP16_MAX, NRD_FP16_MAX); + gOut_SpecSh[pixelPos] = clamp(specularSH, -NRD_FP16_MAX, NRD_FP16_MAX); #endif #endif } \ No newline at end of file diff --git a/Shaders/Include/RELAX_TemporalAccumulation.hlsli b/Shaders/Include/RELAX_TemporalAccumulation.hlsli index c61d651e..32f8770a 100644 --- a/Shaders/Include/RELAX_TemporalAccumulation.hlsli +++ b/Shaders/Include/RELAX_TemporalAccumulation.hlsli @@ -37,7 +37,7 @@ float loadSurfaceMotionBasedPrevData( float currentReflectionHitT, #endif float NoV, - float parallaxInPixels, + float smbParallaxInPixelsMax, float currentMaterialID, uint materialIDMask, float disocclusionThreshold, @@ -48,8 +48,8 @@ float loadSurfaceMotionBasedPrevData( , out float4 prevDiffuseIllumAnd2ndMoment , out float3 prevDiffuseResponsiveIllum #ifdef RELAX_SH - , out float4 prevDiffuseSH1 - , out float4 prevDiffuseResponsiveSH1 + , out float4 prevDiffuseSH + , out float4 prevDiffuseResponsiveSH #endif #endif #ifdef RELAX_SPECULAR @@ -57,8 +57,8 @@ float loadSurfaceMotionBasedPrevData( , out float3 prevSpecularResponsiveIllum , out float prevReflectionHitT #ifdef RELAX_SH - , out float4 prevSpecularSH1 - , out float4 prevSpecularResponsiveSH1 + , out float4 prevSpecularSH + , out float4 prevSpecularResponsiveSH #endif #endif ) @@ -86,19 +86,19 @@ float loadSurfaceMotionBasedPrevData( float2 gatherOrigin10 = (float2(bilinearOrigin) + float2(2.0, 0.0)) * gResourceSizeInvPrev; float2 gatherOrigin01 = (float2(bilinearOrigin) + float2(0.0, 2.0)) * gResourceSizeInvPrev; float2 gatherOrigin11 = (float2(bilinearOrigin) + float2(2.0, 2.0)) * gResourceSizeInvPrev; - float4 prevViewZs00 = UnpackViewZ(gPrevViewZ.GatherRed(gNearestClamp, gatherOrigin00).wzxy); - float4 prevViewZs10 = UnpackViewZ(gPrevViewZ.GatherRed(gNearestClamp, gatherOrigin10).wzxy); - float4 prevViewZs01 = UnpackViewZ(gPrevViewZ.GatherRed(gNearestClamp, gatherOrigin01).wzxy); - float4 prevViewZs11 = UnpackViewZ(gPrevViewZ.GatherRed(gNearestClamp, gatherOrigin11).wzxy); - float4 prevMaterialIDs00 = gPrevMaterialID.GatherRed(gNearestClamp, gatherOrigin00).wzxy; - float4 prevMaterialIDs10 = gPrevMaterialID.GatherRed(gNearestClamp, gatherOrigin10).wzxy; - float4 prevMaterialIDs01 = gPrevMaterialID.GatherRed(gNearestClamp, gatherOrigin01).wzxy; - float4 prevMaterialIDs11 = gPrevMaterialID.GatherRed(gNearestClamp, gatherOrigin11).wzxy; + float4 prevViewZs00 = UnpackViewZ(gPrev_ViewZ.GatherRed(gNearestClamp, gatherOrigin00).wzxy); + float4 prevViewZs10 = UnpackViewZ(gPrev_ViewZ.GatherRed(gNearestClamp, gatherOrigin10).wzxy); + float4 prevViewZs01 = UnpackViewZ(gPrev_ViewZ.GatherRed(gNearestClamp, gatherOrigin01).wzxy); + float4 prevViewZs11 = UnpackViewZ(gPrev_ViewZ.GatherRed(gNearestClamp, gatherOrigin11).wzxy); + float4 prevMaterialIDs00 = gPrev_MateriallID.GatherRed(gNearestClamp, gatherOrigin00).wzxy * 255.0; + float4 prevMaterialIDs10 = gPrev_MateriallID.GatherRed(gNearestClamp, gatherOrigin10).wzxy * 255.0; + float4 prevMaterialIDs01 = gPrev_MateriallID.GatherRed(gNearestClamp, gatherOrigin01).wzxy * 255.0; + float4 prevMaterialIDs11 = gPrev_MateriallID.GatherRed(gNearestClamp, gatherOrigin11).wzxy * 255.0; // Calculating disocclusion threshold float pixelSize = PixelRadiusToWorld(gUnproject, gOrthoMode, 1.0, currentLinearZ); float frustumSize = pixelSize * min(gRectSize.x, gRectSize.y); - float disocclusionThresholdSlopeScale = 1.0 / lerp(lerp(0.05, 1.0, NoV), 1.0, saturate(parallaxInPixels / 30.0)); + float disocclusionThresholdSlopeScale = 1.0 / lerp(lerp(0.05, 1.0, NoV), 1.0, saturate(smbParallaxInPixelsMax / 30.0)); float4 smbDisocclusionThreshold = saturate(disocclusionThreshold * disocclusionThresholdSlopeScale) * frustumSize; smbDisocclusionThreshold *= IsInScreenBilinear(bilinearOrigin, gRectSizePrev); smbDisocclusionThreshold -= NRD_EPS; @@ -123,7 +123,7 @@ float loadSurfaceMotionBasedPrevData( // Using bilinear to average 4 normal samples float2 uv = (float2(bilinearOrigin)+float2(1.0, 1.0)) * gResourceSizeInvPrev; - float3 prevNormalFlat = UnpackPrevNormalRoughness(gPrevNormalRoughness.SampleLevel(gLinearClamp, uv, 0)).xyz; + float3 prevNormalFlat = UnpackPrevNormalRoughness(gPrev_Normal_Roughness.SampleLevel(gLinearClamp, uv, 0)).xyz; prevNormalFlat = Geometry::RotateVector(gWorldPrevToWorld, prevNormalFlat); // Reject backfacing history: if angle between current normal and previous normal is larger than 90 deg @@ -146,10 +146,10 @@ float loadSurfaceMotionBasedPrevData( prevPixelPosFloat, gResourceSizeInvPrev, bilinearCustomWeights, useBicubic #ifdef RELAX_DIFFUSE - , gPrevDiffuseIllumination, prevDiffuseIllumAnd2ndMoment + , gHistory_Diff, prevDiffuseIllumAnd2ndMoment #endif #ifdef RELAX_SPECULAR - , gPrevSpecularIllumination, prevSpecularIllumAnd2ndMoment + , gHistory_Spec, prevSpecularIllumAnd2ndMoment #endif ); @@ -160,10 +160,10 @@ float loadSurfaceMotionBasedPrevData( prevPixelPosFloat, gResourceSizeInvPrev, bilinearCustomWeights, useBicubic #ifdef RELAX_DIFFUSE - , gPrevDiffuseIlluminationResponsive, diff + , gHistory_DiffFast, diff #endif #ifdef RELAX_SPECULAR - , gPrevSpecularIlluminationResponsive, spec + , gHistory_SpecFast, spec #endif ); @@ -179,18 +179,18 @@ float loadSurfaceMotionBasedPrevData( // Fitering previous SH data #ifdef RELAX_SH #ifdef RELAX_DIFFUSE - prevDiffuseSH1 = BilinearWithCustomWeightsFloat4(gPrevDiffuseSH1, bilinearOrigin, bilinearCustomWeights); - prevDiffuseResponsiveSH1 = BilinearWithCustomWeightsFloat4(gPrevDiffuseResponsiveSH1, bilinearOrigin, bilinearCustomWeights); + prevDiffuseSH = BilinearWithCustomWeightsFloat4(gHistory_DiffSh, bilinearOrigin, bilinearCustomWeights); + prevDiffuseResponsiveSH = BilinearWithCustomWeightsFloat4(gHistory_DiffShFast, bilinearOrigin, bilinearCustomWeights); #endif #ifdef RELAX_SPECULAR - prevSpecularSH1 = BilinearWithCustomWeightsFloat4(gPrevSpecularSH1, bilinearOrigin, bilinearCustomWeights); - prevSpecularResponsiveSH1 = BilinearWithCustomWeightsFloat4(gPrevSpecularResponsiveSH1, bilinearOrigin, bilinearCustomWeights); + prevSpecularSH = BilinearWithCustomWeightsFloat4(gHistory_SpecSh, bilinearOrigin, bilinearCustomWeights); + prevSpecularResponsiveSH = BilinearWithCustomWeightsFloat4(gHistory_SpecShFast, bilinearOrigin, bilinearCustomWeights); #endif #endif // Fitering more previous data that does not need bicubic float2 gatherOrigin = (float2(bilinearOrigin) + 1.0) * gResourceSizeInvPrev; - float4 prevHistoryLengths = gPrevHistoryLength.GatherRed(gNearestClamp, gatherOrigin).wzxy; + float4 prevHistoryLengths = gPrev_HistoryLength.GatherRed(gNearestClamp, gatherOrigin).wzxy; historyLength = 255.0 * BilinearWithCustomWeightsImmediateFloat( prevHistoryLengths.x, prevHistoryLengths.y, @@ -199,7 +199,7 @@ float loadSurfaceMotionBasedPrevData( bilinearCustomWeights); #ifdef RELAX_SPECULAR - float4 prevReflectionHitTs = gPrevReflectionHitT.GatherRed(gNearestClamp, gatherOrigin).wzxy; + float4 prevReflectionHitTs = gPrev_SpecHitDist.GatherRed(gNearestClamp, gatherOrigin).wzxy; prevReflectionHitT = BilinearWithCustomWeightsImmediateFloat(prevReflectionHitTs.x, prevReflectionHitTs.y, prevReflectionHitTs.z, prevReflectionHitTs.w, bilinearCustomWeights); prevReflectionHitT = max(0.001, prevReflectionHitT); #endif @@ -232,7 +232,7 @@ float loadVirtualMotionBasedPrevData( float currentMaterialID, uint materialIDMask, float2 prevSurfaceMotionBasedUV, - float parallaxInPixels, + float smbParallaxInPixelsMax, float NoV, float disocclusionThreshold, out float4 prevSpecularIllumAnd2ndMoment, @@ -242,8 +242,8 @@ float loadVirtualMotionBasedPrevData( out float prevReflectionHitT, out float2 prevUVVMB #ifdef RELAX_SH - , out float4 prevSpecularSH1 - , out float4 prevSpecularResponsiveSH1 + , out float4 prevSpecularSH + , out float4 prevSpecularResponsiveSH #endif ) { @@ -274,8 +274,8 @@ float loadVirtualMotionBasedPrevData( vmbDisocclusionThreshold -= NRD_EPS; // Checking bilinear footprint only for virtual motion based specular reprojection - float4 prevViewZs = UnpackViewZ(gPrevViewZ.GatherRed(gNearestClamp, gatherOrigin).wzxy); - float4 prevMaterialIDs = gPrevMaterialID.GatherRed(gNearestClamp, gatherOrigin).wzxy; + float4 prevViewZs = UnpackViewZ(gPrev_ViewZ.GatherRed(gNearestClamp, gatherOrigin).wzxy); + float4 prevMaterialIDs = gPrev_MateriallID.GatherRed(gNearestClamp, gatherOrigin).wzxy * 255.0; float3 prevWorldPosInTap; float4 bilinearTapsValid; @@ -297,8 +297,8 @@ float loadVirtualMotionBasedPrevData( prevRoughness = 0; prevReflectionHitT = gDenoisingRange; #ifdef RELAX_SH - prevSpecularSH1 = 0; - prevSpecularResponsiveSH1 = 0; + prevSpecularSH = 0; + prevSpecularResponsiveSH = 0; #endif // Weighted bilinear (or bicubic optionally) for prev specular data based on virtual motion. @@ -315,7 +315,7 @@ float loadVirtualMotionBasedPrevData( BicubicFilterNoCornersWithFallbackToBilinearFilterWithCustomWeights( prevVirtualPixelPosFloat, gResourceSizeInvPrev, bilinearCustomWeights, useBicubic, - gPrevSpecularIllumination, prevSpecularIllumAnd2ndMoment); + gHistory_Spec, prevSpecularIllumAnd2ndMoment); prevSpecularIllumAnd2ndMoment = max(prevSpecularIllumAnd2ndMoment, 0.0); @@ -323,21 +323,21 @@ float loadVirtualMotionBasedPrevData( BicubicFilterNoCornersWithFallbackToBilinearFilterWithCustomWeights( prevVirtualPixelPosFloat, gResourceSizeInvPrev, bilinearCustomWeights, useBicubic, - gPrevSpecularIlluminationResponsive, prevSpecularResponsiveIllum); + gHistory_SpecFast, prevSpecularResponsiveIllum); prevSpecularResponsiveIllum = max(prevSpecularResponsiveIllum, 0.0); // Fitering previous SH data #ifdef RELAX_SH - prevSpecularSH1 = BilinearWithCustomWeightsFloat4(gPrevSpecularSH1, bilinearOrigin, bilinearCustomWeights); - prevSpecularResponsiveSH1 = BilinearWithCustomWeightsFloat4(gPrevSpecularResponsiveSH1, bilinearOrigin, bilinearCustomWeights); + prevSpecularSH = BilinearWithCustomWeightsFloat4(gHistory_SpecSh, bilinearOrigin, bilinearCustomWeights); + prevSpecularResponsiveSH = BilinearWithCustomWeightsFloat4(gHistory_SpecShFast, bilinearOrigin, bilinearCustomWeights); #endif // Fitering previous data that does not need bicubic - prevReflectionHitT = gPrevReflectionHitT.SampleLevel(gLinearClamp, prevUVVMB * gResolutionScalePrev, 0).x; + prevReflectionHitT = gPrev_SpecHitDist.SampleLevel(gLinearClamp, prevUVVMB * gResolutionScalePrev, 0).x; prevReflectionHitT = max(0.001, prevReflectionHitT); - float4 prevNormalRoughness = UnpackPrevNormalRoughness(gPrevNormalRoughness.SampleLevel(gLinearClamp, prevUVVMB * gResolutionScalePrev, 0)); + float4 prevNormalRoughness = UnpackPrevNormalRoughness(gPrev_Normal_Roughness.SampleLevel(gLinearClamp, prevUVVMB * gResolutionScalePrev, 0)); prevNormal = prevNormalRoughness.xyz; prevNormal = Geometry::RotateVector(gWorldPrevToWorld, prevNormal); prevRoughness = prevNormalRoughness.w; @@ -353,11 +353,11 @@ void Preload(uint2 sharedPos, int2 globalPos) { globalPos = clamp(globalPos, 0, gRectSize - 1.0); - float4 normalRoughness = NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness[WithRectOrigin(globalPos)]); + float4 normalRoughness = NRD_FrontEnd_UnpackNormalAndRoughness(gIn_Normal_Roughness[WithRectOrigin(globalPos)]); float4 normalSpecHitT = normalRoughness; #ifdef RELAX_SPECULAR - float4 inSpecularIllumination = gSpecIllumination[globalPos]; + float4 inSpecularIllumination = gIn_Spec[globalPos]; normalSpecHitT.a = inSpecularIllumination.a; #endif @@ -368,7 +368,7 @@ void Preload(uint2 sharedPos, int2 globalPos) [numthreads(GROUP_X, GROUP_Y, 1)] NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPos : SV_GroupThreadId, uint threadIndex : SV_GroupIndex) { - float isSky = gTiles[pixelPos >> 4]; + float isSky = gIn_Tiles[pixelPos >> 4]; PRELOAD_INTO_SMEM_WITH_TILE_CHECK; // Tile-based early out @@ -376,7 +376,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo return; // Early out if linearZ is beyond denoising range - float currentLinearZ = UnpackViewZ(gViewZ[WithRectOrigin(pixelPos)]); + float currentLinearZ = UnpackViewZ(gIn_ViewZ[WithRectOrigin(pixelPos)]); if (currentLinearZ > gDenoisingRange) return; @@ -384,7 +384,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo // Reading current GBuffer data float currentMaterialID; - float4 currentNormalRoughness = NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness[WithRectOrigin(pixelPos)], currentMaterialID); + float4 currentNormalRoughness = NRD_FrontEnd_UnpackNormalAndRoughness(gIn_Normal_Roughness[WithRectOrigin(pixelPos)], currentMaterialID); float3 currentNormal = currentNormalRoughness.xyz; float currentRoughness = currentNormalRoughness.w; @@ -396,35 +396,35 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo // Getting previous position float2 pixelUv = float2(pixelPos + 0.5) * gRectSizeInv; - float3 mv = gMv[WithRectOrigin(pixelPos)] * gMvScale.xyz; + float3 mv = gIn_Mv[WithRectOrigin(pixelPos)] * gMvScale.xyz; float3 prevWorldPos = currentWorldPos; float2 prevUVSMB = pixelUv + mv.xy; - if (gMvScale.w != 0.0) - { - prevWorldPos += mv; - prevUVSMB = Geometry::GetScreenUv(gWorldToClipPrev, prevWorldPos); - } - else + if (gMvScale.w == 0.0) { if (gMvScale.z == 0.0) mv.z = Geometry::AffineTransform(gWorldToViewPrev, currentWorldPos).z - currentLinearZ; prevWorldPos = GetPreviousWorldPosFromClipSpaceXY(prevUVSMB * 2.0 - 1.0, currentLinearZ + mv.z) + gCameraDelta.xyz; } + else + { + prevWorldPos += mv; + prevUVSMB = Geometry::GetScreenUv(gWorldToClipPrev, prevWorldPos); + } // Input noisy data #ifdef RELAX_DIFFUSE - float3 diffuseIllumination = gDiffIllumination[pixelPos].rgb; + float3 diffuseIllumination = gIn_Diff[pixelPos].rgb; #ifdef RELAX_SH - float4 diffuseSH1 = gDiffSH1[pixelPos]; + float4 diffuseSH = gIn_DiffSh[pixelPos]; #endif #endif #ifdef RELAX_SPECULAR - float4 specularIllumination = gSpecIllumination[pixelPos]; + float4 specularIllumination = gIn_Spec[pixelPos]; #ifdef RELAX_SH - float4 specularSH1 = gSpecSH1[pixelPos]; + float4 specularSH = gIn_SpecSh[pixelPos]; #endif #endif @@ -467,7 +467,12 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo #endif // Calculating surface parallax - float parallaxInPixels = ComputeParallaxInPixels(prevWorldPos + gCameraDelta.xyz, gOrthoMode == 0.0 ? prevUVSMB : pixelUv, gWorldToClipPrev, gRectSize); + float smbParallaxInPixels1 = ComputeParallaxInPixels( prevWorldPos + gCameraDelta.xyz, gOrthoMode == 0.0 ? prevUVSMB : pixelUv, gWorldToClipPrev, gRectSize ); + float smbParallaxInPixels2 = ComputeParallaxInPixels( prevWorldPos - gCameraDelta.xyz, gOrthoMode == 0.0 ? pixelUv : prevUVSMB, gWorldToClip, gRectSize ); + + float smbParallaxInPixelsMax = max( smbParallaxInPixels1, smbParallaxInPixels2 ); + float smbParallaxInPixelsMin = min( smbParallaxInPixels1, smbParallaxInPixels2 ); + float pixelSize = PixelRadiusToWorld(gUnproject, gOrthoMode, 1.0, currentLinearZ); // Calculating disocclusion threshold @@ -475,7 +480,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo if(currentMaterialID == gStrandMaterialID) disocclusionThresholdMix = NRD_GetNormalizedStrandThickness(gStrandThickness, pixelSize); if(gHasDisocclusionThresholdMix && NRD_USE_DISOCCLUSION_THRESHOLD_MIX) - disocclusionThresholdMix = gDisocclusionThresholdMix[WithRectOrigin(pixelPos)]; + disocclusionThresholdMix = gIn_DisocclusionThresholdMix[WithRectOrigin(pixelPos)]; float disocclusionThreshold = lerp(gDisocclusionThreshold, gDisocclusionThresholdAlternate, disocclusionThresholdMix); @@ -485,8 +490,8 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo float4 prevDiffuseIlluminationAnd2ndMomentSMB; float3 prevDiffuseIlluminationAnd2ndMomentSMBResponsive; #ifdef RELAX_SH - float4 prevDiffuseSH1; - float4 prevDiffuseResponsiveSH1; + float4 prevDiffuseSH; + float4 prevDiffuseResponsiveSH; #endif #endif @@ -495,8 +500,8 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo float3 prevSpecularIlluminationAnd2ndMomentSMBResponsive; float prevReflectionHitTSMB; #ifdef RELAX_SH - float4 prevSpecularSMBSH1; - float4 prevSpecularSMBResponsiveSH1; + float4 prevSpecularSMBSH; + float4 prevSpecularSMBResponsiveSH; #endif #endif @@ -511,7 +516,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo specularIllumination.a, #endif NoV, - parallaxInPixels, + smbParallaxInPixelsMax, currentMaterialID, gDiffMaterialMask | gSpecMaterialMask, // TODO: improve? disocclusionThreshold, @@ -521,8 +526,8 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo , prevDiffuseIlluminationAnd2ndMomentSMB , prevDiffuseIlluminationAnd2ndMomentSMBResponsive #ifdef RELAX_SH - , prevDiffuseSH1 - , prevDiffuseResponsiveSH1 + , prevDiffuseSH + , prevDiffuseResponsiveSH #endif #endif #ifdef RELAX_SPECULAR @@ -530,8 +535,8 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo , prevSpecularIlluminationAnd2ndMomentSMBResponsive , prevReflectionHitTSMB #ifdef RELAX_SH - , prevSpecularSMBSH1 - , prevSpecularSMBResponsiveSH1 + , prevSpecularSMBSH + , prevSpecularSMBResponsiveSH #endif #endif ); @@ -580,7 +585,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo if (gHasHistoryConfidence && NRD_USE_HISTORY_CONFIDENCE) { - float inDiffConfidence = gDiffConfidence[WithRectOrigin(pixelPos)]; + float inDiffConfidence = gIn_DiffConfidence[WithRectOrigin(pixelPos)]; diffMaxAccumulatedFrameNum *= inDiffConfidence; diffMaxFastAccumulatedFrameNum *= inDiffConfidence; } @@ -605,25 +610,25 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo float3 accumulatedDiffuseIlluminationResponsive = lerp(prevDiffuseIlluminationAnd2ndMomentSMBResponsive.rgb, diffuseIllumination.rgb, diffuseAlphaResponsive); // Write out the diffuse results - gOutDiffuseIllumination[pixelPos] = accumulatedDiffuseIlluminationAnd2ndMoment; - gOutDiffuseIlluminationResponsive[pixelPos] = float4(accumulatedDiffuseIlluminationResponsive, 0); + gOut_Diff[pixelPos] = accumulatedDiffuseIlluminationAnd2ndMoment; + gOut_DiffFast[pixelPos] = float4(accumulatedDiffuseIlluminationResponsive, 0); #ifdef RELAX_SH - float4 accumulatedDiffuseSH1 = lerp(prevDiffuseSH1, diffuseSH1, diffuseAlpha); - float4 accumulatedDiffuseResponsiveSH1 = lerp(prevDiffuseResponsiveSH1, diffuseSH1, diffuseAlphaResponsive); - gOutDiffuseSH1[pixelPos] = accumulatedDiffuseSH1; - gOutDiffuseResponsiveSH1[pixelPos] = float4(accumulatedDiffuseResponsiveSH1); + float4 accumulatedDiffuseSH = lerp(prevDiffuseSH, diffuseSH, diffuseAlpha); + float4 accumulatedDiffuseResponsiveSH = lerp(prevDiffuseResponsiveSH, diffuseSH, diffuseAlphaResponsive); + gOut_DiffSh[pixelPos] = accumulatedDiffuseSH; + gOut_DiffShFast[pixelPos] = float4(accumulatedDiffuseResponsiveSH); #endif #endif - gOutHistoryLength[pixelPos] = historyLength / 255.0; + gOut_HistoryLength[pixelPos] = historyLength / 255.0; #ifdef RELAX_SPECULAR float specMaxAccumulatedFrameNum = gSpecMaxAccumulatedFrameNum; float specMaxFastAccumulatedFrameNum = gSpecMaxFastAccumulatedFrameNum; if (gHasHistoryConfidence && NRD_USE_HISTORY_CONFIDENCE) { - float inSpecConfidence = gSpecConfidence[WithRectOrigin(pixelPos)]; + float inSpecConfidence = gIn_SpecConfidence[WithRectOrigin(pixelPos)]; specMaxAccumulatedFrameNum *= inSpecConfidence; specMaxFastAccumulatedFrameNum *= inSpecConfidence; } @@ -636,77 +641,84 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo float hitDist = minHitDist3x3 == NRD_INF ? 0.0 : minHitDist3x3; // Calculating curvature along the direction of motion - // IMPORTANT: this code allows to get non-zero parallax on objects attached to the camera - float2 uvForZeroParallax = gOrthoMode == 0.0 ? prevUVSMB : pixelUv; - float2 deltaUv = Geometry::GetScreenUv(gWorldToClipPrev, prevWorldPos - gCameraDelta.xyz) - uvForZeroParallax; - deltaUv *= gRectSize; - float deltaUvLen = length(deltaUv); - deltaUv /= max(deltaUvLen, 1.0 / 256.0); - float2 motionUv = pixelUv + 0.99 * deltaUv * gRectSizeInv; // stay in SMEM - - // Construct the other edge point "x" - float z = UnpackViewZ(gViewZ.SampleLevel(gLinearClamp, WithRectOffset(motionUv * gResolutionScale), 0)); - float3 x = GetCurrentWorldPosFromClipSpaceXY(motionUv * 2.0 - 1.0, z); - - // Interpolate normal at "x" - Filtering::Bilinear f = Filtering::GetBilinearFilter(motionUv, gRectSize); - - int2 pos = threadPos + BORDER + int2(f.origin) - pixelPos; - pos = clamp(pos, 0, int2(BUFFER_X, BUFFER_Y) - 2); // just in case? - - float3 n00 = sharedNormalSpecHitT[pos.y][pos.x].xyz; - float3 n10 = sharedNormalSpecHitT[pos.y][pos.x + 1].xyz; - float3 n01 = sharedNormalSpecHitT[pos.y + 1][pos.x].xyz; - float3 n11 = sharedNormalSpecHitT[pos.y + 1][pos.x + 1].xyz; - - float3 n = _NRD_SafeNormalize(Filtering::ApplyBilinearFilter(n00, n10, n01, n11, f)); - - // ( Optional ) High parallax - flattens surface on high motion ( test 132, e9 ) - // IMPORTANT: a must for 8-bit and 10-bit normals ( tests b7, b10, b33 ) - float deltaUvLenFixed = deltaUvLen * (NRD_USE_HIGH_PARALLAX_CURVATURE_SILHOUETTE_FIX ? NoV : 1.0); // it fixes silhouettes, but leads to less flattening - float2 motionUvHigh = pixelUv + deltaUvLenFixed * deltaUv * gRectSizeInv; - if (NRD_USE_HIGH_PARALLAX_CURVATURE && deltaUvLenFixed > 1.0 && IsInScreenNearest(motionUvHigh)) + float curvature = 0.0; { - float zHigh = UnpackViewZ(gViewZ.SampleLevel(gLinearClamp, WithRectOffset(motionUvHigh * gResolutionScale), 0)); - float3 xHigh = GetCurrentWorldPosFromClipSpaceXY(motionUvHigh * 2.0 - 1.0, zHigh); + // IMPORTANT: non-zero parallax on objects attached to the camera is needed + // IMPORTANT: the direction of "deltaUv" is important ( test 1 ) + float2 uvForZeroParallax = gOrthoMode == 0.0 ? prevUVSMB : pixelUv; + float2 deltaUv = uvForZeroParallax - Geometry::GetScreenUv( gWorldToClipPrev, prevWorldPos + gCameraDelta.xyz ); // TODO: repeats code for "smbParallaxInPixels1" with "-" sign + deltaUv *= gRectSize; + deltaUv /= max( smbParallaxInPixels1, 1.0 / 256.0 ); + + // 10 edge + float3 n10, x10; + { + float3 x = GetCurrentWorldPosFromClipSpaceXY( ( pixelUv + float2( 1, 0 ) * gRectSizeInv ) * 2.0 - 1.0, 1.0 ); + float3 v = gOrthoMode == 0.0 ? normalize( -x ) : gFrustumForward.xyz; + float3 o = gOrthoMode == 0.0 ? 0 : x; - #if( NRD_NORMAL_ENCODING == NRD_NORMAL_ENCODING_R10G10B10A2_UNORM ) - f = Filtering::GetBilinearFilter(motionUvHigh, gRectSize); + x10 = o + v * dot( currentWorldPos - o, currentNormal ) / dot( currentNormal, v ); // line-plane intersection + n10 = sharedNormalSpecHitT[ threadPos.y + BORDER ][ threadPos.x + BORDER + 1 ].xyz; + } - f.origin = clamp(f.origin, 0, gRectSize - 2.0); - pos = gRectOrigin + int2(f.origin); + // 01 edge + float3 n01, x01; + { + float3 x = GetCurrentWorldPosFromClipSpaceXY( ( pixelUv + float2( 0, 1 ) * gRectSizeInv ) * 2.0 - 1.0, 1.0 ); + float3 v = gOrthoMode == 0.0 ? normalize( -x ) : gFrustumForward.xyz; + float3 o = gOrthoMode == 0.0 ? 0 : x; - n00 = NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness[pos]).xyz; - n10 = NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness[pos + int2(1, 0)]).xyz; - n01 = NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness[pos + int2(0, 1)]).xyz; - n11 = NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness[pos + int2(1, 1)]).xyz; + x01 = o + v * dot( currentWorldPos - o, currentNormal ) / dot( currentNormal, v ); // line-plane intersection + n01 = sharedNormalSpecHitT[ threadPos.y + BORDER + 1 ][ threadPos.x + BORDER ].xyz; + } - float3 nHigh = _NRD_SafeNormalize(Filtering::ApplyBilinearFilter(n00, n10, n01, n11, f)); - #else - float3 nHigh = NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness.SampleLevel(gLinearClamp, WithRectOffset(motionUvHigh * gResolutionScale), 0)).xyz; - #endif + // Mix + float2 w = abs( deltaUv ) + 1.0 / 256.0; + w /= w.x + w.y; - float zError = abs(zHigh - currentLinearZ) * rcp(max(zHigh, currentLinearZ)); - bool cmp = zError < NRD_CURVATURE_Z_THRESHOLD; + float3 x = x10 * w.x + x01 * w.y; + float3 n = normalize( n10 * w.x + n01 * w.y ); - n = cmp ? nHigh : n; - x = cmp ? xHigh : x; - } + // ( Optional ) High parallax - flattens surface on high motion ( test 132, e9 ) + // IMPORTANT: a must for 8-bit and 10-bit normals ( tests b7, b10, b33 ) + float deltaUvLenFixed = smbParallaxInPixelsMin; // not needed for objects attached to the camera! + deltaUvLenFixed *= NRD_USE_HIGH_PARALLAX_CURVATURE_SILHOUETTE_FIX ? NoV : 1.0; // it fixes silhouettes, but leads to less flattening + + float2 motionUvHigh = pixelUv + deltaUvLenFixed * deltaUv * gRectSizeInv; + motionUvHigh = ( floor( motionUvHigh * gRectSize ) + 0.5 ) * gRectSizeInv; // Snap to the pixel center! + + if( NRD_USE_HIGH_PARALLAX_CURVATURE && deltaUvLenFixed > 1.0 && IsInScreenNearest( motionUvHigh ) ) + { + float2 uvScaled = WithRectOffset( ClampUvToViewport( motionUvHigh ) ); - // Estimate curvature for the edge { x; currentWorldPos } - float3 edge = x - currentWorldPos; - float edgeLenSq = Math::LengthSquared(edge); - float curvature = dot(n - currentNormal, edge) * Math::PositiveRcp(edgeLenSq); + float zHigh = UnpackViewZ( gIn_ViewZ.SampleLevel( gNearestClamp, uvScaled, 0 ) ); + float3 xHigh = GetCurrentWorldPosFromClipSpaceXY( motionUvHigh * 2.0 - 1.0, zHigh ); - // Correction #1 - this is needed if camera is "inside" a concave mirror ( tests 133, 164, 171 - 176 ) - if (length(currentWorldPos) < -1.0 / curvature) - curvature *= NoV; + float3 nHigh = NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Normal_Roughness.SampleLevel( gNearestClamp, uvScaled, 0 ) ).xyz; - // Correction #2 - very negative inconsistent with previous frame curvature blows up reprojection ( tests 164, 171 - 176 ) - float2 uv1 = Geometry::GetScreenUv(gWorldToClipPrev, currentWorldPos - V * ApplyThinLensEquation(hitDist, curvature)); - float2 uv2 = Geometry::GetScreenUv(gWorldToClipPrev, currentWorldPos); - float a = length((uv1 - uv2) * gRectSize); - curvature *= float(a < NRD_MAX_ALLOWED_VIRTUAL_MOTION_ACCELERATION * deltaUvLen + gRectSizeInv.x); + // Replace if same surface + float zError = abs( zHigh - currentLinearZ ) * rcp( max( zHigh, currentLinearZ ) ); + bool cmp = zError < NRD_CURVATURE_Z_THRESHOLD; // TODO: use common disocclusion logic? + + n = cmp ? nHigh : n; + x = cmp ? xHigh : x; + } + + // Estimate curvature for the edge { x; currentWorldPos } + float3 edge = x - currentWorldPos; + float edgeLenSq = Math::LengthSquared( edge ); + curvature = dot( n - currentNormal, edge ) * Math::PositiveRcp( edgeLenSq ); + + // Correction #1 - this is needed if camera is "inside" a concave mirror ( tests 133, 164, 171 - 176 ) + if( length( currentWorldPos ) < -1.0 / curvature ) // TODO: test 78 + curvature *= NoV; + + // Correction #2 - very negative inconsistent with previous frame curvature blows up reprojection ( tests 164, 171 - 176 ) + float2 uv1 = Geometry::GetScreenUv( gWorldToClipPrev, currentWorldPos - V * ApplyThinLensEquation( hitDist, curvature ) ); + float2 uv2 = Geometry::GetScreenUv( gWorldToClipPrev, currentWorldPos ); + float a = length( ( uv1 - uv2 ) * gRectSize ); + curvature *= float( a < NRD_MAX_ALLOWED_VIRTUAL_MOTION_ACCELERATION * smbParallaxInPixelsMax + gRectSizeInv.x ); + } // Thin lens equation for adjusting reflection HitT float hitDistFocused = ApplyThinLensEquation(hitDist, curvature); @@ -719,8 +731,8 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo float prevRoughnessVMB; float prevReflectionHitTVMB; #ifdef RELAX_SH - float4 prevSpecularVMBSH1; - float4 prevSpecularVMBResponsiveSH1; + float4 prevSpecularVMBSH; + float4 prevSpecularVMBResponsiveSH; #endif float VMBReprojectionFound = loadVirtualMotionBasedPrevData( @@ -736,7 +748,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo currentMaterialID, gSpecMaterialMask, prevUVSMB, - parallaxInPixels, + smbParallaxInPixelsMax, NoV, disocclusionThreshold, prevSpecularIlluminationAnd2ndMomentVMB, @@ -746,8 +758,8 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo prevReflectionHitTVMB, prevUVVMB #ifdef RELAX_SH - , prevSpecularVMBSH1 - , prevSpecularVMBResponsiveSH1 + , prevSpecularVMBSH + , prevSpecularVMBResponsiveSH #endif ); @@ -771,8 +783,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo // Normal weight for virtual motion based reprojection float lobeHalfAngle = max(atan(GetSpecLobeTanHalfAngle(currentRoughnessModified)), RELAX_NORMAL_ULP); - float angle = lobeHalfAngle + curvatureAngle; - float normalWeight = GetEncodingAwareNormalWeight(currentNormal, prevNormalVMB, lobeHalfAngle, curvatureAngle, RELAX_NORMAL_ULP); + float normalWeight = GetEncodingAwareNormalWeight(currentNormal, prevNormalVMB, lobeHalfAngle, curvatureAngle, RELAX_NORMAL_ULP, true); virtualHistoryAmount *= lerp(1.0 - saturate(uvDiffLengthInPixels), 1.0, normalWeight); // jitter friendly // Roughness weight for virtual motion based reprojection @@ -788,12 +799,12 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo uvDiff *= saturate(uvDiffLengthInPixels / 0.1) + uvDiffLengthInPixels / 2.0; float2 backUV1 = prevUVVMB + 1.0 * uvDiff; float2 backUV2 = prevUVVMB + 2.0 * uvDiff; - float4 backNormalRoughness1 = UnpackPrevNormalRoughness(gPrevNormalRoughness.SampleLevel(gLinearClamp, backUV1 * gResolutionScalePrev, 0)); - float4 backNormalRoughness2 = UnpackPrevNormalRoughness(gPrevNormalRoughness.SampleLevel(gLinearClamp, backUV2 * gResolutionScalePrev, 0)); + float4 backNormalRoughness1 = UnpackPrevNormalRoughness(gPrev_Normal_Roughness.SampleLevel(gLinearClamp, backUV1 * gResolutionScalePrev, 0)); + float4 backNormalRoughness2 = UnpackPrevNormalRoughness(gPrev_Normal_Roughness.SampleLevel(gLinearClamp, backUV2 * gResolutionScalePrev, 0)); backNormalRoughness1.rgb = Geometry::RotateVector(gWorldPrevToWorld, backNormalRoughness1.rgb); backNormalRoughness2.rgb = Geometry::RotateVector(gWorldPrevToWorld, backNormalRoughness2.rgb); - float prevPrevNormalWeight = IsInScreenNearest(backUV1) ? GetEncodingAwareNormalWeight(prevNormalVMB, backNormalRoughness1.rgb, lobeHalfAngle, curvatureAngle * 2.0, RELAX_NORMAL_ULP) : 1.0; - prevPrevNormalWeight *= IsInScreenNearest(backUV2) ? GetEncodingAwareNormalWeight(prevNormalVMB, backNormalRoughness2.rgb, lobeHalfAngle, curvatureAngle * 3.0, RELAX_NORMAL_ULP) : 1.0; + float prevPrevNormalWeight = IsInScreenNearest(backUV1) ? GetEncodingAwareNormalWeight(prevNormalVMB, backNormalRoughness1.rgb, lobeHalfAngle, curvatureAngle * 2.0, RELAX_NORMAL_ULP, true) : 1.0; + prevPrevNormalWeight *= IsInScreenNearest(backUV2) ? GetEncodingAwareNormalWeight(prevNormalVMB, backNormalRoughness2.rgb, lobeHalfAngle, curvatureAngle * 3.0, RELAX_NORMAL_ULP, true) : 1.0; virtualHistoryAmount *= 0.33 + 0.67 * prevPrevNormalWeight; specVMBConfidence *= 0.33 + 0.67 * prevPrevNormalWeight; // Taking in account roughness 1 and 2 frames back helps cleaning up surfaces wigh varying roughness @@ -832,7 +843,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo // Current specular signal ( surface motion ) float specSMBConfidence = (SMBReprojectionFound > 0 ? 1.0 : 0.0) * - GetNormalWeight(V, Vprev, lobeHalfAngle * NoV / gFramerateScale); + GetEncodingAwareNormalWeight(V, Vprev, lobeHalfAngle * NoV / gFramerateScale, 0.0, 0.0, false); float specSMBAlpha = 1.0 - specSMBConfidence; float specSMBResponsiveAlpha = 1.0 - specSMBConfidence; @@ -843,7 +854,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo if (gSpecCheckerboard != 2) specHasData = checkerboard == gSpecCheckerboard; - if (!specHasData && (parallaxInPixels < 0.5)) + if (!specHasData && (smbParallaxInPixelsMax < 0.5)) { // Adjusting surface motion based specular accumulation weights for checkerboard specSMBAlpha *= 1.0 - gCheckerboardResolveAccumSpeed * (SMBReprojectionFound > 0 ? 1.0 : 0.0); @@ -866,7 +877,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo specVMBHitTAlpha = max(specVMBHitTAlpha, 1.0 / (1.0 + specHistoryFrames)); [flatten] - if (!specHasData && (parallaxInPixels < 0.5)) + if (!specHasData && (smbParallaxInPixelsMax < 0.5)) { // Adjusting virtual motion based specular accumulation weights for checkerboard specVMBAlpha *= 1.0 - gCheckerboardResolveAccumSpeed * (VMBReprojectionFound > 0 ? 1.0 : 0.0); @@ -892,16 +903,16 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo float accumulatedSpecular2ndMoment = lerp(accumulatedSpecularM2SMB, accumulatedSpecularM2VMB, virtualHistoryAmount); #ifdef RELAX_SH - float4 accumulatedSpecularSMBSH1 = lerp(prevSpecularSMBSH1, specularSH1, specSMBAlpha); - float4 accumulatedSpecularSMBResponsiveSH1 = lerp(prevSpecularSMBResponsiveSH1, specularSH1, specSMBResponsiveAlpha); + float4 accumulatedSpecularSMBSH = lerp(prevSpecularSMBSH, specularSH, specSMBAlpha); + float4 accumulatedSpecularSMBResponsiveSH = lerp(prevSpecularSMBResponsiveSH, specularSH, specSMBResponsiveAlpha); - float4 accumulatedSpecularVMBSH1 = lerp(prevSpecularVMBSH1, specularSH1, specVMBAlpha); - float4 accumulatedSpecularVMBResponsiveSH1 = lerp(prevSpecularVMBResponsiveSH1, specularSH1, specVMBResponsiveAlpha); + float4 accumulatedSpecularVMBSH = lerp(prevSpecularVMBSH, specularSH, specVMBAlpha); + float4 accumulatedSpecularVMBResponsiveSH = lerp(prevSpecularVMBResponsiveSH, specularSH, specVMBResponsiveAlpha); - float4 accumulatedSpecularSH1 = lerp(accumulatedSpecularSMBSH1, accumulatedSpecularVMBSH1, virtualHistoryAmount); - float4 accumulatedSpecularResponsiveSH1 = lerp(accumulatedSpecularSMBResponsiveSH1, accumulatedSpecularVMBResponsiveSH1, virtualHistoryAmount); - gOutSpecularSH1[pixelPos] = float4(accumulatedSpecularSH1.rgb, currentRoughnessModified); - gOutSpecularResponsiveSH1[pixelPos] = accumulatedSpecularResponsiveSH1; + float4 accumulatedSpecularSH = lerp(accumulatedSpecularSMBSH, accumulatedSpecularVMBSH, virtualHistoryAmount); + float4 accumulatedSpecularResponsiveSH = lerp(accumulatedSpecularSMBResponsiveSH, accumulatedSpecularVMBResponsiveSH, virtualHistoryAmount); + gOut_SpecSh[pixelPos] = float4(accumulatedSpecularSH.rgb, currentRoughnessModified); + gOut_SpecShFast[pixelPos] = accumulatedSpecularResponsiveSH; #endif // If zero specular sample (color = 0), artificially adding variance for pixels with low reprojection confidence @@ -909,10 +920,10 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo if (accumulatedSpecular2ndMoment == 0) accumulatedSpecular2ndMoment = gSpecVarianceBoost * (1.0 - specularHistoryConfidence); // Write out the results - gOutSpecularIllumination[pixelPos] = float4(accumulatedSpecularIllumination, accumulatedSpecular2ndMoment); - gOutSpecularIlluminationResponsive[pixelPos] = float4(accumulatedSpecularIlluminationResponsive, hitDist); + gOut_Spec[pixelPos] = float4(accumulatedSpecularIllumination, accumulatedSpecular2ndMoment); + gOut_SpecFast[pixelPos] = float4(accumulatedSpecularIlluminationResponsive, hitDist); - gOutReflectionHitT[pixelPos] = accumulatedReflectionHitT; - gOutSpecularReprojectionConfidence[pixelPos] = specularHistoryConfidence; + gOut_SpecHitDist[pixelPos] = accumulatedReflectionHitT; + gOut_SpecReprojectionConfidence[pixelPos] = specularHistoryConfidence; #endif } diff --git a/Shaders/Include/SIGMA_Blur.hlsli b/Shaders/Include/SIGMA_Blur.hlsli index 26369cbe..aaa63792 100644 --- a/Shaders/Include/SIGMA_Blur.hlsli +++ b/Shaders/Include/SIGMA_Blur.hlsli @@ -50,25 +50,15 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : int2 smemPos = threadPos + BORDER; float2 centerData = s_Penumbra_ViewZ[ smemPos.y ][ smemPos.x ]; float centerPenumbra = centerData.x; - float centerSignNoL = float( centerPenumbra != 0.0 ); float viewZ = centerData.y; // Early out if( viewZ > gDenoisingRange ) return; - // Copy history - #ifdef SIGMA_FIRST_PASS - if( gStabilizationStrength != 0 ) - gOut_History[ pixelPos ] = gIn_History[ pixelPos ]; - #endif - // Tile-based early out ( potentially ) float2 pixelUv = float2( pixelPos + 0.5 ) * gRectSizeInv; float tileValue = TextureCubic( gIn_Tiles, pixelUv * gResolutionScale ); - #ifdef SIGMA_FIRST_PASS - tileValue *= all( pixelPos < gRectSize ); // due to USE_MAX_DIMS - #endif if( ( tileValue == 0.0 && NRD_USE_TILE_CHECK ) || centerPenumbra == 0.0 ) { @@ -87,9 +77,11 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float3 Nv = Geometry::RotateVector( gWorldToView, N ); // Parameters - float unprojectZ = PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, viewZ ); + float pixelSize = PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, viewZ ); float frustumSize = GetFrustumSize( gMinRectDimMulUnproject, gOrthoMode, viewZ ); - float2 geometryWeightParams = GetGeometryWeightParams( gPlaneDistSensitivity, frustumSize, Xv, Nv, 1.0 ); + float3 Vv = GetViewVector( Xv, true ); + float NoV = abs( dot( Nv, Vv ) ); + float2 geometryWeightParams = GetGeometryWeightParams( gPlaneDistSensitivity, frustumSize, Xv, Nv, 0.0 ); // Estimate penumbra size and filter shadow ( dense ) float2 sum = 0; @@ -105,42 +97,36 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : { int2 pos = threadPos + int2( i, j ); + // Fetch data float2 data = s_Penumbra_ViewZ[ pos.y ][ pos.x ]; float penum = data.x; - float z = data.y; - float signNoL = float( penum != 0.0 ); + float zs = data.y; SIGMA_TYPE s = s_Shadow_Translucency[ pos.y ][ pos.x ]; - float w; + // Sample weight + float w = 1.0; if( i == BORDER && j == BORDER ) - { centerTap = s; - w = 1.0; - } else { float2 uv = pixelUv + float2( i - BORDER, j - BORDER ) * gRectSizeInv; - float3 Xvs = Geometry::ReconstructViewPosition( uv, gFrustum, z, gOrthoMode ); - float NoX = dot( Nv, Xvs ); + float3 Xvs = Geometry::ReconstructViewPosition( uv, gFrustum, zs, gOrthoMode ); - w = ComputeWeight( NoX, geometryWeightParams.x, geometryWeightParams.y ); + w *= ComputeWeight( dot( Nv, Xvs ), geometryWeightParams.x, geometryWeightParams.y ); + w *= AreBothLitOrUnlit( centerPenumbra, penum ); w *= GetGaussianWeight( length( float2( i - BORDER, j - BORDER ) / BORDER ) ); - w *= float( z < gDenoisingRange ); - w *= float( centerSignNoL == signNoL ); - - s = Denanify( w, s ); } - float2 ww = w; - ww.y *= saturate( 1.0 - s.x ); // TODO: non linear? + // Accumulate + result += w == 0.0 ? 0.0 : s * w; + sum.x += w; - float penumInPixels = penum / unprojectZ; - ww.y /= 1.0 + penumInPixels; // prefer smaller penumbra + w *= pixelSize / ( pixelSize + penum ); // prefer smaller penumbra, same as "w /= 1.0 + penumInPixels", where penumInPixels = penum / pixelSize + w *= !IsLit( penum ); - result += s * ww.x; - penumbra += ww.y == 0.0 ? 0.0 : penum * ww.y; - sum += ww; + penumbra += w == 0.0 ? 0.0 : penum * w; + sum.y += w; } } @@ -150,37 +136,55 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : penumbra /= max( sum.y, NRD_EPS ); // yes, without patching sum.y = float( sum.y != 0.0 ); - // Avoid 1-pixel wide blur if penumbra size < 1 pixel - float penumbraInPixels = penumbra / unprojectZ; - float f = Math::LinearStep( 0.75, 1.25, penumbraInPixels ); - result = lerp( centerTap, result, f ); + // Avoid blurry result if penumbra size < BORDER + float penumbraInPixels = penumbra / pixelSize; + float f = Math::SmoothStep( 0.0, BORDER, penumbraInPixels ); + result = lerp( centerTap, result, f ); // TODO: not the best solution + +#if( SIGMA_USE_SPARSE_BLUR == 1 ) + // Avoid unnecessary weight increase for the unfiltered center sample if the blur radius is small + f = lerp( 4.0, 1.0, f ); // TODO: adds blurriness + + result *= f; + penumbra *= f; + sum *= f; + + // Blur radius + float blurRadius = GetKernelRadiusInPixels( penumbra, pixelSize, tileValue ); // Tangent basis with anisotropy - float3x3 mWorldToLocal = Geometry::GetBasis( Nv ); - float3 Tv = mWorldToLocal[ 0 ]; - float3 Bv = mWorldToLocal[ 1 ]; + float4 rotator = GetBlurKernelRotation( SIGMA_ROTATOR_MODE, pixelPos, gRotator, gFrameIndex ); - float3 t = cross( gLightDirectionView.xyz, Nv ); // TODO: add support for other light types to bring proper anisotropic filtering - if( length( t ) > 0.001 ) - { - Tv = normalize( t ); - Bv = cross( Tv, Nv ); + #if( SIGMA_USE_SCREEN_SPACE_SAMPLING == 1 ) + float2 skew = lerp( 1.0 - abs( Nv.xy ), 1.0, NoV ); + skew /= max( skew.x, skew.y ); - float cosa = abs( dot( Nv, gLightDirectionView.xyz ) ); - float skewFactor = lerp( 0.25, 1.0, cosa ); + skew *= gRectSizeInv * blurRadius; - //Tv *= skewFactor; // TODO: let's not srink filtering in the other direction - Bv /= skewFactor; - } + float4 scaledRotator = Geometry::ScaleRotator( rotator, skew ); + #else + float3x3 mWorldToLocal = Geometry::GetBasis( Nv ); + float3 Tv = mWorldToLocal[ 0 ]; + float3 Bv = mWorldToLocal[ 1 ]; - // Blur radius - float worldRadius = GetKernelRadiusInPixels( penumbra, unprojectZ, tileValue ) * unprojectZ; + float3 t = cross( gLightDirectionView.xyz, Nv ); // TODO: add support for other light types to bring proper anisotropic filtering + if( length( t ) > 0.001 ) + { + Tv = normalize( t ); + Bv = cross( Tv, Nv ); - Tv *= worldRadius; - Bv *= worldRadius; + float cosa = abs( dot( Nv, gLightDirectionView.xyz ) ); + float skewFactor = lerp( 0.25, 1.0, cosa ); - // Random rotation - float4 rotator = GetBlurKernelRotation( SIGMA_ROTATOR_MODE, pixelPos, gRotator, gFrameIndex ); + //Tv *= skewFactor; // TODO: let's not srink filtering in the other direction + Bv /= skewFactor; // TODO: good for test 197, but adds bad correlations in test 212 + } + + float worldRadius = blurRadius * pixelSize; + + Tv *= worldRadius; + Bv *= worldRadius; + #endif // Estimate penumbra size and filter shadow ( sparse ) float invEstimatedPenumbra = 1.0 / max( penumbra, NRD_EPS ); @@ -190,7 +194,12 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : { // Sample coordinates float3 offset = SIGMA_POISSON_SAMPLES[ n ]; - float2 uv = GetKernelSampleCoordinates( gViewToClip, offset, Xv, Tv, Bv, rotator ); + + #if( SIGMA_USE_SCREEN_SPACE_SAMPLING == 1 ) + float2 uv = pixelUv + Geometry::RotateVector( scaledRotator, offset.xy ); + #else + float2 uv = GetKernelSampleCoordinates( gViewToClip, offset, Xv, Tv, Bv, rotator ); + #endif // Snap to the pixel center! uv = ( floor( uv * gRectSize ) + 0.5 ) * gRectSizeInv; @@ -200,47 +209,41 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Fetch data float penum = gIn_Penumbra.SampleLevel( gNearestClamp, uvScaled, 0 ); - float z = UnpackViewZ( gIn_ViewZ.SampleLevel( gNearestClamp, WithRectOffset( uvScaled ), 0 ) ); - float signNoL = float( penum != 0.0 ); - - // Sample weight - float3 Xvs = Geometry::ReconstructViewPosition( uv, gFrustum, z, gOrthoMode ); - float NoX = dot( Nv, Xvs ); - - float w = IsInScreenNearest( uv ); - w *= GetGaussianWeight( offset.z ); - w *= ComputeWeight( NoX, geometryWeightParams.x, geometryWeightParams.y ); - w *= float( z < gDenoisingRange ); - w *= float( centerSignNoL == signNoL ); + float zs = UnpackViewZ( gIn_ViewZ.SampleLevel( gNearestClamp, WithRectOffset( uvScaled ), 0 ) ); - // Avoid umbra leaking inside wide penumbra - float t = saturate( penum * invEstimatedPenumbra ); - w *= Math::SmoothStep( 0.0, 1.0, t ); // TODO: it works surprisingly well, keep an eye on it! - - // Fetch shadow SIGMA_TYPE s; #if( !defined SIGMA_FIRST_PASS || defined SIGMA_TRANSLUCENT ) s = gIn_Shadow_Translucency.SampleLevel( gNearestClamp, uvScaled, 0 ); #else s = IsLit( penum ); #endif - s = Denanify( w, s ); #ifndef SIGMA_FIRST_PASS s = SIGMA_BackEnd_UnpackShadow( s ); #endif + // Sample weight + float3 Xvs = Geometry::ReconstructViewPosition( uv, gFrustum, zs, gOrthoMode ); + + float w = IsInScreenNearest( uv ); + w *= ComputeWeight( dot( Nv, Xvs ), geometryWeightParams.x, geometryWeightParams.y ); + w *= AreBothLitOrUnlit( centerPenumbra, penum ); + w *= GetGaussianWeight( offset.z ); + + // Avoid umbra leaking inside wide penumbra + w *= saturate( penum * invEstimatedPenumbra ); // TODO: it works surprisingly well, keep an eye on it! + // Accumulate - float2 ww = w; - ww.y *= saturate( 1.0 - s.x ); // TODO: non linear? + result += w == 0.0 ? 0.0 : s * w; + sum.x += w; - float penumInPixels = penum / unprojectZ; - ww.y /= 1.0 + penumInPixels; // prefer smaller penumbra + w *= pixelSize / ( pixelSize + penum ); // prefer smaller penumbra, same as "w /= 1.0 + penumInPixels", where penumInPixels = penum / pixelSize + w *= !IsLit( penum ); - result += s * ww.x; - penumbra += ww.y == 0.0 ? 0.0 : penum * ww.y; - sum += ww; + penumbra += w == 0.0 ? 0.0 : penum * w; + sum.y += w; } +#endif result /= sum.x; penumbra = sum.y == 0.0 ? centerPenumbra : penumbra / sum.y; diff --git a/Shaders/Include/SIGMA_ClassifyTiles.hlsli b/Shaders/Include/SIGMA_ClassifyTiles.hlsli index 77a4ecf5..5acc7b03 100644 --- a/Shaders/Include/SIGMA_ClassifyTiles.hlsli +++ b/Shaders/Include/SIGMA_ClassifyTiles.hlsli @@ -52,8 +52,8 @@ NRD_EXPORT void NRD_CS_MAIN( uint2 threadPos : SV_GroupThreadId, uint2 tilePos : mask += ( isInf ? 1 : 0 ) << 18; float hitDist = ( isLit || isInf ) ? 0 : h; - float unprojectZ = PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, viewZ ); - float pixelRadius = GetKernelRadiusInPixels( hitDist, unprojectZ ); + float pixelSize = PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, viewZ ); + float pixelRadius = GetKernelRadiusInPixels( hitDist, pixelSize ); maxRadius = max( pixelRadius, maxRadius ); } diff --git a/Shaders/Include/SIGMA_Common.hlsli b/Shaders/Include/SIGMA_Common.hlsli index 71e46761..ba03e0c8 100644 --- a/Shaders/Include/SIGMA_Common.hlsli +++ b/Shaders/Include/SIGMA_Common.hlsli @@ -13,12 +13,31 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #define PackShadow( s ) Math::Sqrt01( s ) // must match "SIGMA_BackEnd_UnpackShadow" #define IsLit( p ) ( p >= NRD_FP16_MAX ) +float3 GetViewVector( float3 X, bool isViewSpace = false ) +{ + return gOrthoMode == 0.0 ? normalize( -X ) : ( isViewSpace ? float3( 0, 0, -1 ) : gViewVectorWorld.xyz ); +} + float GetKernelRadiusInPixels( float hitDist, float unprojectZ, float scale = 1.0 ) { float unclampedRadius = hitDist / unprojectZ; - float minRadius = min( unclampedRadius, BORDER ); + unclampedRadius *= scale; + + #if( SIGMA_5X5_BLUR_RADIUS_ESTIMATION_KERNEL == 1 ) + float minRadius = min( unclampedRadius, 2.0 ); + #else + float minRadius = min( unclampedRadius, 1.0 ); + #endif + + return clamp( unclampedRadius, minRadius, SIGMA_MAX_PIXEL_RADIUS ); +} + +float AreBothLitOrUnlit( float penumbra1, float penumbra2 ) +{ + bool NoL1 = penumbra1 == 0.0; + bool NoL2 = penumbra2 == 0.0; - return clamp( unclampedRadius * scale, minRadius, SIGMA_MAX_PIXEL_RADIUS ); + return float( NoL1 == NoL2 ); } // TODO: move code below to STL.hlsl diff --git a/Shaders/Include/SIGMA_Config.hlsli b/Shaders/Include/SIGMA_Config.hlsli index 528ec1ee..cf64f923 100644 --- a/Shaders/Include/SIGMA_Config.hlsli +++ b/Shaders/Include/SIGMA_Config.hlsli @@ -15,10 +15,17 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #define SIGMA_USE_CATROM 1 // sharper reprojection #define SIGMA_5X5_TEMPORAL_KERNEL 1 // provides variance estimation in a wider radius #define SIGMA_5X5_BLUR_RADIUS_ESTIMATION_KERNEL 1 // helps to improve stability, but adds 10% of overhead +#define SIGMA_ADJUST_HISTORY_LENGTH_BY_ANTILAG 1 // TODO: is it needed? +#define SIGMA_USE_SPARSE_BLUR 1 // can be disabled for debugging purposes +#define SIGMA_USE_SCREEN_SPACE_SAMPLING 1 // almost matches world-space sampling but simpler code ( TODO: doesn't elongate shadow ) -// Switches ( default 0 ) -#define SIGMA_SHOW 0 // 1 - tiles, 2 - history weight, 3 - penumbra size in pixels -#define SIGMA_SHOW_PENUMBRA_SIZE 0 +// Show +#define SIGMA_SHOW_TILES 1 +#define SIGMA_SHOW_HISTORY_WEIGHT 2 +#define SIGMA_SHOW_HISTORY_LENGTH 3 +#define SIGMA_SHOW_PENUMBRA_SIZE 4 + +#define SIGMA_SHOW 0 // 0 or SIGMA_SHOW_X // Settings #define SIGMA_ROTATOR_MODE NRD_FRAME @@ -26,8 +33,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #define SIGMA_POISSON_SAMPLES g_Special8 #define SIGMA_MAX_PIXEL_RADIUS 32.0 #define SIGMA_TS_SIGMA_SCALE 3.0 -#define SIGMA_TS_MAX_HISTORY_WEIGHT 0.8 // 4 frames ( longer accumulation worsens shadows in motion, since there is no shadow MV ) -#define SIGMA_TS_ANTILAG_POWER 1.0 +#define SIGMA_MAX_ACCUM_FRAME_NUM 7 // Data type #ifdef SIGMA_TRANSLUCENT @@ -41,8 +47,12 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. NRD_CONSTANT( float4x4, gWorldToView ) \ NRD_CONSTANT( float4x4, gViewToClip ) \ NRD_CONSTANT( float4x4, gWorldToClipPrev ) \ + NRD_CONSTANT( float4x4, gWorldToViewPrev ) \ + NRD_CONSTANT( float4, gViewVectorWorld ) \ NRD_CONSTANT( float4, gLightDirectionView ) \ NRD_CONSTANT( float4, gFrustum ) \ + NRD_CONSTANT( float4, gFrustumPrev ) \ + NRD_CONSTANT( float4, gCameraDelta ) \ NRD_CONSTANT( float4, gMvScale ) \ NRD_CONSTANT( float2, gResourceSizeInv ) \ NRD_CONSTANT( float2, gResourceSizeInvPrev ) \ @@ -64,4 +74,5 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. NRD_CONSTANT( float, gSplitScreen ) \ NRD_CONSTANT( float, gViewZScale ) \ NRD_CONSTANT( float, gMinRectDimMulUnproject ) \ - NRD_CONSTANT( uint, gFrameIndex ) + NRD_CONSTANT( uint, gFrameIndex ) \ + NRD_CONSTANT( uint, gIsRectChanged ) diff --git a/Shaders/Include/SIGMA_Copy.hlsli b/Shaders/Include/SIGMA_Copy.hlsli new file mode 100644 index 00000000..556160fe --- /dev/null +++ b/Shaders/Include/SIGMA_Copy.hlsli @@ -0,0 +1,22 @@ +/* +Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + +NVIDIA CORPORATION and its licensors retain all intellectual property +and proprietary rights in and to this software, related documentation +and any modifications thereto. Any use, reproduction, disclosure or +distribution of this software and related documentation without an express +license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +[numthreads( GROUP_X, GROUP_Y, 1 )] +NRD_EXPORT void NRD_CS_MAIN( uint2 pixelPos : SV_DispatchThreadId ) +{ + // Tile-based early out + float isSky = gIn_Tiles[ pixelPos >> 4 ].y; + if( isSky != 0.0 && !gIsRectChanged ) + return; + + // TODO: introduce "CopyResource" in NRD API? + gOut_History[ pixelPos ] = gIn_History[ pixelPos ]; + gOut_HistoryLength[ pixelPos ] = gIn_HistoryLength[ pixelPos ]; +} diff --git a/Shaders/Source/SIGMA_Shadow_SmoothTiles.cs.hlsl b/Shaders/Include/SIGMA_SmoothTiles.hlsli similarity index 88% rename from Shaders/Source/SIGMA_Shadow_SmoothTiles.cs.hlsl rename to Shaders/Include/SIGMA_SmoothTiles.hlsli index 3d83a0b1..937ad6a2 100644 --- a/Shaders/Source/SIGMA_Shadow_SmoothTiles.cs.hlsl +++ b/Shaders/Include/SIGMA_SmoothTiles.hlsli @@ -8,15 +8,6 @@ distribution of this software and related documentation without an express license agreement from NVIDIA CORPORATION is strictly prohibited. */ -#include "NRD.hlsli" -#include "ml.hlsli" - -#include "SIGMA_Config.hlsli" -#include "SIGMA_SmoothTiles.resources.hlsli" - -#include "Common.hlsli" -#include "SIGMA_Common.hlsli" - groupshared float s_Tile[ BUFFER_Y ][ BUFFER_X ]; void Preload( uint2 sharedPos, int2 globalPos ) diff --git a/Shaders/Include/SIGMA_SplitScreen.hlsli b/Shaders/Include/SIGMA_SplitScreen.hlsli index 9f780a74..fd8dd85a 100644 --- a/Shaders/Include/SIGMA_SplitScreen.hlsli +++ b/Shaders/Include/SIGMA_SplitScreen.hlsli @@ -25,7 +25,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 pixelPos : SV_DispatchThreadId) s = IsLit( data.x ); #endif - #if( SIGMA_SHOW_PENUMBRA_SIZE == 1 ) + #if( SIGMA_SHOW == SIGMA_SHOW_PENUMBRA_SIZE ) s = PackShadow( data.x ); #endif diff --git a/Shaders/Include/SIGMA_TemporalStabilization.hlsli b/Shaders/Include/SIGMA_TemporalStabilization.hlsli index 2c26b1bd..2f505f01 100644 --- a/Shaders/Include/SIGMA_TemporalStabilization.hlsli +++ b/Shaders/Include/SIGMA_TemporalStabilization.hlsli @@ -8,23 +8,35 @@ distribution of this software and related documentation without an express license agreement from NVIDIA CORPORATION is strictly prohibited. */ -groupshared float2 s_Penumbra_ViewZ[ BUFFER_Y ][ BUFFER_X ]; +groupshared float s_Penumbra[ BUFFER_Y ][ BUFFER_X ]; groupshared SIGMA_TYPE s_Shadow_Translucency[ BUFFER_Y ][ BUFFER_X ]; void Preload( uint2 sharedPos, int2 globalPos ) { globalPos = clamp( globalPos, 0, gRectSizeMinusOne ); - float2 data; - data.x = gIn_Penumbra[ globalPos ]; - data.y = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( globalPos ) ] ); - - s_Penumbra_ViewZ[ sharedPos.y ][ sharedPos.x ] = data; - SIGMA_TYPE s = gIn_Shadow_Translucency[ globalPos ]; s = SIGMA_BackEnd_UnpackShadow( s ); s_Shadow_Translucency[ sharedPos.y ][ sharedPos.x ] = s; + s_Penumbra[ sharedPos.y ][ sharedPos.x ] = gIn_Penumbra[ globalPos ]; +} + +uint PackViewZAndHistoryLength( float viewZ, float historyLength ) +{ + uint p = asuint( viewZ ) & ~7; + p |= min( uint( historyLength + 0.5 ), 7 ); + + return p; +} + +void BicubicFilterNoCornersWithFallbackToBilinearFilterWithCustomWeights( + float2 samplePos, float2 invResourceSize, + float4 bilinearCustomWeights, bool useBicubic, + Texture2D tex0, out SIGMA_TYPE c0 ) +{ + _BicubicFilterNoCornersWithFallbackToBilinearFilterWithCustomWeights_Init; + _BicubicFilterNoCornersWithFallbackToBilinearFilterWithCustomWeights_Color( c0, tex0 ); } [numthreads( GROUP_X, GROUP_Y, 1 )] @@ -34,22 +46,16 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float isSky = gIn_Tiles[ pixelPos >> 4 ].y; PRELOAD_INTO_SMEM_WITH_TILE_CHECK; - // Tile-based early out - if( isSky != 0.0 || any( pixelPos > gRectSizeMinusOne ) ) - return; - // Center data int2 smemPos = threadPos + BORDER; - float2 centerData = s_Penumbra_ViewZ[ smemPos.y ][ smemPos.x ]; - float centerPenumbra = centerData.x; - float centerSignNoL = float( centerData.x != 0.0 ); - float viewZ = centerData.y; + float centerPenumbra = s_Penumbra[ smemPos.y ][ smemPos.x ]; + float viewZ = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( pixelPos ) ] ); - // Early out - if( viewZ > gDenoisingRange ) + // Early out #1 + if( isSky != 0.0 || any( pixelPos > gRectSizeMinusOne ) || viewZ > gDenoisingRange ) return; - // Tile-based early out ( potentially ) + // Early out #2 float2 pixelUv = float2( pixelPos + 0.5 ) * gRectSizeInv; float tileValue = TextureCubic( gIn_Tiles, pixelUv * gResolutionScale ); bool isHardShadow = ( ( tileValue == 0.0 && NRD_USE_TILE_CHECK ) || centerPenumbra == 0.0 ) && SIGMA_USE_EARLY_OUT_IN_TS; @@ -57,6 +63,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : if( isHardShadow && SIGMA_SHOW == 0 ) { gOut_Shadow_Translucency[ pixelPos ] = PackShadow( s_Shadow_Translucency[ smemPos.y ][ smemPos.x ] ); + gOut_HistoryLength[ pixelPos ] = PackViewZAndHistoryLength( viewZ, SIGMA_MAX_ACCUM_FRAME_NUM ); // TODO: yes, SIGMA_MAX_ACCUM_FRAME_NUM to allow accumulation in neighbors return; } @@ -67,9 +74,6 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : SIGMA_TYPE m2 = 0; SIGMA_TYPE input = 0; - float viewZnearest = viewZ; - int2 offseti = int2( BORDER, BORDER ); - [unroll] for( j = 0; j <= BORDER * 2; j++ ) { @@ -77,28 +81,17 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : for( i = 0; i <= BORDER * 2; i++ ) { int2 pos = threadPos + int2( i, j ); - float2 data = s_Penumbra_ViewZ[ pos.y ][ pos.x ]; - SIGMA_TYPE s = s_Shadow_Translucency[ pos.y ][ pos.x ]; - float penum = data.x; - float z = data.y; - float signNoL = float( penum != 0.0 ); float w = 1.0; if( i == BORDER && j == BORDER ) input = s; else { - w = abs( z - viewZ ) / max( z, viewZ ) < 0.02; // TODO: slope scale? - w *= IsLit( penum ) == IsLit( centerPenumbra ); // no-harm on a flat surface due to wide spatials, needed to prevent bleeding from one surface to another - w *= float( z < gDenoisingRange ); // ignore sky - w *= float( centerSignNoL == signNoL ); // ignore samples with different NoL signs - - if( z < viewZnearest ) - { - viewZnearest = z; - offseti = int2( i, j ); - } + float penum = s_Penumbra[ pos.y ][ pos.x ]; + + w = AreBothLitOrUnlit( centerPenumbra, penum ); + w *= GetGaussianWeight( length( float2( i - BORDER, j - BORDER ) / BORDER ) ); } m1 += s * w; @@ -107,52 +100,99 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : } } - float invSum = Math::PositiveRcp( sum ); - m1 *= invSum; - m2 *= invSum; + m1 /= sum; // sum can't be 0 + m2 /= sum; SIGMA_TYPE sigma = GetStdDev( m1, m2 ); - // Compute previous pixel position - float3 Xv = Geometry::ReconstructViewPosition( pixelUv, gFrustum, viewZnearest, gOrthoMode ); + // Current and previous positions + float3 Xv = Geometry::ReconstructViewPosition( pixelUv, gFrustum, viewZ, gOrthoMode ); float3 X = Geometry::RotateVectorInverse( gWorldToView, Xv ); - float3 mv = gIn_Mv[ WithRectOrigin( pixelPos ) + offseti - BORDER ] * gMvScale.xyz; - float2 pixelUvPrev = pixelUv + mv.xy; - if( gMvScale.w != 0.0 ) - pixelUvPrev = Geometry::GetScreenUv( gWorldToClipPrev, X + mv ); + float3 mv = gIn_Mv[ WithRectOrigin( pixelPos ) ] * gMvScale.xyz; + float3 Xprev = X; + float2 smbPixelUv = pixelUv + mv.xy; + + if( gMvScale.w == 0.0 ) + { + if( gMvScale.z == 0.0 ) + mv.z = Geometry::AffineTransform( gWorldToViewPrev, X ).z - viewZ; + + float viewZprev = viewZ + mv.z; + float3 Xvprevlocal = Geometry::ReconstructViewPosition( smbPixelUv, gFrustumPrev, viewZprev, gOrthoMode ); // TODO: use gOrthoModePrev + + Xprev = Geometry::RotateVectorInverse( gWorldToViewPrev, Xvprevlocal ) + gCameraDelta.xyz; + } + else + { + Xprev += mv; + smbPixelUv = Geometry::GetScreenUv( gWorldToClipPrev, Xprev ); + } + + // History length + Filtering::Bilinear smbBilinearFilter = Filtering::GetBilinearFilter( smbPixelUv, gRectSizePrev ); + float2 smbBilinearGatherUv = ( smbBilinearFilter.origin + 1.0 ) * gResourceSizeInvPrev; + uint4 prevData = gIn_HistoryLength.GatherRed( gNearestClamp, smbBilinearGatherUv ).wzxy; + float4 prevViewZ = asfloat( prevData & ~7 ); + float4 prevHistoryLength = float4( prevData & 7 ); + + float frustumSize = GetFrustumSize( gMinRectDimMulUnproject, gOrthoMode, viewZ ); + float disocclusionThreshold = GetDisocclusionThreshold( NRD_DISOCCLUSION_THRESHOLD, frustumSize, 1.0 ); // TODO: slope scale? + disocclusionThreshold *= IsInScreenNearest( smbPixelUv ); + disocclusionThreshold -= NRD_EPS; + + float3 Xvprev = Geometry::AffineTransform( gWorldToViewPrev, Xprev ); + float4 smbPlaneDist = abs( prevViewZ - Xvprev.z ); + float4 smbOcclusion = step( smbPlaneDist, disocclusionThreshold ); + + float4 smbOcclusionWeights = Filtering::GetBilinearCustomWeights( smbBilinearFilter, smbOcclusion ); + float historyLength = Filtering::ApplyBilinearCustomWeights( prevHistoryLength.x, prevHistoryLength.y, prevHistoryLength.z, prevHistoryLength.w, smbOcclusionWeights ); // Sample history + bool isCatRomAllowed = dot( smbOcclusionWeights, 1.0 ) > 3.5; + SIGMA_TYPE history; - BicubicFilterNoCorners( saturate( pixelUvPrev ) * gRectSizePrev, gResourceSizeInvPrev, SIGMA_USE_CATROM, gIn_History, history ); + BicubicFilterNoCornersWithFallbackToBilinearFilterWithCustomWeights( + saturate( smbPixelUv ) * gRectSizePrev, gResourceSizeInvPrev, + smbOcclusionWeights, isCatRomAllowed, + gIn_History, history ); history = saturate( history ); history = SIGMA_BackEnd_UnpackShadow( history ); // Clamp history - SIGMA_TYPE inputMin = m1 - sigma * SIGMA_TS_SIGMA_SCALE; - SIGMA_TYPE inputMax = m1 + sigma * SIGMA_TS_SIGMA_SCALE; + sigma *= lerp( SIGMA_TS_SIGMA_SCALE, 1.0, 1.0 / ( 1.0 + historyLength ) ); // TODO: lerp( SIGMA_TS_SIGMA_SCALE, 1.0, 0.125 ) != SIGMA_TS_SIGMA_SCALE + + SIGMA_TYPE inputMin = m1 - sigma; + SIGMA_TYPE inputMax = m1 + sigma; SIGMA_TYPE historyClamped = clamp( history, inputMin, inputMax ); // Antilag float antilag = abs( historyClamped.x - history.x ); - antilag = Math::Pow01( antilag, SIGMA_TS_ANTILAG_POWER ); - antilag = 1.0 - antilag; + #if( SIGMA_ADJUST_HISTORY_LENGTH_BY_ANTILAG == 1 ) + antilag = Math::Sqrt01( antilag ); + #endif + antilag = saturate( 1.0 - antilag ); - // Dark magic ( helps to smooth out "penumbra to 1" regions ) - historyClamped = lerp( historyClamped, history, 0.5 ); + #if( SIGMA_ADJUST_HISTORY_LENGTH_BY_ANTILAG == 1 ) + historyLength *= antilag; // TODO: reduce influence if history is short? + #endif // History weight - float historyWeight = SIGMA_TS_MAX_HISTORY_WEIGHT; - historyWeight *= IsInScreenNearest( pixelUvPrev ); - historyWeight *= antilag; - historyWeight *= gStabilizationStrength; + float historyWeight = historyLength / ( 1.0 + historyLength ); + #if( SIGMA_ADJUST_HISTORY_LENGTH_BY_ANTILAG == 0 ) + historyWeight *= antilag; + #endif - // Combine with current frame - SIGMA_TYPE result = lerp( input, historyClamped, historyWeight ); + // Street magic ( helps to smooth out "penumbra to 1" regions ) + float streetMagic = 0.6 * historyWeight; // TODO: * historyClamped.x? * float( historyClamped.x != 0.0 )? + historyClamped = lerp( historyClamped, history, streetMagic ); - // Debug - #if( SIGMA_SHOW == 1 ) + // Combine with the current frame + SIGMA_TYPE result = lerp( input, historyClamped, min( gStabilizationStrength, historyWeight ) ); + + // Debug ( don't forget that ".x" is used in antilag computations! ) + #if( SIGMA_SHOW == SIGMA_SHOW_TILES ) tileValue = gIn_Tiles[ pixelPos >> 4 ].x; tileValue = float( tileValue != 0.0 ); // optional, just to show fully discarded tiles @@ -162,20 +202,23 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : result = tileValue; #endif - // Show grid ( works badly with TAA ) result *= all( ( pixelPos & 15 ) != 0 ); - #elif( SIGMA_SHOW == 2 ) - // .x - is used in antilag computations! + #elif( SIGMA_SHOW == SIGMA_SHOW_HISTORY_WEIGHT ) + #ifdef SIGMA_TRANSLUCENT + result.yzw = historyWeight * float( !isHardShadow ); + #endif + #elif( SIGMA_SHOW == SIGMA_SHOW_HISTORY_LENGTH ) #ifdef SIGMA_TRANSLUCENT - historyWeight *= float( !isHardShadow ); - result.yzw = historyWeight; + result.yzw = historyLength / SIGMA_MAX_ACCUM_FRAME_NUM; #endif - #elif( SIGMA_SHOW == 3 ) - float unprojectZ = PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, viewZ ); - float penumbraInPixels = centerPenumbra / unprojectZ; - result = saturate( penumbraInPixels / 10.0 ); + #elif( SIGMA_SHOW == SIGMA_SHOW_PENUMBRA_SIZE ) + result = centerPenumbra; // like in SplitScreen #endif + // Update history length for the next frame + historyLength = min( historyLength + 1.0, SIGMA_MAX_ACCUM_FRAME_NUM ); + // Output gOut_Shadow_Translucency[ pixelPos ] = PackShadow( result ); + gOut_HistoryLength[ pixelPos ] = PackViewZAndHistoryLength( viewZ, historyLength ); } diff --git a/Shaders/Resources/REBLUR_PrePass.resources.hlsli b/Shaders/Resources/REBLUR_PrePass.resources.hlsli index fdd111dd..068bd385 100644 --- a/Shaders/Resources/REBLUR_PrePass.resources.hlsli +++ b/Shaders/Resources/REBLUR_PrePass.resources.hlsli @@ -35,7 +35,7 @@ NRD_SAMPLERS_END NRD_OUTPUTS_START NRD_OUTPUT( RWTexture2D, gOut_Diff, u, 0 ) NRD_OUTPUT( RWTexture2D, gOut_Spec, u, 1 ) - NRD_OUTPUT( RWTexture2D, gOut_Spec_HitDistForTracking, u, 2 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecHitDistForTracking, u, 2 ) #ifdef REBLUR_SH NRD_OUTPUT( RWTexture2D, gOut_DiffSh, u, 3 ) NRD_OUTPUT( RWTexture2D, gOut_SpecSh, u, 4 ) @@ -75,7 +75,7 @@ NRD_SAMPLERS_END NRD_OUTPUTS_START NRD_OUTPUT( RWTexture2D, gOut_Spec, u, 0 ) - NRD_OUTPUT( RWTexture2D, gOut_Spec_HitDistForTracking, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecHitDistForTracking, u, 1 ) #ifdef REBLUR_SH NRD_OUTPUT( RWTexture2D, gOut_SpecSh, u, 2 ) #endif diff --git a/Shaders/Resources/REBLUR_TemporalAccumulation.resources.hlsli b/Shaders/Resources/REBLUR_TemporalAccumulation.resources.hlsli index 1a84717d..aa6bf036 100644 --- a/Shaders/Resources/REBLUR_TemporalAccumulation.resources.hlsli +++ b/Shaders/Resources/REBLUR_TemporalAccumulation.resources.hlsli @@ -24,27 +24,27 @@ NRD_SAMPLERS_END NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 1 ) NRD_INPUT( Texture2D, gIn_ViewZ, t, 2 ) NRD_INPUT( Texture2D, gIn_Mv, t, 3 ) - NRD_INPUT( Texture2D, gIn_Prev_ViewZ, t, 4 ) - NRD_INPUT( Texture2D, gIn_Prev_Normal_Roughness, t, 5 ) - NRD_INPUT( Texture2D, gIn_Prev_InternalData, t, 6 ) + NRD_INPUT( Texture2D, gPrev_ViewZ, t, 4 ) + NRD_INPUT( Texture2D, gPrev_Normal_Roughness, t, 5 ) + NRD_INPUT( Texture2D, gPrev_InternalData, t, 6 ) NRD_INPUT( Texture2D, gIn_DisocclusionThresholdMix, t, 7 ) - NRD_INPUT( Texture2D, gIn_Diff_Confidence, t, 8 ) - NRD_INPUT( Texture2D, gIn_Spec_Confidence, t, 9 ) + NRD_INPUT( Texture2D, gIn_DiffConfidence, t, 8 ) + NRD_INPUT( Texture2D, gIn_SpecConfidence, t, 9 ) NRD_INPUT( Texture2D, gIn_Diff, t, 10 ) NRD_INPUT( Texture2D, gIn_Spec, t, 11 ) - NRD_INPUT( Texture2D, gIn_Diff_History, t, 12 ) - NRD_INPUT( Texture2D, gIn_Spec_History, t, 13 ) - NRD_INPUT( Texture2D, gIn_DiffFast_History, t, 14 ) - NRD_INPUT( Texture2D, gIn_SpecFast_History, t, 15 ) - NRD_INPUT( Texture2D, gIn_Prev_Spec_HitDistForTracking, t, 16 ) + NRD_INPUT( Texture2D, gHistory_Diff, t, 12 ) + NRD_INPUT( Texture2D, gHistory_Spec, t, 13 ) + NRD_INPUT( Texture2D, gHistory_DiffFast, t, 14 ) + NRD_INPUT( Texture2D, gHistory_SpecFast, t, 15 ) + NRD_INPUT( Texture2D, gPrev_SpecHitDistForTracking, t, 16 ) #ifndef REBLUR_OCCLUSION - NRD_INPUT( Texture2D, gIn_Spec_HitDistForTracking, t, 17 ) + NRD_INPUT( Texture2D, gIn_SpecHitDistForTracking, t, 17 ) #endif #ifdef REBLUR_SH NRD_INPUT( Texture2D, gIn_DiffSh, t, 18 ) NRD_INPUT( Texture2D, gIn_SpecSh, t, 19 ) - NRD_INPUT( Texture2D, gIn_DiffSh_History, t, 20 ) - NRD_INPUT( Texture2D, gIn_SpecSh_History, t, 21 ) + NRD_INPUT( Texture2D, gHistory_DiffSh, t, 20 ) + NRD_INPUT( Texture2D, gHistory_SpecSh, t, 21 ) #endif NRD_INPUTS_END @@ -53,7 +53,7 @@ NRD_SAMPLERS_END NRD_OUTPUT( RWTexture2D, gOut_Spec, u, 1 ) NRD_OUTPUT( RWTexture2D, gOut_DiffFast, u, 2 ) NRD_OUTPUT( RWTexture2D, gOut_SpecFast, u, 3 ) - NRD_OUTPUT( RWTexture2D, gOut_Spec_HitDistForTracking, u, 4 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecHitDistForTracking, u, 4 ) NRD_OUTPUT( RWTexture2D, gOut_Data1, u, 5 ) #ifndef REBLUR_OCCLUSION NRD_OUTPUT( RWTexture2D, gOut_Data2, u, 6 ) @@ -71,17 +71,17 @@ NRD_SAMPLERS_END NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 1 ) NRD_INPUT( Texture2D, gIn_ViewZ, t, 2 ) NRD_INPUT( Texture2D, gIn_Mv, t, 3 ) - NRD_INPUT( Texture2D, gIn_Prev_ViewZ, t, 4 ) - NRD_INPUT( Texture2D, gIn_Prev_Normal_Roughness, t, 5 ) - NRD_INPUT( Texture2D, gIn_Prev_InternalData, t, 6 ) + NRD_INPUT( Texture2D, gPrev_ViewZ, t, 4 ) + NRD_INPUT( Texture2D, gPrev_Normal_Roughness, t, 5 ) + NRD_INPUT( Texture2D, gPrev_InternalData, t, 6 ) NRD_INPUT( Texture2D, gIn_DisocclusionThresholdMix, t, 7 ) - NRD_INPUT( Texture2D, gIn_Diff_Confidence, t, 8 ) + NRD_INPUT( Texture2D, gIn_DiffConfidence, t, 8 ) NRD_INPUT( Texture2D, gIn_Diff, t, 9 ) - NRD_INPUT( Texture2D, gIn_Diff_History, t, 10 ) - NRD_INPUT( Texture2D, gIn_DiffFast_History, t, 11 ) + NRD_INPUT( Texture2D, gHistory_Diff, t, 10 ) + NRD_INPUT( Texture2D, gHistory_DiffFast, t, 11 ) #ifdef REBLUR_SH NRD_INPUT( Texture2D, gIn_DiffSh, t, 12 ) - NRD_INPUT( Texture2D, gIn_DiffSh_History, t, 13 ) + NRD_INPUT( Texture2D, gHistory_DiffSh, t, 13 ) #endif NRD_INPUTS_END @@ -104,28 +104,28 @@ NRD_SAMPLERS_END NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 1 ) NRD_INPUT( Texture2D, gIn_ViewZ, t, 2 ) NRD_INPUT( Texture2D, gIn_Mv, t, 3 ) - NRD_INPUT( Texture2D, gIn_Prev_ViewZ, t, 4 ) - NRD_INPUT( Texture2D, gIn_Prev_Normal_Roughness, t, 5 ) - NRD_INPUT( Texture2D, gIn_Prev_InternalData, t, 6 ) + NRD_INPUT( Texture2D, gPrev_ViewZ, t, 4 ) + NRD_INPUT( Texture2D, gPrev_Normal_Roughness, t, 5 ) + NRD_INPUT( Texture2D, gPrev_InternalData, t, 6 ) NRD_INPUT( Texture2D, gIn_DisocclusionThresholdMix, t, 7 ) - NRD_INPUT( Texture2D, gIn_Spec_Confidence, t, 8 ) + NRD_INPUT( Texture2D, gIn_SpecConfidence, t, 8 ) NRD_INPUT( Texture2D, gIn_Spec, t, 9 ) - NRD_INPUT( Texture2D, gIn_Spec_History, t, 10 ) - NRD_INPUT( Texture2D, gIn_SpecFast_History, t, 11 ) - NRD_INPUT( Texture2D, gIn_Prev_Spec_HitDistForTracking, t, 12 ) + NRD_INPUT( Texture2D, gHistory_Spec, t, 10 ) + NRD_INPUT( Texture2D, gHistory_SpecFast, t, 11 ) + NRD_INPUT( Texture2D, gPrev_SpecHitDistForTracking, t, 12 ) #ifndef REBLUR_OCCLUSION - NRD_INPUT( Texture2D, gIn_Spec_HitDistForTracking, t, 13 ) + NRD_INPUT( Texture2D, gIn_SpecHitDistForTracking, t, 13 ) #endif #ifdef REBLUR_SH NRD_INPUT( Texture2D, gIn_SpecSh, t, 14 ) - NRD_INPUT( Texture2D, gIn_SpecSh_History, t, 15 ) + NRD_INPUT( Texture2D, gHistory_SpecSh, t, 15 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START NRD_OUTPUT( RWTexture2D, gOut_Spec, u, 0 ) NRD_OUTPUT( RWTexture2D, gOut_SpecFast, u, 1 ) - NRD_OUTPUT( RWTexture2D, gOut_Spec_HitDistForTracking, u, 2 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecHitDistForTracking, u, 2 ) NRD_OUTPUT( RWTexture2D, gOut_Data1, u, 3 ) #ifndef REBLUR_OCCLUSION NRD_OUTPUT( RWTexture2D, gOut_Data2, u, 4 ) diff --git a/Shaders/Resources/REBLUR_TemporalStabilization.resources.hlsli b/Shaders/Resources/REBLUR_TemporalStabilization.resources.hlsli index 9861437a..9bf146a5 100644 --- a/Shaders/Resources/REBLUR_TemporalStabilization.resources.hlsli +++ b/Shaders/Resources/REBLUR_TemporalStabilization.resources.hlsli @@ -28,14 +28,14 @@ NRD_SAMPLERS_END NRD_INPUT( Texture2D, gIn_Data2, t, 5 ) NRD_INPUT( Texture2D, gIn_Diff, t, 6 ) NRD_INPUT( Texture2D, gIn_Spec, t, 7 ) - NRD_INPUT( Texture2D, gIn_Diff_StabilizedHistory, t, 8 ) - NRD_INPUT( Texture2D, gIn_Spec_StabilizedHistory, t, 9 ) - NRD_INPUT( Texture2D, gIn_Spec_HitDistForTracking, t, 10 ) + NRD_INPUT( Texture2D, gHistory_DiffStabilized, t, 8 ) + NRD_INPUT( Texture2D, gHistory_SpecStabilized, t, 9 ) + NRD_INPUT( Texture2D, gIn_SpecHitDistForTracking, t, 10 ) #ifdef REBLUR_SH NRD_INPUT( Texture2D, gIn_DiffSh, t, 11 ) NRD_INPUT( Texture2D, gIn_SpecSh, t, 12 ) - NRD_INPUT( Texture2D, gIn_DiffSh_StabilizedHistory, t, 13 ) - NRD_INPUT( Texture2D, gIn_SpecSh_StabilizedHistory, t, 14 ) + NRD_INPUT( Texture2D, gHistory_DiffShStabilized, t, 13 ) + NRD_INPUT( Texture2D, gHistory_SpecShStabilized, t, 14 ) #endif NRD_INPUTS_END @@ -59,10 +59,10 @@ NRD_SAMPLERS_END NRD_INPUT( Texture2D, gIn_Data1, t, 3 ) NRD_INPUT( Texture2D, gIn_Data2, t, 4 ) NRD_INPUT( Texture2D, gIn_Diff, t, 5 ) - NRD_INPUT( Texture2D, gIn_Diff_StabilizedHistory, t, 6 ) + NRD_INPUT( Texture2D, gHistory_DiffStabilized, t, 6 ) #ifdef REBLUR_SH NRD_INPUT( Texture2D, gIn_DiffSh, t, 7 ) - NRD_INPUT( Texture2D, gIn_DiffSh_StabilizedHistory, t, 8 ) + NRD_INPUT( Texture2D, gHistory_DiffShStabilized, t, 8 ) #endif NRD_INPUTS_END @@ -85,11 +85,11 @@ NRD_SAMPLERS_END NRD_INPUT( Texture2D, gIn_Data1, t, 4 ) NRD_INPUT( Texture2D, gIn_Data2, t, 5 ) NRD_INPUT( Texture2D, gIn_Spec, t, 6 ) - NRD_INPUT( Texture2D, gIn_Spec_StabilizedHistory, t, 7 ) - NRD_INPUT( Texture2D, gIn_Spec_HitDistForTracking, t, 8 ) + NRD_INPUT( Texture2D, gHistory_SpecStabilized, t, 7 ) + NRD_INPUT( Texture2D, gIn_SpecHitDistForTracking, t, 8 ) #ifdef REBLUR_SH NRD_INPUT( Texture2D, gIn_SpecSh, t, 9 ) - NRD_INPUT( Texture2D, gIn_SpecSh_StabilizedHistory, t, 10 ) + NRD_INPUT( Texture2D, gHistory_SpecShStabilized, t, 10 ) #endif NRD_INPUTS_END diff --git a/Shaders/Resources/RELAX_AntiFirefly.resources.hlsli b/Shaders/Resources/RELAX_AntiFirefly.resources.hlsli index 44f78a5b..66387091 100644 --- a/Shaders/Resources/RELAX_AntiFirefly.resources.hlsli +++ b/Shaders/Resources/RELAX_AntiFirefly.resources.hlsli @@ -20,42 +20,42 @@ NRD_SAMPLERS_END #if( defined RELAX_DIFFUSE && defined RELAX_SPECULAR ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gSpecIllumination, t, 1 ) - NRD_INPUT( Texture2D, gDiffIllumination, t, 2 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 3 ) - NRD_INPUT( Texture2D, gViewZ, t, 4 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Spec, t, 1 ) + NRD_INPUT( Texture2D, gIn_Diff, t, 2 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 3 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 4 ) NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutSpecularIllumination, u, 0 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseIllumination, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_Spec, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Diff, u, 1 ) NRD_OUTPUTS_END #elif( defined RELAX_DIFFUSE ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gDiffIllumination, t, 1 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 2 ) - NRD_INPUT(Texture2D, gViewZ, t, 3 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Diff, t, 1 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 2 ) + NRD_INPUT(Texture2D, gIn_ViewZ, t, 3 ) NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutDiffuseIllumination, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Diff, u, 0 ) NRD_OUTPUTS_END #elif( defined RELAX_SPECULAR ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gSpecIllumination, t, 1 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 2 ) - NRD_INPUT( Texture2D, gViewZ, t, 3 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Spec, t, 1 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 2 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 3 ) NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutSpecularIllumination, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Spec, u, 0 ) NRD_OUTPUTS_END #endif diff --git a/Shaders/Resources/RELAX_Atrous.resources.hlsli b/Shaders/Resources/RELAX_Atrous.resources.hlsli index 964918d0..89e16ba2 100644 --- a/Shaders/Resources/RELAX_Atrous.resources.hlsli +++ b/Shaders/Resources/RELAX_Atrous.resources.hlsli @@ -22,70 +22,70 @@ NRD_SAMPLERS_END #if( defined RELAX_DIFFUSE && defined RELAX_SPECULAR ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gSpecIlluminationAndVariance, t, 1 ) - NRD_INPUT( Texture2D, gDiffIlluminationAndVariance, t, 2 ) - NRD_INPUT( Texture2D, gHistoryLength, t, 3 ) - NRD_INPUT( Texture2D, gSpecReprojectionConfidence, t, 4 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 5 ) - NRD_INPUT( Texture2D, gViewZ, t, 6 ) - NRD_INPUT( Texture2D, gSpecConfidence, t, 7 ) - NRD_INPUT( Texture2D, gDiffConfidence, t, 8 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Spec_Variance, t, 1 ) + NRD_INPUT( Texture2D, gIn_Diff_Variance, t, 2 ) + NRD_INPUT( Texture2D, gIn_HistoryLength, t, 3 ) + NRD_INPUT( Texture2D, gIn_SpecReprojectionConfidence, t, 4 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 5 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 6 ) + NRD_INPUT( Texture2D, gIn_SpecConfidence, t, 7 ) + NRD_INPUT( Texture2D, gIn_DiffConfidence, t, 8 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gSpecSH1, t, 9 ) - NRD_INPUT( Texture2D, gDiffSH1, t, 10 ) + NRD_INPUT( Texture2D, gIn_SpecSh, t, 9 ) + NRD_INPUT( Texture2D, gIn_DiffSh, t, 10 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutSpecularIlluminationAndVariance, u, 0 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseIlluminationAndVariance, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_Spec_Variance, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Diff_Variance, u, 1 ) #ifdef RELAX_SH - NRD_OUTPUT( RWTexture2D, gOutSpecularSH1, u, 2 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseSH1, u, 3 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecSh, u, 2 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffSh, u, 3 ) #endif NRD_OUTPUTS_END #elif( defined RELAX_DIFFUSE ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gDiffIlluminationAndVariance, t, 1 ) - NRD_INPUT( Texture2D, gHistoryLength, t, 2 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 3 ) - NRD_INPUT( Texture2D, gViewZ, t, 4 ) - NRD_INPUT( Texture2D, gDiffConfidence, t, 5 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Diff_Variance, t, 1 ) + NRD_INPUT( Texture2D, gIn_HistoryLength, t, 2 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 3 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 4 ) + NRD_INPUT( Texture2D, gIn_DiffConfidence, t, 5 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gDiffSH1, t, 6 ) + NRD_INPUT( Texture2D, gIn_DiffSh, t, 6 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutDiffuseIlluminationAndVariance, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Diff_Variance, u, 0 ) #ifdef RELAX_SH - NRD_OUTPUT( RWTexture2D, gOutDiffuseSH1, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffSh, u, 1 ) #endif NRD_OUTPUTS_END #elif( defined RELAX_SPECULAR ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gSpecIlluminationAndVariance, t, 1 ) - NRD_INPUT( Texture2D, gHistoryLength, t, 2 ) - NRD_INPUT( Texture2D, gSpecReprojectionConfidence, t, 3 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 4 ) - NRD_INPUT( Texture2D, gViewZ, t, 5 ) - NRD_INPUT( Texture2D, gSpecConfidence, t, 6 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Spec_Variance, t, 1 ) + NRD_INPUT( Texture2D, gIn_HistoryLength, t, 2 ) + NRD_INPUT( Texture2D, gIn_SpecReprojectionConfidence, t, 3 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 4 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 5 ) + NRD_INPUT( Texture2D, gIn_SpecConfidence, t, 6 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gSpecSH1, t, 7 ) + NRD_INPUT( Texture2D, gIn_SpecSh, t, 7 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutSpecularIlluminationAndVariance, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Spec_Variance, u, 0 ) #ifdef RELAX_SH - NRD_OUTPUT( RWTexture2D, gOutSpecularSH1, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecSh, u, 1 ) #endif NRD_OUTPUTS_END diff --git a/Shaders/Resources/RELAX_AtrousSmem.resources.hlsli b/Shaders/Resources/RELAX_AtrousSmem.resources.hlsli index 82bd33d8..c52cdc11 100644 --- a/Shaders/Resources/RELAX_AtrousSmem.resources.hlsli +++ b/Shaders/Resources/RELAX_AtrousSmem.resources.hlsli @@ -22,30 +22,30 @@ NRD_SAMPLERS_END #if( defined RELAX_DIFFUSE && defined RELAX_SPECULAR ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gSpecIlluminationAnd2ndMoment, t, 1 ) - NRD_INPUT( Texture2D, gDiffIlluminationAnd2ndMoment, t, 2 ) - NRD_INPUT( Texture2D, gHistoryLength, t, 3 ) - NRD_INPUT( Texture2D, gSpecReprojectionConfidence, t, 4 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 5 ) - NRD_INPUT( Texture2D, gViewZ, t, 6 ) - NRD_INPUT( Texture2D, gSpecConfidence, t, 7 ) - NRD_INPUT( Texture2D, gDiffConfidence, t, 8 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Spec_Variance, t, 1 ) + NRD_INPUT( Texture2D, gIn_Diff_Variance, t, 2 ) + NRD_INPUT( Texture2D, gIn_HistoryLength, t, 3 ) + NRD_INPUT( Texture2D, gIn_SpecReprojectionConfidence, t, 4 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 5 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 6 ) + NRD_INPUT( Texture2D, gIn_SpecConfidence, t, 7 ) + NRD_INPUT( Texture2D, gIn_DiffConfidence, t, 8 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gSpecSH1, t, 9 ) - NRD_INPUT( Texture2D, gDiffSH1, t, 10 ) + NRD_INPUT( Texture2D, gIn_SpecSh, t, 9 ) + NRD_INPUT( Texture2D, gIn_DiffSh, t, 10 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutSpecularIlluminationAndVariance, u, 0 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseIlluminationAndVariance, u, 1 ) - NRD_OUTPUT( RWTexture2D, gOutNormalRoughness, u, 2 ) - NRD_OUTPUT( RWTexture2D, gOutMaterialID, u, 3 ) - NRD_OUTPUT( RWTexture2D, gOutViewZ, u, 4 ) + NRD_OUTPUT( RWTexture2D, gOut_Spec_Variance, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Diff_Variance, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_NormalRoughness, u, 2 ) + NRD_OUTPUT( RWTexture2D, gOut_MaterialID, u, 3 ) + NRD_OUTPUT( RWTexture2D, gOut_ViewZ, u, 4 ) #ifdef RELAX_SH - NRD_OUTPUT( RWTexture2D, gOutSpecularSH1, u, 5 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseSH1, u, 6 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecSh, u, 5 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffSh, u, 6 ) #endif NRD_OUTPUTS_END @@ -53,49 +53,49 @@ NRD_SAMPLERS_END #elif( defined RELAX_DIFFUSE ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gDiffIlluminationAnd2ndMoment, t, 1 ) - NRD_INPUT( Texture2D, gHistoryLength, t, 2 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 3 ) - NRD_INPUT( Texture2D, gViewZ, t, 4 ) - NRD_INPUT( Texture2D, gDiffConfidence, t, 5 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Diff_Variance, t, 1 ) + NRD_INPUT( Texture2D, gIn_HistoryLength, t, 2 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 3 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 4 ) + NRD_INPUT( Texture2D, gIn_DiffConfidence, t, 5 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gDiffSH1, t, 6 ) + NRD_INPUT( Texture2D, gIn_DiffSh, t, 6 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutDiffuseIlluminationAndVariance, u, 0 ) - NRD_OUTPUT( RWTexture2D, gOutNormalRoughness, u, 1 ) - NRD_OUTPUT( RWTexture2D, gOutMaterialID, u, 2 ) - NRD_OUTPUT( RWTexture2D, gOutViewZ, u, 3 ) + NRD_OUTPUT( RWTexture2D, gOut_Diff_Variance, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_NormalRoughness, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_MaterialID, u, 2 ) + NRD_OUTPUT( RWTexture2D, gOut_ViewZ, u, 3 ) #ifdef RELAX_SH - NRD_OUTPUT( RWTexture2D, gOutDiffuseSH1, u, 4 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffSh, u, 4 ) #endif NRD_OUTPUTS_END #elif( defined RELAX_SPECULAR ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gSpecIlluminationAnd2ndMoment, t, 1 ) - NRD_INPUT( Texture2D, gHistoryLength, t, 2 ) - NRD_INPUT( Texture2D, gSpecReprojectionConfidence, t, 3 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 4 ) - NRD_INPUT( Texture2D, gViewZ, t, 5 ) - NRD_INPUT( Texture2D, gSpecConfidence, t, 6 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Spec_Variance, t, 1 ) + NRD_INPUT( Texture2D, gIn_HistoryLength, t, 2 ) + NRD_INPUT( Texture2D, gIn_SpecReprojectionConfidence, t, 3 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 4 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 5 ) + NRD_INPUT( Texture2D, gIn_SpecConfidence, t, 6 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gSpecSH1, t, 7 ) + NRD_INPUT( Texture2D, gIn_SpecSh, t, 7 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutSpecularIlluminationAndVariance, u, 0 ) - NRD_OUTPUT( RWTexture2D, gOutNormalRoughness, u, 1 ) - NRD_OUTPUT( RWTexture2D, gOutMaterialID, u, 2 ) - NRD_OUTPUT( RWTexture2D, gOutViewZ, u, 3 ) + NRD_OUTPUT( RWTexture2D, gOut_Spec_Variance, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_NormalRoughness, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_MaterialID, u, 2 ) + NRD_OUTPUT( RWTexture2D, gOut_ViewZ, u, 3 ) #ifdef RELAX_SH - NRD_OUTPUT( RWTexture2D, gOutSpecularSH1, u, 4 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecSh, u, 4 ) #endif NRD_OUTPUTS_END diff --git a/Shaders/Resources/RELAX_Copy.resources.hlsli b/Shaders/Resources/RELAX_Copy.resources.hlsli index a8091ba1..71382e70 100644 --- a/Shaders/Resources/RELAX_Copy.resources.hlsli +++ b/Shaders/Resources/RELAX_Copy.resources.hlsli @@ -20,33 +20,33 @@ NRD_SAMPLERS_END #if( defined RELAX_DIFFUSE && defined RELAX_SPECULAR ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gSpecIllumination, t, 0 ) - NRD_INPUT( Texture2D, gDiffIllumination, t, 1 ) + NRD_INPUT( Texture2D, gIn_Spec, t, 0 ) + NRD_INPUT( Texture2D, gIn_Diff, t, 1 ) NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutSpecularIllumination, u, 0 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseIllumination, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_Spec, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Diff, u, 1 ) NRD_OUTPUTS_END #elif( defined RELAX_DIFFUSE ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gDiffIllumination, t, 0 ) + NRD_INPUT( Texture2D, gIn_Diff, t, 0 ) NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutDiffuseIllumination, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Diff, u, 0 ) NRD_OUTPUTS_END #elif( defined RELAX_SPECULAR ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gSpecIllumination, t, 0 ) + NRD_INPUT( Texture2D, gIn_Spec, t, 0 ) NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutSpecularIllumination, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Spec, u, 0 ) NRD_OUTPUTS_END #endif diff --git a/Shaders/Resources/RELAX_HistoryClamping.resources.hlsli b/Shaders/Resources/RELAX_HistoryClamping.resources.hlsli index f3aa5ecd..ac0c88a7 100644 --- a/Shaders/Resources/RELAX_HistoryClamping.resources.hlsli +++ b/Shaders/Resources/RELAX_HistoryClamping.resources.hlsli @@ -20,81 +20,81 @@ NRD_SAMPLERS_END #if( defined RELAX_DIFFUSE && defined RELAX_SPECULAR ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gNoisySpecularIllumination, t, 1 ) - NRD_INPUT( Texture2D, gNoisyDiffuseIllumination, t, 2 ) - NRD_INPUT( Texture2D, gSpecIllumination, t, 3 ) - NRD_INPUT( Texture2D, gDiffIllumination, t, 4 ) - NRD_INPUT( Texture2D, gSpecIlluminationResponsive, t, 5 ) - NRD_INPUT( Texture2D, gDiffIlluminationResponsive, t, 6 ) - NRD_INPUT( Texture2D, gHistoryLength, t, 7 ) + 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 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gSpecSH1, t, 8 ) - NRD_INPUT( Texture2D, gDiffSH1, t, 9 ) - NRD_INPUT( Texture2D, gSpecResponsiveSH1, t, 10 ) - NRD_INPUT( Texture2D, gDiffResponsiveSH1, t, 11 ) + 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 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutSpecularIllumination, u, 0 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseIllumination, u, 1 ) - NRD_OUTPUT( RWTexture2D, gOutSpecularIlluminationResponsive, u, 2 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseIlluminationResponsive, u, 3 ) - NRD_OUTPUT( RWTexture2D, gOutHistoryLength, u, 4 ) + NRD_OUTPUT( RWTexture2D, gOut_Spec, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Diff, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecFast, u, 2 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffFast, u, 3 ) + NRD_OUTPUT( RWTexture2D, gOut_HistoryLength, u, 4 ) #ifdef RELAX_SH - NRD_OUTPUT( RWTexture2D, gOutSpecularSH1, u, 5 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseSH1, u, 6 ) - NRD_OUTPUT( RWTexture2D, gOutSpecularResponsiveSH1, u, 7 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseResponsiveSH1, u, 8 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecSh, u, 5 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffSh, u, 6 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecShFast, u, 7 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffShFast, u, 8 ) #endif NRD_OUTPUTS_END #elif( defined RELAX_DIFFUSE ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gNoisyDiffuseIllumination, t, 1 ) - NRD_INPUT( Texture2D, gDiffIllumination, t, 2 ) - NRD_INPUT( Texture2D, gDiffIlluminationResponsive, t, 3 ) - NRD_INPUT( Texture2D, gHistoryLength, t, 4 ) + 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 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gDiffSH1, t, 5 ) - NRD_INPUT( Texture2D, gDiffResponsiveSH1, t, 6 ) + NRD_INPUT( Texture2D, gIn_DiffSh, t, 5 ) + NRD_INPUT( Texture2D, gIn_DiffShFast, t, 6 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutDiffuseIllumination, u, 0 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseIlluminationResponsive, u, 1 ) - NRD_OUTPUT( RWTexture2D, gOutHistoryLength, u, 2 ) + NRD_OUTPUT( RWTexture2D, gOut_Diff, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffFast, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_HistoryLength, u, 2 ) #ifdef RELAX_SH - NRD_OUTPUT( RWTexture2D, gOutDiffuseSH1, u, 3 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseResponsiveSH1, u, 4 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffSh, u, 3 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffShFast, u, 4 ) #endif NRD_OUTPUTS_END #elif( defined RELAX_SPECULAR ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gNoisySpecularIllumination, t, 1 ) - NRD_INPUT( Texture2D, gSpecIllumination, t, 2 ) - NRD_INPUT( Texture2D, gSpecIlluminationResponsive, t, 3 ) - NRD_INPUT( Texture2D, gHistoryLength, t, 4 ) + 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 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gSpecSH1, t, 5 ) - NRD_INPUT( Texture2D, gSpecResponsiveSH1, t, 6 ) + NRD_INPUT( Texture2D, gIn_SpecSh, t, 5 ) + NRD_INPUT( Texture2D, gIn_SpecShFast, t, 6 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutSpecularIllumination, u, 0 ) - NRD_OUTPUT( RWTexture2D, gOutSpecularIlluminationResponsive, u, 1 ) - NRD_OUTPUT( RWTexture2D, gOutHistoryLength, u, 2 ) + NRD_OUTPUT( RWTexture2D, gOut_Spec, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecFast, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_HistoryLength, u, 2 ) #ifdef RELAX_SH - NRD_OUTPUT( RWTexture2D, gOutSpecularSH1, u, 3 ) - NRD_OUTPUT( RWTexture2D, gOutSpecularResponsiveSH1, u, 4 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecSh, u, 3 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecShFast, u, 4 ) #endif NRD_OUTPUTS_END diff --git a/Shaders/Resources/RELAX_HistoryFix.resources.hlsli b/Shaders/Resources/RELAX_HistoryFix.resources.hlsli index 70da9f2f..a9cc898e 100644 --- a/Shaders/Resources/RELAX_HistoryFix.resources.hlsli +++ b/Shaders/Resources/RELAX_HistoryFix.resources.hlsli @@ -20,64 +20,64 @@ NRD_SAMPLERS_END #if( defined RELAX_DIFFUSE && defined RELAX_SPECULAR ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gSpecIllumination, t, 1 ) - NRD_INPUT( Texture2D, gDiffIllumination, t, 2 ) - NRD_INPUT( Texture2D, gHistoryLength, t, 3 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 4 ) - NRD_INPUT( Texture2D, gViewZ, t, 5 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Spec, t, 1 ) + NRD_INPUT( Texture2D, gIn_Diff, t, 2 ) + NRD_INPUT( Texture2D, gIn_HistoryLength, t, 3 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 4 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 5 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gSpecSH1, t, 6 ) - NRD_INPUT( Texture2D, gDiffSH1, t, 7 ) + NRD_INPUT( Texture2D, gIn_SpecSh, t, 6 ) + NRD_INPUT( Texture2D, gIn_DiffSh, t, 7 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutSpecularIllumination, u, 0 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseIllumination, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_Spec, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Diff, u, 1 ) #ifdef RELAX_SH - NRD_OUTPUT( RWTexture2D, gOutSpecularSH1, u, 2 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseSH1, u, 3 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecSh, u, 2 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffSh, u, 3 ) #endif NRD_OUTPUTS_END #elif( defined RELAX_DIFFUSE ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gDiffIllumination, t, 1 ) - NRD_INPUT( Texture2D, gHistoryLength, t, 2 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 3 ) - NRD_INPUT( Texture2D, gViewZ, t, 4 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Diff, t, 1 ) + NRD_INPUT( Texture2D, gIn_HistoryLength, t, 2 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 3 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 4 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gDiffSH1, t, 5 ) + NRD_INPUT( Texture2D, gIn_DiffSh, t, 5 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutDiffuseIllumination, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Diff, u, 0 ) #ifdef RELAX_SH - NRD_OUTPUT( RWTexture2D, gOutDiffuseSH1, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffSh, u, 1 ) #endif NRD_OUTPUTS_END #elif( defined RELAX_SPECULAR ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gSpecIllumination, t, 1 ) - NRD_INPUT( Texture2D, gHistoryLength, t, 2 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 3 ) - NRD_INPUT( Texture2D, gViewZ, t, 4 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Spec, t, 1 ) + NRD_INPUT( Texture2D, gIn_HistoryLength, t, 2 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 3 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 4 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gSpecSH1, t, 5 ) + NRD_INPUT( Texture2D, gIn_SpecSh, t, 5 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutSpecularIllumination, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Spec, u, 0 ) #ifdef RELAX_SH - NRD_OUTPUT( RWTexture2D, gOutSpecularSH1, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecSh, u, 1 ) #endif NRD_OUTPUTS_END diff --git a/Shaders/Resources/RELAX_HitDistReconstruction.resources.hlsli b/Shaders/Resources/RELAX_HitDistReconstruction.resources.hlsli index 15569e32..25770ef9 100644 --- a/Shaders/Resources/RELAX_HitDistReconstruction.resources.hlsli +++ b/Shaders/Resources/RELAX_HitDistReconstruction.resources.hlsli @@ -19,42 +19,42 @@ NRD_SAMPLERS_END #if( defined RELAX_DIFFUSE && defined RELAX_SPECULAR ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gSpecIllumination, t, 1 ) - NRD_INPUT( Texture2D, gDiffIllumination, t, 2 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 3 ) - NRD_INPUT( Texture2D, gViewZ, t, 4 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Spec, t, 1 ) + NRD_INPUT( Texture2D, gIn_Diff, t, 2 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 3 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 4 ) NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutSpecularIllumination, u, 0 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseIllumination, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_Spec, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Diff, u, 1 ) NRD_OUTPUTS_END #elif( defined RELAX_DIFFUSE ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gDiffIllumination, t, 1 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 2 ) - NRD_INPUT( Texture2D, gViewZ, t, 3 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Diff, t, 1 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 2 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 3 ) NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutDiffuseIllumination, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Diff, u, 0 ) NRD_OUTPUTS_END #elif( defined RELAX_SPECULAR ) NRD_INPUTS_START - NRD_INPUT(Texture2D, gTiles, t, 0) - NRD_INPUT( Texture2D, gSpecIllumination, t, 1 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 2 ) - NRD_INPUT( Texture2D, gViewZ, t, 3 ) + NRD_INPUT(Texture2D, gIn_Tiles, t, 0) + NRD_INPUT( Texture2D, gIn_Spec, t, 1 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 2 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 3 ) NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutSpecularIllumination, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Spec, u, 0 ) NRD_OUTPUTS_END #endif diff --git a/Shaders/Resources/RELAX_PrePass.resources.hlsli b/Shaders/Resources/RELAX_PrePass.resources.hlsli index d75c2c6c..bfd1ccf5 100644 --- a/Shaders/Resources/RELAX_PrePass.resources.hlsli +++ b/Shaders/Resources/RELAX_PrePass.resources.hlsli @@ -21,61 +21,61 @@ NRD_SAMPLERS_END #if( defined RELAX_DIFFUSE && defined RELAX_SPECULAR ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gSpecIllumination, t, 1 ) - NRD_INPUT( Texture2D, gDiffIllumination, t, 2 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 3 ) - NRD_INPUT( Texture2D, gViewZ, t, 4 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Spec, t, 1 ) + NRD_INPUT( Texture2D, gIn_Diff, t, 2 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 3 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 4 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gSpecSH1, t, 5 ) - NRD_INPUT( Texture2D, gDiffSH1, t, 6 ) + NRD_INPUT( Texture2D, gIn_SpecSh, t, 5 ) + NRD_INPUT( Texture2D, gIn_DiffSh, t, 6 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutSpecularIllumination, u, 0 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseIllumination, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_Spec, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Diff, u, 1 ) #ifdef RELAX_SH - NRD_OUTPUT( RWTexture2D, gOutSpecularSH1, u, 2 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseSH1, u, 3 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecSh, u, 2 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffSh, u, 3 ) #endif NRD_OUTPUTS_END #elif( defined RELAX_DIFFUSE ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gDiffIllumination, t, 1 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 2 ) - NRD_INPUT( Texture2D, gViewZ, t, 3 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Diff, t, 1 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 2 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 3 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gDiffSH1, t, 4 ) + NRD_INPUT( Texture2D, gIn_DiffSh, t, 4 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutDiffuseIllumination, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Diff, u, 0 ) #ifdef RELAX_SH - NRD_OUTPUT( RWTexture2D, gOutDiffuseSH1, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffSh, u, 1 ) #endif NRD_OUTPUTS_END #elif( defined RELAX_SPECULAR ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gSpecIllumination, t, 1 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 2 ) - NRD_INPUT( Texture2D, gViewZ, t, 3 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Spec, t, 1 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 2 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 3 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gSpecSH1, t, 4 ) + NRD_INPUT( Texture2D, gIn_SpecSh, t, 4 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutSpecularIllumination, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Spec, u, 0 ) #ifdef RELAX_SH - NRD_OUTPUT( RWTexture2D, gOutSpecularSH1, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecSh, u, 1 ) #endif NRD_OUTPUTS_END diff --git a/Shaders/Resources/RELAX_TemporalAccumulation.resources.hlsli b/Shaders/Resources/RELAX_TemporalAccumulation.resources.hlsli index 6189d7df..275acc54 100644 --- a/Shaders/Resources/RELAX_TemporalAccumulation.resources.hlsli +++ b/Shaders/Resources/RELAX_TemporalAccumulation.resources.hlsli @@ -20,116 +20,116 @@ NRD_SAMPLERS_END #if( defined RELAX_DIFFUSE && defined RELAX_SPECULAR ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gSpecIllumination, t, 1 ) - NRD_INPUT( Texture2D, gDiffIllumination, t, 2 ) - NRD_INPUT( Texture2D, gMv, t, 3 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 4 ) - NRD_INPUT( Texture2D, gViewZ, t, 5 ) - NRD_INPUT( Texture2D, gPrevSpecularIlluminationResponsive, t, 6 ) - NRD_INPUT( Texture2D, gPrevDiffuseIlluminationResponsive, t, 7 ) - NRD_INPUT( Texture2D, gPrevSpecularIllumination, t, 8 ) - NRD_INPUT( Texture2D, gPrevDiffuseIllumination, t, 9 ) - NRD_INPUT( Texture2D, gPrevNormalRoughness, t, 10 ) - NRD_INPUT( Texture2D, gPrevViewZ, t, 11 ) - NRD_INPUT( Texture2D, gPrevReflectionHitT, t, 12 ) - NRD_INPUT( Texture2D, gPrevHistoryLength, t, 13 ) - NRD_INPUT( Texture2D, gPrevMaterialID, t, 14 ) - NRD_INPUT( Texture2D, gSpecConfidence, t, 15 ) - NRD_INPUT( Texture2D, gDiffConfidence, t, 16 ) - NRD_INPUT( Texture2D, gDisocclusionThresholdMix, t, 17 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Spec, t, 1 ) + NRD_INPUT( Texture2D, gIn_Diff, t, 2 ) + NRD_INPUT( Texture2D, gIn_Mv, t, 3 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 4 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 5 ) + NRD_INPUT( Texture2D, gHistory_SpecFast, t, 6 ) + NRD_INPUT( Texture2D, gHistory_DiffFast, t, 7 ) + NRD_INPUT( Texture2D, gHistory_Spec, t, 8 ) + NRD_INPUT( Texture2D, gHistory_Diff, t, 9 ) + NRD_INPUT( Texture2D, gPrev_Normal_Roughness, t, 10 ) + NRD_INPUT( Texture2D, gPrev_ViewZ, t, 11 ) + NRD_INPUT( Texture2D, gPrev_SpecHitDist, t, 12 ) + NRD_INPUT( Texture2D, gPrev_HistoryLength, t, 13 ) + NRD_INPUT( Texture2D, gPrev_MateriallID, t, 14 ) + NRD_INPUT( Texture2D, gIn_SpecConfidence, t, 15 ) + NRD_INPUT( Texture2D, gIn_DiffConfidence, t, 16 ) + NRD_INPUT( Texture2D, gIn_DisocclusionThresholdMix, t, 17 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gSpecSH1, t, 18 ) - NRD_INPUT( Texture2D, gDiffSH1, t, 19 ) - NRD_INPUT( Texture2D, gPrevSpecularResponsiveSH1, t, 20 ) - NRD_INPUT( Texture2D, gPrevDiffuseResponsiveSH1, t, 21 ) - NRD_INPUT( Texture2D, gPrevSpecularSH1, t, 22 ) - NRD_INPUT( Texture2D, gPrevDiffuseSH1, t, 23 ) + NRD_INPUT( Texture2D, gIn_SpecSh, t, 18 ) + NRD_INPUT( Texture2D, gIn_DiffSh, t, 19 ) + NRD_INPUT( Texture2D, gHistory_SpecShFast, t, 20 ) + NRD_INPUT( Texture2D, gHistory_DiffShFast, t, 21 ) + NRD_INPUT( Texture2D, gHistory_SpecSh, t, 22 ) + NRD_INPUT( Texture2D, gHistory_DiffSh, t, 23 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutSpecularIllumination, u, 0 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseIllumination, u, 1 ) - NRD_OUTPUT( RWTexture2D, gOutSpecularIlluminationResponsive, u, 2 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseIlluminationResponsive, u, 3 ) - NRD_OUTPUT( RWTexture2D, gOutReflectionHitT, u, 4 ) - NRD_OUTPUT( RWTexture2D, gOutHistoryLength, u, 5 ) - NRD_OUTPUT( RWTexture2D, gOutSpecularReprojectionConfidence, u, 6 ) + NRD_OUTPUT( RWTexture2D, gOut_Spec, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_Diff, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecFast, u, 2 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffFast, u, 3 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecHitDist, u, 4 ) + NRD_OUTPUT( RWTexture2D, gOut_HistoryLength, u, 5 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecReprojectionConfidence, u, 6 ) #ifdef RELAX_SH - NRD_OUTPUT( RWTexture2D, gOutSpecularSH1, u, 7 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseSH1, u, 8 ) - NRD_OUTPUT( RWTexture2D, gOutSpecularResponsiveSH1, u, 9 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseResponsiveSH1, u, 10 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecSh, u, 7 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffSh, u, 8 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecShFast, u, 9 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffShFast, u, 10 ) #endif NRD_OUTPUTS_END #elif( defined RELAX_DIFFUSE ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gDiffIllumination, t, 1 ) - NRD_INPUT( Texture2D, gMv, t, 2 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 3 ) - NRD_INPUT( Texture2D, gViewZ, t, 4 ) - NRD_INPUT( Texture2D, gPrevDiffuseIlluminationResponsive, t, 5 ) - NRD_INPUT( Texture2D, gPrevDiffuseIllumination, t, 6 ) - NRD_INPUT( Texture2D, gPrevNormalRoughness, t, 7 ) - NRD_INPUT( Texture2D, gPrevViewZ, t, 8 ) - NRD_INPUT( Texture2D, gPrevHistoryLength, t, 9 ) - NRD_INPUT( Texture2D, gPrevMaterialID, t, 10 ) - NRD_INPUT( Texture2D, gDiffConfidence, t, 11 ) - NRD_INPUT( Texture2D, gDisocclusionThresholdMix, t, 12) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Diff, t, 1 ) + NRD_INPUT( Texture2D, gIn_Mv, t, 2 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 3 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 4 ) + NRD_INPUT( Texture2D, gHistory_DiffFast, t, 5 ) + NRD_INPUT( Texture2D, gHistory_Diff, t, 6 ) + NRD_INPUT( Texture2D, gPrev_Normal_Roughness, t, 7 ) + NRD_INPUT( Texture2D, gPrev_ViewZ, t, 8 ) + NRD_INPUT( Texture2D, gPrev_HistoryLength, t, 9 ) + NRD_INPUT( Texture2D, gPrev_MateriallID, t, 10 ) + NRD_INPUT( Texture2D, gIn_DiffConfidence, t, 11 ) + NRD_INPUT( Texture2D, gIn_DisocclusionThresholdMix, t, 12) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gDiffSH1, t, 13 ) - NRD_INPUT( Texture2D, gPrevDiffuseResponsiveSH1, t, 14 ) - NRD_INPUT( Texture2D, gPrevDiffuseSH1, t, 15 ) + NRD_INPUT( Texture2D, gIn_DiffSh, t, 13 ) + NRD_INPUT( Texture2D, gHistory_DiffShFast, t, 14 ) + NRD_INPUT( Texture2D, gHistory_DiffSh, t, 15 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutDiffuseIllumination, u, 0 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseIlluminationResponsive, u, 1 ) - NRD_OUTPUT( RWTexture2D, gOutHistoryLength, u, 2 ) + NRD_OUTPUT( RWTexture2D, gOut_Diff, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffFast, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_HistoryLength, u, 2 ) #ifdef RELAX_SH - NRD_OUTPUT( RWTexture2D, gOutDiffuseSH1, u, 3 ) - NRD_OUTPUT( RWTexture2D, gOutDiffuseResponsiveSH1, u, 4 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffSh, u, 3 ) + NRD_OUTPUT( RWTexture2D, gOut_DiffShFast, u, 4 ) #endif NRD_OUTPUTS_END #elif( defined RELAX_SPECULAR ) NRD_INPUTS_START - NRD_INPUT( Texture2D, gTiles, t, 0 ) - NRD_INPUT( Texture2D, gSpecIllumination, t, 1 ) - NRD_INPUT( Texture2D, gMv, t, 2 ) - NRD_INPUT( Texture2D, gNormalRoughness, t, 3 ) - NRD_INPUT( Texture2D, gViewZ, t, 4 ) - NRD_INPUT( Texture2D, gPrevSpecularIlluminationResponsive, t, 5 ) - NRD_INPUT( Texture2D, gPrevSpecularIllumination, t, 6 ) - NRD_INPUT( Texture2D, gPrevNormalRoughness, t, 7 ) - NRD_INPUT( Texture2D, gPrevViewZ, t, 8 ) - NRD_INPUT( Texture2D, gPrevReflectionHitT, t, 9 ) - NRD_INPUT( Texture2D, gPrevHistoryLength, t, 10 ) - NRD_INPUT( Texture2D, gPrevMaterialID, t, 11 ) - NRD_INPUT( Texture2D, gSpecConfidence, t, 12 ) - NRD_INPUT( Texture2D, gDisocclusionThresholdMix, t, 13 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_Spec, t, 1 ) + NRD_INPUT( Texture2D, gIn_Mv, t, 2 ) + NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 3 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 4 ) + NRD_INPUT( Texture2D, gHistory_SpecFast, t, 5 ) + NRD_INPUT( Texture2D, gHistory_Spec, t, 6 ) + NRD_INPUT( Texture2D, gPrev_Normal_Roughness, t, 7 ) + NRD_INPUT( Texture2D, gPrev_ViewZ, t, 8 ) + NRD_INPUT( Texture2D, gPrev_SpecHitDist, t, 9 ) + NRD_INPUT( Texture2D, gPrev_HistoryLength, t, 10 ) + NRD_INPUT( Texture2D, gPrev_MateriallID, t, 11 ) + NRD_INPUT( Texture2D, gIn_SpecConfidence, t, 12 ) + NRD_INPUT( Texture2D, gIn_DisocclusionThresholdMix, t, 13 ) #ifdef RELAX_SH - NRD_INPUT( Texture2D, gSpecSH1, t, 14 ) - NRD_INPUT( Texture2D, gPrevSpecularResponsiveSH1, t, 15 ) - NRD_INPUT( Texture2D, gPrevSpecularSH1, t, 16 ) + NRD_INPUT( Texture2D, gIn_SpecSh, t, 14 ) + NRD_INPUT( Texture2D, gHistory_SpecShFast, t, 15 ) + NRD_INPUT( Texture2D, gHistory_SpecSh, t, 16 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOutSpecularIllumination, u, 0 ) - NRD_OUTPUT( RWTexture2D, gOutSpecularIlluminationResponsive, u, 1 ) - NRD_OUTPUT( RWTexture2D, gOutReflectionHitT, u, 2 ) - NRD_OUTPUT( RWTexture2D, gOutHistoryLength, u, 3 ) - NRD_OUTPUT( RWTexture2D, gOutSpecularReprojectionConfidence, u, 4 ) + NRD_OUTPUT( RWTexture2D, gOut_Spec, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecFast, u, 1 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecHitDist, u, 2 ) + NRD_OUTPUT( RWTexture2D, gOut_HistoryLength, u, 3 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecReprojectionConfidence, u, 4 ) #ifdef RELAX_SH - NRD_OUTPUT( RWTexture2D, gOutSpecularSH1, u, 5 ) - NRD_OUTPUT( RWTexture2D, gOutSpecularResponsiveSH1, u, 6 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecSh, u, 5 ) + NRD_OUTPUT( RWTexture2D, gOut_SpecShFast, u, 6 ) #endif NRD_OUTPUTS_END diff --git a/Shaders/Resources/SIGMA_Blur.resources.hlsli b/Shaders/Resources/SIGMA_Blur.resources.hlsli index 9f47b3fc..2a6433d1 100644 --- a/Shaders/Resources/SIGMA_Blur.resources.hlsli +++ b/Shaders/Resources/SIGMA_Blur.resources.hlsli @@ -23,12 +23,7 @@ NRD_INPUTS_START NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 1 ) NRD_INPUT( Texture2D, gIn_Penumbra, t, 2 ) NRD_INPUT( Texture2D, gIn_Tiles, t, 3 ) - #ifdef SIGMA_FIRST_PASS - NRD_INPUT( Texture2D, gIn_History, t, 4 ) - #ifdef SIGMA_TRANSLUCENT - NRD_INPUT( Texture2D, gIn_Shadow_Translucency, t, 5 ) - #endif - #else + #if( defined SIGMA_TRANSLUCENT || !defined SIGMA_FIRST_PASS ) NRD_INPUT( Texture2D, gIn_Shadow_Translucency, t, 4 ) #endif NRD_INPUTS_END @@ -36,9 +31,6 @@ NRD_INPUTS_END NRD_OUTPUTS_START NRD_OUTPUT( RWTexture2D, gOut_Penumbra, u, 0 ) NRD_OUTPUT( RWTexture2D, gOut_Shadow_Translucency, u, 1 ) - #ifdef SIGMA_FIRST_PASS - NRD_OUTPUT( RWTexture2D, gOut_History, u, 2 ) - #endif NRD_OUTPUTS_END // Macro magic diff --git a/Shaders/Resources/SIGMA_Copy.resources.hlsli b/Shaders/Resources/SIGMA_Copy.resources.hlsli new file mode 100644 index 00000000..2c17f5f4 --- /dev/null +++ b/Shaders/Resources/SIGMA_Copy.resources.hlsli @@ -0,0 +1,34 @@ +/* +Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + +NVIDIA CORPORATION and its licensors retain all intellectual property +and proprietary rights in and to this software, related documentation +and any modifications thereto. Any use, reproduction, disclosure or +distribution of this software and related documentation without an express +license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +NRD_CONSTANTS_START( SIGMA_CopyConstants ) + SIGMA_SHARED_CONSTANTS +NRD_CONSTANTS_END + +NRD_INPUTS_START + NRD_INPUT( Texture2D, gIn_Tiles, t, 0 ) + NRD_INPUT( Texture2D, gIn_History, t, 1 ) + NRD_INPUT( Texture2D, gIn_HistoryLength, t, 2 ) +NRD_INPUTS_END + +NRD_OUTPUTS_START + NRD_OUTPUT( RWTexture2D, gOut_History, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_HistoryLength, u, 1 ) +NRD_OUTPUTS_END + +// Macro magic +#define SIGMA_CopyGroupX 8 +#define SIGMA_CopyGroupY 16 + +// Redirection +#undef GROUP_X +#undef GROUP_Y +#define GROUP_X SIGMA_CopyGroupX +#define GROUP_Y SIGMA_CopyGroupY diff --git a/Shaders/Resources/SIGMA_TemporalStabilization.resources.hlsli b/Shaders/Resources/SIGMA_TemporalStabilization.resources.hlsli index 4045d467..111d87c5 100644 --- a/Shaders/Resources/SIGMA_TemporalStabilization.resources.hlsli +++ b/Shaders/Resources/SIGMA_TemporalStabilization.resources.hlsli @@ -23,11 +23,13 @@ NRD_INPUTS_START NRD_INPUT( Texture2D, gIn_Penumbra, t, 2 ) NRD_INPUT( Texture2D, gIn_Shadow_Translucency, t, 3 ) NRD_INPUT( Texture2D, gIn_History, t, 4 ) - NRD_INPUT( Texture2D, gIn_Tiles, t, 5 ) + NRD_INPUT( Texture2D, gIn_HistoryLength, t, 5 ) + NRD_INPUT( Texture2D, gIn_Tiles, t, 6 ) NRD_INPUTS_END NRD_OUTPUTS_START NRD_OUTPUT( RWTexture2D, gOut_Shadow_Translucency, u, 0 ) + NRD_OUTPUT( RWTexture2D, gOut_HistoryLength, u, 1 ) NRD_OUTPUTS_END // Macro magic diff --git a/Shaders/Source/SIGMA_Copy.cs.hlsl b/Shaders/Source/SIGMA_Copy.cs.hlsl new file mode 100644 index 00000000..4276258d --- /dev/null +++ b/Shaders/Source/SIGMA_Copy.cs.hlsl @@ -0,0 +1,18 @@ +/* +Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + +NVIDIA CORPORATION and its licensors retain all intellectual property +and proprietary rights in and to this software, related documentation +and any modifications thereto. Any use, reproduction, disclosure or +distribution of this software and related documentation without an express +license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#include "NRD.hlsli" +#include "ml.hlsli" + +#include "SIGMA_Config.hlsli" +#include "SIGMA_Copy.resources.hlsli" + +#include "Common.hlsli" +#include "SIGMA_Copy.hlsli" diff --git a/Shaders/Source/SIGMA_SmoothTiles.cs.hlsl b/Shaders/Source/SIGMA_SmoothTiles.cs.hlsl new file mode 100644 index 00000000..15110065 --- /dev/null +++ b/Shaders/Source/SIGMA_SmoothTiles.cs.hlsl @@ -0,0 +1,19 @@ +/* +Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + +NVIDIA CORPORATION and its licensors retain all intellectual property +and proprietary rights in and to this software, related documentation +and any modifications thereto. Any use, reproduction, disclosure or +distribution of this software and related documentation without an express +license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#include "NRD.hlsli" +#include "ml.hlsli" + +#include "SIGMA_Config.hlsli" +#include "SIGMA_SmoothTiles.resources.hlsli" + +#include "Common.hlsli" +#include "SIGMA_Common.hlsli" +#include "SIGMA_SmoothTiles.hlsli" diff --git a/Source/Denoisers/Reference.hpp b/Source/Denoisers/Reference.hpp index 9155800b..7a6918b8 100644 --- a/Source/Denoisers/Reference.hpp +++ b/Source/Denoisers/Reference.hpp @@ -27,19 +27,25 @@ void nrd::InstanceImpl::Add_Reference(DenoiserData& denoiserData) PushPass("Temporal accumulation"); { + // Inputs PushInput( AsUint(ResourceType::IN_SIGNAL) ); + // Outputs PushOutput( AsUint(Permanent::HISTORY) ); + // Shaders AddDispatch( REFERENCE_TemporalAccumulation, REFERENCE_TemporalAccumulation, 1 ); } PushPass("Copy"); { + // Inputs PushInput( AsUint(Permanent::HISTORY) ); + // Outputs PushOutput( AsUint(ResourceType::OUT_SIGNAL) ); + // Shaders AddDispatch( REFERENCE_Copy, REFERENCE_Copy, 1 ); } @@ -58,17 +64,21 @@ void nrd::InstanceImpl::Update_Reference(const DenoiserData& denoiserData) if (m_WorldToClip != m_WorldToClipPrev || m_CommonSettings.accumulationMode != AccumulationMode::CONTINUE || m_CommonSettings.rectSize[0] != m_CommonSettings.rectSizePrev[0] || - m_CommonSettings.rectSize[1] != m_CommonSettings.rectSizePrev[1]) + m_CommonSettings.rectSize[1] != m_CommonSettings.rectSizePrev[1] + ) m_AccumulatedFrameNum = 0; else - m_AccumulatedFrameNum = min(m_AccumulatedFrameNum + 1, settings.maxAccumulatedFrameNum); + { + uint32_t maxAccumulatedFRameNum = min(settings.maxAccumulatedFrameNum, REFERENCE_MAX_HISTORY_FRAME_NUM); + m_AccumulatedFrameNum = min(m_AccumulatedFrameNum + 1, maxAccumulatedFRameNum); + } NRD_DECLARE_DIMS; { // ACCUMULATE REFERENCE_TemporalAccumulationConstants* consts = (REFERENCE_TemporalAccumulationConstants*)PushDispatch(denoiserData, AsUint(Dispatch::ACCUMULATE)); consts->gRectOrigin = uint2(m_CommonSettings.rectOrigin[0], m_CommonSettings.rectOrigin[1]); - consts->gAccumSpeed = 1.0f / (1.0f + float(m_AccumulatedFrameNum)); + consts->gAccumSpeed = 1.0f / (1.0f + m_AccumulatedFrameNum); consts->gDebug = m_CommonSettings.debug; } diff --git a/Source/Denoisers/Relax_Diffuse.hpp b/Source/Denoisers/Relax_Diffuse.hpp index aea78a4f..495b08c5 100644 --- a/Source/Denoisers/Relax_Diffuse.hpp +++ b/Source/Denoisers/Relax_Diffuse.hpp @@ -31,7 +31,6 @@ void nrd::InstanceImpl::Add_RelaxDiffuse(DenoiserData& denoiserData) AddTextureToPermanentPool( {Format::RGBA8_UNORM, 1} ); AddTextureToPermanentPool( {Format::R8_UNORM, 1} ); AddTextureToPermanentPool( {Format::R32_SFLOAT, 1} ); - AddTextureToPermanentPool( {Format::R32_SFLOAT, 1} ); enum class Transient { diff --git a/Source/Denoisers/Sigma_Shadow.hpp b/Source/Denoisers/Sigma_Shadow.hpp index 564e5b16..63f0c13a 100644 --- a/Source/Denoisers/Sigma_Shadow.hpp +++ b/Source/Denoisers/Sigma_Shadow.hpp @@ -15,6 +15,13 @@ void nrd::InstanceImpl::Add_SigmaShadow(DenoiserData& denoiserData) denoiserData.settings.sigma = SigmaSettings(); denoiserData.settingsSize = sizeof(denoiserData.settings.sigma); + enum class Permanent + { + HISTORY_LENGTH = PERMANENT_POOL_START, + }; + + AddTextureToPermanentPool( {Format::R32_UINT, 1} ); + enum class Transient { DATA_1 = TRANSIENT_POOL_START, @@ -22,6 +29,7 @@ void nrd::InstanceImpl::Add_SigmaShadow(DenoiserData& denoiserData) TEMP_1, TEMP_2, HISTORY, + HISTORY_LENGTH, TILES, SMOOTHED_TILES, }; @@ -31,40 +39,63 @@ void nrd::InstanceImpl::Add_SigmaShadow(DenoiserData& denoiserData) AddTextureToTransientPool( {Format::R8_UNORM, 1} ); AddTextureToTransientPool( {Format::R8_UNORM, 1} ); AddTextureToTransientPool( {Format::R8_UNORM, 1} ); + AddTextureToTransientPool( {Format::R32_UINT, 1} ); AddTextureToTransientPool( {Format::RGBA8_UNORM, 16} ); AddTextureToTransientPool( {Format::RG8_UNORM, 16} ); PushPass("Classify tiles"); { + // Inputs PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::IN_PENUMBRA) ); + // Outputs PushOutput( AsUint(Transient::TILES) ); + // Shaders AddDispatch( SIGMA_Shadow_ClassifyTiles, SIGMA_ClassifyTiles, 1 ); } PushPass("Smooth tiles"); { + // Inputs PushInput( AsUint(Transient::TILES) ); + // Outputs PushOutput( AsUint(Transient::SMOOTHED_TILES) ); - AddDispatch( SIGMA_Shadow_SmoothTiles, SIGMA_SmoothTiles, 16 ); + // Shaders + AddDispatch( SIGMA_SmoothTiles, SIGMA_SmoothTiles, 16 ); + } + + PushPass("Copy"); + { + // Inputs + PushInput( AsUint(Transient::SMOOTHED_TILES) ); + PushInput( AsUint(ResourceType::OUT_SHADOW_TRANSLUCENCY) ); + PushInput( AsUint(Permanent::HISTORY_LENGTH) ); + + // Outputs + PushOutput( AsUint(Transient::HISTORY) ); + PushOutput( AsUint(Transient::HISTORY_LENGTH) ); + + // Shaders + AddDispatch( SIGMA_Copy, SIGMA_Copy, USE_MAX_DIMS ); } PushPass("Blur"); { + // Inputs PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::IN_NORMAL_ROUGHNESS) ); PushInput( AsUint(ResourceType::IN_PENUMBRA) ); PushInput( AsUint(Transient::SMOOTHED_TILES) ); - PushInput( AsUint(ResourceType::OUT_SHADOW_TRANSLUCENCY) ); + // Outputs PushOutput( AsUint(Transient::DATA_1) ); PushOutput( AsUint(Transient::TEMP_1) ); - PushOutput( AsUint(Transient::HISTORY) ); + // Shaders AddDispatch( SIGMA_Shadow_Blur, SIGMA_Blur, USE_MAX_DIMS ); } @@ -74,40 +105,51 @@ void nrd::InstanceImpl::Add_SigmaShadow(DenoiserData& denoiserData) PushPass("Post-blur"); { + // Inputs PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::IN_NORMAL_ROUGHNESS) ); PushInput( AsUint(Transient::DATA_1) ); PushInput( AsUint(Transient::SMOOTHED_TILES) ); PushInput( AsUint(Transient::TEMP_1) ); + // Outputs PushOutput( AsUint(Transient::DATA_2) ); PushOutput( isStabilizationEnabled ? AsUint(Transient::TEMP_2) : AsUint(ResourceType::OUT_SHADOW_TRANSLUCENCY) ); + // Shaders AddDispatch( SIGMA_Shadow_PostBlur, SIGMA_Blur, 1 ); } } PushPass("Temporal stabilization"); { + // Inputs PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::IN_MV) ); PushInput( AsUint(Transient::DATA_2) ); PushInput( AsUint(Transient::TEMP_2) ); PushInput( AsUint(Transient::HISTORY) ); + PushInput( AsUint(Transient::HISTORY_LENGTH) ); PushInput( AsUint(Transient::SMOOTHED_TILES) ); + // Outputs PushOutput( AsUint(ResourceType::OUT_SHADOW_TRANSLUCENCY) ); + PushOutput( AsUint(Permanent::HISTORY_LENGTH) ); + // Shaders AddDispatch( SIGMA_Shadow_TemporalStabilization, SIGMA_TemporalStabilization, 1 ); } PushPass("Split screen"); { + // Inputs PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::IN_PENUMBRA) ); + // Outputs PushOutput( AsUint(ResourceType::OUT_SHADOW_TRANSLUCENCY) ); + // Shaders AddDispatch( SIGMA_Shadow_SplitScreen, SIGMA_SplitScreen, 1 ); } diff --git a/Source/Denoisers/Sigma_ShadowTranslucency.hpp b/Source/Denoisers/Sigma_ShadowTranslucency.hpp index f677e167..6c101c2a 100644 --- a/Source/Denoisers/Sigma_ShadowTranslucency.hpp +++ b/Source/Denoisers/Sigma_ShadowTranslucency.hpp @@ -15,6 +15,13 @@ void nrd::InstanceImpl::Add_SigmaShadowTranslucency(nrd::DenoiserData& denoiserD denoiserData.settings.sigma = SigmaSettings(); denoiserData.settingsSize = sizeof(denoiserData.settings.sigma); + enum class Permanent + { + HISTORY_LENGTH = PERMANENT_POOL_START, + }; + + AddTextureToPermanentPool( {Format::R32_UINT, 1} ); + enum class Transient { DATA_1 = TRANSIENT_POOL_START, @@ -22,6 +29,7 @@ void nrd::InstanceImpl::Add_SigmaShadowTranslucency(nrd::DenoiserData& denoiserD TEMP_1, TEMP_2, HISTORY, + HISTORY_LENGTH, TILES, SMOOTHED_TILES, }; @@ -31,43 +39,66 @@ void nrd::InstanceImpl::Add_SigmaShadowTranslucency(nrd::DenoiserData& denoiserD AddTextureToTransientPool( {Format::RGBA8_UNORM, 1} ); AddTextureToTransientPool( {Format::RGBA8_UNORM, 1} ); AddTextureToTransientPool( {Format::RGBA8_UNORM, 1} ); + AddTextureToTransientPool( {Format::R32_UINT, 1} ); AddTextureToTransientPool( {Format::RGBA8_UNORM, 16} ); AddTextureToTransientPool( {Format::RG8_UNORM, 16} ); PushPass("Classify tiles"); { + // Inputs PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::IN_PENUMBRA) ); PushInput( AsUint(ResourceType::IN_TRANSLUCENCY) ); + // Outputs PushOutput( AsUint(Transient::TILES) ); + // Shaders AddDispatch( SIGMA_ShadowTranslucency_ClassifyTiles, SIGMA_ClassifyTiles, 1 ); } PushPass("Smooth tiles"); { + // Inputs PushInput( AsUint(Transient::TILES) ); + // Outputs PushOutput( AsUint(Transient::SMOOTHED_TILES) ); - AddDispatch( SIGMA_Shadow_SmoothTiles, SIGMA_SmoothTiles, 16 ); + // Shaders + AddDispatch( SIGMA_SmoothTiles, SIGMA_SmoothTiles, 16 ); + } + + PushPass("Copy"); + { + // Inputs + PushInput( AsUint(Transient::SMOOTHED_TILES) ); + PushInput( AsUint(ResourceType::OUT_SHADOW_TRANSLUCENCY) ); + PushInput( AsUint(Permanent::HISTORY_LENGTH) ); + + // Outputs + PushOutput( AsUint(Transient::HISTORY) ); + PushOutput( AsUint(Transient::HISTORY_LENGTH) ); + + // Shaders + AddDispatch( SIGMA_Copy, SIGMA_Copy, USE_MAX_DIMS ); } PushPass("Blur"); { + // Inputs PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::IN_NORMAL_ROUGHNESS) ); PushInput( AsUint(ResourceType::IN_PENUMBRA) ); PushInput( AsUint(Transient::SMOOTHED_TILES) ); - PushInput( AsUint(ResourceType::OUT_SHADOW_TRANSLUCENCY) ); PushInput( AsUint(ResourceType::IN_TRANSLUCENCY) ); + // Outputs PushOutput( AsUint(Transient::DATA_1) ); PushOutput( AsUint(Transient::TEMP_1) ); - PushOutput( AsUint(Transient::HISTORY) ); - AddDispatch( SIGMA_ShadowTranslucency_Blur, SIGMA_Blur, USE_MAX_DIMS ); + // Shaders + AddDispatch( SIGMA_ShadowTranslucency_Blur, SIGMA_Blur, 1 ); } for (int i = 0; i < SIGMA_POST_BLUR_PERMUTATION_NUM; i++) @@ -76,41 +107,52 @@ void nrd::InstanceImpl::Add_SigmaShadowTranslucency(nrd::DenoiserData& denoiserD PushPass("Post-blur"); { + // Inputs PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::IN_NORMAL_ROUGHNESS) ); PushInput( AsUint(Transient::DATA_1) ); PushInput( AsUint(Transient::SMOOTHED_TILES) ); PushInput( AsUint(Transient::TEMP_1) ); + // Outputs PushOutput( AsUint(Transient::DATA_2) ); PushOutput( isStabilizationEnabled ? AsUint(Transient::TEMP_2) : AsUint(ResourceType::OUT_SHADOW_TRANSLUCENCY) ); + // Shaders AddDispatch( SIGMA_ShadowTranslucency_PostBlur, SIGMA_Blur, 1 ); } } PushPass("Temporal stabilization"); { + // Inputs PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::IN_MV) ); PushInput( AsUint(Transient::DATA_2) ); PushInput( AsUint(Transient::TEMP_2) ); PushInput( AsUint(Transient::HISTORY) ); + PushInput( AsUint(Transient::HISTORY_LENGTH) ); PushInput( AsUint(Transient::SMOOTHED_TILES) ); + // Outputs PushOutput( AsUint(ResourceType::OUT_SHADOW_TRANSLUCENCY) ); + PushOutput( AsUint(Permanent::HISTORY_LENGTH) ); + // Shaders AddDispatch( SIGMA_ShadowTranslucency_TemporalStabilization, SIGMA_TemporalStabilization, 1 ); } PushPass("Split screen"); { + // Inputs PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::IN_PENUMBRA) ); PushInput( AsUint(ResourceType::IN_TRANSLUCENCY) ); + // Outputs PushOutput( AsUint(ResourceType::OUT_SHADOW_TRANSLUCENCY) ); + // Shaders AddDispatch( SIGMA_ShadowTranslucency_SplitScreen, SIGMA_SplitScreen, 1 ); } diff --git a/Source/InstanceImpl.cpp b/Source/InstanceImpl.cpp index d4303602..ad846c02 100644 --- a/Source/InstanceImpl.cpp +++ b/Source/InstanceImpl.cpp @@ -287,9 +287,13 @@ nrd::Result nrd::InstanceImpl::SetCommonSettings(const CommonSettings& commonSet float angle1 = Sequence::Weyl1D(0.5f, commonSettings.frameIndex) * radians(90.0f); m_Rotator_PrePass = Geometry::GetRotator(angle1); - float angle2 = Sequence::Weyl1D(0.0f, commonSettings.frameIndex) * radians(90.0f); - m_Rotator_Blur = Geometry::GetRotator(angle2); - m_Rotator_PostBlur = Geometry::GetRotator(angle2 + radians(45.0f)); + 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); + m_Rotator_Blur = 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); + m_Rotator_PostBlur = Geometry::CombineRotators(Geometry::GetRotator(a2), Geometry::GetRotator(a3)); // Main matrices m_ViewToClip = float4x4 diff --git a/Source/Reblur.cpp b/Source/Reblur.cpp index 6c479139..f55071c8 100644 --- a/Source/Reblur.cpp +++ b/Source/Reblur.cpp @@ -123,7 +123,7 @@ void nrd::InstanceImpl::Update_Reblur(const DenoiserData& denoiserData) const ReblurProps& props = g_ReblurProps[ size_t(denoiserData.desc.denoiser) - size_t(Denoiser::REBLUR_DIFFUSE) ]; bool enableHitDistanceReconstruction = settings.hitDistanceReconstructionMode != HitDistanceReconstructionMode::OFF && settings.checkerboardMode == CheckerboardMode::OFF; - bool skipTemporalStabilization = settings.stabilizationStrength == 0.0f; + bool skipTemporalStabilization = settings.maxStabilizedFrameNum == 0; bool skipPrePass = (settings.diffusePrepassBlurRadius == 0.0f || !props.hasDiffuse) && (settings.specularPrepassBlurRadius == 0.0f || !props.hasSpecular) && settings.checkerboardMode == CheckerboardMode::OFF; @@ -324,7 +324,8 @@ void nrd::InstanceImpl::AddSharedConstants_Reblur(const ReblurSettings& settings float diffusePrepassBlurRadius = settings.diffusePrepassBlurRadius * worstResolutionScale; float specularPrepassBlurRadius = settings.specularPrepassBlurRadius * worstResolutionScale; float disocclusionThresholdBonus = (1.0f + m_JitterDelta) / float(rectH); - float stabilizationStrength = m_CommonSettings.accumulationMode == AccumulationMode::CONTINUE ? settings.stabilizationStrength : 0.0f; + float stabilizationStrength = settings.maxStabilizedFrameNum / (1.0f + settings.maxStabilizedFrameNum); + float hitDistanceStabilizationStrength = settings.maxStabilizedFrameNumForHitDistance / (1.0f + settings.maxStabilizedFrameNumForHitDistance); uint32_t maxAccumulatedFrameNum = min(settings.maxAccumulatedFrameNum, REBLUR_MAX_HISTORY_FRAME_NUM); uint32_t diffCheckerboard = 2; @@ -342,6 +343,7 @@ void nrd::InstanceImpl::AddSharedConstants_Reblur(const ReblurSettings& settings } SharedConstants* consts = (SharedConstants*)data; + consts->gWorldToClip = m_WorldToClip; consts->gViewToClip = m_ViewToClip; consts->gViewToWorld = m_ViewToWorld; consts->gWorldToViewPrev = m_WorldToViewPrev; @@ -350,7 +352,7 @@ void nrd::InstanceImpl::AddSharedConstants_Reblur(const ReblurSettings& settings consts->gFrustum = m_Frustum; consts->gFrustumPrev = m_FrustumPrev; consts->gCameraDelta = m_CameraDelta.xmm; - consts->gAntilagParams = float4(settings.antilagSettings.luminanceSigmaScale, settings.antilagSettings.hitDistanceSigmaScale, settings.antilagSettings.luminanceAntilagPower, settings.antilagSettings.hitDistanceAntilagPower); + consts->gAntilagParams = float4(settings.antilagSettings.luminanceSigmaScale, settings.antilagSettings.hitDistanceSigmaScale, settings.antilagSettings.luminanceSensitivity, settings.antilagSettings.hitDistanceSensitivity); consts->gHitDistParams = float4(settings.hitDistanceParameters.A, settings.hitDistanceParameters.B, settings.hitDistanceParameters.C, settings.hitDistanceParameters.D); consts->gViewVectorWorld = m_ViewDirection.xmm; consts->gViewVectorWorldPrev = m_ViewDirectionPrev.xmm; @@ -371,9 +373,11 @@ void nrd::InstanceImpl::AddSharedConstants_Reblur(const ReblurSettings& settings consts->gRectSizeMinusOne = int2(rectW - 1, rectH - 1); consts->gDisocclusionThreshold = m_CommonSettings.disocclusionThreshold + disocclusionThresholdBonus; consts->gDisocclusionThresholdAlternate = m_CommonSettings.disocclusionThresholdAlternate + disocclusionThresholdBonus; + consts->gCameraAttachedReflectionMaterialID = m_CommonSettings.cameraAttachedReflectionMaterialID; consts->gStrandMaterialID = m_CommonSettings.strandMaterialID; - consts->gStabilizationStrength = stabilizationStrength; - consts->gHitDistStabilizationStrength = min(stabilizationStrength, settings.hitDistanceStabilizationStrength); + consts->gStrandThickness = m_CommonSettings.strandThickness; + consts->gStabilizationStrength = isHistoryReset ? 0.0f : stabilizationStrength; + consts->gHitDistStabilizationStrength = isHistoryReset ? 0.0f : hitDistanceStabilizationStrength; consts->gDebug = m_CommonSettings.debug; consts->gOrthoMode = m_OrthoMode; consts->gUnproject = unproject; @@ -499,7 +503,6 @@ void nrd::InstanceImpl::AddSharedConstants_Reblur(const ReblurSettings& settings #include "Denoisers/Reblur_Diffuse.hpp" - // REBLUR_DIFFUSE_OCCLUSION #ifdef NRD_EMBEDS_DXBC_SHADERS #include "REBLUR_DiffuseOcclusion_HitDistReconstruction.cs.dxbc.h" @@ -551,7 +554,6 @@ void nrd::InstanceImpl::AddSharedConstants_Reblur(const ReblurSettings& settings #include "Denoisers/Reblur_DiffuseOcclusion.hpp" - // REBLUR_DIFFUSE_SH #ifdef NRD_EMBEDS_DXBC_SHADERS #include "REBLUR_DiffuseSh_PrePass.cs.dxbc.h" @@ -615,7 +617,6 @@ void nrd::InstanceImpl::AddSharedConstants_Reblur(const ReblurSettings& settings #include "Denoisers/Reblur_DiffuseSh.hpp" - // REBLUR_SPECULAR #ifdef NRD_EMBEDS_DXBC_SHADERS #include "REBLUR_Specular_HitDistReconstruction.cs.dxbc.h" @@ -692,7 +693,6 @@ void nrd::InstanceImpl::AddSharedConstants_Reblur(const ReblurSettings& settings #include "Denoisers/Reblur_Specular.hpp" - // REBLUR_SPECULAR_OCCLUSION #ifdef NRD_EMBEDS_DXBC_SHADERS #include "REBLUR_SpecularOcclusion_HitDistReconstruction.cs.dxbc.h" @@ -744,7 +744,6 @@ void nrd::InstanceImpl::AddSharedConstants_Reblur(const ReblurSettings& settings #include "Denoisers/Reblur_SpecularOcclusion.hpp" - // REBLUR_SPECULAR_SH #ifdef NRD_EMBEDS_DXBC_SHADERS #include "REBLUR_SpecularSh_PrePass.cs.dxbc.h" @@ -808,7 +807,6 @@ void nrd::InstanceImpl::AddSharedConstants_Reblur(const ReblurSettings& settings #include "Denoisers/Reblur_SpecularSh.hpp" - // REBLUR_DIFFUSE_SPECULAR #ifdef NRD_EMBEDS_DXBC_SHADERS #include "REBLUR_DiffuseSpecular_HitDistReconstruction.cs.dxbc.h" @@ -884,7 +882,6 @@ void nrd::InstanceImpl::AddSharedConstants_Reblur(const ReblurSettings& settings #include "Denoisers/Reblur_DiffuseSpecular.hpp" - // REBLUR_DIFFUSE_SPECULAR_OCCLUSION #ifdef NRD_EMBEDS_DXBC_SHADERS #include "REBLUR_DiffuseSpecularOcclusion_HitDistReconstruction.cs.dxbc.h" @@ -936,7 +933,6 @@ void nrd::InstanceImpl::AddSharedConstants_Reblur(const ReblurSettings& settings #include "Denoisers/Reblur_DiffuseSpecularOcclusion.hpp" - // REBLUR_DIFFUSE_SPECULAR_SH #ifdef NRD_EMBEDS_DXBC_SHADERS #include "REBLUR_DiffuseSpecularSh_PrePass.cs.dxbc.h" @@ -1000,7 +996,6 @@ void nrd::InstanceImpl::AddSharedConstants_Reblur(const ReblurSettings& settings #include "Denoisers/Reblur_DiffuseSpecularSh.hpp" - // REBLUR_DIFFUSE_DIRECTIONAL_OCCLUSION #ifdef NRD_EMBEDS_DXBC_SHADERS #include "REBLUR_DiffuseDirectionalOcclusion_PrePass.cs.dxbc.h" diff --git a/Source/Relax.cpp b/Source/Relax.cpp index 77237c2a..82b0baea 100644 --- a/Source/Relax.cpp +++ b/Source/Relax.cpp @@ -98,6 +98,7 @@ void nrd::InstanceImpl::AddSharedConstants_Relax(const RelaxSettings& settings, } SharedConstants* consts = (SharedConstants*)data; + consts->gWorldToClip = m_WorldToClip; consts->gWorldToClipPrev = m_WorldToClipPrev; consts->gWorldToViewPrev = m_WorldToViewPrev; consts->gWorldPrevToWorld = m_WorldPrevToWorld; @@ -120,21 +121,21 @@ 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 = uint2(rectW, rectH); - consts->gSpecMaxAccumulatedFrameNum = (float)settings.specularMaxAccumulatedFrameNum; - consts->gSpecMaxFastAccumulatedFrameNum = (float)settings.specularMaxFastAccumulatedFrameNum; - consts->gDiffMaxAccumulatedFrameNum = (float)settings.diffuseMaxAccumulatedFrameNum; - consts->gDiffMaxFastAccumulatedFrameNum = (float)settings.diffuseMaxFastAccumulatedFrameNum; + 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->gDisocclusionThreshold = m_CommonSettings.disocclusionThreshold + disocclusionThresholdBonus; consts->gDisocclusionThresholdAlternate = m_CommonSettings.disocclusionThresholdAlternate + disocclusionThresholdBonus; consts->gStrandMaterialID = m_CommonSettings.strandMaterialID; + consts->gStrandThickness = m_CommonSettings.strandThickness; consts->gRoughnessFraction = settings.roughnessFraction; consts->gSpecVarianceBoost = settings.specularVarianceBoost; consts->gSplitScreen = m_CommonSettings.splitScreen; consts->gDiffBlurRadius = settings.diffusePrepassBlurRadius; consts->gSpecBlurRadius = settings.specularPrepassBlurRadius; consts->gDepthThreshold = settings.depthThreshold; - consts->gDiffLobeAngleFraction = settings.diffuseLobeAngleFraction; - consts->gSpecLobeAngleFraction = settings.specularLobeAngleFraction; + consts->gLobeAngleFraction = settings.lobeAngleFraction; consts->gSpecLobeAngleSlack = radians(settings.specularLobeAngleSlack); consts->gHistoryFixEdgeStoppingNormalPower = settings.historyFixEdgeStoppingNormalPower; consts->gRoughnessEdgeStoppingRelaxation = settings.roughnessEdgeStoppingRelaxation; @@ -346,7 +347,6 @@ void nrd::InstanceImpl::Update_Relax(const DenoiserData& denoiserData) #include "Denoisers/Relax_Diffuse.hpp" - // RELAX_DIFFUSE_SH #ifdef NRD_EMBEDS_DXBC_SHADERS #include "RELAX_DiffuseSh_PrePass.cs.dxbc.h" @@ -386,7 +386,6 @@ void nrd::InstanceImpl::Update_Relax(const DenoiserData& denoiserData) #include "Denoisers/Relax_DiffuseSh.hpp" - // RELAX_SPECULAR #ifdef NRD_EMBEDS_DXBC_SHADERS #include "RELAX_Specular_HitDistReconstruction.cs.dxbc.h" @@ -432,7 +431,6 @@ void nrd::InstanceImpl::Update_Relax(const DenoiserData& denoiserData) #include "Denoisers/Relax_Specular.hpp" - // RELAX_SPECULAR_SH #ifdef NRD_EMBEDS_DXBC_SHADERS #include "RELAX_SpecularSh_PrePass.cs.dxbc.h" @@ -472,7 +470,6 @@ void nrd::InstanceImpl::Update_Relax(const DenoiserData& denoiserData) #include "Denoisers/Relax_SpecularSh.hpp" - // RELAX_DIFFUSE_SPECULAR #ifdef NRD_EMBEDS_DXBC_SHADERS #include "RELAX_DiffuseSpecular_HitDistReconstruction.cs.dxbc.h" @@ -518,7 +515,6 @@ void nrd::InstanceImpl::Update_Relax(const DenoiserData& denoiserData) #include "Denoisers/Relax_DiffuseSpecular.hpp" - // RELAX_DIFFUSE_SPECULAR_SH #ifdef NRD_EMBEDS_DXBC_SHADERS #include "RELAX_DiffuseSpecularSh_PrePass.cs.dxbc.h" diff --git a/Source/Sigma.cpp b/Source/Sigma.cpp index f2aad4fb..8bdf92cc 100644 --- a/Source/Sigma.cpp +++ b/Source/Sigma.cpp @@ -14,6 +14,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #include "../Shaders/Resources/SIGMA_ClassifyTiles.resources.hlsli" #include "../Shaders/Resources/SIGMA_SmoothTiles.resources.hlsli" #include "../Shaders/Resources/SIGMA_Blur.resources.hlsli" +#include "../Shaders/Resources/SIGMA_Copy.resources.hlsli" #include "../Shaders/Resources/SIGMA_TemporalStabilization.resources.hlsli" #include "../Shaders/Resources/SIGMA_SplitScreen.resources.hlsli" @@ -27,7 +28,8 @@ void nrd::InstanceImpl::Update_SigmaShadow(const DenoiserData& denoiserData) { CLASSIFY_TILES, SMOOTH_TILES = CLASSIFY_TILES + SIGMA_NO_PERMUTATIONS, - BLUR = SMOOTH_TILES + SIGMA_NO_PERMUTATIONS, + COPY = SMOOTH_TILES + SIGMA_NO_PERMUTATIONS, + BLUR = COPY + SIGMA_NO_PERMUTATIONS, POST_BLUR = BLUR + SIGMA_NO_PERMUTATIONS, TEMPORAL_STABILIZATION = POST_BLUR + SIGMA_POST_BLUR_PERMUTATION_NUM, SPLIT_SCREEN = TEMPORAL_STABILIZATION + SIGMA_NO_PERMUTATIONS, @@ -54,6 +56,13 @@ void nrd::InstanceImpl::Update_SigmaShadow(const DenoiserData& denoiserData) AddSharedConstants_Sigma(settings, consts); } + // COPY + if (settings.maxStabilizedFrameNum) + { + void* consts = PushDispatch(denoiserData, AsUint(Dispatch::COPY)); + AddSharedConstants_Sigma(settings, consts); + } + { // BLUR SIGMA_BlurConstants* consts = (SIGMA_BlurConstants*)PushDispatch(denoiserData, AsUint(Dispatch::BLUR)); AddSharedConstants_Sigma(settings, consts); @@ -61,14 +70,14 @@ void nrd::InstanceImpl::Update_SigmaShadow(const DenoiserData& denoiserData) } { // POST_BLUR - uint32_t passIndex = AsUint(Dispatch::POST_BLUR) + (settings.stabilizationStrength != 0.0f ? 1 : 0); + uint32_t passIndex = AsUint(Dispatch::POST_BLUR) + (settings.maxStabilizedFrameNum ? 1 : 0); SIGMA_BlurConstants* consts = (SIGMA_BlurConstants*)PushDispatch(denoiserData, passIndex); AddSharedConstants_Sigma(settings, consts); consts->gRotator = m_Rotator_PostBlur; // TODO: push constant } // TEMPORAL_STABILIZATION - if (settings.stabilizationStrength != 0.0f) + if (settings.maxStabilizedFrameNum) { void* consts = PushDispatch(denoiserData, AsUint(Dispatch::TEMPORAL_STABILIZATION)); AddSharedConstants_Sigma(settings, consts); @@ -95,14 +104,21 @@ void nrd::InstanceImpl::AddSharedConstants_Sigma(const SigmaSettings& settings, uint16_t tilesW = DivideUp(rectW, 16); uint16_t tilesH = DivideUp(rectH, 16); + bool isRectChanged = rectW != rectWprev || rectH != rectHprev; + uint32_t frameNum = min(settings.maxStabilizedFrameNum, SIGMA_MAX_HISTORY_FRAME_NUM); float3 lightDirectionView = Rotate(m_WorldToView, float3(settings.lightDirection[0], settings.lightDirection[1], settings.lightDirection[2])); + float stabilizationStrength = frameNum / (1.0f + frameNum); SharedConstants* consts = (SharedConstants*)data; consts->gWorldToView = m_WorldToView; consts->gViewToClip = m_ViewToClip; consts->gWorldToClipPrev = m_WorldToClipPrev; + consts->gWorldToViewPrev = m_WorldToViewPrev; + consts->gViewVectorWorld = m_ViewDirection.xmm; consts->gLightDirectionView = float4(lightDirectionView.x, lightDirectionView.y, lightDirectionView.z, 0.0f); consts->gFrustum = m_Frustum; + consts->gFrustumPrev = m_FrustumPrev; + consts->gCameraDelta = m_CameraDelta.xmm; consts->gMvScale = float4(m_CommonSettings.motionVectorScale[0], m_CommonSettings.motionVectorScale[1], m_CommonSettings.motionVectorScale[2], m_CommonSettings.isMotionVectorInWorldSpace ? 1.0f : 0.0f); consts->gResourceSizeInv = float2(1.0f / float(resourceW), 1.0f / float(resourceH)); consts->gResourceSizeInvPrev = float2(1.0f / float(resourceWprev), 1.0f / float(resourceHprev)); @@ -119,18 +135,34 @@ void nrd::InstanceImpl::AddSharedConstants_Sigma(const SigmaSettings& settings, consts->gUnproject = unproject; consts->gDenoisingRange = m_CommonSettings.denoisingRange; consts->gPlaneDistSensitivity = settings.planeDistanceSensitivity; - consts->gStabilizationStrength = m_CommonSettings.accumulationMode == AccumulationMode::CONTINUE ? settings.stabilizationStrength : 0.0f; + consts->gStabilizationStrength = m_CommonSettings.accumulationMode == AccumulationMode::CONTINUE ? stabilizationStrength : 0.0f; consts->gDebug = m_CommonSettings.debug; consts->gSplitScreen = m_CommonSettings.splitScreen; consts->gViewZScale = m_CommonSettings.viewZScale; consts->gMinRectDimMulUnproject = (float)min(rectW, rectH) * unproject; consts->gFrameIndex = m_CommonSettings.frameIndex; + consts->gIsRectChanged = isRectChanged ? 1 : 0; } +// SIGMA_SHARED +#ifdef NRD_EMBEDS_DXBC_SHADERS + #include "SIGMA_Copy.cs.dxbc.h" + #include "SIGMA_SmoothTiles.cs.dxbc.h" +#endif + +#ifdef NRD_EMBEDS_DXIL_SHADERS + #include "SIGMA_Copy.cs.dxil.h" + #include "SIGMA_SmoothTiles.cs.dxil.h" +#endif + +#ifdef NRD_EMBEDS_SPIRV_SHADERS + #include "SIGMA_Copy.cs.spirv.h" + #include "SIGMA_SmoothTiles.cs.spirv.h" +#endif + // SIGMA_SHADOW #ifdef NRD_EMBEDS_DXBC_SHADERS #include "SIGMA_Shadow_ClassifyTiles.cs.dxbc.h" - #include "SIGMA_Shadow_SmoothTiles.cs.dxbc.h" #include "SIGMA_Shadow_Blur.cs.dxbc.h" #include "SIGMA_Shadow_PostBlur.cs.dxbc.h" #include "SIGMA_Shadow_TemporalStabilization.cs.dxbc.h" @@ -139,7 +171,6 @@ void nrd::InstanceImpl::AddSharedConstants_Sigma(const SigmaSettings& settings, #ifdef NRD_EMBEDS_DXIL_SHADERS #include "SIGMA_Shadow_ClassifyTiles.cs.dxil.h" - #include "SIGMA_Shadow_SmoothTiles.cs.dxil.h" #include "SIGMA_Shadow_Blur.cs.dxil.h" #include "SIGMA_Shadow_PostBlur.cs.dxil.h" #include "SIGMA_Shadow_TemporalStabilization.cs.dxil.h" @@ -148,7 +179,6 @@ void nrd::InstanceImpl::AddSharedConstants_Sigma(const SigmaSettings& settings, #ifdef NRD_EMBEDS_SPIRV_SHADERS #include "SIGMA_Shadow_ClassifyTiles.cs.spirv.h" - #include "SIGMA_Shadow_SmoothTiles.cs.spirv.h" #include "SIGMA_Shadow_Blur.cs.spirv.h" #include "SIGMA_Shadow_PostBlur.cs.spirv.h" #include "SIGMA_Shadow_TemporalStabilization.cs.spirv.h" @@ -157,7 +187,6 @@ void nrd::InstanceImpl::AddSharedConstants_Sigma(const SigmaSettings& settings, #include "Denoisers/Sigma_Shadow.hpp" - // SIGMA_SHADOW_TRANSLUCENCY #ifdef NRD_EMBEDS_DXBC_SHADERS #include "SIGMA_ShadowTranslucency_ClassifyTiles.cs.dxbc.h" diff --git a/UPDATE.md b/UPDATE.md index 5a474d06..44dbd5b5 100644 --- a/UPDATE.md +++ b/UPDATE.md @@ -268,3 +268,21 @@ A single NRD instance can now include any combination of denoisers, including re - removed the constructor with arguments - creation parameters grouped into `IntegrationCreationDesc`, which need to be passed to `Initialize` - added a few potentially useful flags to `IntegrationCreationDesc` + +## To v4.11 +- *API*: + - exposed `DEFAULT_ACCUMULATION_TIME` for all denoisers + - added some missing `MAX_HISTORY_FRAME_NUM` constants + - exposed `GetMaxAccumulatedFrameNum` helper, converting time to frames +- *REBLUR*: + - `stabilizationStrength` replaced with `maxStabilizedFrameNum` + - `hitDistanceStabilizationStrength` replaced with `maxStabilizedFrameNumForHitDistance` + - `luminanceAntilagPower` replaced with `luminanceSensitivity` + - `hitDistanceAntilagPower` replaced with `hitDistanceSensitivity` + - tweaked the default values for `ReblurAntilagSettings` + - the new default value for `planeDistanceSensitivity = 0.02` matches the behavior for the old value `0.005` + - slightly reduced `lobeAngleFraction` to squeeze more normal details (it's safe to use the old value `0.2`) +- *SIGMA*: + - `stabilizationStrength` replaced with `maxStabilizedFrameNum` + - the new default value for `planeDistanceSensitivity = 0.02` matches the behavior for the old value `0.005` +