From 8d3c2459830b921843323efc495841de1f19f1e6 Mon Sep 17 00:00:00 2001 From: dzhdan Date: Thu, 9 May 2024 18:06:11 +0800 Subject: [PATCH] v4.8.0: HIGHLIGHTS: - NRD: improved FP16 viewZ support - SIGMA: made more friendly to per light shadow denoising (multi-light scenario) - removed unused (non-denoisers) "SPECULAR_REFLECTION_MV" & "SPECULAR_DELTA_MV" DETAILS: - NRD: exposed "CommonSettings::viewZScale", which should help to improve FP16 support - SIGMA: "IN_SHADOWDATA" => "IN_PENUMBRA", "IN_SHADOW_TRANSLUCENCY" => "IN_TRANSLUCENCY" - SIGMA: massaged front-end functions - SIGMA: switched to use common "IN_VIEWZ" input instead of a custom one (it eliminates a need to clone ViewZ in case of multiple lights) - REBLUR: minor tweaks - SPECULAR_REFLECTION_MV: deprecated and removed - SPECULAR_DELTA_MV: deprecated and removed - updated docs --- CMakeLists.txt | 1 - External/MathLib | 2 +- Include/NRD.h | 4 +- Include/NRDDescs.h | 76 +++---- Include/NRDSettings.h | 47 ++--- README.md | 41 ++-- Resources/Version.h | 2 +- Shaders.cfg | 2 - Shaders/Include/Common.hlsli | 7 +- Shaders/Include/NRD.hlsli | 89 ++------ Shaders/Include/REBLUR_Blur.hlsli | 4 +- Shaders/Include/REBLUR_Common.hlsli | 7 +- .../REBLUR_Common_DiffuseSpatialFilter.hlsli | 4 +- .../REBLUR_Common_SpecularSpatialFilter.hlsli | 4 +- Shaders/Include/REBLUR_Config.hlsli | 1 + Shaders/Include/REBLUR_HistoryFix.hlsli | 6 +- .../REBLUR_HitDistReconstruction.hlsli | 2 +- Shaders/Include/REBLUR_PostBlur.hlsli | 2 +- Shaders/Include/REBLUR_PrePass.hlsli | 6 +- Shaders/Include/REBLUR_SplitScreen.hlsli | 2 +- .../Include/REBLUR_TemporalAccumulation.hlsli | 94 +++++---- .../REBLUR_TemporalStabilization.hlsli | 2 +- Shaders/Include/RELAX_Config.hlsli | 1 + Shaders/Include/RELAX_PrePass.hlsli | 4 +- Shaders/Include/RELAX_SplitScreen.hlsli | 2 +- .../Include/RELAX_TemporalAccumulation.hlsli | 4 +- Shaders/Include/SIGMA_Blur.hlsli | 70 +++--- Shaders/Include/SIGMA_ClassifyTiles.hlsli | 11 +- Shaders/Include/SIGMA_Common.hlsli | 10 +- Shaders/Include/SIGMA_Config.hlsli | 4 +- Shaders/Include/SIGMA_SplitScreen.hlsli | 4 +- .../Include/SIGMA_TemporalStabilization.hlsli | 19 +- Shaders/Resources/Clear_Float.resources.hlsli | 1 + Shaders/Resources/Clear_Uint.resources.hlsli | 1 + .../REFERENCE_SplitScreen.resources.hlsli | 1 + ...RENCE_TemporalAccumulation.resources.hlsli | 3 +- Shaders/Resources/SIGMA_Blur.resources.hlsli | 15 +- .../SIGMA_ClassifyTiles.resources.hlsli | 5 +- .../SIGMA_SplitScreen.resources.hlsli | 5 +- ...IGMA_TemporalStabilization.resources.hlsli | 11 +- .../SpecularDeltaMv_Compute.resources.hlsli | 45 ---- ...ecularReflectionMv_Compute.resources.hlsli | 56 ----- Shaders/Source/REBLUR_ClassifyTiles.cs.hlsl | 4 +- Shaders/Source/REBLUR_Validation.cs.hlsl | 6 +- .../Source/SpecularDeltaMv_Compute.cs.hlsl | 149 ------------- .../SpecularReflectionMv_Compute.cs.hlsl | 199 ------------------ Source/Denoisers/Sigma_Shadow.hpp | 15 +- Source/Denoisers/Sigma_ShadowTranslucency.hpp | 23 +- Source/Denoisers/SpecularDeltaMv.hpp | 63 ------ Source/Denoisers/SpecularReflectionMv.hpp | 67 ------ Source/InstanceImpl.cpp | 21 +- Source/InstanceImpl.h | 5 +- Source/Reblur.cpp | 1 + Source/{Other.cpp => Reference.cpp} | 32 --- Source/Relax.cpp | 1 + Source/Sigma.cpp | 1 + Source/Wrapper.cpp | 21 +- UPDATE.md | 15 ++ 58 files changed, 330 insertions(+), 970 deletions(-) delete mode 100644 Shaders/Resources/SpecularDeltaMv_Compute.resources.hlsli delete mode 100644 Shaders/Resources/SpecularReflectionMv_Compute.resources.hlsli delete mode 100644 Shaders/Source/SpecularDeltaMv_Compute.cs.hlsl delete mode 100644 Shaders/Source/SpecularReflectionMv_Compute.cs.hlsl delete mode 100644 Source/Denoisers/SpecularDeltaMv.hpp delete mode 100644 Source/Denoisers/SpecularReflectionMv.hpp rename Source/{Other.cpp => Reference.cpp} (57%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 922a075..8553cd1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -195,7 +195,6 @@ if (NOT NRD_DISABLE_SHADER_COMPILATION) if (NRD_EMBEDS_SPIRV_SHADERS) set (SHADERMAKE_COMMANDS ${SHADERMAKE_COMMANDS} COMMAND ShaderMake -p SPIRV --compiler "${DXC_SPIRV_PATH}" ${SHADERMAKE_GENERAL_ARGS} - -D VULKAN --sRegShift 100 --tRegShift 200 --bRegShift 300 diff --git a/External/MathLib b/External/MathLib index 310266c..6520942 160000 --- a/External/MathLib +++ b/External/MathLib @@ -1 +1 @@ -Subproject commit 310266c8cec4dd5408485c4ae9ffe6567e5e0683 +Subproject commit 65209425eb201fd602f60f4498f74e3d8d0f5a52 diff --git a/Include/NRD.h b/Include/NRD.h index 3efed55..24951fa 100644 --- a/Include/NRD.h +++ b/Include/NRD.h @@ -28,9 +28,9 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #include #define NRD_VERSION_MAJOR 4 -#define NRD_VERSION_MINOR 7 +#define NRD_VERSION_MINOR 8 #define NRD_VERSION_BUILD 0 -#define NRD_VERSION_DATE "17 April 2024" +#define NRD_VERSION_DATE "9 May 2024" #if defined(_MSC_VER) #define NRD_CALL __fastcall diff --git a/Include/NRDDescs.h b/Include/NRDDescs.h index e38bef3..4715591 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 7 +#define NRD_DESCS_VERSION_MINOR 8 static_assert(NRD_VERSION_MAJOR == NRD_DESCS_VERSION_MAJOR && NRD_VERSION_MINOR == NRD_DESCS_VERSION_MINOR, "Please, update all NRD SDK files"); @@ -92,10 +92,11 @@ namespace nrd IN_SPEC_SH0, IN_SPEC_SH1, - // Shadow data and optional translucency (RG16f+ and RGBA8+ for translucency) - // SIGMA: use "SIGMA_FrontEnd_PackShadow" for encoding - IN_SHADOWDATA, - IN_SHADOW_TRANSLUCENCY, + // Penumbra and optional translucency (R16f+ and RGBA8+ for translucency) + // SIGMA: use "SIGMA_FrontEnd_PackPenumbra" for penumbra properties encoding + // SIGMA: use "SIGMA_FrontEnd_PackTranslucency" for translucency encoding + IN_PENUMBRA, + IN_TRANSLUCENCY, // Some signal (R8+) IN_SIGNAL, @@ -108,22 +109,21 @@ namespace nrd // OUTPUTS //============================================================================================================================= - // IMPORTANT: These textures can be potentially used as history buffers! // IMPORTANT: Most of denoisers do not write into output pixels outside of "CommonSettings::denoisingRange"! // Radiance and hit distance // REBLUR: use "REBLUR_BackEnd_UnpackRadianceAndNormHitDist" for decoding (RGBA16f+) // RELAX: use "RELAX_BackEnd_UnpackRadiance" for decoding (R11G11B10f+) - OUT_DIFF_RADIANCE_HITDIST, - OUT_SPEC_RADIANCE_HITDIST, + OUT_DIFF_RADIANCE_HITDIST, // IMPORTANT: used as history if "stabilizationStrength != 0" + OUT_SPEC_RADIANCE_HITDIST, // IMPORTANT: used as history if "stabilizationStrength != 0" // SH data // REBLUR: use "REBLUR_BackEnd_UnpackSh" for decoding (2x RGBA16f+) // RELAX: use "RELAX_BackEnd_UnpackSh" for decoding (2x RGBA16f+) - OUT_DIFF_SH0, - OUT_DIFF_SH1, - OUT_SPEC_SH0, - OUT_SPEC_SH1, + OUT_DIFF_SH0, // IMPORTANT: used as history if "stabilizationStrength != 0" + OUT_DIFF_SH1, // IMPORTANT: used as history if "stabilizationStrength != 0" + OUT_SPEC_SH0, // IMPORTANT: used as history if "stabilizationStrength != 0" + OUT_SPEC_SH1, // IMPORTANT: used as history if "stabilizationStrength != 0" // Normalized hit distance (R8+) OUT_DIFF_HITDIST, @@ -131,21 +131,15 @@ namespace nrd // Bent normal and normalized hit distance (RGBA8+) // REBLUR: use "REBLUR_BackEnd_UnpackDirectionalOcclusion" for decoding - OUT_DIFF_DIRECTION_HITDIST, + OUT_DIFF_DIRECTION_HITDIST, // IMPORTANT: used as history if "stabilizationStrength != 0" // Shadow and optional transcluceny (R8+ or RGBA8+) // SIGMA: use "SIGMA_BackEnd_UnpackShadow" for decoding - OUT_SHADOW_TRANSLUCENCY, + OUT_SHADOW_TRANSLUCENCY, // IMPORTANT: used as history if "stabilizationStrength != 0" // Denoised signal (R8+) OUT_SIGNAL, - // 2D screen-space specular motion (RG16f+), MV = previous - current - OUT_REFLECTION_MV, - - // 2D screen-space refraction motion (RG16f+), MV = previous - current - OUT_DELTA_MV, - // (Optional) Debug output (RGBA8+), .w = transparency // Used if "CommonSettings::enableValidation = true" OUT_VALIDATION, @@ -168,10 +162,8 @@ namespace nrd /* IMPORTANT: IN_MV, IN_NORMAL_ROUGHNESS, IN_VIEWZ are used by any denoiser These denoisers DON'T use: - SIGMA_SHADOW - IN_VIEWZ - SIGMA_SHADOW_TRANSLUCENCY - IN_VIEWZ + SIGMA_SHADOW & SIGMA_SHADOW_TRANSLUCENCY - IN_MV, if "stabilizationStrength = 0" REFERENCE - IN_MV, IN_NORMAL_ROUGHNESS, IN_VIEWZ - SPECULAR_DELTA_MV - IN_NORMAL_ROUGHNESS, IN_VIEWZ */ // ============================================================================================================================= @@ -225,18 +217,6 @@ namespace nrd // OUTPUTS - OUT_DIFF_DIRECTION_HITDIST REBLUR_DIFFUSE_DIRECTIONAL_OCCLUSION, - // ============================================================================================================================= - // SIGMA - // ============================================================================================================================= - - // INPUTS - IN_SHADOWDATA, OUT_SHADOW_TRANSLUCENCY (used as history) - // OUTPUTS - OUT_SHADOW_TRANSLUCENCY - SIGMA_SHADOW, - - // INPUTS - IN_SHADOWDATA, IN_SHADOW_TRANSLUCENCY, OUT_SHADOW_TRANSLUCENCY (used as history) - // OUTPUTS - OUT_SHADOW_TRANSLUCENCY - SIGMA_SHADOW_TRANSLUCENCY, - // ============================================================================================================================= // RELAX // ============================================================================================================================= @@ -272,24 +252,24 @@ namespace nrd RELAX_DIFFUSE_SPECULAR_SH, // ============================================================================================================================= - // REFERENCE + // SIGMA // ============================================================================================================================= - // INPUTS - IN_SIGNAL - // OUTPUTS - OUT_SIGNAL - REFERENCE, + // INPUTS - IN_PENUMBRA, OUT_SHADOW_TRANSLUCENCY + // OUTPUTS - OUT_SHADOW_TRANSLUCENCY + SIGMA_SHADOW, + + // INPUTS - IN_PENUMBRA, IN_TRANSLUCENCY, OUT_SHADOW_TRANSLUCENCY + // OUTPUTS - OUT_SHADOW_TRANSLUCENCY + SIGMA_SHADOW_TRANSLUCENCY, // ============================================================================================================================= - // MOTION VECTORS + // REFERENCE // ============================================================================================================================= - // INPUTS - IN_SPEC_HITDIST - // OUTPUTS - OUT_REFLECTION_MV - SPECULAR_REFLECTION_MV, - - // INPUTS - IN_DELTA_PRIMARY_POS, IN_DELTA_SECONDARY_POS - // OUTPUT - OUT_DELTA_MV - SPECULAR_DELTA_MV, + // INPUTS - IN_SIGNAL + // OUTPUTS - OUT_SIGNAL + REFERENCE, MAX_NUM }; @@ -479,7 +459,7 @@ namespace nrd ComputeShaderDesc computeShaderSPIRV; const char* shaderFileName; const char* shaderEntryPointName; - const ResourceRangeDesc* resourceRanges; // up to 2 ranges: "TEXTURE" inputs (optional) and "TEXTURE_STORAGE" outputs + const ResourceRangeDesc* resourceRanges; // up to 2 ranges: "TEXTURE" inputs (optional) and "TEXTURE_STORAGE" outputs uint32_t resourceRangesNum; // Hint that pipeline has a constant buffer with shared parameters from "InstanceDesc" diff --git a/Include/NRDSettings.h b/Include/NRDSettings.h index f0f5a8a..83c11db 100644 --- a/Include/NRDSettings.h +++ b/Include/NRDSettings.h @@ -11,7 +11,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #pragma once #define NRD_SETTINGS_VERSION_MAJOR 4 -#define NRD_SETTINGS_VERSION_MINOR 7 +#define NRD_SETTINGS_VERSION_MINOR 8 static_assert(NRD_VERSION_MAJOR == NRD_SETTINGS_VERSION_MAJOR && NRD_VERSION_MINOR == NRD_SETTINGS_VERSION_MINOR, "Please, update all NRD SDK files"); @@ -109,6 +109,9 @@ namespace nrd uint16_t rectSize[2] = {}; uint16_t rectSizePrev[2] = {}; + // (>0) - viewZ = IN_VIEWZ * viewZScale (mostly for FP16 viewZ) + float viewZScale = 1.0f; + // (ms) - user provided if > 0, otherwise - tracked internally float timeDeltaBetweenFrames = 0.0f; @@ -257,22 +260,6 @@ namespace nrd bool usePrepassOnlyForSpecularMotionEstimation = false; }; - // SIGMA - - struct SigmaSettings - { - // Direction to the light source - // 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 %) - stabilizes output, more stabilization improves antilag (clean signals can use lower values) - // 0 - disables the stabilization pass and makes denoising spatial only (no history) - float stabilizationStrength = 1.0f; - }; - // RELAX const uint32_t RELAX_MAX_HISTORY_FRAME_NUM = 255; @@ -379,25 +366,27 @@ namespace nrd bool enableMaterialTestForSpecular = false; }; - // REFERENCE + // SIGMA - struct ReferenceSettings + struct SigmaSettings { - // (>= 0) - maximum number of linearly accumulated frames ( = FPS * "time of accumulation") - uint32_t maxAccumulatedFrameNum = 1024; - }; + // Direction to the light source + // IMPORTANT: it is needed only for directional light sources (sun) + float lightDirection[3] = {0.0f, 0.0f, 0.0f}; - // SPECULAR_REFLECTION_MV + // (normalized %) - represents maximum allowed deviation from local tangent plane + float planeDistanceSensitivity = 0.005f; - struct SpecularReflectionMvSettings - { - float unused; + // (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) + float stabilizationStrength = 1.0f; }; - // SPECULAR_DELTA_MV + // REFERENCE - struct SpecularDeltaMvSettings + struct ReferenceSettings { - float unused; + // (>= 0) - maximum number of linearly accumulated frames ( = FPS * "time of accumulation") + uint32_t maxAccumulatedFrameNum = 1024; }; } diff --git a/README.md b/README.md index c7d10a3..02ce2d0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# NVIDIA REAL-TIME DENOISERS v4.7.0 (NRD) +# NVIDIA REAL-TIME DENOISERS v4.8.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) @@ -18,7 +18,7 @@ For quick starting see *[NRD sample](https://github.com/NVIDIAGameWorks/NRDSampl 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.30 ms (0.24 mns if temporal stabilization is off) +- `SIGMA_SHADOW` - 0.30 ms (0.24 ms if temporal stabilization is off) - `SIGMA_SHADOW_TRANSLUCENCY` - 0.40 ms (0.30 ms if temporal stabilization is off) Supported signal types: @@ -309,8 +309,8 @@ The *Persistent* column (matches *NRD Permanent pool*) indicates how much of the | | REBLUR_DIFFUSE_SPECULAR_OCCLUSION | 72.12 | 38.12 | 34.00 | | | REBLUR_DIFFUSE_SPECULAR_SH | 270.31 | 105.62 | 164.69 | | | REBLUR_DIFFUSE_DIRECTIONAL_OCCLUSION | 86.69 | 42.25 | 44.44 | -| | SIGMA_SHADOW | 23.38 | 0.00 | 23.38 | -| | SIGMA_SHADOW_TRANSLUCENCY | 42.31 | 0.00 | 42.31 | +| | SIGMA_SHADOW | 15.00 | 0.00 | 15.00 | +| | SIGMA_SHADOW_TRANSLUCENCY | 33.94 | 0.00 | 33.94 | | | RELAX_DIFFUSE | 99.25 | 63.31 | 35.94 | | | RELAX_DIFFUSE_SH | 158.31 | 88.62 | 69.69 | | | RELAX_SPECULAR | 101.44 | 63.38 | 38.06 | @@ -329,8 +329,8 @@ The *Persistent* column (matches *NRD Permanent pool*) indicates how much of the | | REBLUR_DIFFUSE_SPECULAR_OCCLUSION | 127.56 | 67.50 | 60.06 | | | REBLUR_DIFFUSE_SPECULAR_SH | 480.06 | 187.50 | 292.56 | | | REBLUR_DIFFUSE_DIRECTIONAL_OCCLUSION | 153.81 | 75.00 | 78.81 | -| | SIGMA_SHADOW | 41.38 | 0.00 | 41.38 | -| | SIGMA_SHADOW_TRANSLUCENCY | 75.12 | 0.00 | 75.12 | +| | SIGMA_SHADOW | 26.38 | 0.00 | 26.38 | +| | SIGMA_SHADOW_TRANSLUCENCY | 60.12 | 0.00 | 60.12 | | | RELAX_DIFFUSE | 176.31 | 112.50 | 63.81 | | | RELAX_DIFFUSE_SH | 281.31 | 157.50 | 123.81 | | | RELAX_SPECULAR | 180.06 | 112.50 | 67.56 | @@ -349,8 +349,8 @@ The *Persistent* column (matches *NRD Permanent pool*) indicates how much of the | | REBLUR_DIFFUSE_SPECULAR_OCCLUSION | 271.00 | 143.44 | 127.56 | | | REBLUR_DIFFUSE_SPECULAR_SH | 1020.06 | 398.44 | 621.62 | | | REBLUR_DIFFUSE_DIRECTIONAL_OCCLUSION | 326.81 | 159.38 | 167.44 | -| | SIGMA_SHADOW | 88.06 | 0.00 | 88.06 | -| | SIGMA_SHADOW_TRANSLUCENCY | 159.69 | 0.00 | 159.69 | +| | SIGMA_SHADOW | 56.19 | 0.00 | 56.19 | +| | SIGMA_SHADOW_TRANSLUCENCY | 127.81 | 0.00 | 127.81 | | | RELAX_DIFFUSE | 374.69 | 239.12 | 135.56 | | | RELAX_DIFFUSE_SH | 597.81 | 334.75 | 263.06 | | | RELAX_SPECULAR | 382.69 | 239.12 | 143.56 | @@ -749,7 +749,11 @@ maxAccumulatedFrameNum > maxFastAccumulatedFrameNum > historyFixFrameNum **[SIGMA]** Using "blue" noise can help to avoid shadow shimmering. It works best if the pattern is static on the screen. -**[SIGMA]** *SIGMA_TRANSLUCENT_SHADOW* can be used for shadow denoising from multiple light sources: +**[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: + - light count independent memory usage + - no need to manage history buffers for lights + +**[SIGMA]** In theory *SIGMA_TRANSLUCENT_SHADOW* can be used as a "single-pass" shadow denoiser for shadows from multiple light sources: *L[i]* - unshadowed analytical lighting from a single light source (**not noisy**)
*S[i]* - stochastically sampled light visibility for *L[i]* (**noisy**)
@@ -766,7 +770,9 @@ Or:
Input data preparation example: ```cpp float3 Lsum = 0; -float2x3 multiLightShadowData = SIGMA_FrontEnd_MultiLightStart( ); +float3 LSsum = 0.0; +float Wsum = 0.0; +float Psum = 0.0; for( uint i = 0; i < N; i++ ) { @@ -775,15 +781,20 @@ for( uint i = 0; i < N; i++ ) // "distanceToOccluder" should respect rules described in NRD.hlsli in "INPUT PARAMETERS" section float distanceToOccluder = SampleShadow( i ); + float shadow = !IsOccluded( distanceToOccluder ); + LSsum += L * shadow; // The weight should be zero if a pixel is not in the penumbra, but it is not trivial to compute... float weight = ...; + weight *= Luminance( L ); + Wsum += weight; - SIGMA_FrontEnd_MultiLightUpdate( L, distanceToOccluder, tanOfLightAngularRadius, weight, multiLightShadowData ); + float penumbraRadius = SIGMA_FrontEnd_PackPenumbra( ... ).x; + Psum += penumbraRadius * weight; } -float4 shadowTranslucency; -float2 shadowData = SIGMA_FrontEnd_MultiLightEnd( viewZ, multiLightShadowData, Lsum, shadowTranslucency ); +float3 translucency = LSsum / max( Lsum, NRD_EPS ); +float penumbraRadius = Psum / max( Wsum, NRD_EPS ); ``` After denoising the final result can be computed as: @@ -797,7 +808,3 @@ Is this a biased solution? If spatial filtering is off - no, because we just reo - if shadows overlap, a separate pass is needed to analyze noisy input and classify pixels as *umbra* - *penumbra* (and optionally *empty space*). Raster shadow maps can be used for this if available - it is not recommended to mix 1 cd and 100000 cd lights, since FP32 texture will be needed for a weighted sum. In this case, it's better to process the sun and other bright light sources separately. - -**[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: - - light count independent memory usage - - no need to manage history buffers for lights diff --git a/Resources/Version.h b/Resources/Version.h index 02ca3ba..2fde9ab 100644 --- a/Resources/Version.h +++ b/Resources/Version.h @@ -22,7 +22,7 @@ Versioning rules: */ #define VERSION_MAJOR 4 -#define VERSION_MINOR 7 +#define VERSION_MINOR 8 #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 1374289..4aa73fb 100644 --- a/Shaders.cfg +++ b/Shaders.cfg @@ -241,5 +241,3 @@ 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 -SpecularDeltaMv_Compute.cs.hlsl -T cs -SpecularReflectionMv_Compute.cs.hlsl -T cs diff --git a/Shaders/Include/Common.hlsli b/Shaders/Include/Common.hlsli index 176c9ea..6c1063e 100644 --- a/Shaders/Include/Common.hlsli +++ b/Shaders/Include/Common.hlsli @@ -122,7 +122,7 @@ Usage: PrintfAt( "a = %f, b = %f, c = %u", a, b, c ); #endif */ -#if( defined( __hlsl_dx_compiler ) && defined( VULKAN ) ) +#if( defined( __hlsl_dx_compiler ) && defined( __spirv__ ) ) #define PRINTF_AVAILABLE #define PrintfAt(...) \ if( uint( pixelPos.x ) == gPrintfAt.x && uint( pixelPos.y ) == gPrintfAt.y ) \ @@ -198,6 +198,11 @@ static const float3 g_Special8[ 8 ] = #define CompareMaterials( m0, m, mask ) 1.0 #endif +float UnpackViewZ( float z ) +{ + return abs( z * gViewZScale ); +} + float PixelRadiusToWorld( float unproject, float orthoMode, float pixelRadius, float viewZ ) { return pixelRadius * unproject * lerp( viewZ, 1.0, abs( orthoMode ) ); diff --git a/Shaders/Include/NRD.hlsli b/Shaders/Include/NRD.hlsli index 9c37039..0140b9a 100644 --- a/Shaders/Include/NRD.hlsli +++ b/Shaders/Include/NRD.hlsli @@ -8,7 +8,9 @@ distribution of this software and related documentation without an express license agreement from NVIDIA CORPORATION is strictly prohibited. */ -// NRD v4.7 +// NRD v4.8 + +// IMPORTANT: DO NOT MODIFY THIS FILE WITHOUT FULL RECOMPILATION OF NRD LIBRARY! //================================================================================================================================= // INPUT PARAMETERS @@ -64,8 +66,6 @@ float tanOfLightAngularRadius: - in other words, tanOfLightAngularRadius = lightRadius / distanceToLight */ -// IMPORTANT: DO NOT MODIFY THIS FILE WITHOUT FULL RECOMPILATION OF NRD LIBRARY! - #ifndef NRD_INCLUDED #define NRD_INCLUDED @@ -283,11 +283,6 @@ float tanOfLightAngularRadius: #define NRD_INF 1e6 // Misc -float _NRD_PackViewZ( float z ) -{ - return clamp( z * NRD_FP16_VIEWZ_SCALE, -NRD_FP16_MAX, NRD_FP16_MAX ); -} - float3 _NRD_SafeNormalize( float3 v ) { return v * rsqrt( dot( v, v ) + 1e-9 ); @@ -738,75 +733,37 @@ float4 RELAX_FrontEnd_PackSh( float3 radiance, float hitDist, float3 direction, // FRONT-END - SIGMA //================================================================================================================================= -// SIGMA ( single light ) - -// X => IN_SHADOWDATA -float2 SIGMA_FrontEnd_PackShadow( float viewZ, float distanceToOccluder, float tanOfLightAngularRadius ) -{ - float2 r; - r.x = 0.0; - r.y = _NRD_PackViewZ( viewZ ); - - if( distanceToOccluder >= NRD_FP16_MAX ) - r.x = NRD_FP16_MAX; - else if( distanceToOccluder != 0.0 ) - { - float penumbraRadius = distanceToOccluder * tanOfLightAngularRadius; - r.x = min( penumbraRadius, 32768.0 ); - } - - return r; -} +// SIGMA single light -// X => IN_SHADOWDATA and IN_SHADOW_TRANSLUCENCY -float2 SIGMA_FrontEnd_PackShadow( float viewZ, float distanceToOccluder, float tanOfLightAngularRadius, float3 translucency, out float4 out2 ) +// Infinite ( directional ) light source +// X => IN_PENUMBRA +float SIGMA_FrontEnd_PackPenumbra( float distanceToOccluder, float tanOfLightAngularRadius ) { - // IN_SHADOW_TRANSLUCENCY - out2.x = float( distanceToOccluder >= NRD_FP16_MAX ); - out2.yzw = saturate( translucency ); + float penumbraSize = distanceToOccluder * tanOfLightAngularRadius; + float penumbraRadius = penumbraSize * 0.5; - // IN_SHADOWDATA - float2 out1 = SIGMA_FrontEnd_PackShadow( viewZ, distanceToOccluder, tanOfLightAngularRadius ); - - return out1; + return distanceToOccluder >= NRD_FP16_MAX ? NRD_FP16_MAX : min( penumbraRadius, 32768.0 ); } -// SIGMA multi-light ( experimental ) - -#define SIGMA_MULTILIGHT_DATATYPE float2x3 - -SIGMA_MULTILIGHT_DATATYPE SIGMA_FrontEnd_MultiLightStart( ) +// Local light source +// X => IN_PENUMBRA +// "lightSize" must be an acceptable projection to the plane perpendicular to the light direction +float SIGMA_FrontEnd_PackPenumbra( float distanceToOccluder, float distanceToLight, float lightSize ) { - return float2x3( float3( 0, 0, 0 ), float3( 0, 0, 0 ) ); -} + float penumbraSize = lightSize * distanceToOccluder / max( distanceToLight - distanceToOccluder, NRD_EPS ); + float penumbraRadius = penumbraSize * 0.5; -void SIGMA_FrontEnd_MultiLightUpdate( float3 L, float distanceToOccluder, float tanOfLightAngularRadius, float weight, inout SIGMA_MULTILIGHT_DATATYPE multiLightShadowData ) -{ - float shadow = float( distanceToOccluder == NRD_FP16_MAX ); - float distanceToOccluderProj = SIGMA_FrontEnd_PackShadow( 0, distanceToOccluder, tanOfLightAngularRadius ).x; - - // Weighted sum for "pseudo" translucency - multiLightShadowData[ 0 ] += L * shadow; - - // Weighted sum for distance to occluder (denoising will be driven by most important light) - weight *= _NRD_Luminance( L ); - - multiLightShadowData[ 1 ] += float3( distanceToOccluderProj * weight, weight, 0 ); + return distanceToOccluder >= NRD_FP16_MAX ? NRD_FP16_MAX : min( penumbraRadius, 32768.0 ); } -// X => IN_SHADOWDATA and IN_SHADOW_TRANSLUCENCY -float2 SIGMA_FrontEnd_MultiLightEnd( float viewZ, SIGMA_MULTILIGHT_DATATYPE multiLightShadowData, float3 Lsum, out float4 out2 ) +// X => IN_TRANSLUCENCY +float4 SIGMA_FrontEnd_PackTranslucency( float distanceToOccluder, float3 translucency ) { - // IN_SHADOW_TRANSLUCENCY - out2.yzw = multiLightShadowData[ 0 ] / max( Lsum, NRD_EPS ); - out2.x = _NRD_Luminance( out2.yzw ); - - // IN_SHADOWDATA - float2 out1; - out1.x = multiLightShadowData[ 1 ].x / max( multiLightShadowData[ 1 ].y, NRD_EPS ); - out1.y = _NRD_PackViewZ( viewZ ); + float4 r; + r.x = float( distanceToOccluder >= NRD_FP16_MAX ); + r.yzw = saturate( translucency ); - return out1; + return r; } //================================================================================================================================= diff --git a/Shaders/Include/REBLUR_Blur.hlsli b/Shaders/Include/REBLUR_Blur.hlsli index 0721214..b28be56 100644 --- a/Shaders/Include/REBLUR_Blur.hlsli +++ b/Shaders/Include/REBLUR_Blur.hlsli @@ -17,8 +17,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : return; // Early out - float viewZ = abs( gIn_ViewZ[ WithRectOrigin( pixelPos ) ] ); - gOut_ViewZ[ pixelPos ] = PackViewZ( viewZ ); + float viewZ = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( pixelPos ) ] ); + gOut_ViewZ[ pixelPos ] = REBLUR_PackViewZ( viewZ ); if( viewZ > gDenoisingRange ) return; diff --git a/Shaders/Include/REBLUR_Common.hlsli b/Shaders/Include/REBLUR_Common.hlsli index cc0ecb0..0864f69 100644 --- a/Shaders/Include/REBLUR_Common.hlsli +++ b/Shaders/Include/REBLUR_Common.hlsli @@ -22,8 +22,8 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. // Internal data ( from the previous frame ) -#define PackViewZ( p ) min( p * NRD_FP16_VIEWZ_SCALE, NRD_FP16_MAX ) -#define UnpackViewZ( p ) ( p / NRD_FP16_VIEWZ_SCALE ) +#define REBLUR_PackViewZ( p ) min( p * NRD_FP16_VIEWZ_SCALE, NRD_FP16_MAX ) +#define REBLUR_UnpackViewZ( p ) ( p / NRD_FP16_VIEWZ_SCALE ) float4 PackNormalRoughness( float4 p ) { @@ -337,7 +337,8 @@ float2x3 GetKernelBasis( float3 D, float3 N, float NoD, float roughness = 1.0, f float skewFactor = lerp( 0.5 + 0.5 * roughness, 1.0, NoD ); skewFactor = lerp( skewFactor, 1.0, anisoFade ); - T *= skewFactor; // TODO: B /= skewFactor? + //T *= skewFactor; // TODO: let's not srink filtering in the other direction + B /= skewFactor; } return float2x3( T, B ); diff --git a/Shaders/Include/REBLUR_Common_DiffuseSpatialFilter.hlsli b/Shaders/Include/REBLUR_Common_DiffuseSpatialFilter.hlsli index 72b3b47..9b9e887 100644 --- a/Shaders/Include/REBLUR_Common_DiffuseSpatialFilter.hlsli +++ b/Shaders/Include/REBLUR_Common_DiffuseSpatialFilter.hlsli @@ -120,9 +120,9 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. // Fetch data #if( REBLUR_SPATIAL_MODE == REBLUR_POST_BLUR ) - float zs = UnpackViewZ( gIn_ViewZ.SampleLevel( gNearestClamp, uvScaled, 0 ) ); + float zs = REBLUR_UnpackViewZ( gIn_ViewZ.SampleLevel( gNearestClamp, uvScaled, 0 ) ); #else - float zs = abs( gIn_ViewZ.SampleLevel( gNearestClamp, WithRectOffset( uvScaled ), 0 ) ); + float zs = UnpackViewZ( gIn_ViewZ.SampleLevel( gNearestClamp, WithRectOffset( uvScaled ), 0 ) ); #endif float3 Xvs = STL::Geometry::ReconstructViewPosition( uv, gFrustum, zs, gOrthoMode ); diff --git a/Shaders/Include/REBLUR_Common_SpecularSpatialFilter.hlsli b/Shaders/Include/REBLUR_Common_SpecularSpatialFilter.hlsli index cac1136..c473981 100644 --- a/Shaders/Include/REBLUR_Common_SpecularSpatialFilter.hlsli +++ b/Shaders/Include/REBLUR_Common_SpecularSpatialFilter.hlsli @@ -140,9 +140,9 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. // Fetch data #if( REBLUR_SPATIAL_MODE == REBLUR_POST_BLUR ) - float zs = UnpackViewZ( gIn_ViewZ.SampleLevel( gNearestClamp, uvScaled, 0 ) ); + float zs = REBLUR_UnpackViewZ( gIn_ViewZ.SampleLevel( gNearestClamp, uvScaled, 0 ) ); #else - float zs = abs( gIn_ViewZ.SampleLevel( gNearestClamp, WithRectOffset( uvScaled ), 0 ) ); + float zs = UnpackViewZ( gIn_ViewZ.SampleLevel( gNearestClamp, WithRectOffset( uvScaled ), 0 ) ); #endif float3 Xvs = STL::Geometry::ReconstructViewPosition( uv, gFrustum, zs, gOrthoMode ); diff --git a/Shaders/Include/REBLUR_Config.hlsli b/Shaders/Include/REBLUR_Config.hlsli index 85c858a..351c260 100644 --- a/Shaders/Include/REBLUR_Config.hlsli +++ b/Shaders/Include/REBLUR_Config.hlsli @@ -139,6 +139,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. NRD_CONSTANT( float, gUsePrepassNotOnlyForSpecularMotionEstimation ) \ NRD_CONSTANT( float, gSplitScreen ) \ NRD_CONSTANT( float, gCheckerboardResolveAccumSpeed ) \ + NRD_CONSTANT( float, gViewZScale ) \ NRD_CONSTANT( uint, gHasHistoryConfidence ) \ NRD_CONSTANT( uint, gHasDisocclusionThresholdMix ) \ NRD_CONSTANT( uint, gDiffCheckerboard ) \ diff --git a/Shaders/Include/REBLUR_HistoryFix.hlsli b/Shaders/Include/REBLUR_HistoryFix.hlsli index 969494b..40f3c07 100644 --- a/Shaders/Include/REBLUR_HistoryFix.hlsli +++ b/Shaders/Include/REBLUR_HistoryFix.hlsli @@ -42,7 +42,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : return; // Early out - float viewZ = abs( gIn_ViewZ[ WithRectOrigin( pixelPos ) ] ); + float viewZ = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( pixelPos ) ] ); if( viewZ > gDenoisingRange ) return; @@ -148,7 +148,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : pos = clamp( pos, 0, gRectSizeMinusOne ); // Fetch data - float z = abs( gIn_ViewZ[ WithRectOrigin( pos ) ] ); + float z = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( pos ) ] ); float materialIDs; float4 Ns = gIn_Normal_Roughness[ WithRectOrigin( pos ) ]; @@ -337,7 +337,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : pos = clamp( pos, 0, gRectSizeMinusOne ); // Fetch data - float z = abs( gIn_ViewZ[ WithRectOrigin( pos ) ] ); + float z = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( pos ) ] ); float materialIDs; float4 Ns = gIn_Normal_Roughness[ WithRectOrigin( pos ) ]; diff --git a/Shaders/Include/REBLUR_HitDistReconstruction.hlsli b/Shaders/Include/REBLUR_HitDistReconstruction.hlsli index 2b63a2d..7aa1a3c 100644 --- a/Shaders/Include/REBLUR_HitDistReconstruction.hlsli +++ b/Shaders/Include/REBLUR_HitDistReconstruction.hlsli @@ -15,7 +15,7 @@ void Preload( uint2 sharedPos, int2 globalPos ) { globalPos = clamp( globalPos, 0, gRectSizeMinusOne ); - float viewZ = abs( gIn_ViewZ[ WithRectOrigin( globalPos ) ] ); + float viewZ = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( globalPos ) ] ); float4 normalAndRoughness = NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Normal_Roughness[ WithRectOrigin( globalPos ) ] ); s_Normal_Roughness[ sharedPos.y ][ sharedPos.x ] = normalAndRoughness; diff --git a/Shaders/Include/REBLUR_PostBlur.hlsli b/Shaders/Include/REBLUR_PostBlur.hlsli index b1172e6..c2bc692 100644 --- a/Shaders/Include/REBLUR_PostBlur.hlsli +++ b/Shaders/Include/REBLUR_PostBlur.hlsli @@ -22,7 +22,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : } // Early out - float viewZ = UnpackViewZ( gIn_ViewZ[ pixelPos ] ); + float viewZ = REBLUR_UnpackViewZ( gIn_ViewZ[ pixelPos ] ); if( viewZ > gDenoisingRange ) { // ~0 normal is needed to allow bilinear filter in TA ( 0 can't be used due to "division by zero" in "UnpackNormalRoughness" ) diff --git a/Shaders/Include/REBLUR_PrePass.hlsli b/Shaders/Include/REBLUR_PrePass.hlsli index b11918b..e4ad010 100644 --- a/Shaders/Include/REBLUR_PrePass.hlsli +++ b/Shaders/Include/REBLUR_PrePass.hlsli @@ -17,7 +17,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : return; // Early out - float viewZ = abs( gIn_ViewZ[ WithRectOrigin( pixelPos ) ] ); + float viewZ = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( pixelPos ) ] ); if( viewZ > gDenoisingRange ) return; @@ -27,8 +27,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : int3 checkerboardPos = pixelPos.xxy + int3( -1, 1, 0 ); checkerboardPos.x = max( checkerboardPos.x, 0 ); checkerboardPos.y = min( checkerboardPos.y, gRectSizeMinusOne.x ); - float viewZ0 = abs( gIn_ViewZ[ WithRectOrigin( checkerboardPos.xz ) ] ); - float viewZ1 = abs( gIn_ViewZ[ WithRectOrigin( checkerboardPos.yz ) ] ); + 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; diff --git a/Shaders/Include/REBLUR_SplitScreen.hlsli b/Shaders/Include/REBLUR_SplitScreen.hlsli index 9cc9a29..baa8d45 100644 --- a/Shaders/Include/REBLUR_SplitScreen.hlsli +++ b/Shaders/Include/REBLUR_SplitScreen.hlsli @@ -15,7 +15,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 pixelPos : SV_DispatchThreadId ) if( pixelUv.x > gSplitScreen || any( pixelPos > gRectSizeMinusOne ) ) return; - float viewZ = gIn_ViewZ[ WithRectOrigin( pixelPos ) ]; + float viewZ = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( pixelPos ) ] ); uint2 checkerboardPos = pixelPos; #ifdef REBLUR_DIFFUSE diff --git a/Shaders/Include/REBLUR_TemporalAccumulation.hlsli b/Shaders/Include/REBLUR_TemporalAccumulation.hlsli index 86e8cba..690ddee 100644 --- a/Shaders/Include/REBLUR_TemporalAccumulation.hlsli +++ b/Shaders/Include/REBLUR_TemporalAccumulation.hlsli @@ -49,7 +49,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : return; // Early out - float viewZ = abs( gIn_ViewZ[ WithRectOrigin( pixelPos ) ] ); + float viewZ = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( pixelPos ) ] ); if( viewZ > gDenoisingRange ) return; @@ -166,10 +166,10 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float4 smbViewZ2 = gIn_Prev_ViewZ.GatherRed( gNearestClamp, smbCatromGatherUv, float2( 1, 3 ) ).wzxy; float4 smbViewZ3 = gIn_Prev_ViewZ.GatherRed( gNearestClamp, smbCatromGatherUv, float2( 3, 3 ) ).wzxy; - float3 prevViewZ0 = UnpackViewZ( smbViewZ0.yzw ); - float3 prevViewZ1 = UnpackViewZ( smbViewZ1.xzw ); - float3 prevViewZ2 = UnpackViewZ( smbViewZ2.xyw ); - float3 prevViewZ3 = UnpackViewZ( smbViewZ3.xyz ); + float3 prevViewZ0 = REBLUR_UnpackViewZ( smbViewZ0.yzw ); + float3 prevViewZ1 = REBLUR_UnpackViewZ( smbViewZ1.xzw ); + float3 prevViewZ2 = REBLUR_UnpackViewZ( smbViewZ2.xyw ); + float3 prevViewZ3 = REBLUR_UnpackViewZ( smbViewZ3.xyz ); // Previous normal averaged for all pixels in 2x2 footprint // IMPORTANT: bilinear filter can touch sky pixels, due to this reason "Post Blur" writes special values into sky-pixels @@ -271,8 +271,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : int3 checkerboardPos = pixelPos.xxy + int3( -1, 1, 0 ); checkerboardPos.x = max( checkerboardPos.x, 0 ); checkerboardPos.y = min( checkerboardPos.y, gRectSizeMinusOne.x ); - float viewZ0 = abs( gIn_ViewZ[ WithRectOrigin( checkerboardPos.xz ) ] ); - float viewZ1 = abs( gIn_ViewZ[ WithRectOrigin( checkerboardPos.yz ) ] ); + 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; @@ -334,7 +334,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float2 motionUv = pixelUv + 0.99 * deltaUv * gRectSizeInv; // stay in SMEM // Construct the other edge point "x" - float z = abs( gIn_ViewZ.SampleLevel( gLinearClamp, WithRectOffset( motionUv * gResolutionScale ), 0 ) ); + float z = UnpackViewZ( gIn_ViewZ.SampleLevel( gLinearClamp, WithRectOffset( motionUv * gResolutionScale ), 0 ) ); float3 x = STL::Geometry::ReconstructViewPosition( motionUv, gFrustum, z, gOrthoMode ); x = STL::Geometry::RotateVector( gViewToWorld, x ); @@ -358,7 +358,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : if( NRD_USE_HIGH_PARALLAX_CURVATURE && deltaUvLenFixed > 1.0 && IsInScreenNearest( motionUvHigh ) ) { // Construct the other edge point "xHigh" - float zHigh = abs( gIn_ViewZ.SampleLevel( gLinearClamp, WithRectOffset( motionUvHigh * gResolutionScale ), 0 ) ); + float zHigh = UnpackViewZ( gIn_ViewZ.SampleLevel( gLinearClamp, WithRectOffset( motionUvHigh * gResolutionScale ), 0 ) ); float3 xHigh = STL::Geometry::ReconstructViewPosition( motionUvHigh, gFrustum, zHigh, gOrthoMode ); xHigh = STL::Geometry::RotateVector( gViewToWorld, xHigh ); @@ -435,20 +435,24 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float virtualHistoryNormalBasedConfidence = 1.0 / ( 1.0 + 0.5 * Dfactor * saturate( length( N - vmbN ) - NRD_NORMAL_ULP ) * max( parallaxEstimation, vmbPixelsTraveled ) ); // Virtual motion - disocclusion: plane distance and roughness - float4 vmbOcclusionThreshold = disocclusionThresholdMulFrustumSize; - vmbOcclusionThreshold *= lerp( 0.05, 1.0, NoV ); // yes, "*" not "/" - vmbOcclusionThreshold *= float( dot( vmbN, N ) > 0.0 ); // TODO: Navg? - vmbOcclusionThreshold *= IsInScreenBilinear( vmbBilinearFilter.origin, gRectSizePrev ); - vmbOcclusionThreshold -= NRD_EPS; - - float4 vmbViewZ = UnpackViewZ( gIn_Prev_ViewZ.GatherRed( gNearestClamp, vmbBilinearGatherUv ).wzxy ); - float3 vmbVv = STL::Geometry::ReconstructViewPosition( vmbPixelUv, gFrustumPrev, 1.0 ); // unnormalized, orthoMode = 0 - float3 vmbV = STL::Geometry::RotateVectorInverse( gWorldToViewPrev, vmbVv ); - float NoXcurr = dot( N, X - gCameraDelta.xyz ); - float4 NoXprev = ( N.x * vmbV.x + N.y * vmbV.y ) * ( gOrthoMode == 0 ? vmbViewZ : gOrthoMode ) + N.z * vmbV.z * vmbViewZ; - float4 vmbPlaneDist = abs( NoXprev - NoXcurr ); - float4 vmbOcclusion = step( vmbPlaneDist, vmbOcclusionThreshold ); - vmbOcclusion *= step( 0.5, roughnessWeight ); + float4 vmbOcclusion; + { + float4 vmbOcclusionThreshold = disocclusionThresholdMulFrustumSize; + vmbOcclusionThreshold *= lerp( 0.25, 1.0, NoV ); // yes, "*" not "/" // TODO: it's from commit "fixed suboptimal "vmb" reprojection behavior in disocclusions", but is it really needed? + vmbOcclusionThreshold *= float( dot( vmbN, N ) > 0.0 ); // TODO: Navg? + vmbOcclusionThreshold *= IsInScreenBilinear( vmbBilinearFilter.origin, gRectSizePrev ); + vmbOcclusionThreshold -= NRD_EPS; + + float4 vmbViewZ = REBLUR_UnpackViewZ( gIn_Prev_ViewZ.GatherRed( gNearestClamp, vmbBilinearGatherUv ).wzxy ); + float3 vmbVv = STL::Geometry::ReconstructViewPosition( vmbPixelUv, gFrustumPrev, 1.0 ); // unnormalized, orthoMode = 0 + float3 vmbV = STL::Geometry::RotateVectorInverse( gWorldToViewPrev, vmbVv ); + float NoXcurr = dot( N, X - gCameraDelta.xyz ); + float4 NoXprev = ( N.x * vmbV.x + N.y * vmbV.y ) * ( gOrthoMode == 0 ? vmbViewZ : gOrthoMode ) + N.z * vmbV.z * vmbViewZ; + float4 vmbPlaneDist = abs( NoXprev - NoXcurr ); + + vmbOcclusion = step( vmbPlaneDist, vmbOcclusionThreshold ); + vmbOcclusion *= step( 0.5, roughnessWeight ); + } // Virtual motion - disocclusion: materialID uint4 vmbInternalData = gIn_Prev_InternalData.GatherRed( gNearestClamp, vmbBilinearGatherUv ).wzxy; @@ -503,23 +507,26 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Virtual motion - virtual parallax difference // Tests 3, 6, 8, 11, 14, 100, 103, 104, 106, 109, 110, 114, 120, 127, 130, 131, 132, 138, 139 and 9e - float hitDistForTrackingPrev = gIn_Prev_Spec_HitDistForTracking.SampleLevel( gLinearClamp, vmbPixelUv * gResolutionScalePrev, 0 ); - float3 XvirtualPrev = GetXvirtual( hitDistForTrackingPrev, curvature, X, Xprev, V, Dfactor ); - float XvirtualLengthPrev = length( XvirtualPrev ); - float2 vmbPixelUvPrev = STL::Geometry::GetScreenUv( gWorldToClipPrev, XvirtualPrev ); - - #if( REBLUR_USE_MORE_STRICT_PARALLAX_BASED_CHECK == 1 ) - float unproj1 = min( hitDistForTracking, hitDistForTrackingPrev ) / PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, max( XvirtualLength, XvirtualLengthPrev ) ); - float lobeRadiusInPixels = lobeTanHalfAngle * unproj1; - #else - // Works better if "percentOfVolume" is 0.3-0.6 - float unproj1 = hitDistForTracking / PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, XvirtualLength ); - float unproj2 = hitDistForTrackingPrev / PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, XvirtualLengthPrev ); - float lobeRadiusInPixels = lobeTanHalfAngle * min( unproj1, unproj2 ); - #endif + float virtualHistoryParallaxBasedConfidence; + { + float hitDistForTrackingPrev = gIn_Prev_Spec_HitDistForTracking.SampleLevel( gLinearClamp, vmbPixelUv * gResolutionScalePrev, 0 ); + float3 XvirtualPrev = GetXvirtual( hitDistForTrackingPrev, curvature, X, Xprev, V, Dfactor ); + float XvirtualLengthPrev = length( XvirtualPrev ); + float2 vmbPixelUvPrev = STL::Geometry::GetScreenUv( gWorldToClipPrev, XvirtualPrev ); + + #if( REBLUR_USE_MORE_STRICT_PARALLAX_BASED_CHECK == 1 ) + float unproj1 = min( hitDistForTracking, hitDistForTrackingPrev ) / PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, max( XvirtualLength, XvirtualLengthPrev ) ); + float lobeRadiusInPixels = lobeTanHalfAngle * unproj1; + #else + // Works better if "percentOfVolume" is 0.3-0.6 + float unproj1 = hitDistForTracking / PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, XvirtualLength ); + float unproj2 = hitDistForTrackingPrev / PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, XvirtualLengthPrev ); + float lobeRadiusInPixels = lobeTanHalfAngle * min( unproj1, unproj2 ); + #endif - float deltaParallaxInPixels = length( ( vmbPixelUvPrev - vmbPixelUv ) * gRectSize ); - float virtualHistoryParallaxBasedConfidence = STL::Math::SmoothStep( lobeRadiusInPixels + 0.25, 0.0, deltaParallaxInPixels ); + float deltaParallaxInPixels = length( ( vmbPixelUvPrev - vmbPixelUv ) * gRectSize ); + virtualHistoryParallaxBasedConfidence = STL::Math::SmoothStep( lobeRadiusInPixels + 0.25, 0.0, deltaParallaxInPixels ); + } // Virtual motion - normal & roughness prev-prev tests // IMPORTANT: 2 is needed because: @@ -596,7 +603,14 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Virtual history amount - other ( tests 65, 66, 103, 111, 132, e9, e11 ) virtualHistoryAmount *= STL::Math::SmoothStep( 0.05, 0.95, Dfactor ); virtualHistoryAmount *= virtualHistoryRoughnessBasedConfidence; - virtualHistoryAmount *= saturate( vmbSpecAccumSpeed / ( smbSpecAccumSpeed + NRD_EPS ) ); // *** + + // Fallback to "smb" if "vmb" history is short // *** + // Interactive comparison of two methods: https://www.desmos.com/calculator/syocjyk9wc + // TODO: the amount gets shifted heavily towards "smb" if "smb" > "vmb" even by 5 frames + float vmbToSmbRatio = saturate( vmbSpecAccumSpeed / ( smbSpecAccumSpeed + NRD_EPS ) ); + float smbBonusFrames = max( smbSpecAccumSpeed - vmbSpecAccumSpeed, 0.0 ); + virtualHistoryAmount *= vmbToSmbRatio; + virtualHistoryAmount /= 1.0 + smbBonusFrames * ( 1.0 - vmbToSmbRatio ); #if( REBLUR_VIRTUAL_HISTORY_AMOUNT != 2 ) virtualHistoryAmount = REBLUR_VIRTUAL_HISTORY_AMOUNT; diff --git a/Shaders/Include/REBLUR_TemporalStabilization.hlsli b/Shaders/Include/REBLUR_TemporalStabilization.hlsli index 6943f4a..b46f76c 100644 --- a/Shaders/Include/REBLUR_TemporalStabilization.hlsli +++ b/Shaders/Include/REBLUR_TemporalStabilization.hlsli @@ -49,7 +49,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : return; // Early out - float viewZ = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( pixelPos ) ] ); + float viewZ = REBLUR_UnpackViewZ( gIn_ViewZ[ WithRectOrigin( pixelPos ) ] ); if( viewZ > gDenoisingRange ) return; // IMPORTANT: no data output, must be rejected by the "viewZ" check! diff --git a/Shaders/Include/RELAX_Config.hlsli b/Shaders/Include/RELAX_Config.hlsli index 62b92db..d7ec060 100644 --- a/Shaders/Include/RELAX_Config.hlsli +++ b/Shaders/Include/RELAX_Config.hlsli @@ -80,6 +80,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. NRD_CONSTANT( float, gJitterDelta ) \ NRD_CONSTANT( float, gHistoryFixFrameNum ) \ NRD_CONSTANT( float, gHistoryThreshold ) \ + NRD_CONSTANT( float, gViewZScale ) \ NRD_CONSTANT( uint, gRoughnessEdgeStoppingEnabled ) \ NRD_CONSTANT( uint, gFrameIndex ) \ NRD_CONSTANT( uint, gDiffCheckerboard ) \ diff --git a/Shaders/Include/RELAX_PrePass.hlsli b/Shaders/Include/RELAX_PrePass.hlsli index e113dcd..9c8b69b 100644 --- a/Shaders/Include/RELAX_PrePass.hlsli +++ b/Shaders/Include/RELAX_PrePass.hlsli @@ -143,7 +143,7 @@ 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 = abs(gViewZ.SampleLevel(gNearestClamp, WithRectOffset(uvScaled), 0)); + float sampleViewZ = UnpackViewZ(gViewZ.SampleLevel(gNearestClamp, WithRectOffset(uvScaled), 0)); float3 sampleWorldPos = GetCurrentWorldPosFromClipSpaceXY(uv * 2.0 - 1.0, sampleViewZ); // Sample weight @@ -286,7 +286,7 @@ NRD_EXPORT void NRD_CS_MAIN(int2 pixelPos : SV_DispatchThreadId, uint2 threadPos float4 sampleNormalRoughness = NRD_FrontEnd_UnpackNormalAndRoughness(gNormalRoughness.SampleLevel(gNearestClamp, WithRectOffset(uvScaled), 0), sampleMaterialID); float3 sampleNormal = sampleNormalRoughness.rgb; float sampleRoughness = sampleNormalRoughness.a; - float sampleViewZ = abs(gViewZ.SampleLevel(gNearestClamp, WithRectOffset(uvScaled), 0)); + float sampleViewZ = UnpackViewZ(gViewZ.SampleLevel(gNearestClamp, WithRectOffset(uvScaled), 0)); // Sample weight float sampleWeight = IsInScreenNearest(uv); diff --git a/Shaders/Include/RELAX_SplitScreen.hlsli b/Shaders/Include/RELAX_SplitScreen.hlsli index dfae7b6..fba7543 100644 --- a/Shaders/Include/RELAX_SplitScreen.hlsli +++ b/Shaders/Include/RELAX_SplitScreen.hlsli @@ -15,7 +15,7 @@ NRD_EXPORT void NRD_CS_MAIN( uint2 pixelPos : SV_DispatchThreadId ) if( pixelUv.x > gSplitScreen || any( pixelPos >= gRectSize ) ) return; - float viewZ = gIn_ViewZ[ WithRectOrigin( pixelPos ) ]; + float viewZ = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( pixelPos ) ] ); uint2 checkerboardPos = pixelPos; #ifdef RELAX_DIFFUSE diff --git a/Shaders/Include/RELAX_TemporalAccumulation.hlsli b/Shaders/Include/RELAX_TemporalAccumulation.hlsli index d3deeec..bdaf2a5 100644 --- a/Shaders/Include/RELAX_TemporalAccumulation.hlsli +++ b/Shaders/Include/RELAX_TemporalAccumulation.hlsli @@ -654,7 +654,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo float2 motionUv = pixelUv + 0.99 * deltaUv * gRectSizeInv; // stay in SMEM // Construct the other edge point "x" - float z = abs(gViewZ.SampleLevel(gLinearClamp, WithRectOffset(motionUv * gResolutionScale), 0)); + float z = UnpackViewZ(gViewZ.SampleLevel(gLinearClamp, WithRectOffset(motionUv * gResolutionScale), 0)); float3 x = GetCurrentWorldPosFromClipSpaceXY(motionUv * 2.0 - 1.0, z); // Interpolate normal at "x" @@ -676,7 +676,7 @@ NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId, uint2 threadPo float2 motionUvHigh = pixelUv + deltaUvLenFixed * deltaUv * gRectSizeInv; if (NRD_USE_HIGH_PARALLAX_CURVATURE && deltaUvLenFixed > 1.0 && IsInScreenNearest(motionUvHigh)) { - float zHigh = abs(gViewZ.SampleLevel(gLinearClamp, WithRectOffset(motionUvHigh * gResolutionScale), 0)); + float zHigh = UnpackViewZ(gViewZ.SampleLevel(gLinearClamp, WithRectOffset(motionUvHigh * gResolutionScale), 0)); float3 xHigh = GetCurrentWorldPosFromClipSpaceXY(motionUvHigh * 2.0 - 1.0, zHigh); #if( NRD_NORMAL_ENCODING == NRD_NORMAL_ENCODING_R10G10B10A2_UNORM ) diff --git a/Shaders/Include/SIGMA_Blur.hlsli b/Shaders/Include/SIGMA_Blur.hlsli index 98ecfb4..86592b2 100644 --- a/Shaders/Include/SIGMA_Blur.hlsli +++ b/Shaders/Include/SIGMA_Blur.hlsli @@ -8,17 +8,18 @@ distribution of this software and related documentation without an express license agreement from NVIDIA CORPORATION is strictly prohibited. */ -groupshared float2 s_Data[ BUFFER_Y ][ BUFFER_X ]; +groupshared float2 s_Penumbra_ViewZ[ 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 = gIn_Hit_ViewZ[ globalPos ]; - data.y = abs( data.y ) / NRD_FP16_VIEWZ_SCALE; + float2 data; + data.x = gIn_Penumbra[ globalPos ]; + data.y = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( globalPos ) ] ); - s_Data[ sharedPos.y ][ sharedPos.x ] = data; + s_Penumbra_ViewZ[ sharedPos.y ][ sharedPos.x ] = data; SIGMA_TYPE s; #if( !defined SIGMA_FIRST_PASS || defined SIGMA_TRANSLUCENT ) @@ -47,8 +48,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Center data int2 smemPos = threadPos + BORDER; - float2 centerData = s_Data[ smemPos.y ][ smemPos.x ]; - float centerHitDist = centerData.x; + float2 centerData = s_Penumbra_ViewZ[ smemPos.y ][ smemPos.x ]; + float centerPenumbra = centerData.x; float centerSignNoL = float( centerData.x != 0.0 ); float viewZ = centerData.y; @@ -69,9 +70,9 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : tileValue *= all( pixelPos < gRectSize ); // due to USE_MAX_DIMS #endif - if( ( tileValue == 0.0 && NRD_USE_TILE_CHECK ) || centerHitDist == 0.0 ) + if( ( tileValue == 0.0 && NRD_USE_TILE_CHECK ) || centerPenumbra == 0.0 ) { - gOut_Hit_ViewZ[ pixelPos ] = float2( 0.0, viewZ * NRD_FP16_VIEWZ_SCALE ); + gOut_Penumbra[ pixelPos ] = 0; gOut_Shadow_Translucency[ pixelPos ] = PackShadow( s_Shadow_Translucency[ smemPos.y ][ smemPos.x ] ); return; @@ -91,7 +92,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Estimate average distance to occluder float2 sum = 0; - float hitDist = 0; + float penumbra = 0; SIGMA_TYPE result = 0; [unroll] @@ -102,9 +103,9 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : { int2 pos = threadPos + int2( i, j ); - float2 data = s_Data[ pos.y ][ pos.x ]; - float h = data.x; - float signNoL = float( data.x != 0.0 ); + float2 data = s_Penumbra_ViewZ[ pos.y ][ pos.x ]; + float p = data.x; + float signNoL = float( p != 0.0 ); float z = data.y; float w = 1.0; @@ -124,25 +125,19 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : s = Denanify( w, s ); float2 ww = w; - ww.y *= float( s.x != 1.0 ); // TODO: what if s.x == 1.0, but h < NRD_FP16_MAX? - ww.y *= 1.0 / ( 1.0 + h * SIGMA_PENUMBRA_WEIGHT_SCALE ); // prefer smaller penumbra + ww.y *= !IsLit( p ); + ww.y *= 1.0 / ( 1.0 + p * SIGMA_PENUMBRA_WEIGHT_SCALE ); // prefer smaller penumbra result += s * ww.x; - hitDist += h * ww.y; + penumbra += p * ww.y; sum += ww; } } - result /= sum.x; - hitDist /= max( sum.y, NRD_EPS ); // yes, without patching - - float invHitDist = 1.0 / max( hitDist, NRD_EPS ); + result /= sum.x; // TODO: lerp to center if blur radius < BORDER + penumbra /= max( sum.y, NRD_EPS ); // yes, without patching - // Blur radius - float unprojectZ = PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, viewZ ); - float worldRadius = GetKernelRadiusInPixels( hitDist, unprojectZ ) * unprojectZ; - worldRadius *= tileValue; // helps to prevent blurring "inside" umbra - worldRadius /= SIGMA_SPATIAL_PASSES_NUM; + float invHitDist = 1.0 / max( penumbra, NRD_EPS ); // Tangent basis with anisotropy float3x3 mWorldToLocal = STL::Geometry::GetBasis( Nv ); @@ -158,10 +153,14 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float cosa = abs( dot( Nv, gLightDirectionView.xyz ) ); float skewFactor = lerp( 0.25, 1.0, cosa ); - //Tv *= skewFactor; // TODO: needed? + //Tv *= skewFactor; // TODO: let's not srink filtering in the other direction Bv /= skewFactor; } + // Blur radius + float unprojectZ = PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, viewZ ); + float worldRadius = GetKernelRadiusInPixels( penumbra, unprojectZ, tileValue ) * unprojectZ; + Tv *= worldRadius; Bv *= worldRadius; @@ -186,10 +185,9 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : float2 uvScaled = ClampUvToViewport( uv ); // Fetch data - float2 data = gIn_Hit_ViewZ.SampleLevel( gNearestClamp, uvScaled, 0 ); - float h = data.x; - float signNoL = float( data.x != 0.0 ); - float z = abs( data.y ) / NRD_FP16_VIEWZ_SCALE; + float p = gIn_Penumbra.SampleLevel( gNearestClamp, uvScaled, 0 ); + float signNoL = float( p != 0.0 ); + float z = UnpackViewZ( gIn_ViewZ.SampleLevel( gNearestClamp, WithRectOffset( uvScaled ), 0 ) ); // Sample weight float3 Xvs = STL::Geometry::ReconstructViewPosition( uv, gFrustum, z, gOrthoMode ); @@ -202,7 +200,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : w *= float( centerSignNoL == signNoL ); // Avoid umbra leaking inside wide penumbra - float t = saturate( h * invHitDist ); + float t = saturate( p * invHitDist ); w *= STL::Math::LinearStep( 0.0, 0.1, t ); // Fetch shadow @@ -210,7 +208,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : #if( !defined SIGMA_FIRST_PASS || defined SIGMA_TRANSLUCENT ) s = gIn_Shadow_Translucency.SampleLevel( gNearestClamp, uvScaled, 0 ); #else - s = IsLit( h ); + s = IsLit( p ); #endif s = Denanify( w, s ); @@ -220,22 +218,22 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Accumulate float2 ww = w; - ww.y *= float( s.x != 1.0 ); // TODO: what if s.x == 1.0, but h < NRD_FP16_MAX? - ww.y *= 1.0 / ( 1.0 + h * SIGMA_PENUMBRA_WEIGHT_SCALE ); // prefer smaller penumbra + ww.y *= !IsLit( p ); + ww.y *= 1.0 / ( 1.0 + p * SIGMA_PENUMBRA_WEIGHT_SCALE ); // prefer smaller penumbra result += s * ww.x; - hitDist += h * ww.y; + penumbra += p * ww.y; sum += ww; } result /= sum.x; - hitDist = sum.y == 0.0 ? centerHitDist : hitDist / sum.y; + penumbra = sum.y == 0.0 ? centerPenumbra : penumbra / sum.y; // Output #ifndef SIGMA_FIRST_PASS if( gStabilizationStrength != 0 ) #endif - gOut_Hit_ViewZ[ pixelPos ] = float2( hitDist, viewZ * NRD_FP16_VIEWZ_SCALE ); + gOut_Penumbra[ pixelPos ] = penumbra; gOut_Shadow_Translucency[ pixelPos ] = PackShadow( result ); } diff --git a/Shaders/Include/SIGMA_ClassifyTiles.hlsli b/Shaders/Include/SIGMA_ClassifyTiles.hlsli index 8fcd422..9887eb5 100644 --- a/Shaders/Include/SIGMA_ClassifyTiles.hlsli +++ b/Shaders/Include/SIGMA_ClassifyTiles.hlsli @@ -34,13 +34,12 @@ NRD_EXPORT void NRD_CS_MAIN( uint2 threadPos : SV_GroupThreadId, uint2 tilePos : for( uint j = 0; j < 4; j++ ) { uint2 pos = pixelPos + uint2( i, j ); - float2 data = gIn_Hit_ViewZ[ pos ]; - - float viewZ = abs( data.y ) / NRD_FP16_VIEWZ_SCALE; + float h = gIn_Penumbra[ pos ]; + float viewZ = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( pos ) ] ); bool isInf = viewZ > gDenoisingRange; - bool isShadow = data.x == 0; - bool isLit = IsLit( data.x ); + bool isShadow = h == 0; + bool isLit = IsLit( h ); bool isOpaque = true; #ifdef SIGMA_TRANSLUCENT @@ -52,7 +51,7 @@ NRD_EXPORT void NRD_CS_MAIN( uint2 threadPos : SV_GroupThreadId, uint2 tilePos : mask += ( ( ( !isLit && isOpaque ) || isInf || isShadow ) ? 1 : 0 ) << 9; mask += ( isInf ? 1 : 0 ) << 18; - float hitDist = ( isLit || isInf ) ? 0 : data.x; + float hitDist = ( isLit || isInf ) ? 0 : h; float unprojectZ = PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, viewZ ); float pixelRadius = GetKernelRadiusInPixels( hitDist, unprojectZ ); diff --git a/Shaders/Include/SIGMA_Common.hlsli b/Shaders/Include/SIGMA_Common.hlsli index b779b06..c71387f 100644 --- a/Shaders/Include/SIGMA_Common.hlsli +++ b/Shaders/Include/SIGMA_Common.hlsli @@ -11,14 +11,14 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. // Misc #define PackShadow( s ) STL::Math::Sqrt01( s ) // must match "SIGMA_BackEnd_UnpackShadow" -#define IsLit( h ) ( h >= NRD_FP16_MAX ) +#define IsLit( p ) ( p >= NRD_FP16_MAX ) -float GetKernelRadiusInPixels( float hitDist, float unprojectZ ) +float GetKernelRadiusInPixels( float hitDist, float unprojectZ, float scale = 1.0 ) { - float pixelRadius = hitDist / unprojectZ; - pixelRadius = min( pixelRadius, SIGMA_MAX_PIXEL_RADIUS ); + float unclampedRadius = hitDist / unprojectZ; + float minRadius = min( unclampedRadius, BORDER ); - return pixelRadius; + return clamp( unclampedRadius * scale, minRadius, SIGMA_MAX_PIXEL_RADIUS ); } // TODO: move code below to STL.hlsl diff --git a/Shaders/Include/SIGMA_Config.hlsli b/Shaders/Include/SIGMA_Config.hlsli index f62ef56..8b61452 100644 --- a/Shaders/Include/SIGMA_Config.hlsli +++ b/Shaders/Include/SIGMA_Config.hlsli @@ -23,10 +23,9 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #define SIGMA_ROTATOR_MODE NRD_FRAME #define SIGMA_POISSON_SAMPLE_NUM 8 #define SIGMA_POISSON_SAMPLES g_Special8 -#define SIGMA_MAX_PIXEL_RADIUS 32.0 +#define SIGMA_MAX_PIXEL_RADIUS 16.0 // TODO: at least 32 needed for test 200 #define SIGMA_PENUMBRA_WEIGHT_SCALE 10.0 #define SIGMA_MAX_SIGMA_SCALE 3.0 -#define SIGMA_SPATIAL_PASSES_NUM 2 #define SIGMA_TS_MOTION_MAX_REUSE 0.11 // Data type @@ -62,4 +61,5 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. NRD_CONSTANT( float, gStabilizationStrength ) \ NRD_CONSTANT( float, gDebug ) \ NRD_CONSTANT( float, gSplitScreen ) \ + NRD_CONSTANT( float, gViewZScale ) \ NRD_CONSTANT( uint, gFrameIndex ) diff --git a/Shaders/Include/SIGMA_SplitScreen.hlsli b/Shaders/Include/SIGMA_SplitScreen.hlsli index 7f41e45..9f09b6d 100644 --- a/Shaders/Include/SIGMA_SplitScreen.hlsli +++ b/Shaders/Include/SIGMA_SplitScreen.hlsli @@ -15,8 +15,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 pixelPos : SV_DispatchThreadId) if( pixelUv.x > gSplitScreen || any( pixelPos > gRectSizeMinusOne ) ) return; - float2 data = gIn_Hit_ViewZ[ pixelPos ]; - float viewZ = abs( data.y ) / NRD_FP16_VIEWZ_SCALE; + float2 data = gIn_Penumbra[ pixelPos ]; + float viewZ = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( pixelPos ) ] ); SIGMA_TYPE s; #ifdef SIGMA_TRANSLUCENT diff --git a/Shaders/Include/SIGMA_TemporalStabilization.hlsli b/Shaders/Include/SIGMA_TemporalStabilization.hlsli index 3fbb865..e7db0b8 100644 --- a/Shaders/Include/SIGMA_TemporalStabilization.hlsli +++ b/Shaders/Include/SIGMA_TemporalStabilization.hlsli @@ -8,17 +8,18 @@ distribution of this software and related documentation without an express license agreement from NVIDIA CORPORATION is strictly prohibited. */ -groupshared float2 s_Data[ BUFFER_Y ][ BUFFER_X ]; +groupshared float2 s_Penumbra_ViewZ[ 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 = gIn_Hit_ViewZ[ globalPos ]; - data.y = abs( data.y ) / NRD_FP16_VIEWZ_SCALE; + float2 data; + data.x = gIn_Penumbra[ globalPos ]; + data.y = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( globalPos ) ] ); - s_Data[ sharedPos.y ][ sharedPos.x ] = data; + s_Penumbra_ViewZ[ sharedPos.y ][ sharedPos.x ] = data; SIGMA_TYPE s = gIn_Shadow_Translucency[ globalPos ]; s = SIGMA_BackEnd_UnpackShadow( s ); @@ -39,8 +40,8 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Center data int2 smemPos = threadPos + BORDER; - float2 centerData = s_Data[ smemPos.y ][ smemPos.x ]; - float centerHitDist = centerData.x; + float2 centerData = s_Penumbra_ViewZ[ smemPos.y ][ smemPos.x ]; + float centerPenumbra = centerData.x; float centerSignNoL = float( centerData.x != 0.0 ); float viewZ = centerData.y; @@ -49,7 +50,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : return; // Early out - if( centerHitDist == 0.0 && SIGMA_SHOW_TILES == 0 ) + if( centerPenumbra == 0.0 && SIGMA_SHOW_TILES == 0 ) { gOut_Shadow_Translucency[ pixelPos ] = PackShadow( s_Shadow_Translucency[ smemPos.y ][ smemPos.x ] ); @@ -72,7 +73,7 @@ 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_Data[ pos.y ][ pos.x ]; + float2 data = s_Penumbra_ViewZ[ pos.y ][ pos.x ]; SIGMA_TYPE s = s_Shadow_Translucency[ pos.y ][ pos.x ]; float signNoL = float( data.x != 0.0 ); @@ -155,7 +156,7 @@ NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : // Reduce history in regions with hard shadows float unprojectZ = PixelRadiusToWorld( gUnproject, gOrthoMode, 1.0, viewZ ); - float pixelRadius = GetKernelRadiusInPixels( centerHitDist, unprojectZ ); + float pixelRadius = GetKernelRadiusInPixels( centerPenumbra, unprojectZ ); historyWeight *= STL::Math::LinearStep( 0.0, 0.5, pixelRadius ); // Combine with current frame diff --git a/Shaders/Resources/Clear_Float.resources.hlsli b/Shaders/Resources/Clear_Float.resources.hlsli index e85a08e..1d810ec 100644 --- a/Shaders/Resources/Clear_Float.resources.hlsli +++ b/Shaders/Resources/Clear_Float.resources.hlsli @@ -10,6 +10,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. NRD_CONSTANTS_START( Clear_FloatConstants ) NRD_CONSTANT( float, gDebug ) // only for availability in Common.hlsl + NRD_CONSTANT( float, gViewZScale ) // only for availability in Common.hlsl NRD_CONSTANTS_END NRD_OUTPUTS_START diff --git a/Shaders/Resources/Clear_Uint.resources.hlsli b/Shaders/Resources/Clear_Uint.resources.hlsli index c267dcc..9880501 100644 --- a/Shaders/Resources/Clear_Uint.resources.hlsli +++ b/Shaders/Resources/Clear_Uint.resources.hlsli @@ -10,6 +10,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. NRD_CONSTANTS_START( Clear_UintConstants ) NRD_CONSTANT( float, gDebug ) // only for availability in Common.hlsl + NRD_CONSTANT( float, gViewZScale ) // only for availability in Common.hlsl NRD_CONSTANTS_END NRD_OUTPUTS_START diff --git a/Shaders/Resources/REFERENCE_SplitScreen.resources.hlsli b/Shaders/Resources/REFERENCE_SplitScreen.resources.hlsli index c42e6f4..02d3beb 100644 --- a/Shaders/Resources/REFERENCE_SplitScreen.resources.hlsli +++ b/Shaders/Resources/REFERENCE_SplitScreen.resources.hlsli @@ -10,6 +10,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. NRD_CONSTANTS_START( REFERENCE_SplitScreenConstants ) NRD_CONSTANT( float, gDebug ) // only for availability in Common.hlsl + NRD_CONSTANT( float, gViewZScale ) // only for availability in Common.hlsl NRD_CONSTANTS_END NRD_INPUTS_START diff --git a/Shaders/Resources/REFERENCE_TemporalAccumulation.resources.hlsli b/Shaders/Resources/REFERENCE_TemporalAccumulation.resources.hlsli index 1bcac13..db9a397 100644 --- a/Shaders/Resources/REFERENCE_TemporalAccumulation.resources.hlsli +++ b/Shaders/Resources/REFERENCE_TemporalAccumulation.resources.hlsli @@ -13,7 +13,8 @@ NRD_CONSTANTS_START( REFERENCE_TemporalAccumulationConstants ) NRD_CONSTANT( float2, gRectSizeInv ) NRD_CONSTANT( float, gSplitScreen ) NRD_CONSTANT( float, gAccumSpeed ) - NRD_CONSTANT( float, gDebug ) + NRD_CONSTANT( float, gDebug ) // only for availability in Common.hlsl + NRD_CONSTANT( float, gViewZScale ) // only for availability in Common.hlsl NRD_CONSTANTS_END NRD_INPUTS_START diff --git a/Shaders/Resources/SIGMA_Blur.resources.hlsli b/Shaders/Resources/SIGMA_Blur.resources.hlsli index 8479b18..9f47b3f 100644 --- a/Shaders/Resources/SIGMA_Blur.resources.hlsli +++ b/Shaders/Resources/SIGMA_Blur.resources.hlsli @@ -19,21 +19,22 @@ NRD_SAMPLERS_START NRD_SAMPLERS_END NRD_INPUTS_START - NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 0 ) - NRD_INPUT( Texture2D, gIn_Hit_ViewZ, t, 1 ) - NRD_INPUT( Texture2D, gIn_Tiles, t, 2 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 0 ) + 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, 3 ) + NRD_INPUT( Texture2D, gIn_History, t, 4 ) #ifdef SIGMA_TRANSLUCENT - NRD_INPUT( Texture2D, gIn_Shadow_Translucency, t, 4 ) + NRD_INPUT( Texture2D, gIn_Shadow_Translucency, t, 5 ) #endif #else - NRD_INPUT( Texture2D, gIn_Shadow_Translucency, t, 3 ) + NRD_INPUT( Texture2D, gIn_Shadow_Translucency, t, 4 ) #endif NRD_INPUTS_END NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOut_Hit_ViewZ, u, 0 ) + 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 ) diff --git a/Shaders/Resources/SIGMA_ClassifyTiles.resources.hlsli b/Shaders/Resources/SIGMA_ClassifyTiles.resources.hlsli index c3c2288..d5c3647 100644 --- a/Shaders/Resources/SIGMA_ClassifyTiles.resources.hlsli +++ b/Shaders/Resources/SIGMA_ClassifyTiles.resources.hlsli @@ -18,9 +18,10 @@ NRD_SAMPLERS_START NRD_SAMPLERS_END NRD_INPUTS_START - NRD_INPUT( Texture2D, gIn_Hit_ViewZ, t, 0 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 0 ) + NRD_INPUT( Texture2D, gIn_Penumbra, t, 1 ) #ifdef SIGMA_TRANSLUCENT - NRD_INPUT( Texture2D, gIn_Shadow_Translucency, t, 1 ) + NRD_INPUT( Texture2D, gIn_Shadow_Translucency, t, 2 ) #endif NRD_INPUTS_END diff --git a/Shaders/Resources/SIGMA_SplitScreen.resources.hlsli b/Shaders/Resources/SIGMA_SplitScreen.resources.hlsli index c6485c8..0309875 100644 --- a/Shaders/Resources/SIGMA_SplitScreen.resources.hlsli +++ b/Shaders/Resources/SIGMA_SplitScreen.resources.hlsli @@ -18,9 +18,10 @@ NRD_SAMPLERS_START NRD_SAMPLERS_END NRD_INPUTS_START - NRD_INPUT( Texture2D, gIn_Hit_ViewZ, t, 0 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 0 ) + NRD_INPUT( Texture2D, gIn_Penumbra, t, 1 ) #ifdef SIGMA_TRANSLUCENT - NRD_INPUT( Texture2D, gIn_Shadow_Translucency, t, 1 ) + NRD_INPUT( Texture2D, gIn_Shadow_Translucency, t, 2 ) #endif NRD_INPUTS_END diff --git a/Shaders/Resources/SIGMA_TemporalStabilization.resources.hlsli b/Shaders/Resources/SIGMA_TemporalStabilization.resources.hlsli index 51eba5b..4045d46 100644 --- a/Shaders/Resources/SIGMA_TemporalStabilization.resources.hlsli +++ b/Shaders/Resources/SIGMA_TemporalStabilization.resources.hlsli @@ -18,11 +18,12 @@ NRD_SAMPLERS_START NRD_SAMPLERS_END NRD_INPUTS_START - NRD_INPUT( Texture2D, gIn_Mv, t, 0 ) - NRD_INPUT( Texture2D, gIn_Hit_ViewZ, t, 1 ) - NRD_INPUT( Texture2D, gIn_Shadow_Translucency, t, 2 ) - NRD_INPUT( Texture2D, gIn_History, t, 3 ) - NRD_INPUT( Texture2D, gIn_Tiles, t, 4 ) + NRD_INPUT( Texture2D, gIn_ViewZ, t, 0 ) + NRD_INPUT( Texture2D, gIn_Mv, t, 1 ) + 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_INPUTS_END NRD_OUTPUTS_START diff --git a/Shaders/Resources/SpecularDeltaMv_Compute.resources.hlsli b/Shaders/Resources/SpecularDeltaMv_Compute.resources.hlsli deleted file mode 100644 index 1a2e416..0000000 --- a/Shaders/Resources/SpecularDeltaMv_Compute.resources.hlsli +++ /dev/null @@ -1,45 +0,0 @@ -/* -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( SpecularDeltaMv_ComputeConstants ) - NRD_CONSTANT( float4x4, gWorldToClipPrev ) - NRD_CONSTANT( float4, gMvScale ) - NRD_CONSTANT( uint2, gRectOrigin ) - NRD_CONSTANT( uint2, gRectSize ) - NRD_CONSTANT( float2, gRectSizeInv ) - NRD_CONSTANT( float, gDebug ) -NRD_CONSTANTS_END - -NRD_SAMPLERS_START - NRD_SAMPLER( SamplerState, gNearestClamp, s, 0 ) - NRD_SAMPLER( SamplerState, gLinearClamp, s, 1 ) -NRD_SAMPLERS_END - -NRD_INPUTS_START - NRD_INPUT( Texture2D, gIn_Mv, t, 0 ) - NRD_INPUT( Texture2D, gIn_DeltaPrimaryPos, t, 1 ) - NRD_INPUT( Texture2D, gIn_DeltaSecondaryPos, t, 2 ) - NRD_INPUT( Texture2D, gIn_PrevDeltaSecondaryPos, t, 3 ) -NRD_INPUTS_END - -NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOut_DeltaMv, u, 0 ) - NRD_OUTPUT( RWTexture2D, gOut_DeltaSecondaryPos, u, 1 ) -NRD_OUTPUTS_END - -// Macro magic -#define SpecularDeltaMv_ComputeGroupX 16 -#define SpecularDeltaMv_ComputeGroupY 16 - -// Redirection -#undef GROUP_X -#undef GROUP_Y -#define GROUP_X SpecularDeltaMv_ComputeGroupX -#define GROUP_Y SpecularDeltaMv_ComputeGroupY diff --git a/Shaders/Resources/SpecularReflectionMv_Compute.resources.hlsli b/Shaders/Resources/SpecularReflectionMv_Compute.resources.hlsli deleted file mode 100644 index 393ac49..0000000 --- a/Shaders/Resources/SpecularReflectionMv_Compute.resources.hlsli +++ /dev/null @@ -1,56 +0,0 @@ -/* -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( SpecularReflectionMv_ComputeConstants ) - NRD_CONSTANT( float4x4, gViewToWorld ) - NRD_CONSTANT( float4x4, gWorldToClip ) - NRD_CONSTANT( float4x4, gWorldToClipPrev ) - NRD_CONSTANT( float4x4, gWorldToViewPrev ) - NRD_CONSTANT( float4, gFrustumPrev ) - NRD_CONSTANT( float4, gFrustum ) - NRD_CONSTANT( float4, gViewVectorWorld ) // .w - unused - NRD_CONSTANT( float4, gCameraDelta ) // .w - unused - NRD_CONSTANT( float4, gMvScale ) - NRD_CONSTANT( float2, gRectSize ) - NRD_CONSTANT( float2, gRectSizeInv ) - NRD_CONSTANT( float2, gRectOffset ) - NRD_CONSTANT( float2, gResolutionScale ) - NRD_CONSTANT( uint2, gRectOrigin ) - NRD_CONSTANT( float, gDenoisingRange ) - NRD_CONSTANT( float, gOrthoMode ) - NRD_CONSTANT( float, gUnproject ) - NRD_CONSTANT( float, gDebug ) -NRD_CONSTANTS_END - -NRD_SAMPLERS_START - NRD_SAMPLER( SamplerState, gNearestClamp, s, 0 ) - NRD_SAMPLER( SamplerState, gLinearClamp, s, 1 ) -NRD_SAMPLERS_END - -NRD_INPUTS_START - NRD_INPUT( Texture2D, gIn_Mv, t, 0 ) - NRD_INPUT( Texture2D, gIn_Normal_Roughness, t, 1 ) - NRD_INPUT( Texture2D, gIn_ViewZ, t, 2 ) - NRD_INPUT( Texture2D, gIn_HitDist, t, 3 ) -NRD_INPUTS_END - -NRD_OUTPUTS_START - NRD_OUTPUT( RWTexture2D, gOut_SpecularReflectionMv, u, 0 ) -NRD_OUTPUTS_END - -// Macro magic -#define SpecularReflectionMv_ComputeGroupX 16 -#define SpecularReflectionMv_ComputeGroupY 16 - -// Redirection -#undef GROUP_X -#undef GROUP_Y -#define GROUP_X SpecularReflectionMv_ComputeGroupX -#define GROUP_Y SpecularReflectionMv_ComputeGroupY diff --git a/Shaders/Source/REBLUR_ClassifyTiles.cs.hlsl b/Shaders/Source/REBLUR_ClassifyTiles.cs.hlsl index 6bf381f..c97a7f6 100644 --- a/Shaders/Source/REBLUR_ClassifyTiles.cs.hlsl +++ b/Shaders/Source/REBLUR_ClassifyTiles.cs.hlsl @@ -14,6 +14,8 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #include "REBLUR_Config.hlsli" #include "REBLUR_ClassifyTiles.resources.hlsli" +#include "Common.hlsli" + groupshared uint s_isSky; [numthreads( 8, 4, 1 )] @@ -34,7 +36,7 @@ NRD_EXPORT void NRD_CS_MAIN( uint2 threadPos : SV_GroupThreadId, uint2 tilePos : for( uint j = 0; j < 4; j++ ) { uint2 pos = pixelPos + uint2( i, j ); - float viewZ = abs( gIn_ViewZ[ pos ] ); + float viewZ = UnpackViewZ( gIn_ViewZ[ WithRectOrigin( pos ) ] ); isSky += viewZ > gDenoisingRange ? 1 : 0; } diff --git a/Shaders/Source/REBLUR_Validation.cs.hlsl b/Shaders/Source/REBLUR_Validation.cs.hlsl index 8f35ddf..c3be5c2 100644 --- a/Shaders/Source/REBLUR_Validation.cs.hlsl +++ b/Shaders/Source/REBLUR_Validation.cs.hlsl @@ -45,9 +45,9 @@ NRD_EXPORT void NRD_CS_MAIN( uint2 pixelPos : SV_DispatchThreadId ) float2 viewportUvScaled = viewportUv * gResolutionScale; - float4 normalAndRoughness = NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Normal_Roughness.SampleLevel( gNearestClamp, viewportUvScaled, 0 ) ); - float viewZ = gIn_ViewZ.SampleLevel( gNearestClamp, viewportUvScaled, 0 ); - float3 mv = gIn_Mv.SampleLevel( gNearestClamp, viewportUvScaled, 0 ) * gMvScale.xyz; + float4 normalAndRoughness = NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Normal_Roughness.SampleLevel( gNearestClamp, WithRectOffset( viewportUvScaled ), 0 ) ); + float viewZ = UnpackViewZ( gIn_ViewZ.SampleLevel( gNearestClamp, WithRectOffset( viewportUvScaled ), 0 ) ); + float3 mv = gIn_Mv.SampleLevel( gNearestClamp, WithRectOffset( viewportUvScaled ), 0 ) * gMvScale.xyz; float4 diff = gIn_Diff.SampleLevel( gNearestClamp, viewportUvScaled * float2( gDiffCheckerboard != 2 ? 0.5 : 1.0, 1.0 ), 0 ); float4 spec = gIn_Spec.SampleLevel( gNearestClamp, viewportUvScaled * float2( gSpecCheckerboard != 2 ? 0.5 : 1.0, 1.0 ), 0 ); diff --git a/Shaders/Source/SpecularDeltaMv_Compute.cs.hlsl b/Shaders/Source/SpecularDeltaMv_Compute.cs.hlsl deleted file mode 100644 index fe29acd..0000000 --- a/Shaders/Source/SpecularDeltaMv_Compute.cs.hlsl +++ /dev/null @@ -1,149 +0,0 @@ -/* -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 "STL.hlsli" - -#include "SpecularDeltaMv_Compute.resources.hlsli" - -#include "Common.hlsli" - -// acos(dot(a,b)) has severe precision issues for small angles -// length(cross(a,b)) == length(a) * length(b) * sin(angle) -// dot(a,b) == length(a) * length(b) * cos(angle) -float GetAngle(float3 a, float3 b) -{ - float s = saturate(length(cross(a, b))); - float c = saturate(dot(a, b)); - return atan2(s, c); -} - -float3 LoadCandidate(float2 samplePos) -{ - return gIn_PrevDeltaSecondaryPos.SampleLevel(gLinearClamp, samplePos * gRectSizeInv, 0.f).xyz; -} - -float LoadAngle(float2 samplePos, float3 primaryPos, float3 refDir) -{ - float3 candidate = LoadCandidate(samplePos); - float3 cDir = normalize(candidate - primaryPos); - float angle = GetAngle(cDir, refDir); - // angle^2 behaves much better - return angle * angle; -} - -[numthreads(GROUP_X, GROUP_Y, 1)] -NRD_EXPORT void NRD_CS_MAIN(uint2 pixelPos : SV_DispatchThreadId) -{ - static const float kMotionEpsilon = 1.e-4; - static const float kAngleEpsilon = 1.e-8; - static const float kAngleConvergenceEpsilon = 1.e-2; - // TODO: Expose these 2 parameters - static const uint kMaxNewtonMethodIterations = 5; - static const uint kMaxLineSearchIterations = 10; - - if (any(pixelPos >= gRectSize)) - return; - - float3 primaryPos = gIn_DeltaPrimaryPos[ pixelPos ].xyz; - float3 secondaryPos = gIn_DeltaSecondaryPos[ pixelPos ].xyz; - - float3 mv = gIn_Mv[ WithRectOrigin( pixelPos ) ] * gMvScale.xyz; - float2 pixelUv = float2(pixelPos + 0.5) * gRectSizeInv; - float2 prevPixelUV = pixelUv + mv.xy; - if( gMvScale.w != 0.0 ) - prevPixelUV = STL::Geometry::GetScreenUv( gWorldToClipPrev, primaryPos + mv ); - - gOut_DeltaSecondaryPos[ pixelPos ] = secondaryPos; - - float2 initialScreenMotion = prevPixelUV - pixelUv; - - // TODO: Add detection for secondary motion. - if (length(initialScreenMotion) >= kMotionEpsilon) - { - float2 prevSamplePos = prevPixelUV * gRectSize; - - float3 v = normalize(secondaryPos - primaryPos); - - float currAngle = LoadAngle(prevSamplePos, primaryPos, v); - - for (uint i = 0; i < kMaxNewtonMethodIterations; ++i) - { - if (currAngle < kAngleEpsilon) - { - gOut_DeltaMv[ pixelPos ] = prevSamplePos * gRectSizeInv - pixelUv; - return; - } - - const float h = 1.f; - float da_dx = (LoadAngle(prevSamplePos + float2(h, 0), primaryPos, v) - LoadAngle(prevSamplePos + float2(-h, 0), primaryPos, v)) / (2.f * h); - float da_dy = (LoadAngle(prevSamplePos + float2(0, h), primaryPos, v) - LoadAngle(prevSamplePos + float2(0, -h), primaryPos, v)) / (2.f * h); - float d2a_dx2 = (LoadAngle(prevSamplePos + float2(h, 0), primaryPos, v) - 2 * currAngle + LoadAngle(prevSamplePos + float2(-h, 0), primaryPos, v)) / (h * h); - float d2a_dy2 = (LoadAngle(prevSamplePos + float2(0, h), primaryPos, v) - 2 * currAngle + LoadAngle(prevSamplePos + float2(0, -h), primaryPos, v)) / (h * h); - float d2a_dxdy = ( - LoadAngle(prevSamplePos + float2(h, h), primaryPos, v) - - LoadAngle(prevSamplePos + float2(h, -h), primaryPos, v) - - LoadAngle(prevSamplePos + float2(-h, h), primaryPos, v) - + LoadAngle(prevSamplePos + float2(-h, -h), primaryPos, v) - ) / (4.f * h * h); - - // Gradient - float f0 = da_dx; - float f1 = da_dy; - - // Hessian - float j00 = d2a_dx2; - float j01 = d2a_dxdy; - float j11 = d2a_dy2; - - // Hessian inverse - float tmp1 = j00*j11 - j01*j01; - - // Can't find a suitable position, fallback to primary surface mvec - if (abs(tmp1) < 1e-15) - { - gOut_DeltaMv[ pixelPos ] = initialScreenMotion; - return; - } - - tmp1 = 1.f / tmp1; - float J00 = j11 * tmp1; - float J01 = -j01 * tmp1; - float J10 = -j01 * tmp1; - float J11 = j00 * tmp1; - - float2 displacement = -float2(J00*f0 + J01*f1, J10*f0 + J11*f1); - - // Backtracking line search with Armijo condition - float t = 1.0; - float alpha = 0.01; // in (0, 0.5] - float beta = 0.5; // in (0, 1) - float2 grad = float2(f0, f1); - - float tmp2 = alpha * dot(grad, displacement); - uint iter = 0; - while (LoadAngle(prevSamplePos + t * displacement, primaryPos, v) > (currAngle + t * tmp2) && iter < kMaxLineSearchIterations) - { - t = beta * t; - ++iter; - } - - prevSamplePos += t * displacement; - } - - if (currAngle < kAngleConvergenceEpsilon) - { - gOut_DeltaMv[ pixelPos ] = prevSamplePos * gRectSizeInv - pixelUv; - return; - } - } - - gOut_DeltaMv[ pixelPos ] = initialScreenMotion; -} diff --git a/Shaders/Source/SpecularReflectionMv_Compute.cs.hlsl b/Shaders/Source/SpecularReflectionMv_Compute.cs.hlsl deleted file mode 100644 index c2f6eb0..0000000 --- a/Shaders/Source/SpecularReflectionMv_Compute.cs.hlsl +++ /dev/null @@ -1,199 +0,0 @@ -/* -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 "STL.hlsli" - -#include "SpecularReflectionMv_Compute.resources.hlsli" - -#include "Common.hlsli" - -groupshared float4 s_Normal_Roughness[ BUFFER_Y ][ BUFFER_X ]; - -void Preload( uint2 sharedPos, int2 globalPos ) -{ - globalPos = clamp( globalPos, 0, gRectSize - 1.0 ); - - s_Normal_Roughness[ sharedPos.y ][ sharedPos.x ] = NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Normal_Roughness[ WithRectOrigin( globalPos ) ] ); -} - -float3 GetViewVector( float3 X, bool isViewSpace = false ) -{ - return gOrthoMode == 0.0 ? normalize( -X ) : ( isViewSpace ? float3( 0, 0, -1 ) : gViewVectorWorld.xyz ); -} - -[numthreads( GROUP_X, GROUP_Y, 1 )] -NRD_EXPORT void NRD_CS_MAIN( int2 threadPos : SV_GroupThreadId, int2 pixelPos : SV_DispatchThreadId, uint threadIndex : SV_GroupIndex ) -{ - float2 pixelUv = float2( pixelPos + 0.5 ) * gRectSizeInv; - - PRELOAD_INTO_SMEM; - - // Early out - float viewZ = gIn_ViewZ[ WithRectOrigin( pixelPos ) ]; - - [branch] - if( viewZ > gDenoisingRange ) - return; - - // Normal and roughness - int2 smemPos = threadPos + BORDER; - float4 normalAndRoughness = s_Normal_Roughness[ smemPos.y ][ smemPos.x ]; - float3 N = normalAndRoughness.xyz; - float roughness = normalAndRoughness.w; - - // Current position and view vectir - float3 Xv = STL::Geometry::ReconstructViewPosition( pixelUv, gFrustum, viewZ, gOrthoMode ); - float3 X = STL::Geometry::RotateVector( gViewToWorld, Xv ); - float3 V = GetViewVector( X ); - float NoV = abs( dot( N, V ) ); - - // Previous position and surface motion uv - float3 mv = gIn_Mv[ WithRectOrigin( pixelPos ) ] * gMvScale.xyz; - float3 Xprev = X; - float2 smbPixelUv = pixelUv + mv.xy; - - if( gMvScale.w != 0.0 ) - { - Xprev += mv; - smbPixelUv = STL::Geometry::GetScreenUv( gWorldToClipPrev, Xprev ); - } - else - { - if( gMvScale.z == 0.0 ) - mv.z = STL::Geometry::AffineTransform( gWorldToViewPrev, X ).z - viewZ; - - float viewZprev = viewZ + mv.z; - float3 Xvprevlocal = STL::Geometry::ReconstructViewPosition( smbPixelUv, gFrustumPrev, viewZprev, gOrthoMode ); // TODO: use gOrthoModePrev - - Xprev = STL::Geometry::RotateVectorInverse( gWorldToViewPrev, Xvprevlocal ) + gCameraDelta.xyz; - } - - // Modified roughness - float3 Navg = N; - - [unroll] - for( j = 0; j <= BORDER * 2; j++ ) - { - [unroll] - for( i = 0; i <= BORDER * 2; i++ ) - { - if( i == BORDER && j == BORDER ) - continue; - - int2 pos = threadPos + int2( i, j ); - Navg += s_Normal_Roughness[ pos.y ][ pos.x ].xyz; - } - } - - Navg /= ( BORDER * 2 + 1 ) * ( BORDER * 2 + 1 ); // needs to be unnormalized! - - float roughnessModified = STL::Filtering::GetModifiedRoughnessFromNormalVariance( roughness, Navg ); - - // Parallax - float smbParallaxInPixels = ComputeParallaxInPixels( Xprev - gCameraDelta.xyz, gOrthoMode == 0.0 ? pixelUv : smbPixelUv, gWorldToClip, gRectSize ); - - // Hit distance - float hitDistForTracking = gIn_HitDist[ pixelPos ]; // TODO: min hitDist logic from REBLUR / RELAX needed - - // Curvature - float curvature; - { - // IMPORTANT: this code allows to get non-zero parallax on objects attached to the camera - float2 uvForZeroParallax = gOrthoMode == 0.0 ? smbPixelUv : pixelUv; - float2 deltaUv = STL::Geometry::GetScreenUv( gWorldToClipPrev, Xprev - 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 = abs( gIn_ViewZ.SampleLevel( gLinearClamp, WithRectOffset( motionUv * gResolutionScale ), 0 ) ); - float3 x = STL::Geometry::ReconstructViewPosition( motionUv, gFrustum, z, gOrthoMode ); - x = STL::Geometry::RotateVector( gViewToWorld, x ); - - // Interpolate normal at "x" - STL::Filtering::Bilinear f = STL::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 = 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; - - float3 n = _NRD_SafeNormalize( STL::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 ) ) - { - // Construct the other edge point "xHigh" - float zHigh = abs( gIn_ViewZ.SampleLevel( gLinearClamp, WithRectOffset( motionUvHigh * gResolutionScale ), 0 ) ); - float3 xHigh = STL::Geometry::ReconstructViewPosition( motionUvHigh, gFrustum, zHigh, gOrthoMode ); - xHigh = STL::Geometry::RotateVector( gViewToWorld, xHigh ); - - // Interpolate normal at "xHigh" - #if( NRD_NORMAL_ENCODING == NRD_NORMAL_ENCODING_R10G10B10A2_UNORM ) - f = STL::Filtering::GetBilinearFilter( motionUvHigh, gRectSize ); - - f.origin = clamp( f.origin, 0, gRectSize - 2.0 ); - pos = gRectOrigin + int2( f.origin ); - - n00 = NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Normal_Roughness[ pos ] ).xyz; - n10 = NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Normal_Roughness[ pos + int2( 1, 0 ) ] ).xyz; - n01 = NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Normal_Roughness[ pos + int2( 0, 1 ) ] ).xyz; - n11 = NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Normal_Roughness[ pos + int2( 1, 1 ) ] ).xyz; - - float3 nHigh = _NRD_SafeNormalize( STL::Filtering::ApplyBilinearFilter( n00, n10, n01, n11, f ) ); - #else - float3 nHigh = NRD_FrontEnd_UnpackNormalAndRoughness( gIn_Normal_Roughness.SampleLevel( gLinearClamp, WithRectOffset( motionUvHigh * gResolutionScale ), 0 ) ).xyz; - #endif - - // Replace if same surface - float zError = abs( zHigh - viewZ ) * rcp( max( zHigh, viewZ ) ); - bool cmp = zError < NRD_CURVATURE_Z_THRESHOLD; - - n = cmp ? nHigh : n; - x = cmp ? xHigh : x; - } - - // Estimate curvature for the edge { x; X } - float3 edge = x - X; - float edgeLenSq = STL::Math::LengthSquared( edge ); - curvature = dot( n - N, edge ) * STL::Math::PositiveRcp( edgeLenSq ); - - // Correction #1 - values below this threshold get turned into garbage due to numerical imprecision - float d = STL::Math::ManhattanDistance( N, n ); - float s = STL::Math::LinearStep( NRD_NORMAL_ENCODING_ERROR, 2.0 * NRD_NORMAL_ENCODING_ERROR, d ); - curvature *= s; - - // Correction #2 - this is needed if camera is "inside" a concave mirror ( tests 133, 164, 171 - 176 ) - if( length( X ) < -1.0 / curvature ) - curvature *= NoV; - - // Correction #3 - very negative inconsistent with previous frame curvature blows up reprojection ( tests 164, 171 - 176 ) - float2 uv1 = STL::Geometry::GetScreenUv( gWorldToClipPrev, X - V * ApplyThinLensEquation( hitDistForTracking, curvature ) ); - float2 uv2 = STL::Geometry::GetScreenUv( gWorldToClipPrev, X ); - float a = length( ( uv1 - uv2 ) * gRectSize ); - curvature *= float( a < NRD_MAX_ALLOWED_VIRTUAL_MOTION_ACCELERATION * deltaUvLen + gRectSizeInv.x ); - } - - // Virtual motion - float dominantFactor = STL::ImportanceSampling::GetSpecularDominantFactor( NoV, roughnessModified, STL_SPECULAR_DOMINANT_DIRECTION_G2 ); - - float3 Xvirtual = GetXvirtual( hitDistForTracking, curvature, X, Xprev, V, dominantFactor ); - float2 vmbPixelUv = STL::Geometry::GetScreenUv( gWorldToClipPrev, Xvirtual ); - - gOut_SpecularReflectionMv[ pixelPos ] = vmbPixelUv - pixelUv; -} diff --git a/Source/Denoisers/Sigma_Shadow.hpp b/Source/Denoisers/Sigma_Shadow.hpp index 08e5ca0..564e5b1 100644 --- a/Source/Denoisers/Sigma_Shadow.hpp +++ b/Source/Denoisers/Sigma_Shadow.hpp @@ -26,8 +26,8 @@ void nrd::InstanceImpl::Add_SigmaShadow(DenoiserData& denoiserData) SMOOTHED_TILES, }; - AddTextureToTransientPool( {Format::RG16_SFLOAT, 1} ); - AddTextureToTransientPool( {Format::RG16_SFLOAT, 1} ); + AddTextureToTransientPool( {Format::R16_SFLOAT, 1} ); + AddTextureToTransientPool( {Format::R16_SFLOAT, 1} ); AddTextureToTransientPool( {Format::R8_UNORM, 1} ); AddTextureToTransientPool( {Format::R8_UNORM, 1} ); AddTextureToTransientPool( {Format::R8_UNORM, 1} ); @@ -36,7 +36,8 @@ void nrd::InstanceImpl::Add_SigmaShadow(DenoiserData& denoiserData) PushPass("Classify tiles"); { - PushInput( AsUint(ResourceType::IN_SHADOWDATA) ); + PushInput( AsUint(ResourceType::IN_VIEWZ) ); + PushInput( AsUint(ResourceType::IN_PENUMBRA) ); PushOutput( AsUint(Transient::TILES) ); @@ -54,8 +55,9 @@ void nrd::InstanceImpl::Add_SigmaShadow(DenoiserData& denoiserData) PushPass("Blur"); { + PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::IN_NORMAL_ROUGHNESS) ); - PushInput( AsUint(ResourceType::IN_SHADOWDATA) ); + PushInput( AsUint(ResourceType::IN_PENUMBRA) ); PushInput( AsUint(Transient::SMOOTHED_TILES) ); PushInput( AsUint(ResourceType::OUT_SHADOW_TRANSLUCENCY) ); @@ -72,6 +74,7 @@ void nrd::InstanceImpl::Add_SigmaShadow(DenoiserData& denoiserData) PushPass("Post-blur"); { + PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::IN_NORMAL_ROUGHNESS) ); PushInput( AsUint(Transient::DATA_1) ); PushInput( AsUint(Transient::SMOOTHED_TILES) ); @@ -86,6 +89,7 @@ void nrd::InstanceImpl::Add_SigmaShadow(DenoiserData& denoiserData) PushPass("Temporal stabilization"); { + PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::IN_MV) ); PushInput( AsUint(Transient::DATA_2) ); PushInput( AsUint(Transient::TEMP_2) ); @@ -99,7 +103,8 @@ void nrd::InstanceImpl::Add_SigmaShadow(DenoiserData& denoiserData) PushPass("Split screen"); { - PushInput( AsUint(ResourceType::IN_SHADOWDATA) ); + PushInput( AsUint(ResourceType::IN_VIEWZ) ); + PushInput( AsUint(ResourceType::IN_PENUMBRA) ); PushOutput( AsUint(ResourceType::OUT_SHADOW_TRANSLUCENCY) ); diff --git a/Source/Denoisers/Sigma_ShadowTranslucency.hpp b/Source/Denoisers/Sigma_ShadowTranslucency.hpp index 4cd7c9f..f677e16 100644 --- a/Source/Denoisers/Sigma_ShadowTranslucency.hpp +++ b/Source/Denoisers/Sigma_ShadowTranslucency.hpp @@ -14,7 +14,7 @@ void nrd::InstanceImpl::Add_SigmaShadowTranslucency(nrd::DenoiserData& denoiserD denoiserData.settings.sigma = SigmaSettings(); denoiserData.settingsSize = sizeof(denoiserData.settings.sigma); - + enum class Transient { DATA_1 = TRANSIENT_POOL_START, @@ -26,8 +26,8 @@ void nrd::InstanceImpl::Add_SigmaShadowTranslucency(nrd::DenoiserData& denoiserD SMOOTHED_TILES, }; - AddTextureToTransientPool( {Format::RG16_SFLOAT, 1} ); - AddTextureToTransientPool( {Format::RG16_SFLOAT, 1} ); + AddTextureToTransientPool( {Format::R16_SFLOAT, 1} ); + AddTextureToTransientPool( {Format::R16_SFLOAT, 1} ); AddTextureToTransientPool( {Format::RGBA8_UNORM, 1} ); AddTextureToTransientPool( {Format::RGBA8_UNORM, 1} ); AddTextureToTransientPool( {Format::RGBA8_UNORM, 1} ); @@ -36,8 +36,9 @@ void nrd::InstanceImpl::Add_SigmaShadowTranslucency(nrd::DenoiserData& denoiserD PushPass("Classify tiles"); { - PushInput( AsUint(ResourceType::IN_SHADOWDATA) ); - PushInput( AsUint(ResourceType::IN_SHADOW_TRANSLUCENCY) ); + PushInput( AsUint(ResourceType::IN_VIEWZ) ); + PushInput( AsUint(ResourceType::IN_PENUMBRA) ); + PushInput( AsUint(ResourceType::IN_TRANSLUCENCY) ); PushOutput( AsUint(Transient::TILES) ); @@ -55,11 +56,12 @@ void nrd::InstanceImpl::Add_SigmaShadowTranslucency(nrd::DenoiserData& denoiserD PushPass("Blur"); { + PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::IN_NORMAL_ROUGHNESS) ); - PushInput( AsUint(ResourceType::IN_SHADOWDATA) ); + PushInput( AsUint(ResourceType::IN_PENUMBRA) ); PushInput( AsUint(Transient::SMOOTHED_TILES) ); PushInput( AsUint(ResourceType::OUT_SHADOW_TRANSLUCENCY) ); - PushInput( AsUint(ResourceType::IN_SHADOW_TRANSLUCENCY) ); + PushInput( AsUint(ResourceType::IN_TRANSLUCENCY) ); PushOutput( AsUint(Transient::DATA_1) ); PushOutput( AsUint(Transient::TEMP_1) ); @@ -74,6 +76,7 @@ void nrd::InstanceImpl::Add_SigmaShadowTranslucency(nrd::DenoiserData& denoiserD PushPass("Post-blur"); { + PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::IN_NORMAL_ROUGHNESS) ); PushInput( AsUint(Transient::DATA_1) ); PushInput( AsUint(Transient::SMOOTHED_TILES) ); @@ -88,6 +91,7 @@ void nrd::InstanceImpl::Add_SigmaShadowTranslucency(nrd::DenoiserData& denoiserD PushPass("Temporal stabilization"); { + PushInput( AsUint(ResourceType::IN_VIEWZ) ); PushInput( AsUint(ResourceType::IN_MV) ); PushInput( AsUint(Transient::DATA_2) ); PushInput( AsUint(Transient::TEMP_2) ); @@ -101,8 +105,9 @@ void nrd::InstanceImpl::Add_SigmaShadowTranslucency(nrd::DenoiserData& denoiserD PushPass("Split screen"); { - PushInput( AsUint(ResourceType::IN_SHADOWDATA) ); - PushInput( AsUint(ResourceType::IN_SHADOW_TRANSLUCENCY) ); + PushInput( AsUint(ResourceType::IN_VIEWZ) ); + PushInput( AsUint(ResourceType::IN_PENUMBRA) ); + PushInput( AsUint(ResourceType::IN_TRANSLUCENCY) ); PushOutput( AsUint(ResourceType::OUT_SHADOW_TRANSLUCENCY) ); diff --git a/Source/Denoisers/SpecularDeltaMv.hpp b/Source/Denoisers/SpecularDeltaMv.hpp deleted file mode 100644 index ee4921f..0000000 --- a/Source/Denoisers/SpecularDeltaMv.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* -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 "../Shaders/Resources/SpecularDeltaMv_Compute.resources.hlsli" - -void nrd::InstanceImpl::Add_SpecularDeltaMv(DenoiserData& denoiserData) -{ - #define DENOISER_NAME SpecularDeltaMv - - denoiserData.settings.specularDeltaMv = SpecularDeltaMvSettings(); - denoiserData.settingsSize = sizeof(denoiserData.settings.specularDeltaMv); - - enum class Permanent - { - DELTA_SECONDARY_POS_CURR = PERMANENT_POOL_START, - DELTA_SECONDARY_POS_PREV - }; - - AddTextureToPermanentPool( {Format::RGBA32_SFLOAT, 1} ); - AddTextureToPermanentPool( {Format::RGBA32_SFLOAT, 1} ); - - PushPass("Compute"); - { - PushInput( AsUint(ResourceType::IN_MV) ); - PushInput( AsUint(ResourceType::IN_DELTA_PRIMARY_POS) ); - PushInput( AsUint(ResourceType::IN_DELTA_SECONDARY_POS) ); - PushInput( AsUint(Permanent::DELTA_SECONDARY_POS_PREV), AsUint(Permanent::DELTA_SECONDARY_POS_CURR) ); - - PushOutput( AsUint(ResourceType::OUT_DELTA_MV) ); - PushOutput( AsUint(Permanent::DELTA_SECONDARY_POS_CURR), AsUint(Permanent::DELTA_SECONDARY_POS_PREV) ); - - AddDispatch( SpecularDeltaMv_Compute, SpecularDeltaMv_Compute, 1 ); - } - - #undef DENOISER_NAME -} - -void nrd::InstanceImpl::Update_SpecularDeltaMv(const DenoiserData& denoiserData) -{ - enum class Dispatch - { - COMPUTE, - }; - - NRD_DECLARE_DIMS; - - { // COMPUTE - SpecularDeltaMv_ComputeConstants* consts = (SpecularDeltaMv_ComputeConstants*)PushDispatch(denoiserData, AsUint(Dispatch::COMPUTE)); - consts->gWorldToClipPrev = m_WorldToClipPrev; - consts->gMvScale = float4(m_CommonSettings.motionVectorScale[0], m_CommonSettings.motionVectorScale[1], m_CommonSettings.motionVectorScale[2], m_CommonSettings.isMotionVectorInWorldSpace ? 1.0f : 0.0f); - consts->gRectOrigin = uint2(m_CommonSettings.rectOrigin[0], m_CommonSettings.rectOrigin[1]); - consts->gRectSize = uint2(rectW, rectH); - consts->gRectSizeInv = float2(1.0f / float(rectW), 1.0f / float(rectH)); - consts->gDebug = m_CommonSettings.debug; - } -} diff --git a/Source/Denoisers/SpecularReflectionMv.hpp b/Source/Denoisers/SpecularReflectionMv.hpp deleted file mode 100644 index 002e690..0000000 --- a/Source/Denoisers/SpecularReflectionMv.hpp +++ /dev/null @@ -1,67 +0,0 @@ -/* -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 "../Shaders/Resources/SpecularReflectionMv_Compute.resources.hlsli" - -void nrd::InstanceImpl::Add_SpecularReflectionMv(DenoiserData& denoiserData) -{ - #define DENOISER_NAME SpecularReflectionMv - - denoiserData.settings.specularReflectionMv = SpecularReflectionMvSettings(); - denoiserData.settingsSize = sizeof(denoiserData.settings.specularReflectionMv); - - PushPass("Compute"); - { - PushInput( AsUint(ResourceType::IN_MV) ); - PushInput( AsUint(ResourceType::IN_NORMAL_ROUGHNESS) ); - PushInput( AsUint(ResourceType::IN_VIEWZ) ); - PushInput( AsUint(ResourceType::IN_SPEC_HITDIST) ); - - PushOutput( AsUint(ResourceType::OUT_REFLECTION_MV) ); - - AddDispatch( SpecularReflectionMv_Compute, SpecularReflectionMv_Compute, 1 ); - } - - #undef DENOISER_NAME -} - -void nrd::InstanceImpl::Update_SpecularReflectionMv(const DenoiserData& denoiserData) -{ - enum class Dispatch - { - COMPUTE, - }; - - NRD_DECLARE_DIMS; - - float unproject = 1.0f / (0.5f * rectH * m_ProjectY); - - { // COMPUTE - SpecularReflectionMv_ComputeConstants* consts = (SpecularReflectionMv_ComputeConstants*)PushDispatch(denoiserData, AsUint(Dispatch::COMPUTE)); - consts->gViewToWorld = m_ViewToWorld; - consts->gWorldToClip = m_WorldToClip; - consts->gWorldToClipPrev = m_WorldToClipPrev; - consts->gWorldToViewPrev = m_WorldToViewPrev; - consts->gFrustumPrev = m_FrustumPrev; - consts->gFrustum = m_Frustum; - consts->gViewVectorWorld = float4(m_ViewDirection.x, m_ViewDirection.y, m_ViewDirection.z, 0.0f); - consts->gCameraDelta = float4(m_CameraDelta.x, m_CameraDelta.y, m_CameraDelta.z, 0.0f); - consts->gMvScale = float4(m_CommonSettings.motionVectorScale[0], m_CommonSettings.motionVectorScale[1], m_CommonSettings.motionVectorScale[2], m_CommonSettings.isMotionVectorInWorldSpace ? 1.0f : 0.0f); - consts->gRectSize = float2(float(rectW), float(rectH)); - consts->gRectSizeInv = float2(1.0f / float(rectW), 1.0f / float(rectH)); - consts->gRectOffset = float2(float(m_CommonSettings.rectOrigin[0]) / float(resourceW), float(m_CommonSettings.rectOrigin[1]) / float(resourceH)); - consts->gResolutionScale = float2(float(rectW) / float(resourceW), float(rectH) / float(resourceH)); - consts->gRectOrigin = uint2(m_CommonSettings.rectOrigin[0], m_CommonSettings.rectOrigin[1]); - consts->gDenoisingRange = m_CommonSettings.denoisingRange; - consts->gOrthoMode = m_OrthoMode; - consts->gUnproject = unproject; - consts->gDebug = m_CommonSettings.debug; - } -} diff --git a/Source/InstanceImpl.cpp b/Source/InstanceImpl.cpp index eeedd45..cc9e7d3 100644 --- a/Source/InstanceImpl.cpp +++ b/Source/InstanceImpl.cpp @@ -155,10 +155,6 @@ nrd::Result nrd::InstanceImpl::Create(const InstanceCreationDesc& instanceCreati Add_ReblurDiffuseSpecularSh(denoiserData); else if (denoiserDesc.denoiser == Denoiser::REBLUR_DIFFUSE_DIRECTIONAL_OCCLUSION) Add_ReblurDiffuseDirectionalOcclusion(denoiserData); - else if (denoiserDesc.denoiser == Denoiser::SIGMA_SHADOW) - Add_SigmaShadow(denoiserData); - else if (denoiserDesc.denoiser == Denoiser::SIGMA_SHADOW_TRANSLUCENCY) - Add_SigmaShadowTranslucency(denoiserData); else if (denoiserDesc.denoiser == Denoiser::RELAX_DIFFUSE) Add_RelaxDiffuse(denoiserData); else if (denoiserDesc.denoiser == Denoiser::RELAX_DIFFUSE_SH) @@ -171,12 +167,12 @@ nrd::Result nrd::InstanceImpl::Create(const InstanceCreationDesc& instanceCreati Add_RelaxDiffuseSpecular(denoiserData); else if (denoiserDesc.denoiser == Denoiser::RELAX_DIFFUSE_SPECULAR_SH) Add_RelaxDiffuseSpecularSh(denoiserData); + else if (denoiserDesc.denoiser == Denoiser::SIGMA_SHADOW) + Add_SigmaShadow(denoiserData); + else if (denoiserDesc.denoiser == Denoiser::SIGMA_SHADOW_TRANSLUCENCY) + Add_SigmaShadowTranslucency(denoiserData); else if (denoiserDesc.denoiser == Denoiser::REFERENCE) Add_Reference(denoiserData); - else if (denoiserDesc.denoiser == Denoiser::SPECULAR_REFLECTION_MV) - Add_SpecularReflectionMv(denoiserData); - else if (denoiserDesc.denoiser == Denoiser::SPECULAR_DELTA_MV) - Add_SpecularDeltaMv(denoiserData); else // Should not be here return Result::INVALID_ARGUMENT; @@ -272,6 +268,7 @@ nrd::Result nrd::InstanceImpl::Create(const InstanceCreationDesc& instanceCreati nrd::Result nrd::InstanceImpl::SetCommonSettings(const CommonSettings& commonSettings) { // TODO: matrix verifications? return INVALID_ARGUMENT? + assert("'viewZScale' can't be <= 0" && commonSettings.viewZScale > 0.0f); assert("'resourceSize' can't be 0" && commonSettings.resourceSize[0] != 0 && commonSettings.resourceSize[1] != 0); assert("'resourceSizePrev' can't be 0" && commonSettings.resourceSizePrev[0] != 0 && commonSettings.resourceSizePrev[1] != 0); assert("'rectSize' can't be 0" && commonSettings.rectSize[0] != 0 && commonSettings.rectSize[1] != 0); @@ -509,18 +506,14 @@ nrd::Result nrd::InstanceImpl::GetComputeDispatches(const Identifier* identifier denoiserData.desc.denoiser == Denoiser::REBLUR_SPECULAR_OCCLUSION || denoiserData.desc.denoiser == Denoiser::REBLUR_DIFFUSE_SPECULAR_OCCLUSION) Update_ReblurOcclusion(denoiserData); - else if (denoiserData.desc.denoiser == Denoiser::SIGMA_SHADOW || denoiserData.desc.denoiser == Denoiser::SIGMA_SHADOW_TRANSLUCENCY) - Update_SigmaShadow(denoiserData); else if (denoiserData.desc.denoiser == Denoiser::RELAX_DIFFUSE || denoiserData.desc.denoiser == Denoiser::RELAX_DIFFUSE_SH || denoiserData.desc.denoiser == Denoiser::RELAX_SPECULAR || denoiserData.desc.denoiser == Denoiser::RELAX_SPECULAR_SH || denoiserData.desc.denoiser == Denoiser::RELAX_DIFFUSE_SPECULAR || denoiserData.desc.denoiser == Denoiser::RELAX_DIFFUSE_SPECULAR_SH) Update_Relax(denoiserData); + else if (denoiserData.desc.denoiser == Denoiser::SIGMA_SHADOW || denoiserData.desc.denoiser == Denoiser::SIGMA_SHADOW_TRANSLUCENCY) + Update_SigmaShadow(denoiserData); else if (denoiserData.desc.denoiser == Denoiser::REFERENCE) Update_Reference(denoiserData); - else if (denoiserData.desc.denoiser == Denoiser::SPECULAR_REFLECTION_MV) - Update_SpecularReflectionMv(denoiserData); - else if (denoiserData.desc.denoiser == Denoiser::SPECULAR_DELTA_MV) - Update_SpecularDeltaMv(denoiserData); } dispatchDescs = m_ActiveDispatches.data(); diff --git a/Source/InstanceImpl.h b/Source/InstanceImpl.h index 07e4f19..cae8c2e 100644 --- a/Source/InstanceImpl.h +++ b/Source/InstanceImpl.h @@ -111,13 +111,10 @@ namespace nrd union Settings { - // Add settings here ReblurSettings reblur; - SigmaSettings sigma; RelaxSettings relax; + SigmaSettings sigma; ReferenceSettings reference; - SpecularReflectionMvSettings specularReflectionMv; - SpecularDeltaMvSettings specularDeltaMv; }; struct DenoiserData diff --git a/Source/Reblur.cpp b/Source/Reblur.cpp index 1b00510..238e369 100644 --- a/Source/Reblur.cpp +++ b/Source/Reblur.cpp @@ -383,6 +383,7 @@ void nrd::InstanceImpl::AddSharedConstants_Reblur(const ReblurSettings& settings consts->gUsePrepassNotOnlyForSpecularMotionEstimation = settings.usePrepassOnlyForSpecularMotionEstimation ? 0.0f : 1.0f; consts->gSplitScreen = m_CommonSettings.splitScreen; consts->gCheckerboardResolveAccumSpeed = m_CheckerboardResolveAccumSpeed; + consts->gViewZScale = m_CommonSettings.viewZScale; consts->gHasHistoryConfidence = m_CommonSettings.isHistoryConfidenceAvailable; consts->gHasDisocclusionThresholdMix = m_CommonSettings.isDisocclusionThresholdMixAvailable; consts->gDiffCheckerboard = diffCheckerboard; diff --git a/Source/Other.cpp b/Source/Reference.cpp similarity index 57% rename from Source/Other.cpp rename to Source/Reference.cpp index 5ed5b7f..5ae3782 100644 --- a/Source/Other.cpp +++ b/Source/Reference.cpp @@ -27,35 +27,3 @@ license agreement from NVIDIA CORPORATION is strictly prohibited. #endif #include "Denoisers/Reference.hpp" - - -// SPECULAR_REFLECTION_MV -#ifdef NRD_EMBEDS_DXBC_SHADERS - #include "SpecularReflectionMv_Compute.cs.dxbc.h" -#endif - -#ifdef NRD_EMBEDS_DXIL_SHADERS - #include "SpecularReflectionMv_Compute.cs.dxil.h" -#endif - -#ifdef NRD_EMBEDS_SPIRV_SHADERS - #include "SpecularReflectionMv_Compute.cs.spirv.h" -#endif - -#include "Denoisers/SpecularReflectionMv.hpp" - - -// SPECULAR_DELTA_MV -#ifdef NRD_EMBEDS_DXBC_SHADERS - #include "SpecularDeltaMv_Compute.cs.dxbc.h" -#endif - -#ifdef NRD_EMBEDS_DXIL_SHADERS - #include "SpecularDeltaMv_Compute.cs.dxil.h" -#endif - -#ifdef NRD_EMBEDS_SPIRV_SHADERS - #include "SpecularDeltaMv_Compute.cs.spirv.h" -#endif - -#include "Denoisers/SpecularDeltaMv.hpp" diff --git a/Source/Relax.cpp b/Source/Relax.cpp index eb3368f..188a69c 100644 --- a/Source/Relax.cpp +++ b/Source/Relax.cpp @@ -162,6 +162,7 @@ void nrd::InstanceImpl::AddSharedConstants_Relax(const RelaxSettings& settings, consts->gJitterDelta = m_JitterDelta; consts->gHistoryFixFrameNum = Min(settings.historyFixFrameNum, 3u) + 1.0f; consts->gHistoryThreshold = (float)settings.spatialVarianceEstimationHistoryThreshold; + consts->gViewZScale = m_CommonSettings.viewZScale; consts->gRoughnessEdgeStoppingEnabled = settings.enableRoughnessEdgeStopping ? 1 : 0; consts->gFrameIndex = m_CommonSettings.frameIndex; consts->gDiffCheckerboard = diffCheckerboard; diff --git a/Source/Sigma.cpp b/Source/Sigma.cpp index d7b2e40..9f073f0 100644 --- a/Source/Sigma.cpp +++ b/Source/Sigma.cpp @@ -122,6 +122,7 @@ void nrd::InstanceImpl::AddSharedConstants_Sigma(const SigmaSettings& settings, consts->gStabilizationStrength = m_CommonSettings.accumulationMode == AccumulationMode::CONTINUE ? settings.stabilizationStrength : 0.0f; consts->gDebug = m_CommonSettings.debug; consts->gSplitScreen = m_CommonSettings.splitScreen; + consts->gViewZScale = m_CommonSettings.viewZScale; consts->gFrameIndex = m_CommonSettings.frameIndex; } diff --git a/Source/Wrapper.cpp b/Source/Wrapper.cpp index f606cf9..0de9eaf 100644 --- a/Source/Wrapper.cpp +++ b/Source/Wrapper.cpp @@ -30,17 +30,15 @@ constexpr std::array g_NrdSupport nrd::Denoiser::REBLUR_DIFFUSE_SPECULAR_OCCLUSION, nrd::Denoiser::REBLUR_DIFFUSE_SPECULAR_SH, nrd::Denoiser::REBLUR_DIFFUSE_DIRECTIONAL_OCCLUSION, - nrd::Denoiser::SIGMA_SHADOW, - nrd::Denoiser::SIGMA_SHADOW_TRANSLUCENCY, nrd::Denoiser::RELAX_DIFFUSE, nrd::Denoiser::RELAX_DIFFUSE_SH, nrd::Denoiser::RELAX_SPECULAR, nrd::Denoiser::RELAX_SPECULAR_SH, nrd::Denoiser::RELAX_DIFFUSE_SPECULAR, nrd::Denoiser::RELAX_DIFFUSE_SPECULAR_SH, + nrd::Denoiser::SIGMA_SHADOW, + nrd::Denoiser::SIGMA_SHADOW_TRANSLUCENCY, nrd::Denoiser::REFERENCE, - nrd::Denoiser::SPECULAR_REFLECTION_MV, - nrd::Denoiser::SPECULAR_DELTA_MV }; constexpr nrd::LibraryDesc g_NrdLibraryDesc = @@ -73,8 +71,8 @@ const char* g_NrdResourceTypeNames[] = "IN_SPEC_CONFIDENCE", "IN_DISOCCLUSION_THRESHOLD_MIX", "IN_BASECOLOR_METALNESS", - "IN_SHADOWDATA", - "IN_SHADOW_TRANSLUCENCY", + "IN_PENUMBRA", + "IN_TRANSLUCENCY", "IN_SIGNAL", "IN_DELTA_PRIMARY_POS", "IN_DELTA_SECONDARY_POS", @@ -90,8 +88,6 @@ const char* g_NrdResourceTypeNames[] = "OUT_DIFF_DIRECTION_HITDIST", "OUT_SHADOW_TRANSLUCENCY", "OUT_SIGNAL", - "OUT_REFLECTION_MV", - "OUT_DELTA_MV", "OUT_VALIDATION", "TRANSIENT_POOL", @@ -112,9 +108,6 @@ const char* g_NrdDenoiserNames[] = "REBLUR_DIFFUSE_SPECULAR_SH", "REBLUR_DIFFUSE_DIRECTIONAL_OCCLUSION", - "SIGMA_SHADOW", - "SIGMA_SHADOW_TRANSLUCENCY", - "RELAX_DIFFUSE", "RELAX_DIFFUSE_SH", "RELAX_SPECULAR", @@ -122,10 +115,10 @@ const char* g_NrdDenoiserNames[] = "RELAX_DIFFUSE_SPECULAR", "RELAX_DIFFUSE_SPECULAR_SH", - "REFERENCE", + "SIGMA_SHADOW", + "SIGMA_SHADOW_TRANSLUCENCY", - "SPECULAR_REFLECTION_MV", - "SPECULAR_DELTA_MV", + "REFERENCE", }; static_assert( GetCountOf(g_NrdDenoiserNames) == (uint32_t)nrd::Denoiser::MAX_NUM ); diff --git a/UPDATE.md b/UPDATE.md index 36e38d7..5e6c838 100644 --- a/UPDATE.md +++ b/UPDATE.md @@ -234,3 +234,18 @@ A single NRD instance can now include any combination of denoisers, including re - clarified usage: - `float shadow = SIGMA_BackEnd_UnpackShadow( OUT_SHADOW_TRANSLUCENCY );` - `float3 translucentShadow = SIGMA_BackEnd_UnpackShadow( OUT_SHADOW_TRANSLUCENCY ).yzw;` + +## To v4.8 + +- *API*: + - exposed `CommonSettings::viewZScale` improving FP16 `viewZ` support +- *SIGMA*: + - explicitly uses `IN_VIEWZ` instead of storing `viewZ` in `IN_SHADOWDATA` + - `IN_SHADOWDATA` renamed to `IN_PENUMBRA` (describes penumbra properties) + - `IN_SHADOW_TRANSLUCENCY` renamed to `IN_TRANSLUCENCY` (describes optional translucency) + - `SIGMA_FrontEnd_PackShadow` has been explicitly separated into 2 functions: + - `IN_SHADOWDATA`: `SIGMA_FrontEnd_PackPenumbra` (2 variants: for infinite and local light sources) + - `IN_SHADOW_TRANSLUCENCY`: `SIGMA_FrontEnd_PackTranslucency` +- Deprecated and removed with all dependencies: + - `SPECULAR_REFLECTION_MV` + - `SPECULAR_DELTA_MV`