Skip to content

Commit

Permalink
Fix denoiser for ray traced reflection (improve quality / fix artifact)
Browse files Browse the repository at this point in the history
Recreated PR from: https://github.cds.internal.unity3d.com/unity/unity/pull/20337

This PR i improves the denoising of the ray traced reflections and fix artifacts. They are challenging to make stable. In This PR we've implemented the ReBlur Denoiser by Nvidia and see if we can get better stability and results.
  • Loading branch information
sebastienlagarde authored and Evergreen committed Apr 26, 2023
1 parent 80189f0 commit 31b60af
Show file tree
Hide file tree
Showing 84 changed files with 2,925 additions and 452 deletions.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Expand Up @@ -168,8 +168,8 @@ This example image uses **Speed From Reflected Surface** to accumulate the sampl
</tr>
<tr>
<td></td>
<td><strong>Affects Smooth Surfaces</strong></td>
<td>Indicates whether the denoiser affects perfectly smooth surfaces (surfaces with a <strong>Smoothness</strong> of 1.0) or not.</td>
<td><strong>Anti-flickering Strength</strong></td>
<td>Controls the anti-flickering strength of the reflection denoiser.</td>
</tr>
</tbody>
</table>
Expand Down
Expand Up @@ -4,6 +4,11 @@ This page contains an overview of new features, improvements, and issues resolve

## Added


## Updated

### Ray-Traced Reflections ReBLUR denoiser
![](Images/WhatsNew16_ReBLUR_Denoiser.png)

Starting from HDRP 16, the Ray-Traced Reflections denoiser has been updated based on the ReBLUR implementation. This new algorithm now includes an anti-flickering setting that improves temporal stability and renders more coherent results from rough to smooth objects.
This new denoiser is used in Raytracing Mode and Mixed Mode and completely replace the previous version.

Expand Up @@ -42,7 +42,7 @@ class HDScreenSpaceReflectionEditor : VolumeComponentWithQualityEditor
SerializedDataParameter m_ClampValue;
SerializedDataParameter m_Denoise;
SerializedDataParameter m_DenoiserRadius;
SerializedDataParameter m_AffectsSmoothSurfaces;
SerializedDataParameter m_DenoiserAntiFlickeringStrength;
SerializedDataParameter m_Mode;

// Mixed
Expand Down Expand Up @@ -92,7 +92,7 @@ public override void OnEnable()
m_ClampValue = Unpack(o.Find(x => x.clampValue));
m_Denoise = Unpack(o.Find(x => x.denoise));
m_DenoiserRadius = Unpack(o.Find(x => x.denoiserRadius));
m_AffectsSmoothSurfaces = Unpack(o.Find(x => x.affectSmoothSurfaces));
m_DenoiserAntiFlickeringStrength = Unpack(o.Find(x => x.denoiserAntiFlickeringStrength));
m_Mode = Unpack(o.Find(x => x.mode));

// Mixed
Expand Down Expand Up @@ -138,7 +138,7 @@ public override void OnEnable()
static public readonly GUIContent k_DenoiseText = EditorGUIUtility.TrTextContent("Denoise", "Enable denoising on the ray traced reflections.");
static public readonly GUIContent k_FullResolutionText = EditorGUIUtility.TrTextContent("Full Resolution", "Enables full resolution mode.");
static public readonly GUIContent k_DenoiseRadiusText = EditorGUIUtility.TrTextContent("Denoiser Radius", "Controls the radius of reflection denoiser.");
static public readonly GUIContent k_AffectsSmoothSurfacesText = EditorGUIUtility.TrTextContent("Affects Smooth Surfaces", "When enabled, the denoiser also affects perfectly smooth surfaces. When you use Quality mode with multiple bounces, the denoiser always affects smooth surfaces by default.");
static public readonly GUIContent k_DenoiserAntiFlickeringStrengthText = EditorGUIUtility.TrTextContent("Anti Flickering", "Controls the anti-flickering strength of reflection denoiser.");
static public readonly GUIContent k_MaxMixedRaySteps = EditorGUIUtility.TrTextContent("Max Ray Steps", "Sets the maximum number of steps HDRP uses for mixed tracing.");

void RayTracingQualityModeGUI()
Expand All @@ -156,7 +156,7 @@ void RayTracingQualityModeGUI()
using (new IndentLevelScope())
{
PropertyField(m_DenoiserRadius, k_DenoiseRadiusText);
PropertyField(m_AffectsSmoothSurfaces, k_AffectsSmoothSurfacesText);
PropertyField(m_DenoiserAntiFlickeringStrength, k_DenoiserAntiFlickeringStrengthText);
}
}
}
Expand All @@ -180,7 +180,7 @@ void RayTracingPerformanceModeGUI(bool mixed)
using (new IndentLevelScope())
{
PropertyField(m_DenoiserRadius, k_DenoiseRadiusText);
PropertyField(m_AffectsSmoothSurfaces, k_AffectsSmoothSurfacesText);
PropertyField(m_DenoiserAntiFlickeringStrength, k_DenoiserAntiFlickeringStrengthText);
}
}
}
Expand Down Expand Up @@ -355,8 +355,8 @@ public override QualitySettingsBlob SaveCustomQualitySettingsAsObject(QualitySet
settings.Save<bool>(m_FullResolution);
settings.Save<bool>(m_RayMaxIterationsRT);
settings.Save<bool>(m_Denoise);
settings.Save<int>(m_DenoiserRadius);
settings.Save<bool>(m_AffectsSmoothSurfaces);
settings.Save<float>(m_DenoiserRadius);
settings.Save<float>(m_DenoiserAntiFlickeringStrength);
// SSR
settings.Save<int>(m_RayMaxIterations);

Expand All @@ -376,8 +376,8 @@ public override void LoadSettingsFromObject(QualitySettingsBlob settings)
settings.TryLoad<bool>(ref m_FullResolution);
settings.TryLoad<bool>(ref m_RayMaxIterationsRT);
settings.TryLoad<bool>(ref m_Denoise);
settings.TryLoad<int>(ref m_DenoiserRadius);
settings.TryLoad<bool>(ref m_AffectsSmoothSurfaces);
settings.TryLoad<float>(ref m_DenoiserRadius);
settings.TryLoad<float>(ref m_DenoiserAntiFlickeringStrength);
}
// SSR
else
Expand All @@ -397,8 +397,8 @@ public override void LoadSettingsFromQualityPreset(RenderPipelineSettings settin
CopySetting(ref m_FullResolution, settings.lightingQualitySettings.RTRFullResolution[level]);
CopySetting(ref m_RayMaxIterationsRT, settings.lightingQualitySettings.RTRRayMaxIterations[level]);
CopySetting(ref m_Denoise, settings.lightingQualitySettings.RTRDenoise[level]);
CopySetting(ref m_DenoiserRadius, settings.lightingQualitySettings.RTRDenoiserRadius[level]);
CopySetting(ref m_AffectsSmoothSurfaces, settings.lightingQualitySettings.RTRSmoothDenoising[level]);
CopySetting(ref m_DenoiserRadius, settings.lightingQualitySettings.RTRDenoiserRadiusDimmer[level]);
CopySetting(ref m_DenoiserAntiFlickeringStrength, settings.lightingQualitySettings.RTRDenoiserAntiFlicker[level]);
}
// SSR
else
Expand Down
Expand Up @@ -92,8 +92,8 @@ public class Styles
public static readonly GUIContent RTRRayMaxIterations = EditorGUIUtility.TrTextContent("Ray Max Iterations");
public static readonly GUIContent RTRDenoise = EditorGUIUtility.TrTextContent("Denoise");
public static readonly GUIContent RTRDenoiserRadius = EditorGUIUtility.TrTextContent("Denoiser Radius");
public static readonly GUIContent RTRSmoothDenoising = EditorGUIUtility.TrTextContent("Affect Smooth Surfaces");

public static readonly GUIContent RTRDenoiserAntiFlicker = EditorGUIUtility.TrTextContent("Anti Flickering Strength");
// RTGI
public static readonly GUIContent RTGISettingsSubTitle = EditorGUIUtility.TrTextContent("Ray Traced Global Illumination (Performance)");
public static readonly GUIContent RTGIRayLength = EditorGUIUtility.TrTextContent("Max Ray Length");
Expand Down
Expand Up @@ -952,8 +952,8 @@ static void DrawRTRQualitySetting(SerializedHDRenderPipelineAsset serialized, in
EditorGUILayout.PropertyField(serialized.renderPipelineSettings.lightingQualitySettings.RTRFullResolution.GetArrayElementAtIndex(tier), Styles.RTRFullResolution);
EditorGUILayout.PropertyField(serialized.renderPipelineSettings.lightingQualitySettings.RTRRayMaxIterations.GetArrayElementAtIndex(tier), Styles.RTRRayMaxIterations);
EditorGUILayout.PropertyField(serialized.renderPipelineSettings.lightingQualitySettings.RTRDenoise.GetArrayElementAtIndex(tier), Styles.RTRDenoise);
EditorGUILayout.PropertyField(serialized.renderPipelineSettings.lightingQualitySettings.RTRDenoiserRadius.GetArrayElementAtIndex(tier), Styles.RTRDenoiserRadius);
EditorGUILayout.PropertyField(serialized.renderPipelineSettings.lightingQualitySettings.RTRSmoothDenoising.GetArrayElementAtIndex(tier), Styles.RTRSmoothDenoising);
EditorGUILayout.PropertyField(serialized.renderPipelineSettings.lightingQualitySettings.RTRDenoiserRadiusDimmer.GetArrayElementAtIndex(tier), Styles.RTRDenoiserRadius);
EditorGUILayout.PropertyField(serialized.renderPipelineSettings.lightingQualitySettings.RTRDenoiserAntiFlicker.GetArrayElementAtIndex(tier), Styles.RTRDenoiserAntiFlicker);
}

static void DrawVolumetricFogQualitySetting(SerializedHDRenderPipelineAsset serialized, int tier)
Expand Down
Expand Up @@ -34,8 +34,8 @@ class SerializedLightingQualitySettings
public SerializedProperty RTRFullResolution;
public SerializedProperty RTRRayMaxIterations;
public SerializedProperty RTRDenoise;
public SerializedProperty RTRDenoiserRadius;
public SerializedProperty RTRSmoothDenoising;
public SerializedProperty RTRDenoiserRadiusDimmer;
public SerializedProperty RTRDenoiserAntiFlicker;

// Ray Traced Global Illumination
public SerializedProperty RTGIRayLength;
Expand Down Expand Up @@ -89,8 +89,8 @@ public SerializedLightingQualitySettings(SerializedProperty root)
RTRFullResolution = root.Find((GlobalLightingQualitySettings s) => s.RTRFullResolution);
RTRRayMaxIterations = root.Find((GlobalLightingQualitySettings s) => s.RTRRayMaxIterations);
RTRDenoise = root.Find((GlobalLightingQualitySettings s) => s.RTRDenoise);
RTRDenoiserRadius = root.Find((GlobalLightingQualitySettings s) => s.RTRDenoiserRadius);
RTRSmoothDenoising = root.Find((GlobalLightingQualitySettings s) => s.RTRSmoothDenoising);
RTRDenoiserRadiusDimmer = root.Find((GlobalLightingQualitySettings s) => s.RTRDenoiserRadiusDimmer);
RTRDenoiserAntiFlicker = root.Find((GlobalLightingQualitySettings s) => s.RTRDenoiserAntiFlicker);

// Ray Traced Global Illumination
RTGIRayLength = root.Find((GlobalLightingQualitySettings s) => s.RTGIRayLength);
Expand Down
Expand Up @@ -92,7 +92,7 @@

// Then export it to the gbuffer
EncodeIntoStandardGBuffer(standardLitData, rayIntersectionGbuffer.gbuffer0, rayIntersectionGbuffer.gbuffer1, rayIntersectionGbuffer.gbuffer2, rayIntersectionGbuffer.gbuffer3);
rayIntersectionGbuffer.t = standardLitData.isUnlit != 0 ? RAY_TRACING_DISTANCE_FLAG_UNLIT : RayTCurrent();
rayIntersectionGbuffer.t = standardLitData.isUnlit != 0 ? -RayTCurrent() : RayTCurrent();
}

// Inject the intersection shader
Expand Down
Expand Up @@ -76,7 +76,7 @@

// Then export it to the gbuffer
EncodeIntoStandardGBuffer(standardLitData, rayIntersectionGbuffer.gbuffer0, rayIntersectionGbuffer.gbuffer1, rayIntersectionGbuffer.gbuffer2, rayIntersectionGbuffer.gbuffer3);
rayIntersectionGbuffer.t = RAY_TRACING_DISTANCE_FLAG_UNLIT;
rayIntersectionGbuffer.t = -RayTCurrent();
}

// Inject the intersection shader
Expand Down
Expand Up @@ -79,7 +79,7 @@ void TRACE_GLOBAL_ILLUMINATION(uint3 dispatchThreadId : SV_DispatchThreadID, uin

#if HALF_RES
// Compute the full resolution pixel for the inputs that do not have a pyramid
inputCoord = inputCoord * 2;
inputCoord = ComputeSourceCoordinates(inputCoord, _RayTracingCheckerIndex);
#endif

// Read the depth value as early as possible
Expand Down Expand Up @@ -212,7 +212,7 @@ void REPROJECT_GLOBAL_ILLUMINATION(uint3 dispatchThreadId : SV_DispatchThreadID,
uint2 currentCoord = dispatchThreadId.xy;
#if HALF_RES
// Compute the full resolution pixel for the inputs that do not have a pyramid
inputCoord = inputCoord * 2;
inputCoord = ComputeSourceCoordinates(inputCoord, _RayTracingCheckerIndex);
#endif

// Read the depth and compute the position
Expand Down
Expand Up @@ -285,38 +285,38 @@ public bool denoise
/// <summary>
/// Controls the radius of reflection denoiser.
/// </summary>
public int denoiserRadius
public float denoiserRadius
{
get
{
if (!UsesQualitySettings() || UsesRayTracingQualityMode())
return m_DenoiserRadius.value;
else
return GetLightingQualitySettings().RTRDenoiserRadius[(int)quality.value];
return GetLightingQualitySettings().RTRDenoiserRadiusDimmer[(int)quality.value];
}
set { m_DenoiserRadius.value = value; }
}
[SerializeField, FormerlySerializedAs("denoiserRadius")]
[SerializeField]
[Tooltip("Controls the radius of the ray traced reflection denoiser.")]
private ClampedIntParameter m_DenoiserRadius = new ClampedIntParameter(8, 1, 32);
private ClampedFloatParameter m_DenoiserRadius = new ClampedFloatParameter(0.75f, 0.0f, 1.0f);

/// <summary>
/// Controls if the denoising should affect pefectly smooth surfaces
/// Controls the anti-flickering strength of the reflection denoiser.
/// </summary>
public bool affectSmoothSurfaces
public float denoiserAntiFlickeringStrength
{
get
{
if (!UsesQualitySettings() || UsesRayTracingQualityMode())
return m_AffectSmoothSurfaces.value;
return m_DenoiserAntiFlickeringStrength.value;
else
return GetLightingQualitySettings().RTRSmoothDenoising[(int)quality.value];
return GetLightingQualitySettings().RTRDenoiserAntiFlicker[(int)quality.value];
}
set { m_AffectSmoothSurfaces.value = value; }
set { m_DenoiserAntiFlickeringStrength.value = value; }
}
[SerializeField]
[Tooltip("Denoiser affects smooth surfaces.")]
private BoolParameter m_AffectSmoothSurfaces = new BoolParameter(false);
[Tooltip("Controls the anti-flickering strength of the reflection denoiser.")]
private ClampedFloatParameter m_DenoiserAntiFlickeringStrength = new ClampedFloatParameter(1.0f, 0.0f, 1.0f);

/// <summary>
/// Controls which version of the effect should be used.
Expand Down
Expand Up @@ -49,11 +49,6 @@ groupshared float gs_cloudLutDensity[CLOUD_MAP_LUT_PRESET_SIZE];
groupshared float gs_cloudLutErosion[CLOUD_MAP_LUT_PRESET_SIZE];
groupshared float gs_cloudLutAO[CLOUD_MAP_LUT_PRESET_SIZE];

uint2 HalfResolutionIndexToOffset(uint index)
{
return uint2(index & 0x1, index / 2);
}

void LoadCloudLutToLDS(uint groupThreadId)
{
float3 densityErosionAO = LOAD_TEXTURE2D_LOD(_CloudLutTexture, int2(0, groupThreadId), 0);
Expand Down Expand Up @@ -860,14 +855,6 @@ VolumetricRayResult TraceVolumetricRay(CloudRay cloudRay)
return volumetricRay;
}

// This function compute the checkerboard undersampling position
int ComputeCheckerBoardIndex(int2 traceCoord, int subPixelIndex)
{
int localOffset = (traceCoord.x & 1 + traceCoord.y & 1) & 1;
int checkerBoardLocation = (subPixelIndex + localOffset) & 0x3;
return checkerBoardLocation;
}

float EvaluateFinalTransmittance(float3 color, float transmittance)
{
// Due to the high intensity of the sun, we often need apply the transmittance in a tonemapped space
Expand Down
Expand Up @@ -64,6 +64,10 @@
#define MV_DILATION DEPTH_DILATION
#endif

#ifndef TEMPORAL_CONTRAST
#define TEMPORAL_CONTRAST 1
#endif


float2 ClampAndScaleForBilinearWithCustomScale(float2 uv, float2 scale)
{
Expand Down Expand Up @@ -520,9 +524,14 @@ void VarianceNeighbourhood(inout NeighbourhoodSamples samples, float historyLuma
#else
float localizedAntiFlicker = antiFlickerParams.x;
#endif

#if TEMPORAL_CONTRAST
// TODO: Because we use a very aggressivley clipped history to compute the temporal contrast (hopefully cutting a chunk of ghosting)
// can we be more aggressive here, being a bit more confident that the issue is from flickering? To investigate.
stDevMultiplier += lerp(0.0, localizedAntiFlicker, smoothstep(0.05, antiFlickerParams.y, temporalContrast));
#else
stDevMultiplier += localizedAntiFlicker;
#endif

#endif

Expand Down
Expand Up @@ -31,8 +31,12 @@ public enum HDCameraFrameHistoryType
RaytracedShadowHistoryValidity,
/// <summary>Ray traced shadow history distance buffer.</summary>
RaytracedShadowDistanceValidity,
/// <summary>Ray traced reflections buffer.</summary>
RaytracedReflection,
/// <summary>Ray traced reflections distance buffer.</summary>
RaytracedReflectionDistance,
/// <summary>Ray traced reflections distance buffer.</summary>
RaytracedReflectionAccumulation,
/// <summary>Ray traced reflections stabilization buffer.</summary>
RaytracedReflectionStabilization,
/// <summary>Ray traced indirect diffuse HF buffer.</summary>
RaytracedIndirectDiffuseHF,
/// <summary>Ray traced indirect diffuse LF buffer.</summary>
Expand Down
Expand Up @@ -143,13 +143,13 @@ internal GlobalLightingQualitySettings()
RTRDenoise[(int)ScalableSettingLevelParameter.Level.Medium] = true;
RTRDenoise[(int)ScalableSettingLevelParameter.Level.High] = true;

RTRDenoiserRadius[(int)ScalableSettingLevelParameter.Level.Low] = 8;
RTRDenoiserRadius[(int)ScalableSettingLevelParameter.Level.Medium] = 12;
RTRDenoiserRadius[(int)ScalableSettingLevelParameter.Level.High] = 16;
RTRDenoiserRadiusDimmer[(int)ScalableSettingLevelParameter.Level.Low] = 0.75f;
RTRDenoiserRadiusDimmer[(int)ScalableSettingLevelParameter.Level.Medium] = 0.75f;
RTRDenoiserRadiusDimmer[(int)ScalableSettingLevelParameter.Level.High] = 1.0f;

RTRSmoothDenoising[(int)ScalableSettingLevelParameter.Level.Low] = true;
RTRSmoothDenoising[(int)ScalableSettingLevelParameter.Level.Medium] = false;
RTRSmoothDenoising[(int)ScalableSettingLevelParameter.Level.High] = false;
RTRDenoiserAntiFlicker[(int)ScalableSettingLevelParameter.Level.Low] = 1.0f;
RTRDenoiserAntiFlicker[(int)ScalableSettingLevelParameter.Level.Medium] = 1.0f;
RTRDenoiserAntiFlicker[(int)ScalableSettingLevelParameter.Level.High] = 1.0f;

// Fog
Fog_ControlMode[(int)ScalableSettingLevelParameter.Level.Low] = FogControl.Balance;
Expand Down Expand Up @@ -261,11 +261,12 @@ internal GlobalLightingQualitySettings()
public int[] RTRRayMaxIterations = new int[s_QualitySettingCount];
/// <summary>Flag that enables the first denoising pass. The array must have one entry per scalable setting level.</summary>
public bool[] RTRDenoise = new bool[s_QualitySettingCount];
/// <summary>Flag that defines the radius of the denoiser. The array must have one entry per scalable setting level.</summary>
[Range(0.0f, 1.0f)]
public float[] RTRDenoiserRadiusDimmer = new float[s_QualitySettingCount];
/// <summary>Flag that defines the radius of the first denoiser. The array must have one entry per scalable setting level, and elements must be between 1 and 32.</summary>
[Range(1, 32)]
public int[] RTRDenoiserRadius = new int[s_QualitySettingCount];
/// <summary>Flag that defines smooth denoising status. The array must have one entry per scalable setting level.</summary>
public bool[] RTRSmoothDenoising = new bool[s_QualitySettingCount];
[Range(0.0f, 1.0f)]
public float[] RTRDenoiserAntiFlicker = new float[s_QualitySettingCount];

// TODO: Volumetric fog quality
/// <summary>Controls which control mode should be used to define the volumetric fog parameters. The array must have one entry per scalable setting level.</summary>
Expand Down

0 comments on commit 31b60af

Please sign in to comment.