diff --git a/com.unity.render-pipelines.high-definition/CHANGELOG.md b/com.unity.render-pipelines.high-definition/CHANGELOG.md index c15c475ca09..f1a0b5f116e 100644 --- a/com.unity.render-pipelines.high-definition/CHANGELOG.md +++ b/com.unity.render-pipelines.high-definition/CHANGELOG.md @@ -159,6 +159,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added an option to extend the camera culling for skinned mesh animation in ray tracing effects (1258547). - 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. ### Fixed - Fix when rescale probe all direction below zero (1219246) diff --git a/com.unity.render-pipelines.high-definition/Documentation~/Override-Contact-Shadows.md b/com.unity.render-pipelines.high-definition/Documentation~/Override-Contact-Shadows.md index 00de0cfcf4f..5e140337cec 100644 --- a/com.unity.render-pipelines.high-definition/Documentation~/Override-Contact-Shadows.md +++ b/com.unity.render-pipelines.high-definition/Documentation~/Override-Contact-Shadows.md @@ -31,6 +31,8 @@ Only one Light can cast Contact Shadows at a time. This means that, if you have | __Fade Out Distance__ | The distance, in meters, over which HDRP fades Contact Shadows out when at the __Max Distance__. | | __Sample Count__ | Use the slider to set the number of samples HDRP uses for ray casting. Increasing this increases quality at the cost of performance. | | __Opacity__ | Use the slider to set the opacity of the Contact Shadows. Lower values result in softer, less prominent shadows. | +| **Ray Bias** | Controls the bias applied to the screen space ray cast to get contact shadows. Higher values can reduce self shadowing, however too high values might lead to peter-panning that can be especially undesirable with contact shadows. | +| **Thickness** | Controls the thickness of the objects found along the ray, essentially thickening the contact shadows. It can be used to fill holes in the shadows, however might also lead to overly wide shadows. | ## Details diff --git a/com.unity.render-pipelines.high-definition/Documentation~/Upgrading-from-2020.1-to-2020.2.md b/com.unity.render-pipelines.high-definition/Documentation~/Upgrading-from-2020.1-to-2020.2.md index 2202e578df3..e5559e72833 100644 --- a/com.unity.render-pipelines.high-definition/Documentation~/Upgrading-from-2020.1-to-2020.2.md +++ b/com.unity.render-pipelines.high-definition/Documentation~/Upgrading-from-2020.1-to-2020.2.md @@ -48,6 +48,8 @@ HDRP now stores OnEnable and OnDemand shadows in a separate atlas and more API i The shader function `SampleShadow_PCSS` now requires you to pass in an additional float2 parameter which contains the shadow atlas resolution in x and the inverse of the atlas resolution in y. +Ray bias and thickness parameters have been added to contact shadows. These might lead to small changes to the visual impact of contact shadows with the default parameters. Please consider tuning those values to fit the needs of your project. + ## Shader config file From Unity 2020.2, due to the change of the shadow map, HDRP moved the HDShadowFilteringQuality enum to HDShadowManager.cs. HDRP also removed ShaderConfig.s_DeferredShadowFiltering and ShaderOptions.DeferredShadowFiltering from the source code because they have no effect anymore. diff --git a/com.unity.render-pipelines.high-definition/Documentation~/whats-new-10-0.md b/com.unity.render-pipelines.high-definition/Documentation~/whats-new-10-0.md index 6b95ca87aa2..e534f4a9bd8 100644 --- a/com.unity.render-pipelines.high-definition/Documentation~/whats-new-10-0.md +++ b/com.unity.render-pipelines.high-definition/Documentation~/whats-new-10-0.md @@ -242,6 +242,10 @@ You can now control the texture mapping mode for all textures in the [AxF Shader For more information about this improvement, see [AxF Shader](AxF-Shader.md). +### Contact Shadows Improvements + +More control is given for contact shadows, in particular now a bias can be set to avoid self intersection issues and a new thickness parameter is introduced to fill gaps that can be left by contact shadows. + ### Exposure #### Exposure curve mapping diff --git a/com.unity.render-pipelines.high-definition/Editor/Lighting/Shadow/ContactShadowsEditor.cs b/com.unity.render-pipelines.high-definition/Editor/Lighting/Shadow/ContactShadowsEditor.cs index a97685d796e..0ece2c40546 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Lighting/Shadow/ContactShadowsEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Lighting/Shadow/ContactShadowsEditor.cs @@ -16,6 +16,8 @@ class ContactShadowsEditor : VolumeComponentWithQualityEditor SerializedDataParameter m_FadeInDistance; SerializedDataParameter m_SampleCount; SerializedDataParameter m_Opacity; + SerializedDataParameter m_Bias; + SerializedDataParameter m_Thickness; public override void OnEnable() { @@ -32,6 +34,8 @@ public override void OnEnable() m_FadeInDistance = Unpack(o.Find(x => x.fadeInDistance)); m_SampleCount = Unpack(o.Find(x => x.sampleCount)); m_Opacity = Unpack(o.Find(x => x.opacity)); + m_Bias = Unpack(o.Find(x => x.rayBias)); + m_Thickness = Unpack(o.Find(x => x.thicknessScale)); } public override void OnInspectorGUI() @@ -49,6 +53,9 @@ public override void OnInspectorGUI() PropertyField(m_FadeInDistance, EditorGUIUtility.TrTextContent("Fade In Distance", "Sets the distance over which HDRP fades Contact Shadows in when past the Min Distance. Uses meters.")); PropertyField(m_FadeDistance, EditorGUIUtility.TrTextContent("Fade Out Distance", "Sets the distance over which HDRP fades Contact Shadows out when at the Max Distance. Uses meters.")); PropertyField(m_Opacity, EditorGUIUtility.TrTextContent("Opacity", "Controls the opacity of the Contact Shadow.")); + PropertyField(m_Bias, EditorGUIUtility.TrTextContent("Bias", "Controls the bias applied to the screen space ray cast to get contact shadows.")); + PropertyField(m_Thickness, EditorGUIUtility.TrTextContent("Thickness", "Controls the thickness of the objects found along the ray, essentially thickening the contact shadows.")); + base.OnInspectorGUI(); GUI.enabled = useCustomValue; PropertyField(m_SampleCount, EditorGUIUtility.TrTextContent("Sample Count", "Controls the number of samples HDRP uses for ray casting.")); diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoop.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoop.cs index 7db486cc8a8..6704448b584 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoop.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoop.cs @@ -3717,7 +3717,7 @@ struct ContactShadowsParameters public Vector4 params1; public Vector4 params2; - public int sampleCount; + public Vector4 params3; public int numTilesX; public int numTilesY; @@ -3762,8 +3762,8 @@ ContactShadowsParameters PrepareContactShadowsParameters(HDCamera hdCamera, floa float contactShadowFadeIn = Mathf.Clamp(m_ContactShadows.fadeInDistance.value, 1e-6f, contactShadowFadeEnd); parameters.params1 = new Vector4(m_ContactShadows.length.value, m_ContactShadows.distanceScaleFactor.value, contactShadowFadeEnd, contactShadowOneOverFadeRange); - parameters.params2 = new Vector4(firstMipOffsetY, contactShadowMinDist, contactShadowFadeIn, 0.0f); - parameters.sampleCount = m_ContactShadows.sampleCount; + parameters.params2 = new Vector4(firstMipOffsetY, contactShadowMinDist, contactShadowFadeIn, m_ContactShadows.rayBias.value * 0.01f); + parameters.params3 = new Vector4(m_ContactShadows.sampleCount, m_ContactShadows.thicknessScale.value * 10.0f , 0.0f, 0.0f); int deferredShadowTileSize = 16; // Must match DeferreDirectionalShadow.compute parameters.numTilesX = (hdCamera.actualWidth + (deferredShadowTileSize - 1)) / deferredShadowTileSize; @@ -3786,7 +3786,7 @@ static void RenderContactShadows( in ContactShadowsParameters parameters, cmd.SetComputeVectorParam(parameters.contactShadowsCS, HDShaderIDs._ContactShadowParamsParameters, parameters.params1); cmd.SetComputeVectorParam(parameters.contactShadowsCS, HDShaderIDs._ContactShadowParamsParameters2, parameters.params2); - cmd.SetComputeIntParam(parameters.contactShadowsCS, HDShaderIDs._DirectionalContactShadowSampleCount, parameters.sampleCount); + cmd.SetComputeVectorParam(parameters.contactShadowsCS, HDShaderIDs._ContactShadowParamsParameters3, parameters.params3); cmd.SetComputeBufferParam(parameters.contactShadowsCS, parameters.kernel, HDShaderIDs._DirectionalLightDatas, lightLoopLightData.directionalLightData); // Send light list to the compute diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ContactShadows.compute b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ContactShadows.compute index 98ac679de1f..9d4fa8e4904 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ContactShadows.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ContactShadows.compute @@ -41,6 +41,16 @@ float SampleDepth(float2 UV, bool HalfRes) return LoadCameraDepth(pixelCoord); } +float GetDepthCompareThreshold(float step, float rayStartZ, float rayOrthoZ) +{ + return abs(rayOrthoZ - rayStartZ) * _ContactShadowThickness * max(0.07, step); +} + +bool CompareDepth(float depthDiff, float compareThreshold) +{ + return abs(compareThreshold - depthDiff) < compareThreshold; +} + bool ScreenSpaceShadowRayCast(float3 positionWS, float3 rayDirWS, float rayLength, uint2 positionSS, out float fade) { @@ -50,7 +60,7 @@ bool ScreenSpaceShadowRayCast(float3 positionWS, float3 rayDirWS, float rayLengt uint taaEnabled = _TaaFrameInfo.w; float dither = InterleavedGradientNoise(positionSS, (_FrameCount % 8u) * taaEnabled) - ditherBias; - float3 rayStartWS = positionWS; + float3 rayStartWS = positionWS - positionWS * _ContactShadowBias; float3 rayEndWS = rayStartWS + rayDirWS * rayLength; float4 rayStartCS = TransformWorldToHClip(rayStartWS); @@ -68,7 +78,7 @@ bool ScreenSpaceShadowRayCast(float3 positionWS, float3 rayDirWS, float rayLengt float3 rayDirCS = rayEndCS.xyz - rayStartCS.xyz; float step = 1.0f / _SampleCount; - float compareThreshold = abs(rayOrthoViewSpace.z - rayStartCS.z) * max(0.07f, step); + float compareThreshold = GetDepthCompareThreshold(step, rayStartCS.z, rayOrthoViewSpace.z); float occluded = 0.0f; @@ -107,7 +117,7 @@ bool ScreenSpaceShadowRayCast(float3 positionWS, float3 rayDirWS, float rayLengt float depthDiff = sampleDepth - sampleAlongRay.z; - if (depthDiff > 0.0f && depthDiff < compareThreshold && sampleAlongRay.z > 0) + if (depthDiff > 0.0f && CompareDepth(depthDiff, compareThreshold) && sampleAlongRay.z > 0) { if (tracingHalfRes) { diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ContactShadows.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ContactShadows.cs index f2da6428bbe..fb7ecc2573a 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ContactShadows.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ContactShadows.cs @@ -43,8 +43,16 @@ public class ContactShadows : VolumeComponentWithQuality /// public MinFloatParameter fadeInDistance = new MinFloatParameter(0.0f, 0.0f); /// - /// Controls the number of samples HDRP takes along each contact shadow ray. Increasing this value can lead to higher quality. + /// Controls the bias applied to the screen space ray cast to get contact shadows. /// + public ClampedFloatParameter rayBias = new ClampedFloatParameter(0.2f, 0.0f, 1.0f); + /// + /// Controls the thickness of the objects found along the ray, essentially thickening the contact shadows. + /// + public ClampedFloatParameter thicknessScale = new ClampedFloatParameter(0.15f, 0.02f, 1.0f); + + + public int sampleCount { get diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ContactShadows.hlsl b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ContactShadows.hlsl index f5f01cb67a9..73949525b49 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ContactShadows.hlsl +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ContactShadows.hlsl @@ -3,6 +3,7 @@ RW_TEXTURE2D_X(uint, _ContactShadowTextureUAV); CBUFFER_START(DeferredShadowParameters) float4 _ContactShadowParamsParameters; float4 _ContactShadowParamsParameters2; +float4 _ContactShadowParamsParameters3; int _SampleCount; CBUFFER_END @@ -13,3 +14,6 @@ CBUFFER_END #define _RenderTargetHeight _ContactShadowParamsParameters2.x #define _ContactShadowMinDistance _ContactShadowParamsParameters2.y #define _ContactShadowFadeInEnd _ContactShadowParamsParameters2.z +#define _ContactShadowBias _ContactShadowParamsParameters2.w +#define _SampleCount (int)_ContactShadowParamsParameters3.x +#define _ContactShadowThickness _ContactShadowParamsParameters3.y diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs index c43119a1969..ad7d2c006c1 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs @@ -179,6 +179,7 @@ static class HDShaderIDs public static readonly int _ContactShadowTextureUAV = Shader.PropertyToID("_ContactShadowTextureUAV"); public static readonly int _ContactShadowParamsParameters = Shader.PropertyToID("_ContactShadowParamsParameters"); public static readonly int _ContactShadowParamsParameters2 = Shader.PropertyToID("_ContactShadowParamsParameters2"); + public static readonly int _ContactShadowParamsParameters3 = Shader.PropertyToID("_ContactShadowParamsParameters3"); public static readonly int _DirectionalContactShadowSampleCount = Shader.PropertyToID("_SampleCount"); public static readonly int _ShadowFrustumPlanes = Shader.PropertyToID("_ShadowFrustumPlanes");