From a7f878c6d504f2ddb83bad599f5c1e83d45ebdf0 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Mon, 6 Jul 2020 09:25:54 +0200 Subject: [PATCH 01/27] stabilize CoC if taa is enabled --- .../PostProcessing/PostProcessSystem.cs | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index f95108fcf97..f9a1bc950b5 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -2201,13 +2201,13 @@ void DoDepthOfField(CommandBuffer cmd, HDCamera camera, RTHandle source, RTHandl m_Pool.Recycle(fullresCoC); // Already cleaned up if TAA is enabled } - static void GrabCoCHistory(HDCamera camera, out RTHandle previous, out RTHandle next) + static void GrabCoCHistory(HDCamera camera, out RTHandle previous, out RTHandle next, bool mipMaps = false) { RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) { return rtHandleSystem.Alloc( Vector2.one, TextureXR.slices, DepthBits.None, GraphicsFormat.R16_SFloat, - dimension: TextureXR.dimension, enableRandomWrite: true, useDynamicScale: true, name: $"{id} CoC History" + dimension: TextureXR.dimension, enableRandomWrite: true, useMipMap: mipMaps, useDynamicScale: true, name: $"{id} CoC History" ); } @@ -2278,6 +2278,25 @@ void DoPhysicallyBasedDepthOfField(CommandBuffer cmd, HDCamera camera, RTHandle cmd.DispatchCompute(cs, kernel, (camera.actualWidth + 7) / 8, (camera.actualHeight + 7) / 8, camera.viewCount); } + if (taaEnabled) + { + GrabCoCHistory(camera, out var prevCoCTex, out var nextCoCTex, true); + Vector2 cocHistoryScale = new Vector2(camera.historyRTHandleProperties.rtHandleScale.z, camera.historyRTHandleProperties.rtHandleScale.w); + + cs = m_Resources.shaders.depthOfFieldCoCReprojectCS; + kernel = cs.FindKernel("KMain"); + cmd.SetComputeVectorParam(cs, HDShaderIDs._Params, new Vector4(camera.resetPostProcessingHistory ? 0f : 0.91f, cocHistoryScale.x, cocHistoryScale.y, 0f)); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputCoCTexture, fullresCoC); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputHistoryCoCTexture, prevCoCTex); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputCoCTexture, nextCoCTex); + cmd.DispatchCompute(cs, kernel, (camera.actualWidth + 7) / 8, (camera.actualHeight + 7) / 8, camera.viewCount); + + // Cleanup the main CoC texture as we don't need it anymore and use the + // re-projected one instead for the following steps + m_Pool.Recycle(fullresCoC); + fullresCoC = nextCoCTex; + } + using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.DepthOfFieldPyramid))) { // To have an adaptive gather radius, we need estimates for the the min and max CoC that intersect a pixel. @@ -2313,7 +2332,8 @@ void DoPhysicallyBasedDepthOfField(CommandBuffer cmd, HDCamera camera, RTHandle cmd.DispatchCompute(cs, kernel, (camera.actualWidth + 7) / 8, (camera.actualHeight + 7) / 8, camera.viewCount); } - m_Pool.Recycle(fullresCoC); + if (!taaEnabled) + m_Pool.Recycle(fullresCoC); // Already cleaned up if TAA is enabled } #endregion From ac9bd9111b9907dc8ea09ed3906641b4b4b578f0 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Mon, 6 Jul 2020 14:24:53 +0200 Subject: [PATCH 02/27] Fixes related to CoC clamping --- .../PostProcessing/Shaders/DoFGather.compute | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 072d3173169..240a00e6fd3 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -78,7 +78,7 @@ float GetCoCRadius(int2 positionSS, out int bucketIndex) { float CoCRadius = LOAD_TEXTURE2D_X(_InputCoCTexture, positionSS).x; bucketIndex = GetCoCBucket(CoCRadius); - return abs(CoCRadius); + return CoCRadius; } float GetCoCMaxRadius(int2 positionSS) @@ -102,8 +102,8 @@ float GetSampleWeight(float cocRadius) if (cocRadius == 0.0) return 0.0; float pixelRadius = 0.7071f; - float singlePixelArea = PI * pixelRadius * pixelRadius; - float diskArea = PI * cocRadius * cocRadius; + float singlePixelArea = 4 * PI * pixelRadius * pixelRadius; + float diskArea = 4 * PI * cocRadius * cocRadius; return diskArea >= singlePixelArea ? rcp(diskArea) : rcp(singlePixelArea); } @@ -158,10 +158,10 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) // Record the central sample { - float weight = GetSampleWeight(centerCoc); + float weight = GetSampleWeight(abs(centerCoc)); totalColor[bucketIndex].xyz = centerColor.xyz * weight; totalColor[bucketIndex].w = weight; - maxCoC[bucketIndex] = centerCoc; + maxCoC[bucketIndex] = abs(centerCoc); prevRingWeight[bucketIndex] = weight; #ifdef ENABLE_ALPHA totalAlpha[bucketIndex] = centerColor.w; @@ -189,7 +189,6 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) float dAng = 2.0f * PI / (ring * RING_DENSITY); - // for high sample counts, checkerboarding looks better #ifndef GRADIENT_NOISE float radius = ring * scaledRad + stratum * scaledRad; float ringOffset = 0.5 * fmod(ring, 2.0f) * dAng; @@ -227,16 +226,15 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) float sampleCoC = GetCoCRadius(sampleTC, sampleBucket); #ifdef COC_FAR_CLAMPING - if (sampleBucket < 1) - sampleCoC = clamp(sampleCoC, 0, centerCoc); + sampleCoC = min(sampleCoC, centerCoc), sampleCoC; #endif - if (sampleCoC > radius) + if (abs(sampleCoC) > radius) { - float weight = GetSampleWeight(sampleCoC); + float weight = GetSampleWeight(abs(sampleCoC)); RING_COLOR[sampleBucket].xyz += sampleColor.xyz * weight; RING_COLOR[sampleBucket].w += weight; - RING_MAXCOC[sampleBucket] = max(RING_MAXCOC[sampleBucket], sampleCoC); + RING_MAXCOC[sampleBucket] = max(RING_MAXCOC[sampleBucket], abs(sampleCoC)); RING_HITS[sampleBucket] += 1.0; #ifdef ENABLE_ALPHA RING_ALPHA[sampleBucket] = sampleColor.w * weight; @@ -245,10 +243,10 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) #ifdef UNIFORM_WEIGHTS else { - RING_COLOR[sampleBucket].xyz += RING_COLOR[sampleBucket].xyz / RING_COLOR[sampleBucket].w; + RING_COLOR[sampleBucket].xyz += RING_COLOR[sampleBucket].w > 0 ? RING_COLOR[sampleBucket].xyz / RING_COLOR[sampleBucket].w : 0; RING_COLOR[sampleBucket].w += 1.0f; #ifdef ENABLE_ALPHA - RING_ALPHA[sampleBucket] += RING_ALPHA[sampleBucket] / RING_COLOR[sampleBucket].w; + RING_ALPHA[sampleBucket] += RING_COLOR[sampleBucket].w > 0 ? RING_ALPHA[sampleBucket] / RING_COLOR[sampleBucket].w : 0; #endif } #endif From d30c2aff81d9b7cc96208200954b0be0625bc1d4 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Mon, 6 Jul 2020 15:23:34 +0200 Subject: [PATCH 03/27] Improve DoF when TAA is active by using different samples each frame --- .../PostProcessing/PostProcessSystem.cs | 53 ++++++++++++++++++- .../PostProcessing/Shaders/DoFGather.compute | 7 +-- .../Camera/HDCameraFrameHistoryType.cs | 4 ++ 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index f9a1bc950b5..5cb2d64a309 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -617,8 +617,23 @@ void PoolSource(ref RTHandle src, RTHandle dst) DoDepthOfField(cmd, camera, source, destination, taaEnabled); PoolSource(ref source, destination); } - } + // When DoF is enabled, TAA runs two times, first to stabilize the color buffer before DoF and tthen after DoF to accumulate aperture samples + if (taaEnabled) + { + using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.TemporalAntialiasing))) + { + var destination = m_Pool.Get(Vector2.one, m_ColorFormat); + var taaParams = PrepareTAAParameters(camera); + GrabTemporalAntialiasingHistoryTexturesPostDoF(camera, out var prevHistory, out var nextHistory); + GrabVelocityMagnitudeHistoryTexturesPostDoF(camera, out var prevMVLen, out var nextMVLen); + DoTemporalAntialiasing(taaParams, cmd, source, destination, motionVecTexture, depthBuffer, depthMipChain, prevHistory, nextHistory, prevMVLen, nextMVLen); + PoolSource(ref source, destination); + } + } + + } + // Motion blur after depth of field for aesthetic reasons (better to see motion // blurred bokeh rather than out of focus motion blur) if (m_MotionBlur.IsActive() && m_AnimatedMaterialsEnabled && !camera.resetPostProcessingHistory && m_MotionBlurFS) @@ -1589,6 +1604,38 @@ RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) ?? camera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.TAAMotionVectorMagnitude, Allocator, 2); previous = camera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.TAAMotionVectorMagnitude); } + + void GrabTemporalAntialiasingHistoryTexturesPostDoF(HDCamera camera, out RTHandle previous, out RTHandle next) + { + RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) + { + return rtHandleSystem.Alloc( + Vector2.one, TextureXR.slices, DepthBits.None, dimension: TextureXR.dimension, + filterMode: FilterMode.Bilinear, colorFormat: m_ColorFormat, + enableRandomWrite: true, useDynamicScale: true, name: $"{id} TAA History" + ); + } + + next = camera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.TemporalAntialiasingPostDoF) + ?? camera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.TemporalAntialiasingPostDoF, Allocator, 2); + previous = camera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.TemporalAntialiasingPostDoF); + } + + void GrabVelocityMagnitudeHistoryTexturesPostDoF(HDCamera camera, out RTHandle previous, out RTHandle next) + { + RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) + { + return rtHandleSystem.Alloc( + Vector2.one, TextureXR.slices, DepthBits.None, dimension: TextureXR.dimension, + filterMode: FilterMode.Bilinear, colorFormat: GraphicsFormat.R16_SFloat, + enableRandomWrite: true, useDynamicScale: true, name: $"{id} Velocity magnitude" + ); + } + + next = camera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.TAAMotionVectorMagnitudePostDoF) + ?? camera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.TAAMotionVectorMagnitudePostDoF, Allocator, 2); + previous = camera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.TAAMotionVectorMagnitudePostDoF); + } #endregion #region Depth Of Field @@ -2323,7 +2370,9 @@ void DoPhysicallyBasedDepthOfField(CommandBuffer cmd, HDCamera camera, RTHandle cs.EnableKeyword("ENABLE_ALPHA"); kernel = cs.FindKernel("KMain"); - float sampleCount = Mathf.Max(m_DepthOfField.nearSampleCount, m_DepthOfField.farSampleCount); + // We use more samples when TAA is disabled, to hide undersampling + float sampleMultipleier = taaEnabled ? 1 : 2; + float sampleCount = sampleMultipleier * Mathf.Max(m_DepthOfField.nearSampleCount, m_DepthOfField.farSampleCount); float mipLevel = Mathf.Ceil(Mathf.Log(cocLimit, 2)); cmd.SetComputeVectorParam(cs, HDShaderIDs._Params, new Vector4(sampleCount, cocLimit, mipLevel, 0.0f)); cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputTexture, source); diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 240a00e6fd3..9b72343a2e2 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -173,9 +173,10 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) float dR = maxRadius * rcp(numRings); float stratum = fmod(posInputs.positionSS.x + posInputs.positionSS.y, 2.0f); - // Note: gradient noise seems to give worse results than s - float noise = InterleavedGradientNoise(posInputs.positionSS.xy, 0); - float noise2 = InterleavedGradientNoise(posInputs.positionSS.xy, 9); + + int sampleOffset = _TaaFrameInfo.w != 0.0 ? _TaaFrameInfo.z : 0; + float noise = InterleavedGradientNoise(posInputs.positionSS.xy, sampleOffset); + float noise2 = InterleavedGradientNoise(posInputs.positionSS.xy, 8 + sampleOffset); // Iterate over the octaweb pattern and gather the DoF samples for (float ring = 1; ring <= numRings; ring += 1.0) diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCameraFrameHistoryType.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCameraFrameHistoryType.cs index 08a16af16a0..21123bb5f9e 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCameraFrameHistoryType.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCameraFrameHistoryType.cs @@ -41,6 +41,10 @@ public enum HDCameraFrameHistoryType RayTracedSubSurface, /// Path tracing buffer. PathTracing, + /// Temporal antialiasing history after DoF. + TemporalAntialiasingPostDoF, + /// Velocity magnitude history used for TAA velocity weighting (after DoF). + TAAMotionVectorMagnitudePostDoF, /// Number of history buffers. Count } From 0475bd9a3b9ffd7efab73aeb33dbfa7a5158f242 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Mon, 6 Jul 2020 16:16:27 +0200 Subject: [PATCH 04/27] Add UI option to run the new physically based DoF --- .../PostProcessing/DepthOfFieldEditor.cs | 4 ++++ .../RenderPipeline/HDRenderPipelineUI.Skin.cs | 1 + .../RenderPipeline/HDRenderPipelineUI.cs | 1 + ...SerializedPostProcessingQualitySettings.cs | 2 ++ .../PostProcessing/Components/DepthOfField.cs | 20 +++++++++++++++++++ .../PostProcessing/PostProcessSystem.cs | 19 +++++++++--------- .../GlobalPostProcessingQualitySettings.cs | 2 ++ 7 files changed, 39 insertions(+), 10 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs index b83769a5e4e..74fcdde03d2 100644 --- a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs @@ -19,6 +19,7 @@ static partial class Styles public static GUIContent k_NearFocusEnd = new GUIContent("End", "Sets the distance from the Camera at which the near field does not blur anymore."); public static GUIContent k_FarFocusEnd = new GUIContent("End", "Sets the distance from the Camera at which the far field blur reaches its maximum blur radius."); + public static GUIContent k_PhysicallyBased = new GUIContent("PhysicallyBased", "Uses a more accurate but slower physically based method to compute DoF."); } SerializedDataParameter m_FocusMode; @@ -41,6 +42,7 @@ static partial class Styles // Advanced settings SerializedDataParameter m_HighQualityFiltering; SerializedDataParameter m_Resolution; + SerializedDataParameter m_PhysicallyBased; public override bool hasAdvancedMode => true; @@ -66,6 +68,7 @@ public override void OnEnable() m_HighQualityFiltering = Unpack(o.Find("m_HighQualityFiltering")); m_Resolution = Unpack(o.Find("m_Resolution")); + m_PhysicallyBased = Unpack(o.Find("m_PhysicallyBased")); } public override void OnInspectorGUI() @@ -132,6 +135,7 @@ public override void OnInspectorGUI() EditorGUILayout.LabelField("Advanced Tweaks", EditorStyles.miniLabel); PropertyField(m_Resolution); PropertyField(m_HighQualityFiltering); + PropertyField(m_PhysicallyBased); GUI.enabled = true; } } diff --git a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.Skin.cs b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.Skin.cs index 5cbdefb0ea0..fbe26589dc7 100644 --- a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.Skin.cs +++ b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.Skin.cs @@ -57,6 +57,7 @@ public class GeneralSection public static readonly GUIContent sampleCountQuality = EditorGUIUtility.TrTextContent("Sample Count"); public static readonly GUIContent resolutionQuality = EditorGUIUtility.TrTextContent("Resolution"); public static readonly GUIContent highQualityFiltering = EditorGUIUtility.TrTextContent("High Quality Filtering"); + public static readonly GUIContent dofPhysicallyBased = EditorGUIUtility.TrTextContent("Physically Based"); public static readonly GUIContent maxSamplesQuality = EditorGUIUtility.TrTextContent("Max Samples"); public static readonly GUIContent SSAOQualitySettingSubTitle = EditorGUIUtility.TrTextContent("Screen Space Ambient Occlusion"); diff --git a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs index f5f7250977e..b9c0361d084 100644 --- a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs +++ b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs @@ -599,6 +599,7 @@ static void DrawDepthOfFieldQualitySetting(SerializedHDRenderPipelineAsset seria EditorGUILayout.PropertyField(serialized.renderPipelineSettings.postProcessQualitySettings.DoFResolution.GetArrayElementAtIndex(tier), Styles.resolutionQuality); EditorGUILayout.PropertyField(serialized.renderPipelineSettings.postProcessQualitySettings.DoFHighFilteringQuality.GetArrayElementAtIndex(tier), Styles.highQualityFiltering); + EditorGUILayout.PropertyField(serialized.renderPipelineSettings.postProcessQualitySettings.DoFPhysicallyBased.GetArrayElementAtIndex(tier), Styles.dofPhysicallyBased); --EditorGUI.indentLevel; } diff --git a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedPostProcessingQualitySettings.cs b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedPostProcessingQualitySettings.cs index 7e6dcc327f8..c6ce192174c 100644 --- a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedPostProcessingQualitySettings.cs +++ b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedPostProcessingQualitySettings.cs @@ -14,6 +14,7 @@ class SerializedPostProcessingQualitySettings public SerializedProperty FarBlurMaxRadius; public SerializedProperty DoFResolution; public SerializedProperty DoFHighFilteringQuality; + public SerializedProperty DoFPhysicallyBased; // Motion Blur public SerializedProperty MotionBlurSampleCount; @@ -36,6 +37,7 @@ public SerializedPostProcessingQualitySettings(SerializedProperty root) FarBlurMaxRadius = root.Find((GlobalPostProcessingQualitySettings s) => s.FarBlurMaxRadius); DoFResolution = root.Find((GlobalPostProcessingQualitySettings s) => s.DoFResolution); DoFHighFilteringQuality = root.Find((GlobalPostProcessingQualitySettings s) => s.DoFHighQualityFiltering); + DoFPhysicallyBased = root.Find((GlobalPostProcessingQualitySettings s) => s.DoFPhysicallyBased); // Motion Blur MotionBlurSampleCount = root.Find((GlobalPostProcessingQualitySettings s) => s.MotionBlurSampleCount); diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/DepthOfField.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/DepthOfField.cs index 5969c50c4de..f2b2f086c9e 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/DepthOfField.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/DepthOfField.cs @@ -204,6 +204,23 @@ public bool highQualityFiltering set { m_HighQualityFiltering.value = value; } } + public bool physicallyBased + { + get + { + if (!UsesQualitySettings()) + { + return m_PhysicallyBased.value && focusMode.value == DepthOfFieldMode.UsePhysicalCamera; + } + else + { + int qualityLevel = (int)quality.levelAndOverride.level; + return GetPostProcessingQualitySettings().DoFPhysicallyBased[qualityLevel] && focusMode.value == DepthOfFieldMode.UsePhysicalCamera; + } + } + set { m_PhysicallyBased.value = value; } + } + /// /// Specifies the resolution at which HDRP processes the depth of field effect. /// @@ -257,6 +274,9 @@ public DepthOfFieldResolution resolution [SerializeField, FormerlySerializedAs("resolution")] DepthOfFieldResolutionParameter m_Resolution = new DepthOfFieldResolutionParameter(DepthOfFieldResolution.Half); + [SerializeField] + BoolParameter m_PhysicallyBased = new BoolParameter(false); + /// /// Tells if the effect needs to be rendered or not. /// diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index 5cb2d64a309..55ee01b5781 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -614,24 +614,23 @@ void PoolSource(ref RTHandle src, RTHandle dst) using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.DepthOfField))) { var destination = m_Pool.Get(Vector2.one, m_ColorFormat); - DoDepthOfField(cmd, camera, source, destination, taaEnabled); + if (!m_DepthOfField.physicallyBased) + DoDepthOfField(cmd, camera, source, destination, taaEnabled); + else + DoPhysicallyBasedDepthOfField(cmd, camera, source, destination, taaEnabled); PoolSource(ref source, destination); - } - // When DoF is enabled, TAA runs two times, first to stabilize the color buffer before DoF and tthen after DoF to accumulate aperture samples - if (taaEnabled) - { - using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.TemporalAntialiasing))) + // When physically based DoF is enabled, TAA runs two times, first to stabilize the color buffer before DoF and then after DoF to accumulate more aperture samples + if (taaEnabled && m_DepthOfField.physicallyBased) { - var destination = m_Pool.Get(Vector2.one, m_ColorFormat); + var taaDestination = m_Pool.Get(Vector2.one, m_ColorFormat); var taaParams = PrepareTAAParameters(camera); GrabTemporalAntialiasingHistoryTexturesPostDoF(camera, out var prevHistory, out var nextHistory); GrabVelocityMagnitudeHistoryTexturesPostDoF(camera, out var prevMVLen, out var nextMVLen); - DoTemporalAntialiasing(taaParams, cmd, source, destination, motionVecTexture, depthBuffer, depthMipChain, prevHistory, nextHistory, prevMVLen, nextMVLen); - PoolSource(ref source, destination); + DoTemporalAntialiasing(taaParams, cmd, source, taaDestination, motionVecTexture, depthBuffer, depthMipChain, prevHistory, nextHistory, prevMVLen, nextMVLen); + PoolSource(ref source, taaDestination); } } - } // Motion blur after depth of field for aesthetic reasons (better to see motion diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/GlobalPostProcessingQualitySettings.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/GlobalPostProcessingQualitySettings.cs index f77d6923019..307f39382ab 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/GlobalPostProcessingQualitySettings.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/GlobalPostProcessingQualitySettings.cs @@ -122,6 +122,8 @@ internal GlobalPostProcessingQualitySettings() public DepthOfFieldResolution[] DoFResolution = new DepthOfFieldResolution[s_QualitySettingCount]; /// Use Depth of field high quality filtering for each quality level. public bool[] DoFHighQualityFiltering = new bool[s_QualitySettingCount]; + /// Use Depth of field high physically based setting for each quality level. + public bool[] DoFPhysicallyBased = new bool[s_QualitySettingCount]; /* Motion Blur */ /// Motion Blur sample count for each quality level. From 518498dab52c0b1faea3286fbc0aeae1d0d1769c Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Mon, 6 Jul 2020 22:08:36 +0200 Subject: [PATCH 05/27] Update documentation with the new option --- .../Documentation~/Post-Processing-Depth-of-Field.md | 1 + 1 file changed, 1 insertion(+) diff --git a/com.unity.render-pipelines.high-definition/Documentation~/Post-Processing-Depth-of-Field.md b/com.unity.render-pipelines.high-definition/Documentation~/Post-Processing-Depth-of-Field.md index 447004a2a5b..79bb21c4292 100644 --- a/com.unity.render-pipelines.high-definition/Documentation~/Post-Processing-Depth-of-Field.md +++ b/com.unity.render-pipelines.high-definition/Documentation~/Post-Processing-Depth-of-Field.md @@ -45,6 +45,7 @@ Depth Of Field includes [more options](More-Options.html) that you must manually | -------------------------- | ------------------------------------------------------------ | | **Resolution** | Use the drop-down to set the resolution at which HDRP processes the depth of field effect. If you target consoles that use a very high resolution (for example, 4k), select **Quarter,** because it is less resource intensive.
• **Quarter**: Uses quarter the screen resolution.
• **Half**: Uses half the screen resolution.
This property only appears when you enable [more options](More-Options.html). | | **High Quality Filtering** | Enable the checkbox to make HDRP use bicubic filtering instead of bilinear filtering. This increases the resource intensity of the Depth Of Field effect, but results in smoother visuals.
This property only appears when you enable [more options](More-Options.html). | +| **Physically Based** | Enable the checkbox to make HDRP use a more accurate but slower physically-based technique for the computation of Deph-of-Field| From 3f55086a7d9e30a43fbb80dc732724b91e0e0e1f Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Tue, 7 Jul 2020 09:23:47 +0200 Subject: [PATCH 06/27] Fix issue with mip maps when switching DoF techniques --- .../Runtime/PostProcessing/PostProcessSystem.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index 55ee01b5781..5947feb5d21 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -2259,6 +2259,13 @@ RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) next = camera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.DepthOfFieldCoC) ?? camera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.DepthOfFieldCoC, Allocator, 2); + + if (mipMaps == true && next.rt.mipmapCount == 1) + { + // if the user switches techniques on-the-fly, the rt might have been allocated previously whitout mips + camera.ReleaseHistoryFrameRT((int)HDCameraFrameHistoryType.DepthOfFieldCoC); + next = camera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.DepthOfFieldCoC, Allocator, 2); + } previous = camera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.DepthOfFieldCoC); } From e0852fe60440c580798a47dad9e381ad6b7946ff Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Tue, 7 Jul 2020 12:43:32 +0200 Subject: [PATCH 07/27] Improve documentation --- .../Documentation~/Post-Processing-Depth-of-Field.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.high-definition/Documentation~/Post-Processing-Depth-of-Field.md b/com.unity.render-pipelines.high-definition/Documentation~/Post-Processing-Depth-of-Field.md index 79bb21c4292..dccf270021f 100644 --- a/com.unity.render-pipelines.high-definition/Documentation~/Post-Processing-Depth-of-Field.md +++ b/com.unity.render-pipelines.high-definition/Documentation~/Post-Processing-Depth-of-Field.md @@ -45,7 +45,7 @@ Depth Of Field includes [more options](More-Options.html) that you must manually | -------------------------- | ------------------------------------------------------------ | | **Resolution** | Use the drop-down to set the resolution at which HDRP processes the depth of field effect. If you target consoles that use a very high resolution (for example, 4k), select **Quarter,** because it is less resource intensive.
• **Quarter**: Uses quarter the screen resolution.
• **Half**: Uses half the screen resolution.
This property only appears when you enable [more options](More-Options.html). | | **High Quality Filtering** | Enable the checkbox to make HDRP use bicubic filtering instead of bilinear filtering. This increases the resource intensity of the Depth Of Field effect, but results in smoother visuals.
This property only appears when you enable [more options](More-Options.html). | -| **Physically Based** | Enable the checkbox to make HDRP use a more accurate but slower physically-based technique for the computation of Deph-of-Field| +| **Physically Based** | Enable the checkbox to make HDRP use a more accurate but slower physically-based technique for the computation of Deph-of-Field. It is highly recommended to enable [Temporal anti-aliasing (TAA)](Anti-Aliasing) at the same time, for improved quality and performance.| From b9ac1ef0b0a86476bff67fcc86bead3c3d31b4f0 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Tue, 7 Jul 2020 14:23:19 +0200 Subject: [PATCH 08/27] Clean-up C# code --- .../PostProcessing/PostProcessSystem.cs | 57 ++++++------------- 1 file changed, 16 insertions(+), 41 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index 5947feb5d21..a6ebbe635d3 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -625,8 +625,9 @@ void PoolSource(ref RTHandle src, RTHandle dst) { var taaDestination = m_Pool.Get(Vector2.one, m_ColorFormat); var taaParams = PrepareTAAParameters(camera); - GrabTemporalAntialiasingHistoryTexturesPostDoF(camera, out var prevHistory, out var nextHistory); - GrabVelocityMagnitudeHistoryTexturesPostDoF(camera, out var prevMVLen, out var nextMVLen); + bool postDof = true; + GrabTemporalAntialiasingHistoryTextures(camera, out var prevHistory, out var nextHistory, postDof); + GrabVelocityMagnitudeHistoryTextures(camera, out var prevMVLen, out var nextMVLen, postDof); DoTemporalAntialiasing(taaParams, cmd, source, taaDestination, motionVecTexture, depthBuffer, depthMipChain, prevHistory, nextHistory, prevMVLen, nextMVLen); PoolSource(ref source, taaDestination); } @@ -1572,7 +1573,7 @@ static void DoTemporalAntialiasing(in TemporalAntiAliasingParameters taaParams, cmd.ClearRandomWriteTargets(); } - void GrabTemporalAntialiasingHistoryTextures(HDCamera camera, out RTHandle previous, out RTHandle next) + void GrabTemporalAntialiasingHistoryTextures(HDCamera camera, out RTHandle previous, out RTHandle next, bool postDoF = false) { RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) { @@ -1583,44 +1584,15 @@ RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) ); } - next = camera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.TemporalAntialiasing) - ?? camera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.TemporalAntialiasing, Allocator, 2); - previous = camera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.TemporalAntialiasing); - } - - void GrabVelocityMagnitudeHistoryTextures(HDCamera camera, out RTHandle previous, out RTHandle next) - { - RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) - { - return rtHandleSystem.Alloc( - Vector2.one, TextureXR.slices, DepthBits.None, dimension: TextureXR.dimension, - filterMode: FilterMode.Bilinear, colorFormat: GraphicsFormat.R16_SFloat, - enableRandomWrite: true, useDynamicScale: true, name: $"{id} Velocity magnitude" - ); - } - - next = camera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.TAAMotionVectorMagnitude) - ?? camera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.TAAMotionVectorMagnitude, Allocator, 2); - previous = camera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.TAAMotionVectorMagnitude); - } - - void GrabTemporalAntialiasingHistoryTexturesPostDoF(HDCamera camera, out RTHandle previous, out RTHandle next) - { - RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) - { - return rtHandleSystem.Alloc( - Vector2.one, TextureXR.slices, DepthBits.None, dimension: TextureXR.dimension, - filterMode: FilterMode.Bilinear, colorFormat: m_ColorFormat, - enableRandomWrite: true, useDynamicScale: true, name: $"{id} TAA History" - ); - } + int historyType = (int)(postDoF ? + HDCameraFrameHistoryType.TemporalAntialiasing : HDCameraFrameHistoryType.TemporalAntialiasingPostDoF); - next = camera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.TemporalAntialiasingPostDoF) - ?? camera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.TemporalAntialiasingPostDoF, Allocator, 2); - previous = camera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.TemporalAntialiasingPostDoF); + next = camera.GetCurrentFrameRT(historyType) + ?? camera.AllocHistoryFrameRT(historyType, Allocator, 2); + previous = camera.GetPreviousFrameRT(historyType); } - void GrabVelocityMagnitudeHistoryTexturesPostDoF(HDCamera camera, out RTHandle previous, out RTHandle next) + void GrabVelocityMagnitudeHistoryTextures(HDCamera camera, out RTHandle previous, out RTHandle next, bool postDoF = false) { RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) { @@ -1631,9 +1603,12 @@ RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) ); } - next = camera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.TAAMotionVectorMagnitudePostDoF) - ?? camera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.TAAMotionVectorMagnitudePostDoF, Allocator, 2); - previous = camera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.TAAMotionVectorMagnitudePostDoF); + int historyType = (int) (postDoF ? + HDCameraFrameHistoryType.TAAMotionVectorMagnitude : HDCameraFrameHistoryType.TAAMotionVectorMagnitudePostDoF); + + next = camera.GetCurrentFrameRT(historyType) + ?? camera.AllocHistoryFrameRT(historyType, Allocator, 2); + previous = camera.GetPreviousFrameRT(historyType); } #endregion From 108a54da438057de9a2a1d0d4b58d5196252970f Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Tue, 7 Jul 2020 14:31:32 +0200 Subject: [PATCH 09/27] Minor changes in the shader --- .../Runtime/PostProcessing/Shaders/DoFGather.compute | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 9b72343a2e2..18c4c27ee46 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -159,8 +159,8 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) // Record the central sample { float weight = GetSampleWeight(abs(centerCoc)); - totalColor[bucketIndex].xyz = centerColor.xyz * weight; - totalColor[bucketIndex].w = weight; + totalColor[bucketIndex] = float4(centerColor.xyz * weight, weight); + totalHits[bucketIndex] = 1.0f; maxCoC[bucketIndex] = abs(centerCoc); prevRingWeight[bucketIndex] = weight; #ifdef ENABLE_ALPHA @@ -227,14 +227,14 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) float sampleCoC = GetCoCRadius(sampleTC, sampleBucket); #ifdef COC_FAR_CLAMPING - sampleCoC = min(sampleCoC, centerCoc), sampleCoC; + if (centerCoc >= 0) + sampleCoC = min(sampleCoC, centerCoc); #endif - if (abs(sampleCoC) > radius) + if (abs(sampleCoC) >= radius) { float weight = GetSampleWeight(abs(sampleCoC)); - RING_COLOR[sampleBucket].xyz += sampleColor.xyz * weight; - RING_COLOR[sampleBucket].w += weight; + RING_COLOR[sampleBucket] += float4(sampleColor.xyz * weight, weight); RING_MAXCOC[sampleBucket] = max(RING_MAXCOC[sampleBucket], abs(sampleCoC)); RING_HITS[sampleBucket] += 1.0; #ifdef ENABLE_ALPHA From 05afe0d4ab7fb012a49215e63e01365e143ec497 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Tue, 7 Jul 2020 15:23:34 +0200 Subject: [PATCH 10/27] Fix near-far blending and cleanup unused code --- .../PostProcessing/PostProcessSystem.cs | 32 ++----------- .../PostProcessing/Shaders/DoFGather.compute | 48 ++----------------- 2 files changed, 8 insertions(+), 72 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index a6ebbe635d3..14a916e26e9 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -2222,25 +2222,19 @@ void DoDepthOfField(CommandBuffer cmd, HDCamera camera, RTHandle source, RTHandl m_Pool.Recycle(fullresCoC); // Already cleaned up if TAA is enabled } - static void GrabCoCHistory(HDCamera camera, out RTHandle previous, out RTHandle next, bool mipMaps = false) + static void GrabCoCHistory(HDCamera camera, out RTHandle previous, out RTHandle next) { RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) { return rtHandleSystem.Alloc( Vector2.one, TextureXR.slices, DepthBits.None, GraphicsFormat.R16_SFloat, - dimension: TextureXR.dimension, enableRandomWrite: true, useMipMap: mipMaps, useDynamicScale: true, name: $"{id} CoC History" + dimension: TextureXR.dimension, enableRandomWrite: true, useDynamicScale: true, name: $"{id} CoC History" ); } next = camera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.DepthOfFieldCoC) ?? camera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.DepthOfFieldCoC, Allocator, 2); - if (mipMaps == true && next.rt.mipmapCount == 1) - { - // if the user switches techniques on-the-fly, the rt might have been allocated previously whitout mips - camera.ReleaseHistoryFrameRT((int)HDCameraFrameHistoryType.DepthOfFieldCoC); - next = camera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.DepthOfFieldCoC, Allocator, 2); - } previous = camera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.DepthOfFieldCoC); } @@ -2306,25 +2300,6 @@ void DoPhysicallyBasedDepthOfField(CommandBuffer cmd, HDCamera camera, RTHandle cmd.DispatchCompute(cs, kernel, (camera.actualWidth + 7) / 8, (camera.actualHeight + 7) / 8, camera.viewCount); } - if (taaEnabled) - { - GrabCoCHistory(camera, out var prevCoCTex, out var nextCoCTex, true); - Vector2 cocHistoryScale = new Vector2(camera.historyRTHandleProperties.rtHandleScale.z, camera.historyRTHandleProperties.rtHandleScale.w); - - cs = m_Resources.shaders.depthOfFieldCoCReprojectCS; - kernel = cs.FindKernel("KMain"); - cmd.SetComputeVectorParam(cs, HDShaderIDs._Params, new Vector4(camera.resetPostProcessingHistory ? 0f : 0.91f, cocHistoryScale.x, cocHistoryScale.y, 0f)); - cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputCoCTexture, fullresCoC); - cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputHistoryCoCTexture, prevCoCTex); - cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputCoCTexture, nextCoCTex); - cmd.DispatchCompute(cs, kernel, (camera.actualWidth + 7) / 8, (camera.actualHeight + 7) / 8, camera.viewCount); - - // Cleanup the main CoC texture as we don't need it anymore and use the - // re-projected one instead for the following steps - m_Pool.Recycle(fullresCoC); - fullresCoC = nextCoCTex; - } - using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.DepthOfFieldPyramid))) { // To have an adaptive gather radius, we need estimates for the the min and max CoC that intersect a pixel. @@ -2362,8 +2337,7 @@ void DoPhysicallyBasedDepthOfField(CommandBuffer cmd, HDCamera camera, RTHandle cmd.DispatchCompute(cs, kernel, (camera.actualWidth + 7) / 8, (camera.actualHeight + 7) / 8, camera.viewCount); } - if (!taaEnabled) - m_Pool.Recycle(fullresCoC); // Already cleaned up if TAA is enabled + m_Pool.Recycle(fullresCoC); } #endregion diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 18c4c27ee46..70e086c8e01 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -22,10 +22,10 @@ RW_TEXTURE2D_X(CTYPE, _OutputTexture); // A set of Defines to fine-tune the algorithm #define NUM_BUCKETS 3 -#define COC_FAR_CLAMPING +//#define COC_FAR_CLAMPING #define CENTER_DENSITY #define RING_DENSITY 8.0 -#define UNIFORM_WEIGHTS +//#define UNIFORM_WEIGHTS //#define ADAPTIVE_RADIUS #define GRADIENT_NOISE //#define OCTAWEB_SORTING @@ -241,16 +241,6 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) RING_ALPHA[sampleBucket] = sampleColor.w * weight; #endif } -#ifdef UNIFORM_WEIGHTS - else - { - RING_COLOR[sampleBucket].xyz += RING_COLOR[sampleBucket].w > 0 ? RING_COLOR[sampleBucket].xyz / RING_COLOR[sampleBucket].w : 0; - RING_COLOR[sampleBucket].w += 1.0f; -#ifdef ENABLE_ALPHA - RING_ALPHA[sampleBucket] += RING_COLOR[sampleBucket].w > 0 ? RING_ALPHA[sampleBucket] / RING_COLOR[sampleBucket].w : 0; -#endif - } -#endif } #ifdef OCTAWEB_SORTING @@ -297,7 +287,6 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) } // Now compute the final color by combining the near, far and in-focus buckets with proper blending - // Far range float3 outColor = totalColor[0].xyz; float totalW = totalColor[0].w; @@ -305,44 +294,17 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) float outAlpha = totalAlpha[0]; #endif -#ifndef UNIFORM_WEIGHTS - // In focus range - { - // TODO: we might need to re-investigate the normaziation here, there is banding - float alpha = saturate(totalColor[1].w * rcp(GetNumSamples(maxCoC[1])) * rcp(GetSampleWeight(maxCoC[1]))); - outColor.xyz = (1.0 - alpha) * outColor.xyz + totalColor[1].xyz; - totalW = (1.0 - alpha) * totalW + totalColor[1].w; -#ifdef ENABLE_ALPHA - outAlpha = (1.0 - alpha) * outAlpha + totalAlpha[1]; -#endif - } - if (totalW > 0) outColor.xyz /= totalW; - - // Near range - float alpha = saturate(3 * totalHits[2] * rcp(GetNumSamples(maxCoC[2]))); - float3 srcColor = totalColor[2].w > 0 ? totalColor[2].xyz / totalColor[2].w : 0.0f; - outColor.xyz = (1.0 - alpha) * outColor.xyz + alpha * srcColor; -#ifdef ENABLE_ALPHA - float srcAlpha = totalColor[2].w > 0 ? totalAlpha[2] / totalColor[2].w : 0.0f; - outAlpha = (1.0 - alpha) * outAlpha + alpha * srcAlpha; - -#endif -#else - // back to front alpha blending of the other buckets for (int j = 1; j < NUM_BUCKETS; ++j) { - // TODO: we might need to re-investigate the normaziation here, there is banding float alpha = saturate(totalColor[j].w * rcp(GetNumSamples(maxCoC[j])) * rcp(GetSampleWeight(maxCoC[j]))); - - outColor.xyz = (1.0 - alpha) * outColor.xyz + totalColor[j].xyz; - totalW = (1.0 - alpha) * totalW + totalColor[j].w; + outColor.xyz = (1.0 - alpha) * outColor.xyz + alpha * totalColor[j].xyz; + totalW = (1.0 - alpha) * totalW + alpha * totalColor[j].w; #ifdef ENABLE_ALPHA - outAlpha = (1.0 - alpha) * outAlpha + totalAlpha[j]; + outAlpha = (1.0 - alpha) * outAlpha + alpha * totalAlpha[j]; #endif } outColor.xyz = outColor.xyz * rcp(totalW); -#endif #ifdef ENABLE_ALPHA _OutputTexture[COORD_TEXTURE2D_X(posInputs.positionSS)] = float4(outColor.xyz, outAlpha * rcp(totalW)); From 78089ab1cec790fcea23c457026f8e6ddc326d02 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Tue, 7 Jul 2020 17:20:00 +0200 Subject: [PATCH 11/27] clean-up shader code --- .../PostProcessing/Shaders/DoFGather.compute | 48 +++++-------------- 1 file changed, 11 insertions(+), 37 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 70e086c8e01..94ef8d62030 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -22,13 +22,13 @@ RW_TEXTURE2D_X(CTYPE, _OutputTexture); // A set of Defines to fine-tune the algorithm #define NUM_BUCKETS 3 -//#define COC_FAR_CLAMPING +#define GRADIENT_NOISE #define CENTER_DENSITY #define RING_DENSITY 8.0 +//#define OCTAWEB_SORTING +//#define COC_FAR_CLAMPING //#define UNIFORM_WEIGHTS //#define ADAPTIVE_RADIUS -#define GRADIENT_NOISE -//#define OCTAWEB_SORTING // DO NOT EDIT: Helper defines so we can have one code path when OCTAWEB_SORTING is enabled or disabled. #ifndef OCTAWEB_SORTING @@ -46,7 +46,6 @@ RW_TEXTURE2D_X(CTYPE, _OutputTexture); #define GROUP_RES 8u #define GROUP_SIZE (GROUP_RES * GROUP_RES) - int GetCoCBucket(float cocSize) { #if (NUM_BUCKETS == 1) @@ -179,7 +178,7 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) float noise2 = InterleavedGradientNoise(posInputs.positionSS.xy, 8 + sampleOffset); // Iterate over the octaweb pattern and gather the DoF samples - for (float ring = 1; ring <= numRings; ring += 1.0) + for (float ring = numRings; ring > 0; ring -= 1.0) { float scaledRad = dR; @@ -244,43 +243,18 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) } #ifdef OCTAWEB_SORTING - // Far bucket - { - totalColor[0] += RING_COLOR[0]; - maxCoC[0] = max(maxCoC[0], RING_MAXCOC[0]); - totalHits[0] += RING_HITS[0]; -#ifdef ENABLE_ALPHA - totalAlpha[0] += RING_ALPHA[0]; -#endif - } - - // In-focus bucket + for (int j = 0; j < NUM_BUCKETS; ++j) { - totalColor[1] += RING_COLOR[1]; - maxCoC[1] = max(maxCoC[1], RING_MAXCOC[1]); - totalHits[1] += RING_HITS[1]; -#ifdef ENABLE_ALPHA - totalAlpha[1] += RING_ALPHA[1]; -#endif - } - - // Near bucket - { - float currentAvg = RING_COLOR[2].w * rcp(ring * RING_DENSITY); - float prevAvg = prevRingWeight[2] * ((ring > 1) ? rcp((ring - 1.0) * RING_DENSITY) : 1); + float currentAvg = RING_COLOR[j].w * rcp(ring * RING_DENSITY);; + float prevAvg = (ring < numRings) ? prevRingWeight[j] : 0; float occlusion = saturate(prevAvg - currentAvg); - //float alpha = saturate(RING_COLOR[2].w * rcp(GetNumSamples(RING_MAXCOC[2])) * rcp(getSampleWeight(RING_MAXCOC[2]))); - float alpha = ringHits[2] * rcp(ring * RING_DENSITY); - - //totalColor[2] += RING_COLOR[2]; - maxCoC[2] = max(maxCoC[2], RING_MAXCOC[2]); - totalHits[2] += RING_HITS[2]; + float alpha = ringHits[j] * rcp(ring * RING_DENSITY); float blendFactor = 1.0 - alpha * occlusion; - totalColor[2] = blendFactor * totalColor[2] + RING_COLOR[2]; - prevRingWeight[2] = ringColor[2].w; + totalColor[j] = blendFactor * totalColor[j] + RING_COLOR[j]; + prevRingWeight[j] = currentAvg; #ifdef ENABLE_ALPHA - totalAlpha[2] += blendFactor * totalAlpha[2] + RING_ALPHA[2]; + totalAlpha[j] += blendFactor * totalAlpha[j] + RING_ALPHA[j]; #endif } #endif From d562971d205ab9490d5dcf06b6fa6a7474bce261 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Tue, 7 Jul 2020 17:29:27 +0200 Subject: [PATCH 12/27] more shader shader clean-up + fix weigths --- .../Runtime/PostProcessing/Shaders/DoFGather.compute | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 94ef8d62030..6ab06bde1f2 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -26,7 +26,6 @@ RW_TEXTURE2D_X(CTYPE, _OutputTexture); #define CENTER_DENSITY #define RING_DENSITY 8.0 //#define OCTAWEB_SORTING -//#define COC_FAR_CLAMPING //#define UNIFORM_WEIGHTS //#define ADAPTIVE_RADIUS @@ -46,6 +45,7 @@ RW_TEXTURE2D_X(CTYPE, _OutputTexture); #define GROUP_RES 8u #define GROUP_SIZE (GROUP_RES * GROUP_RES) + int GetCoCBucket(float cocSize) { #if (NUM_BUCKETS == 1) @@ -101,8 +101,8 @@ float GetSampleWeight(float cocRadius) if (cocRadius == 0.0) return 0.0; float pixelRadius = 0.7071f; - float singlePixelArea = 4 * PI * pixelRadius * pixelRadius; - float diskArea = 4 * PI * cocRadius * cocRadius; + float singlePixelArea = PI * pixelRadius * pixelRadius; + float diskArea = PI * cocRadius * cocRadius; return diskArea >= singlePixelArea ? rcp(diskArea) : rcp(singlePixelArea); } @@ -225,11 +225,6 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) CTYPE sampleColor = LOAD_TEXTURE2D_X(_InputTexture, sampleTC).CTYPE_SWIZZLE; float sampleCoC = GetCoCRadius(sampleTC, sampleBucket); -#ifdef COC_FAR_CLAMPING - if (centerCoc >= 0) - sampleCoC = min(sampleCoC, centerCoc); -#endif - if (abs(sampleCoC) >= radius) { float weight = GetSampleWeight(abs(sampleCoC)); From 16394b5def76edbbb81134bd81093ccc15a5c45f Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Tue, 7 Jul 2020 23:04:46 +0200 Subject: [PATCH 13/27] more shader shader clean-up --- .../PostProcessing/Shaders/DoFGather.compute | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 6ab06bde1f2..4c70d6d188f 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -29,16 +29,14 @@ RW_TEXTURE2D_X(CTYPE, _OutputTexture); //#define UNIFORM_WEIGHTS //#define ADAPTIVE_RADIUS -// DO NOT EDIT: Helper defines so we can have one code path when OCTAWEB_SORTING is enabled or disabled. +// Helper defines so we can have one code path when OCTAWEB_SORTING is enabled or disabled. #ifndef OCTAWEB_SORTING #define RING_COLOR totalColor #define RING_MAXCOC maxCoC - #define RING_HITS totalHits #define RING_ALPHA totalAlpha #else #define RING_COLOR ringColor #define RING_MAXCOC ringMaxCoC - #define RING_HITS ringHits #define RING_ALPHA ringAlpha #endif @@ -113,7 +111,7 @@ float2 PointInCircle(float angle) float GetNumSamples(float radius) { - //TODO: needs to take into account the density push towards the center (when enabled) + // Note: should also take into account the density push towards the center (if enabled), this needs to be fixed at some pointss float numRings = _Params.x; float maxRadius = _Params.y; @@ -149,7 +147,6 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) totalColor[i] = 0.0f; maxCoC[i] = 0.0f; prevRingWeight[i] = 0.0f; - totalHits[i] = 0.0f; #ifdef ENABLE_ALPHA totalAlpha[i] = 0.0f; #endif @@ -159,7 +156,6 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) { float weight = GetSampleWeight(abs(centerCoc)); totalColor[bucketIndex] = float4(centerColor.xyz * weight, weight); - totalHits[bucketIndex] = 1.0f; maxCoC[bucketIndex] = abs(centerCoc); prevRingWeight[bucketIndex] = weight; #ifdef ENABLE_ALPHA @@ -202,7 +198,7 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) float ringMaxCoC[NUM_BUCKETS]; float ringHits[NUM_BUCKETS]; #ifdef ENABLE_ALPHA - float4 ringAlpha[NUM_BUCKETS]; + float ringAlpha[NUM_BUCKETS]; #endif for (int i = 0; i < NUM_BUCKETS; ++i) @@ -230,7 +226,9 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) float weight = GetSampleWeight(abs(sampleCoC)); RING_COLOR[sampleBucket] += float4(sampleColor.xyz * weight, weight); RING_MAXCOC[sampleBucket] = max(RING_MAXCOC[sampleBucket], abs(sampleCoC)); - RING_HITS[sampleBucket] += 1.0; +#ifdef OCTAWEB_SORTING + ringHits[sampleBucket] += 1.0; +#endif #ifdef ENABLE_ALPHA RING_ALPHA[sampleBucket] = sampleColor.w * weight; #endif @@ -241,7 +239,7 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) for (int j = 0; j < NUM_BUCKETS; ++j) { float currentAvg = RING_COLOR[j].w * rcp(ring * RING_DENSITY);; - float prevAvg = (ring < numRings) ? prevRingWeight[j] : 0; + float prevAvg = (ring < numRings) ? prevRingWeight[j] : currentAvg; float occlusion = saturate(prevAvg - currentAvg); float alpha = ringHits[j] * rcp(ring * RING_DENSITY); @@ -256,9 +254,7 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) } // Now compute the final color by combining the near, far and in-focus buckets with proper blending - // Far range - float3 outColor = totalColor[0].xyz; - float totalW = totalColor[0].w; + float4 outColor = totalColor[0]; #ifdef ENABLE_ALPHA float outAlpha = totalAlpha[0]; #endif @@ -267,16 +263,15 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) for (int j = 1; j < NUM_BUCKETS; ++j) { float alpha = saturate(totalColor[j].w * rcp(GetNumSamples(maxCoC[j])) * rcp(GetSampleWeight(maxCoC[j]))); - outColor.xyz = (1.0 - alpha) * outColor.xyz + alpha * totalColor[j].xyz; - totalW = (1.0 - alpha) * totalW + alpha * totalColor[j].w; + outColor = (1.0 - alpha) * outColor + alpha * totalColor[j]; #ifdef ENABLE_ALPHA outAlpha = (1.0 - alpha) * outAlpha + alpha * totalAlpha[j]; #endif } - outColor.xyz = outColor.xyz * rcp(totalW); + outColor.xyz = outColor.xyz* rcp(outColor.w); #ifdef ENABLE_ALPHA - _OutputTexture[COORD_TEXTURE2D_X(posInputs.positionSS)] = float4(outColor.xyz, outAlpha * rcp(totalW)); + _OutputTexture[COORD_TEXTURE2D_X(posInputs.positionSS)] = float4(outColor.xyz, outAlpha * rcp(outColor.w)); #else _OutputTexture[COORD_TEXTURE2D_X(posInputs.positionSS)] = outColor.xyz; #endif From 7cb6509dc6da08db96403f0be113f00ac5cfa037 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Wed, 8 Jul 2020 00:01:51 +0200 Subject: [PATCH 14/27] back-to-front blending clean-up --- .../Runtime/PostProcessing/Shaders/DoFGather.compute | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 4c70d6d188f..1af8c53e120 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -253,14 +253,13 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) #endif } - // Now compute the final color by combining the near, far and in-focus buckets with proper blending - float4 outColor = totalColor[0]; + float4 outColor = 0; #ifdef ENABLE_ALPHA - float outAlpha = totalAlpha[0]; + float outAlpha = 0; #endif - // back to front alpha blending of the other buckets - for (int j = 1; j < NUM_BUCKETS; ++j) + // back to front alpha blending of the near, far and in-focus buckets + for (int j = 0; j < NUM_BUCKETS; ++j) { float alpha = saturate(totalColor[j].w * rcp(GetNumSamples(maxCoC[j])) * rcp(GetSampleWeight(maxCoC[j]))); outColor = (1.0 - alpha) * outColor + alpha * totalColor[j]; From 4dac90011bdca8f29cecb262f0ff4abd3f7048e0 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Wed, 8 Jul 2020 10:05:26 +0200 Subject: [PATCH 15/27] Make Manual CoC work for the new dof --- .../PostProcessing/Components/DepthOfField.cs | 4 +-- .../PostProcessing/PostProcessSystem.cs | 3 ++- .../Shaders/DoFCircleOfConfusion.compute | 25 +++++++++++++++++-- .../PostProcessing/Shaders/DoFGather.compute | 2 +- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/DepthOfField.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/DepthOfField.cs index f2b2f086c9e..1961830c0bd 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/DepthOfField.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/DepthOfField.cs @@ -210,12 +210,12 @@ public bool physicallyBased { if (!UsesQualitySettings()) { - return m_PhysicallyBased.value && focusMode.value == DepthOfFieldMode.UsePhysicalCamera; + return m_PhysicallyBased.value; } else { int qualityLevel = (int)quality.levelAndOverride.level; - return GetPostProcessingQualitySettings().DoFPhysicallyBased[qualityLevel] && focusMode.value == DepthOfFieldMode.UsePhysicalCamera; + return GetPostProcessingQualitySettings().DoFPhysicallyBased[qualityLevel]; } } set { m_PhysicallyBased.value = value; } diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index 14a916e26e9..49e2a8c40b7 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -2293,7 +2293,8 @@ void DoPhysicallyBasedDepthOfField(CommandBuffer cmd, HDCamera camera, RTHandle float nearStart = Mathf.Min(m_DepthOfField.nearFocusStart.value, nearEnd - 1e-5f); float farStart = Mathf.Max(m_DepthOfField.farFocusStart.value, nearEnd); float farEnd = Mathf.Max(m_DepthOfField.farFocusEnd.value, farStart + 1e-5f); - cmd.SetComputeVectorParam(cs, HDShaderIDs._Params, new Vector4(nearStart, nearEnd, farStart, farEnd)); + cmd.SetComputeVectorParam(cs, HDShaderIDs._Params, new Vector4(farStart, nearEnd, 1.0f / (farEnd - farStart), 1.0f / (nearStart - nearEnd))); + cmd.SetComputeVectorParam(cs, HDShaderIDs._Params2, new Vector4(m_DepthOfField.nearMaxBlur, m_DepthOfField.farMaxBlur, 0, 0)); } cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputTexture, fullresCoC); diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFCircleOfConfusion.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFCircleOfConfusion.compute index 81e5829696a..0f5d36d81c2 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFCircleOfConfusion.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFCircleOfConfusion.compute @@ -10,6 +10,7 @@ CBUFFER_START(cb0) float4 _Params; +float4 _Params2; CBUFFER_END // outpute texture @@ -50,7 +51,27 @@ void KMainCoCManual(uint3 dispatchThreadId : SV_DispatchThreadID) { UNITY_XR_ASSIGN_VIEW_INDEX(dispatchThreadId.z); - //TODO + float depth = LoadCameraDepth(dispatchThreadId.xy); + // Note: we can avoid explicit linearization by merging it with the other computations + float linearEyeDepth = LinearEyeDepth(depth, _ZBufferParams); - _OutputTexture[COORD_TEXTURE2D_X(dispatchThreadId.xy)] = 0.0f; + const float FarStart = _Params.x; + const float NearEnd = _Params.y; + const float FarRange = _Params.z; // 1 / (FarEnd - FarStart) + const float NearRange = _Params.w; // 1 / (NearStart - NearEnd) + + const float NearMaxRadius = _Params2.x; + const float FarMaxRadius = _Params2.y; + + float CoC = 0; + if (linearEyeDepth > FarStart) + { + CoC = FarMaxRadius * saturate((linearEyeDepth - FarStart) * FarRange); + } + else if (linearEyeDepth < NearEnd) + { + CoC = - NearMaxRadius * saturate((linearEyeDepth - NearEnd) * NearRange); + } + + _OutputTexture[COORD_TEXTURE2D_X(dispatchThreadId.xy)] = CoC; } diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 1af8c53e120..4bda6bcb2ed 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -96,7 +96,7 @@ float GetSampleWeight(float cocRadius) return 1.0f; #endif - if (cocRadius == 0.0) return 0.0; + if (cocRadius == 0.0) return 1.0; float pixelRadius = 0.7071f; float singlePixelArea = PI * pixelRadius * pixelRadius; From e587d554036fdb6db48c1393ad85558136f7a8ba Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Wed, 8 Jul 2020 10:57:31 +0200 Subject: [PATCH 16/27] Changelog --- com.unity.render-pipelines.high-definition/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/com.unity.render-pipelines.high-definition/CHANGELOG.md b/com.unity.render-pipelines.high-definition/CHANGELOG.md index 4e44dcae455..f65a221d12d 100644 --- a/com.unity.render-pipelines.high-definition/CHANGELOG.md +++ b/com.unity.render-pipelines.high-definition/CHANGELOG.md @@ -160,6 +160,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added decal layer system similar to light layer. Mesh will receive a decal when both decal layer mask matches. - Added shader graph nodes for rendering a complex eye shader. - Added more controls to contact shadows and increased quality in some parts. +- Added a physically based option in DoF volume. ### Fixed - Fix when rescale probe all direction below zero (1219246) From 406c0070ad623677991ed8f2b1a2db63d015a413 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Wed, 8 Jul 2020 14:13:22 +0200 Subject: [PATCH 17/27] Change min aperture to 0.7 --- .../Runtime/RenderPipeline/Camera/HDAdditionalCameraData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDAdditionalCameraData.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDAdditionalCameraData.cs index a9667339265..fe2b89f1c15 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDAdditionalCameraData.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDAdditionalCameraData.cs @@ -13,7 +13,7 @@ public class HDPhysicalCamera /// /// The minimum allowed aperture. /// - public const float kMinAperture = 1f; + public const float kMinAperture = 0.7f; /// /// The maximum allowed aperture. From db8607c90f214ce8c6bd58b9f90c58f075e5ad7d Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Thu, 9 Jul 2020 18:46:42 +0200 Subject: [PATCH 18/27] Add info box when physically based dof is enabled --- .../Editor/PostProcessing/DepthOfFieldEditor.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs index 74fcdde03d2..2d84c177f43 100644 --- a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs @@ -20,6 +20,8 @@ static partial class Styles public static GUIContent k_NearFocusEnd = new GUIContent("End", "Sets the distance from the Camera at which the near field does not blur anymore."); public static GUIContent k_FarFocusEnd = new GUIContent("End", "Sets the distance from the Camera at which the far field blur reaches its maximum blur radius."); public static GUIContent k_PhysicallyBased = new GUIContent("PhysicallyBased", "Uses a more accurate but slower physically based method to compute DoF."); + + public static readonly string InfoBox = "Physically Based DoF currently has a high performance overhead and enabling TAA is also recommended."; } SerializedDataParameter m_FocusMode; @@ -136,6 +138,8 @@ public override void OnInspectorGUI() PropertyField(m_Resolution); PropertyField(m_HighQualityFiltering); PropertyField(m_PhysicallyBased); + if(m_PhysicallyBased.value.boolValue == true) + EditorGUILayout.HelpBox(Styles.InfoBox, MessageType.Info); GUI.enabled = true; } } From 3596ad3d3def843e3251851ae5c0dc5765d0a528 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Thu, 9 Jul 2020 18:48:25 +0200 Subject: [PATCH 19/27] Add info box when physically based dof is enabled --- .../Editor/PostProcessing/DepthOfFieldEditor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs index 2d84c177f43..641a2b98665 100644 --- a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs @@ -21,7 +21,7 @@ static partial class Styles public static GUIContent k_FarFocusEnd = new GUIContent("End", "Sets the distance from the Camera at which the far field blur reaches its maximum blur radius."); public static GUIContent k_PhysicallyBased = new GUIContent("PhysicallyBased", "Uses a more accurate but slower physically based method to compute DoF."); - public static readonly string InfoBox = "Physically Based DoF currently has a high performance overhead and enabling TAA is also recommended."; + public static readonly string InfoBox = "Physically Based DoF currently has a high performance overhead. Enabling TAA is highly recommended when using this option."; } SerializedDataParameter m_FocusMode; From afdd56afcbc2a3178326b5cf79f64f641f47f120 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Thu, 9 Jul 2020 20:33:56 +0200 Subject: [PATCH 20/27] Add s specialized TAA configuration for use with DoF and also stabilize CoC --- .../PostProcessing/PostProcessSystem.cs | 74 ++++++++++++++----- .../Shaders/TemporalAntiAliasing.shader | 15 +++- 2 files changed, 69 insertions(+), 20 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index 49e2a8c40b7..0938dbb0eae 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -624,8 +624,9 @@ void PoolSource(ref RTHandle src, RTHandle dst) if (taaEnabled && m_DepthOfField.physicallyBased) { var taaDestination = m_Pool.Get(Vector2.one, m_ColorFormat); - var taaParams = PrepareTAAParameters(camera); bool postDof = true; + var taaParams = PrepareTAAParameters(camera, postDof); + GrabTemporalAntialiasingHistoryTextures(camera, out var prevHistory, out var nextHistory, postDof); GrabVelocityMagnitudeHistoryTextures(camera, out var prevMVLen, out var nextMVLen, postDof); DoTemporalAntialiasing(taaParams, cmd, source, taaDestination, motionVecTexture, depthBuffer, depthMipChain, prevHistory, nextHistory, prevMVLen, nextMVLen); @@ -1452,7 +1453,7 @@ struct TemporalAntiAliasingParameters public Vector4 taaFilterWeights; } - TemporalAntiAliasingParameters PrepareTAAParameters(HDCamera camera) + TemporalAntiAliasingParameters PrepareTAAParameters(HDCamera camera, bool PostDOF = false) { TemporalAntiAliasingParameters parameters = new TemporalAntiAliasingParameters(); @@ -1465,7 +1466,7 @@ TemporalAntiAliasingParameters PrepareTAAParameters(HDCamera camera) // The anti flicker becomes much more aggressive on higher values float temporalContrastForMaxAntiFlicker = 0.7f - Mathf.Lerp(0.0f, 0.3f, Mathf.SmoothStep(0.5f, 1.0f, camera.taaAntiFlicker)); - parameters.taaParameters = new Vector4(camera.taaHistorySharpening, Mathf.Lerp(minAntiflicker, maxAntiflicker, camera.taaAntiFlicker), motionRejectionMultiplier, temporalContrastForMaxAntiFlicker); + parameters.taaParameters = new Vector4(camera.taaHistorySharpening, PostDOF ? maxAntiflicker : Mathf.Lerp(minAntiflicker, maxAntiflicker, camera.taaAntiFlicker), motionRejectionMultiplier, temporalContrastForMaxAntiFlicker); // Precompute weights used for the Blackman-Harris filter. TODO: Note that these are slightly wrong as they don't take into account the jitter size. This needs to be fixed at some point. float crossWeights = Mathf.Exp(-2.29f * 2); @@ -1504,20 +1505,27 @@ TemporalAntiAliasingParameters PrepareTAAParameters(HDCamera camera) parameters.temporalAAMaterial.EnableKeyword("ENABLE_MV_REJECTION"); } - switch (camera.TAAQuality) + if (PostDOF) { - case HDAdditionalCameraData.TAAQualityLevel.Low: - parameters.temporalAAMaterial.EnableKeyword("LOW_QUALITY"); - break; - case HDAdditionalCameraData.TAAQualityLevel.Medium: - parameters.temporalAAMaterial.EnableKeyword("MEDIUM_QUALITY"); - break; - case HDAdditionalCameraData.TAAQualityLevel.High: - parameters.temporalAAMaterial.EnableKeyword("HIGH_QUALITY"); - break; - default: - parameters.temporalAAMaterial.EnableKeyword("MEDIUM_QUALITY"); - break; + parameters.temporalAAMaterial.EnableKeyword("POST_DOF"); + } + else + { + switch (camera.TAAQuality) + { + case HDAdditionalCameraData.TAAQualityLevel.Low: + parameters.temporalAAMaterial.EnableKeyword("LOW_QUALITY"); + break; + case HDAdditionalCameraData.TAAQualityLevel.Medium: + parameters.temporalAAMaterial.EnableKeyword("MEDIUM_QUALITY"); + break; + case HDAdditionalCameraData.TAAQualityLevel.High: + parameters.temporalAAMaterial.EnableKeyword("HIGH_QUALITY"); + break; + default: + parameters.temporalAAMaterial.EnableKeyword("MEDIUM_QUALITY"); + break; + } } parameters.taaHistoryPropertyBlock = m_TAAHistoryBlitPropertyBlock; @@ -2222,19 +2230,25 @@ void DoDepthOfField(CommandBuffer cmd, HDCamera camera, RTHandle source, RTHandl m_Pool.Recycle(fullresCoC); // Already cleaned up if TAA is enabled } - static void GrabCoCHistory(HDCamera camera, out RTHandle previous, out RTHandle next) + static void GrabCoCHistory(HDCamera camera, out RTHandle previous, out RTHandle next, bool useMips = false) { RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) { return rtHandleSystem.Alloc( Vector2.one, TextureXR.slices, DepthBits.None, GraphicsFormat.R16_SFloat, - dimension: TextureXR.dimension, enableRandomWrite: true, useDynamicScale: true, name: $"{id} CoC History" + dimension: TextureXR.dimension, enableRandomWrite: true, useMipMap:useMips, useDynamicScale: true, name: $"{id} CoC History" ); } next = camera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.DepthOfFieldCoC) ?? camera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.DepthOfFieldCoC, Allocator, 2); + if (useMips == true && next.rt.mipmapCount == 1) + { + camera.ReleaseHistoryFrameRT((int)HDCameraFrameHistoryType.DepthOfFieldCoC); + next = camera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.DepthOfFieldCoC, Allocator, 2); + } + previous = camera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.DepthOfFieldCoC); } @@ -2301,6 +2315,27 @@ void DoPhysicallyBasedDepthOfField(CommandBuffer cmd, HDCamera camera, RTHandle cmd.DispatchCompute(cs, kernel, (camera.actualWidth + 7) / 8, (camera.actualHeight + 7) / 8, camera.viewCount); } + if (taaEnabled) + { + bool useMips = true; + GrabCoCHistory(camera, out var prevCoCTex, out var nextCoCTex, useMips); + var cocHistoryScale = new Vector2(camera.historyRTHandleProperties.rtHandleScale.z, camera.historyRTHandleProperties.rtHandleScale.w); + + //Note: this reprojection creates some ghosting, we should replace it with something based on the new TAA + cs = m_Resources.shaders.depthOfFieldCoCReprojectCS; + kernel = cs.FindKernel("KMain"); + cmd.SetComputeVectorParam(cs, HDShaderIDs._Params, new Vector4(camera.resetPostProcessingHistory ? 0f : 0.91f, cocHistoryScale.x, cocHistoryScale.y, 0f)); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputCoCTexture, fullresCoC); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputHistoryCoCTexture, prevCoCTex); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputCoCTexture, nextCoCTex); + cmd.DispatchCompute(cs, kernel, (camera.actualWidth + 7) / 8, (camera.actualHeight + 7) / 8, camera.viewCount); + + // Cleanup the main CoC texture as we don't need it anymore and use the + // re-projected one instead for the following steps + m_Pool.Recycle(fullresCoC); + fullresCoC = nextCoCTex; + } + using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.DepthOfFieldPyramid))) { // To have an adaptive gather radius, we need estimates for the the min and max CoC that intersect a pixel. @@ -2338,7 +2373,8 @@ void DoPhysicallyBasedDepthOfField(CommandBuffer cmd, HDCamera camera, RTHandle cmd.DispatchCompute(cs, kernel, (camera.actualWidth + 7) / 8, (camera.actualHeight + 7) / 8, camera.viewCount); } - m_Pool.Recycle(fullresCoC); + if (!taaEnabled) + m_Pool.Recycle(fullresCoC); } #endregion diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/TemporalAntiAliasing.shader b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/TemporalAntiAliasing.shader index b88b6224d8d..a297a31f50e 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/TemporalAntiAliasing.shader +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/TemporalAntiAliasing.shader @@ -14,7 +14,7 @@ Shader "Hidden/HDRP/TemporalAA" #pragma multi_compile_local _ FORCE_BILINEAR_HISTORY #pragma multi_compile_local _ ENABLE_MV_REJECTION #pragma multi_compile_local _ ANTI_RINGING - #pragma multi_compile_local LOW_QUALITY MEDIUM_QUALITY HIGH_QUALITY + #pragma multi_compile_local LOW_QUALITY MEDIUM_QUALITY HIGH_QUALITY POST_DOF #pragma only_renderers d3d11 playstation xboxone vulkan metal switch @@ -69,6 +69,19 @@ Shader "Hidden/HDRP/TemporalAA" #define PERCEPTUAL_SPACE 1 #define PERCEPTUAL_SPACE_ONLY_END 0 && (PERCEPTUAL_SPACE == 0) +#elif defined(POST_DOF) + #define YCOCG 1 + #define HISTORY_SAMPLING_METHOD BILINEAR + #define WIDE_NEIGHBOURHOOD 0 + #define NEIGHBOUROOD_CORNER_METHOD VARIANCE + #define CENTRAL_FILTERING NO_FILTERINGs + #define HISTORY_CLIP DIRECT_CLIP + #define ANTI_FLICKER 1 + #define ANTI_FLICKER_MV_DEPENDENT 1 + #define VELOCITY_REJECTION (defined(ENABLE_MV_REJECTION) && 0) + #define PERCEPTUAL_SPACE 1 + #define PERCEPTUAL_SPACE_ONLY_END 0 && (PERCEPTUAL_SPACE == 0) + #endif From b8b8f8a048b9978f2b1a33e96f042824f006b21b Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Thu, 9 Jul 2020 20:44:50 +0200 Subject: [PATCH 21/27] Do not increase sample count when taa is off --- .../Runtime/PostProcessing/PostProcessSystem.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index 0938dbb0eae..b08a6517570 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -2362,9 +2362,7 @@ void DoPhysicallyBasedDepthOfField(CommandBuffer cmd, HDCamera camera, RTHandle cs.EnableKeyword("ENABLE_ALPHA"); kernel = cs.FindKernel("KMain"); - // We use more samples when TAA is disabled, to hide undersampling - float sampleMultipleier = taaEnabled ? 1 : 2; - float sampleCount = sampleMultipleier * Mathf.Max(m_DepthOfField.nearSampleCount, m_DepthOfField.farSampleCount); + float sampleCount = Mathf.Max(m_DepthOfField.nearSampleCount, m_DepthOfField.farSampleCount); float mipLevel = Mathf.Ceil(Mathf.Log(cocLimit, 2)); cmd.SetComputeVectorParam(cs, HDShaderIDs._Params, new Vector4(sampleCount, cocLimit, mipLevel, 0.0f)); cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputTexture, source); From 6d7d52183c7718a6e8bc811794f7be749b09f22c Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Fri, 10 Jul 2020 00:31:01 +0200 Subject: [PATCH 22/27] Fix issue in disc sampling --- .../Runtime/PostProcessing/Shaders/DoFGather.compute | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 4bda6bcb2ed..e2c894cac11 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -96,12 +96,9 @@ float GetSampleWeight(float cocRadius) return 1.0f; #endif - if (cocRadius == 0.0) return 1.0; - float pixelRadius = 0.7071f; - float singlePixelArea = PI * pixelRadius * pixelRadius; - float diskArea = PI * cocRadius * cocRadius; - return diskArea >= singlePixelArea ? rcp(diskArea) : rcp(singlePixelArea); + float radius = max(pixelRadius, cocRadius); + return rcp(PI * radius * radius); } float2 PointInCircle(float angle) @@ -189,7 +186,7 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) float radius = ring * scaledRad + stratum * scaledRad; float ringOffset = 0.5 * fmod(ring, 2.0f) * dAng; #else - float radius = ring * scaledRad + noise2 * scaledRad; + float radius = (ring - 1) * scaledRad + noise2 * scaledRad; float ringOffset = noise * dAng; #endif From ec428cf5cbf6d1a40e4ef0a848f1aa1a17c4bc12 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Fri, 10 Jul 2020 01:39:17 +0200 Subject: [PATCH 23/27] Fix profiling scope for CoC --- .../PostProcessing/PostProcessSystem.cs | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index b08a6517570..188d15649a0 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -2313,27 +2313,27 @@ void DoPhysicallyBasedDepthOfField(CommandBuffer cmd, HDCamera camera, RTHandle cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputTexture, fullresCoC); cmd.DispatchCompute(cs, kernel, (camera.actualWidth + 7) / 8, (camera.actualHeight + 7) / 8, camera.viewCount); - } - if (taaEnabled) - { - bool useMips = true; - GrabCoCHistory(camera, out var prevCoCTex, out var nextCoCTex, useMips); - var cocHistoryScale = new Vector2(camera.historyRTHandleProperties.rtHandleScale.z, camera.historyRTHandleProperties.rtHandleScale.w); + if (taaEnabled) + { + bool useMips = true; + GrabCoCHistory(camera, out var prevCoCTex, out var nextCoCTex, useMips); + var cocHistoryScale = new Vector2(camera.historyRTHandleProperties.rtHandleScale.z, camera.historyRTHandleProperties.rtHandleScale.w); - //Note: this reprojection creates some ghosting, we should replace it with something based on the new TAA - cs = m_Resources.shaders.depthOfFieldCoCReprojectCS; - kernel = cs.FindKernel("KMain"); - cmd.SetComputeVectorParam(cs, HDShaderIDs._Params, new Vector4(camera.resetPostProcessingHistory ? 0f : 0.91f, cocHistoryScale.x, cocHistoryScale.y, 0f)); - cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputCoCTexture, fullresCoC); - cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputHistoryCoCTexture, prevCoCTex); - cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputCoCTexture, nextCoCTex); - cmd.DispatchCompute(cs, kernel, (camera.actualWidth + 7) / 8, (camera.actualHeight + 7) / 8, camera.viewCount); + //Note: this reprojection creates some ghosting, we should replace it with something based on the new TAA + cs = m_Resources.shaders.depthOfFieldCoCReprojectCS; + kernel = cs.FindKernel("KMain"); + cmd.SetComputeVectorParam(cs, HDShaderIDs._Params, new Vector4(camera.resetPostProcessingHistory ? 0f : 0.91f, cocHistoryScale.x, cocHistoryScale.y, 0f)); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputCoCTexture, fullresCoC); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputHistoryCoCTexture, prevCoCTex); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputCoCTexture, nextCoCTex); + cmd.DispatchCompute(cs, kernel, (camera.actualWidth + 7) / 8, (camera.actualHeight + 7) / 8, camera.viewCount); - // Cleanup the main CoC texture as we don't need it anymore and use the - // re-projected one instead for the following steps - m_Pool.Recycle(fullresCoC); - fullresCoC = nextCoCTex; + // Cleanup the main CoC texture as we don't need it anymore and use the + // re-projected one instead for the following steps + m_Pool.Recycle(fullresCoC); + fullresCoC = nextCoCTex; + } } using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.DepthOfFieldPyramid))) From 449be5e60842294fa4b36294de156bbbe62f7dca Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Fri, 10 Jul 2020 10:43:22 +0200 Subject: [PATCH 24/27] Fix for adaptive search radius --- .../PostProcessing/PostProcessSystem.cs | 2 +- .../PostProcessing/Shaders/DoFGather.compute | 30 ++++++++++++++----- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index 188d15649a0..542f41f6bd0 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -2265,7 +2265,7 @@ void DoPhysicallyBasedDepthOfField(CommandBuffer cmd, HDCamera camera, RTHandle // Map the old "max radius" parameters to a bigger range, so we can work on more challenging scenes float maxRadius = Mathf.Max(m_DepthOfField.farMaxBlur, m_DepthOfField.nearMaxBlur); - float cocLimit = Mathf.Clamp(2 * maxRadius, 1, 32); + float cocLimit = Mathf.Clamp(4 * maxRadius, 1, 32); ComputeShader cs; int kernel; diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index e2c894cac11..a434fe80e32 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -23,11 +23,11 @@ RW_TEXTURE2D_X(CTYPE, _OutputTexture); // A set of Defines to fine-tune the algorithm #define NUM_BUCKETS 3 #define GRADIENT_NOISE -#define CENTER_DENSITY +//#define CENTER_DENSITY #define RING_DENSITY 8.0 //#define OCTAWEB_SORTING //#define UNIFORM_WEIGHTS -//#define ADAPTIVE_RADIUS +#define ADAPTIVE_RADIUS // Helper defines so we can have one code path when OCTAWEB_SORTING is enabled or disabled. #ifndef OCTAWEB_SORTING @@ -85,8 +85,23 @@ float GetCoCMaxRadius(int2 positionSS) #else // We only have up to 6 mip levels int lod = min(6, _Params.z); - float maxOverlapingCoC = LOAD_TEXTURE2D_X_LOD(_InputCoCTexture, positionSS >> lod, lod).x; - return abs(maxOverlapingCoC); + uint4 size; + _InputCoCTexture.GetDimensions(lod, size.x, size.y, size.z, size.w); + + // Take RTHandleScale into account and odd texture dimension sizes (it's not enough to do a positionSS >> lod) + uint2 coords = positionSS * _ScreenSize.zw * size.xy * _RTHandleScale.xy; + + // Find the max CoC that is overlapping this pixel by sampling the max neighborhood + float maxOverlapingCoC = abs(LOAD_TEXTURE2D_X_LOD(_InputCoCTexture, coords, lod).x); + maxOverlapingCoC = max(maxOverlapingCoC, abs(LOAD_TEXTURE2D_X_LOD(_InputCoCTexture, coords + uint2 (1, 0), lod).x)); + maxOverlapingCoC = max(maxOverlapingCoC, abs(LOAD_TEXTURE2D_X_LOD(_InputCoCTexture, coords + uint2 (0, 1), lod).x)); + maxOverlapingCoC = max(maxOverlapingCoC, abs(LOAD_TEXTURE2D_X_LOD(_InputCoCTexture, coords + uint2 (1, 1), lod).x)); + maxOverlapingCoC = max(maxOverlapingCoC, abs(LOAD_TEXTURE2D_X_LOD(_InputCoCTexture, coords + uint2 (-1, 0), lod).x)); + maxOverlapingCoC = max(maxOverlapingCoC, abs(LOAD_TEXTURE2D_X_LOD(_InputCoCTexture, coords + uint2 (0, -1), lod).x)); + maxOverlapingCoC = max(maxOverlapingCoC, abs(LOAD_TEXTURE2D_X_LOD(_InputCoCTexture, coords + uint2 (-1, -1), lod).x)); + maxOverlapingCoC = max(maxOverlapingCoC, abs(LOAD_TEXTURE2D_X_LOD(_InputCoCTexture, coords + uint2 (-1, 1), lod).x)); + maxOverlapingCoC = max(maxOverlapingCoC, abs(LOAD_TEXTURE2D_X_LOD(_InputCoCTexture, coords + uint2 (1, -1), lod).x)); + return maxOverlapingCoC; #endif } @@ -106,11 +121,10 @@ float2 PointInCircle(float angle) return float2(cos(angle), sin(angle)); } -float GetNumSamples(float radius) +float GetNumSamples(float radius, float maxRadius) { // Note: should also take into account the density push towards the center (if enabled), this needs to be fixed at some pointss float numRings = _Params.x; - float maxRadius = _Params.y; float dR = maxRadius / numRings; float rings = floor(radius / dR); @@ -258,13 +272,13 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) // back to front alpha blending of the near, far and in-focus buckets for (int j = 0; j < NUM_BUCKETS; ++j) { - float alpha = saturate(totalColor[j].w * rcp(GetNumSamples(maxCoC[j])) * rcp(GetSampleWeight(maxCoC[j]))); + float alpha = saturate(totalColor[j].w * rcp(GetNumSamples(maxCoC[j], maxRadius)) * rcp(GetSampleWeight(maxCoC[j]))); outColor = (1.0 - alpha) * outColor + alpha * totalColor[j]; #ifdef ENABLE_ALPHA outAlpha = (1.0 - alpha) * outAlpha + alpha * totalAlpha[j]; #endif } - outColor.xyz = outColor.xyz* rcp(outColor.w); + outColor.xyz = outColor.xyz * rcp(outColor.w); #ifdef ENABLE_ALPHA _OutputTexture[COORD_TEXTURE2D_X(posInputs.positionSS)] = float4(outColor.xyz, outAlpha * rcp(outColor.w)); From 68e86e4a2f903a9ed88dd2d11b2cf21dfe98b1bc Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Fri, 10 Jul 2020 17:04:33 +0200 Subject: [PATCH 25/27] Review feadback --- .../PostProcessing/PostProcessSystem.cs | 101 ++++++++++-------- .../Shaders/DoFCircleOfConfusion.compute | 15 ++- .../PostProcessing/Shaders/DoFGather.compute | 11 +- .../Shaders/TemporalAntiAliasing.shader | 3 +- .../Camera/HDCameraFrameHistoryType.cs | 2 - .../GlobalPostProcessingQualitySettings.cs | 2 +- 6 files changed, 69 insertions(+), 65 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index 542f41f6bd0..d2ff6c760fb 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -601,6 +601,8 @@ void PoolSource(ref RTHandle src, RTHandle dst) } } + bool postDoFTAAEnabled = false; + // If Path tracing is enabled, then DoF is computed in the path tracer by sampling the lens aperure (when using the physical camera mode) bool isDoFPathTraced = (camera.frameSettings.IsEnabled(FrameSettingsField.RayTracing) && camera.volumeStack.GetComponent().enable.value && @@ -628,12 +630,18 @@ void PoolSource(ref RTHandle src, RTHandle dst) var taaParams = PrepareTAAParameters(camera, postDof); GrabTemporalAntialiasingHistoryTextures(camera, out var prevHistory, out var nextHistory, postDof); - GrabVelocityMagnitudeHistoryTextures(camera, out var prevMVLen, out var nextMVLen, postDof); - DoTemporalAntialiasing(taaParams, cmd, source, taaDestination, motionVecTexture, depthBuffer, depthMipChain, prevHistory, nextHistory, prevMVLen, nextMVLen); + GrabVelocityMagnitudeHistoryTextures(camera, out var prevMVLen, out var nextMVLen); + DoTemporalAntialiasing(taaParams, cmd, source, taaDestination, motionVecTexture, depthBuffer, depthMipChain, prevHistory, nextHistory); PoolSource(ref source, taaDestination); + postDoFTAAEnabled = true; } } } + + if (!postDoFTAAEnabled) + { + ReleasePostDoFTAAHistoryTextures(camera); + } // Motion blur after depth of field for aesthetic reasons (better to see motion // blurred bokeh rather than out of focus motion blur) @@ -1543,8 +1551,8 @@ static void DoTemporalAntialiasing(in TemporalAntiAliasingParameters taaParams, RTHandle depthMipChain, RTHandle prevHistory, RTHandle nextHistory, - RTHandle prevMVLen, - RTHandle nextMVLen) + RTHandle prevMVLen = null, + RTHandle nextMVLen = null) { if (taaParams.camera.resetPostProcessingHistory) { @@ -1561,7 +1569,10 @@ static void DoTemporalAntialiasing(in TemporalAntiAliasingParameters taaParams, taaParams.taaPropertyBlock.SetTexture(HDShaderIDs._CameraMotionVectorsTexture, motionVecTexture); taaParams.taaPropertyBlock.SetTexture(HDShaderIDs._InputTexture, source); taaParams.taaPropertyBlock.SetTexture(HDShaderIDs._InputHistoryTexture, prevHistory); - taaParams.taaPropertyBlock.SetTexture(HDShaderIDs._InputVelocityMagnitudeHistory, prevMVLen); + if (prevMVLen != null) + { + taaParams.taaPropertyBlock.SetTexture(HDShaderIDs._InputVelocityMagnitudeHistory, prevMVLen); + } taaParams.taaPropertyBlock.SetTexture(HDShaderIDs._DepthTexture, depthMipChain); @@ -1575,7 +1586,11 @@ static void DoTemporalAntialiasing(in TemporalAntiAliasingParameters taaParams, CoreUtils.SetRenderTarget(cmd, destination, depthBuffer); cmd.SetRandomWriteTarget(1, nextHistory); - cmd.SetRandomWriteTarget(2, nextMVLen); + if (nextMVLen != null) + { + cmd.SetRandomWriteTarget(2, nextMVLen); + } + cmd.DrawProcedural(Matrix4x4.identity, taaParams.temporalAAMaterial, 0, MeshTopology.Triangles, 3, 1, taaParams.taaPropertyBlock); cmd.DrawProcedural(Matrix4x4.identity, taaParams.temporalAAMaterial, 1, MeshTopology.Triangles, 3, 1, taaParams.taaPropertyBlock); cmd.ClearRandomWriteTargets(); @@ -1593,14 +1608,14 @@ RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) } int historyType = (int)(postDoF ? - HDCameraFrameHistoryType.TemporalAntialiasing : HDCameraFrameHistoryType.TemporalAntialiasingPostDoF); + HDCameraFrameHistoryType.TemporalAntialiasingPostDoF : HDCameraFrameHistoryType.TemporalAntialiasing); next = camera.GetCurrentFrameRT(historyType) ?? camera.AllocHistoryFrameRT(historyType, Allocator, 2); previous = camera.GetPreviousFrameRT(historyType); } - void GrabVelocityMagnitudeHistoryTextures(HDCamera camera, out RTHandle previous, out RTHandle next, bool postDoF = false) + void GrabVelocityMagnitudeHistoryTextures(HDCamera camera, out RTHandle previous, out RTHandle next) { RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) { @@ -1611,12 +1626,18 @@ RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) ); } - int historyType = (int) (postDoF ? - HDCameraFrameHistoryType.TAAMotionVectorMagnitude : HDCameraFrameHistoryType.TAAMotionVectorMagnitudePostDoF); + next = camera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.TAAMotionVectorMagnitude) + ?? camera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.TAAMotionVectorMagnitude, Allocator, 2); + previous = camera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.TAAMotionVectorMagnitude); + } - next = camera.GetCurrentFrameRT(historyType) - ?? camera.AllocHistoryFrameRT(historyType, Allocator, 2); - previous = camera.GetPreviousFrameRT(historyType); + void ReleasePostDoFTAAHistoryTextures(HDCamera camera) + { + var rt = camera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.TemporalAntialiasingPostDoF); + if (rt != null) + { + camera.ReleaseHistoryFrameRT((int)HDCameraFrameHistoryType.TemporalAntialiasingPostDoF); + } } #endregion @@ -1794,21 +1815,8 @@ void DoDepthOfField(CommandBuffer cmd, HDCamera camera, RTHandle source, RTHandl if (taaEnabled) { - GrabCoCHistory(camera, out var prevCoCTex, out var nextCoCTex); - cocHistoryScale = new Vector2(camera.historyRTHandleProperties.rtHandleScale.z, camera.historyRTHandleProperties.rtHandleScale.w); - - cs = m_Resources.shaders.depthOfFieldCoCReprojectCS; - kernel = cs.FindKernel("KMain"); - cmd.SetComputeVectorParam(cs, HDShaderIDs._Params, new Vector4(camera.resetPostProcessingHistory ? 0f : 0.91f, cocHistoryScale.x, cocHistoryScale.y, 0f)); - cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputCoCTexture, fullresCoC); - cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputHistoryCoCTexture, prevCoCTex); - cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputCoCTexture, nextCoCTex); - cmd.DispatchCompute(cs, kernel, (camera.actualWidth + 7) / 8, (camera.actualHeight + 7) / 8, camera.viewCount); - - // Cleanup the main CoC texture as we don't need it anymore and use the - // re-projected one instead for the following steps - m_Pool.Recycle(fullresCoC); - fullresCoC = nextCoCTex; + bool useMips = false; + ReprojectCoCHistory(cmd, camera, useMips, ref fullresCoC); } m_HDInstance.PushFullScreenDebugTexture(camera, cmd, fullresCoC, FullScreenDebugMode.DepthOfFieldCoc); @@ -2252,6 +2260,26 @@ RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) previous = camera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.DepthOfFieldCoC); } + void ReprojectCoCHistory(CommandBuffer cmd, HDCamera camera, bool useMips, ref RTHandle fullresCoC) + { + GrabCoCHistory(camera, out var prevCoCTex, out var nextCoCTex, useMips); + var cocHistoryScale = new Vector2(camera.historyRTHandleProperties.rtHandleScale.z, camera.historyRTHandleProperties.rtHandleScale.w); + + //Note: this reprojection creates some ghosting, we should replace it with something based on the new TAA + ComputeShader cs = m_Resources.shaders.depthOfFieldCoCReprojectCS; + int kernel = cs.FindKernel("KMain"); + cmd.SetComputeVectorParam(cs, HDShaderIDs._Params, new Vector4(camera.resetPostProcessingHistory ? 0f : 0.91f, cocHistoryScale.x, cocHistoryScale.y, 0f)); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputCoCTexture, fullresCoC); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputHistoryCoCTexture, prevCoCTex); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputCoCTexture, nextCoCTex); + cmd.DispatchCompute(cs, kernel, (camera.actualWidth + 7) / 8, (camera.actualHeight + 7) / 8, camera.viewCount); + + // Cleanup the main CoC texture as we don't need it anymore and use the + // re-projected one instead for the following steps + m_Pool.Recycle(fullresCoC); + fullresCoC = nextCoCTex; + } + #endregion #region Depth Of Field (Physically based) @@ -2317,22 +2345,7 @@ void DoPhysicallyBasedDepthOfField(CommandBuffer cmd, HDCamera camera, RTHandle if (taaEnabled) { bool useMips = true; - GrabCoCHistory(camera, out var prevCoCTex, out var nextCoCTex, useMips); - var cocHistoryScale = new Vector2(camera.historyRTHandleProperties.rtHandleScale.z, camera.historyRTHandleProperties.rtHandleScale.w); - - //Note: this reprojection creates some ghosting, we should replace it with something based on the new TAA - cs = m_Resources.shaders.depthOfFieldCoCReprojectCS; - kernel = cs.FindKernel("KMain"); - cmd.SetComputeVectorParam(cs, HDShaderIDs._Params, new Vector4(camera.resetPostProcessingHistory ? 0f : 0.91f, cocHistoryScale.x, cocHistoryScale.y, 0f)); - cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputCoCTexture, fullresCoC); - cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputHistoryCoCTexture, prevCoCTex); - cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputCoCTexture, nextCoCTex); - cmd.DispatchCompute(cs, kernel, (camera.actualWidth + 7) / 8, (camera.actualHeight + 7) / 8, camera.viewCount); - - // Cleanup the main CoC texture as we don't need it anymore and use the - // re-projected one instead for the following steps - m_Pool.Recycle(fullresCoC); - fullresCoC = nextCoCTex; + ReprojectCoCHistory(cmd, camera, useMips, ref fullresCoC); } } diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFCircleOfConfusion.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFCircleOfConfusion.compute index 0f5d36d81c2..8981d33ab2f 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFCircleOfConfusion.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFCircleOfConfusion.compute @@ -13,6 +13,13 @@ float4 _Params; float4 _Params2; CBUFFER_END +#define FarStart _Params.x +#define NearEnd _Params.y +#define FarRange _Params.z // 1 / (FarEnd - FarStart) +#define NearRange _Params.w // 1 / (NearStart - NearEnd) +#define NearMaxRadius _Params2.x +#define FarMaxRadius _Params2.y + // outpute texture RW_TEXTURE2D_X(float, _OutputTexture); @@ -55,14 +62,6 @@ void KMainCoCManual(uint3 dispatchThreadId : SV_DispatchThreadID) // Note: we can avoid explicit linearization by merging it with the other computations float linearEyeDepth = LinearEyeDepth(depth, _ZBufferParams); - const float FarStart = _Params.x; - const float NearEnd = _Params.y; - const float FarRange = _Params.z; // 1 / (FarEnd - FarStart) - const float NearRange = _Params.w; // 1 / (NearStart - NearEnd) - - const float NearMaxRadius = _Params2.x; - const float FarMaxRadius = _Params2.y; - float CoC = 0; if (linearEyeDepth > FarStart) { diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index a434fe80e32..16ff28e61bb 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -23,11 +23,10 @@ RW_TEXTURE2D_X(CTYPE, _OutputTexture); // A set of Defines to fine-tune the algorithm #define NUM_BUCKETS 3 #define GRADIENT_NOISE -//#define CENTER_DENSITY #define RING_DENSITY 8.0 +#define ADAPTIVE_RADIUS //#define OCTAWEB_SORTING //#define UNIFORM_WEIGHTS -#define ADAPTIVE_RADIUS // Helper defines so we can have one code path when OCTAWEB_SORTING is enabled or disabled. #ifndef OCTAWEB_SORTING @@ -123,7 +122,6 @@ float2 PointInCircle(float angle) float GetNumSamples(float radius, float maxRadius) { - // Note: should also take into account the density push towards the center (if enabled), this needs to be fixed at some pointss float numRings = _Params.x; float dR = maxRadius / numRings; @@ -189,11 +187,6 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) { float scaledRad = dR; -#ifdef CENTER_DENSITY - // make the samples more dense at the center - scaledRad = lerp(0.5 * dR, dR, ring * rcp(numRings)); -#endif - float dAng = 2.0f * PI / (ring * RING_DENSITY); #ifndef GRADIENT_NOISE @@ -249,7 +242,7 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) #ifdef OCTAWEB_SORTING for (int j = 0; j < NUM_BUCKETS; ++j) { - float currentAvg = RING_COLOR[j].w * rcp(ring * RING_DENSITY);; + float currentAvg = RING_COLOR[j].w * rcp(ring * RING_DENSITY); float prevAvg = (ring < numRings) ? prevRingWeight[j] : currentAvg; float occlusion = saturate(prevAvg - currentAvg); float alpha = ringHits[j] * rcp(ring * RING_DENSITY); diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/TemporalAntiAliasing.shader b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/TemporalAntiAliasing.shader index a297a31f50e..907473c39e8 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/TemporalAntiAliasing.shader +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/TemporalAntiAliasing.shader @@ -98,9 +98,10 @@ Shader "Hidden/HDRP/TemporalAA" #define _SpeedRejectionIntensity _TaaPostParameters.z #define _ContrastForMaxAntiFlicker _TaaPostParameters.w - +#if VELOCITY_REJECTION TEXTURE2D_X(_InputVelocityMagnitudeHistory); RW_TEXTURE2D_X(float, _OutputVelocityMagnitudeHistory); +#endif float4 _TaaPostParameters; float4 _TaaHistorySize; diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCameraFrameHistoryType.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCameraFrameHistoryType.cs index 21123bb5f9e..6819190f60d 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCameraFrameHistoryType.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCameraFrameHistoryType.cs @@ -44,8 +44,6 @@ public enum HDCameraFrameHistoryType /// Temporal antialiasing history after DoF. TemporalAntialiasingPostDoF, /// Velocity magnitude history used for TAA velocity weighting (after DoF). - TAAMotionVectorMagnitudePostDoF, - /// Number of history buffers. Count } } diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/GlobalPostProcessingQualitySettings.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/GlobalPostProcessingQualitySettings.cs index 307f39382ab..2710fc3a8c3 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/GlobalPostProcessingQualitySettings.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/GlobalPostProcessingQualitySettings.cs @@ -123,7 +123,7 @@ internal GlobalPostProcessingQualitySettings() /// Use Depth of field high quality filtering for each quality level. public bool[] DoFHighQualityFiltering = new bool[s_QualitySettingCount]; /// Use Depth of field high physically based setting for each quality level. - public bool[] DoFPhysicallyBased = new bool[s_QualitySettingCount]; + public bool[] DoFPhysicallyBased = new bool[s_QualitySettingCount]; /* Motion Blur */ /// Motion Blur sample count for each quality level. From f9835c78858ff68a44879d71fb4b432de4c12791 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Fri, 10 Jul 2020 17:43:49 +0200 Subject: [PATCH 26/27] Review feadback 2 --- .../Runtime/PostProcessing/PostProcessSystem.cs | 7 +++---- .../RenderPipeline/Camera/HDCameraFrameHistoryType.cs | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index d2ff6c760fb..ea923f258af 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -630,8 +630,7 @@ void PoolSource(ref RTHandle src, RTHandle dst) var taaParams = PrepareTAAParameters(camera, postDof); GrabTemporalAntialiasingHistoryTextures(camera, out var prevHistory, out var nextHistory, postDof); - GrabVelocityMagnitudeHistoryTextures(camera, out var prevMVLen, out var nextMVLen); - DoTemporalAntialiasing(taaParams, cmd, source, taaDestination, motionVecTexture, depthBuffer, depthMipChain, prevHistory, nextHistory); + DoTemporalAntialiasing(taaParams, cmd, source, taaDestination, motionVecTexture, depthBuffer, depthMipChain, prevHistory, nextHistory, prevMVLen:null, nextMVLen:null); PoolSource(ref source, taaDestination); postDoFTAAEnabled = true; } @@ -1551,8 +1550,8 @@ static void DoTemporalAntialiasing(in TemporalAntiAliasingParameters taaParams, RTHandle depthMipChain, RTHandle prevHistory, RTHandle nextHistory, - RTHandle prevMVLen = null, - RTHandle nextMVLen = null) + RTHandle prevMVLen, + RTHandle nextMVLen) { if (taaParams.camera.resetPostProcessingHistory) { diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCameraFrameHistoryType.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCameraFrameHistoryType.cs index 6819190f60d..95c52429323 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCameraFrameHistoryType.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCameraFrameHistoryType.cs @@ -43,7 +43,7 @@ public enum HDCameraFrameHistoryType PathTracing, /// Temporal antialiasing history after DoF. TemporalAntialiasingPostDoF, - /// Velocity magnitude history used for TAA velocity weighting (after DoF). + /// Number of history buffers. Count } } From 3cb3a4e353d6c5949ef5774d060c1720f5bf2b0e Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Fri, 10 Jul 2020 23:53:57 +0200 Subject: [PATCH 27/27] Fix non-uniform ring weights --- .../PostProcessing/Shaders/DoFGather.compute | 61 ++++++++++--------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 16ff28e61bb..0eaa2ab3cc9 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -13,6 +13,10 @@ CBUFFER_START(cb0) float4 _Params; CBUFFER_END +#define NumRings _Params.x +#define MaxCoCRadius _Params.y +#define MaxCoCMipLevel _Params.z + // Input textures TEXTURE2D_X(_InputTexture); TEXTURE2D_X(_InputCoCTexture); @@ -80,10 +84,10 @@ float GetCoCRadius(int2 positionSS, out int bucketIndex) float GetCoCMaxRadius(int2 positionSS) { #ifndef ADAPTIVE_RADIUS - return _Params.y; + return MaxCoCRadius; #else // We only have up to 6 mip levels - int lod = min(6, _Params.z); + int lod = min(6, MaxCoCMipLevel); uint4 size; _InputCoCTexture.GetDimensions(lod, size.x, size.y, size.z, size.w); @@ -122,22 +126,32 @@ float2 PointInCircle(float angle) float GetNumSamples(float radius, float maxRadius) { - float numRings = _Params.x; - - float dR = maxRadius / numRings; + float dR = maxRadius / NumRings; float rings = floor(radius / dR); float seriesSum = 0.5 * rings * (rings + 1); return 1.0 + seriesSum * RING_DENSITY; } +float GetRingWeight(int index, float dR) +{ + float ringRadius = index * dR; + float ringArea = PI * ringRadius * ringRadius; + + float prevRingRadius = max(0, index - 1) * dR; + float prevRingArea = PI * prevRingRadius * prevRingRadius; + + ringArea = ringArea - prevRingArea; + + float ringSamples = RING_DENSITY * index; + ringSamples = (index == 1) ? ringSamples + 1.0f : ringSamples; + return ringArea * rcp (ringSamples); +} + [numthreads(GROUP_RES, GROUP_RES, 1)] void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) { PositionInputs posInputs = GetPositionInput(float2(dispatchThreadId.xy), _ScreenSize.zw, uint2(GROUP_RES, GROUP_RES)); - - CTYPE centerColor = LOAD_TEXTURE2D_X(_InputTexture, posInputs.positionSS).CTYPE_SWIZZLE; int bucketIndex = 0; - float centerCoc = GetCoCRadius(posInputs.positionSS, bucketIndex); // Bucket 0 : far focus region // Bucket 1 : in focus region @@ -161,21 +175,9 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) #endif } - // Record the central sample - { - float weight = GetSampleWeight(abs(centerCoc)); - totalColor[bucketIndex] = float4(centerColor.xyz * weight, weight); - maxCoC[bucketIndex] = abs(centerCoc); - prevRingWeight[bucketIndex] = weight; -#ifdef ENABLE_ALPHA - totalAlpha[bucketIndex] = centerColor.w; -#endif - } - - float numRings = _Params.x; - float maxRadius = GetCoCMaxRadius(posInputs.positionSS); + float maxRadius = GetCoCMaxRadius(posInputs.positionSS); - float dR = maxRadius * rcp(numRings); + float dR = maxRadius * rcp(NumRings); float stratum = fmod(posInputs.positionSS.x + posInputs.positionSS.y, 2.0f); int sampleOffset = _TaaFrameInfo.w != 0.0 ? _TaaFrameInfo.z : 0; @@ -183,20 +185,21 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) float noise2 = InterleavedGradientNoise(posInputs.positionSS.xy, 8 + sampleOffset); // Iterate over the octaweb pattern and gather the DoF samples - for (float ring = numRings; ring > 0; ring -= 1.0) + for (float ring = NumRings; ring >= 0; ring -= 1.0) { - float scaledRad = dR; - - float dAng = 2.0f * PI / (ring * RING_DENSITY); + float numSamples = max(ring * RING_DENSITY, 1); + float dAng = 2.0f * PI / numSamples; #ifndef GRADIENT_NOISE - float radius = ring * scaledRad + stratum * scaledRad; + float radius = ring * dR + stratum * dR; float ringOffset = 0.5 * fmod(ring, 2.0f) * dAng; #else - float radius = (ring - 1) * scaledRad + noise2 * scaledRad; + float radius = (ring - 1) * dR + noise2 * dR; float ringOffset = noise * dAng; #endif + float ringWeight = GetRingWeight(max(1, ring), dR); + #ifdef OCTAWEB_SORTING float4 ringColor[NUM_BUCKETS]; float ringMaxCoC[NUM_BUCKETS]; @@ -227,7 +230,7 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) if (abs(sampleCoC) >= radius) { - float weight = GetSampleWeight(abs(sampleCoC)); + float weight = ringWeight * GetSampleWeight(abs(sampleCoC)); RING_COLOR[sampleBucket] += float4(sampleColor.xyz * weight, weight); RING_MAXCOC[sampleBucket] = max(RING_MAXCOC[sampleBucket], abs(sampleCoC)); #ifdef OCTAWEB_SORTING