Skip to content

Commit ae165e4

Browse files
Contact shadow min distance + fix scalarization code (#150)
* Min distance * editor update * Update doc * Changelog * fix some ui issues * Update docs according to UI changes Co-authored-by: sebastienlagarde <[email protected]>
1 parent 0467963 commit ae165e4

File tree

8 files changed

+60
-23
lines changed

8 files changed

+60
-23
lines changed

com.unity.render-pipelines.high-definition/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
116116
- Added fabric materials and textures
117117
- Added information for fabric materials in fabric scene
118118
- Added a DisplayInfo attribute to specify a name override and a display order for Volume Component fields (used only in default inspector for now).
119+
- Added Min distance to contact shadows.
119120

120121
### Fixed
121122
- Fix when rescale probe all direction below zero (1219246)
@@ -557,6 +558,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
557558
- Fix MaterialBalls having same guid issue
558559
- Fix spelling and grammatical errors in material samples
559560
- Fixed unneeded cookie texture allocation for cone stop lights.
561+
- Fixed scalarization code for contact shadows.
560562

561563
### Changed
562564
- Improve MIP selection for decals on Transparents
Lines changed: 2 additions & 2 deletions
Loading

com.unity.render-pipelines.high-definition/Documentation~/Override-Contact-Shadows.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ Only one Light can cast Contact Shadows at a time. This means that, if you have
2525
| __Enable__ | Enable the checkbox to make HDRP process Contact Shadows for this [Volume](Volumes.html). |
2626
| __Length__ | Use the slider to set the length of the rays, in meters, that HDRP uses for tracing. It also functions as the maximum distance at which the rays can captures details. |
2727
| __Distance Scale Factor__ | HDRP scales Contact Shadows up with distance. Use the slider to set the value that HDRP uses to dampen the scale to avoid biasing artifacts with distance. |
28+
| __Min Distance__ | The distance from the Camera, in meters, at which HDRP begins to fade in Contact Shadows. |
2829
| __Max Distance__ | The distance from the Camera, in meters, at which HDRP begins to fade Contact Shadows out to zero. |
29-
| __Fade Distance__ | The distance, in meters, over which HDRP fades Contact Shadows out when at the __Max Distance__. |
30+
| __Fade In Distance__ | The distance, in meters, over which HDRP fades Contact Shadows in when past the **Min Distance**. |
31+
| __Fade Out Distance__ | The distance, in meters, over which HDRP fades Contact Shadows out when at the __Max Distance__. |
3032
| __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. |
3133
| __Opacity__ | Use the slider to set the opacity of the Contact Shadows. Lower values result in softer, less prominent shadows. |
3234

com.unity.render-pipelines.high-definition/Editor/Lighting/Shadow/ContactShadowsEditor.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ class ContactShadowsEditor : VolumeComponentWithQualityEditor
1111
SerializedDataParameter m_Length;
1212
SerializedDataParameter m_DistanceScaleFactor;
1313
SerializedDataParameter m_MaxDistance;
14+
SerializedDataParameter m_MinDistance;
1415
SerializedDataParameter m_FadeDistance;
16+
SerializedDataParameter m_FadeInDistance;
1517
SerializedDataParameter m_SampleCount;
1618
SerializedDataParameter m_Opacity;
1719

18-
1920
public override void OnEnable()
2021
{
2122
base.OnEnable();
@@ -26,7 +27,9 @@ public override void OnEnable()
2627
m_Length = Unpack(o.Find(x => x.length));
2728
m_DistanceScaleFactor = Unpack(o.Find(x => x.distanceScaleFactor));
2829
m_MaxDistance = Unpack(o.Find(x => x.maxDistance));
30+
m_MinDistance = Unpack(o.Find(x => x.minDistance));
2931
m_FadeDistance = Unpack(o.Find(x => x.fadeDistance));
32+
m_FadeInDistance = Unpack(o.Find(x => x.fadeInDistance));
3033
m_SampleCount = Unpack(o.Find(x => x.sampleCount));
3134
m_Opacity = Unpack(o.Find(x => x.opacity));
3235
}
@@ -41,8 +44,12 @@ public override void OnInspectorGUI()
4144
{
4245
PropertyField(m_Length, EditorGUIUtility.TrTextContent("Length", "Controls the length of the rays HDRP uses to calculate Contact Shadows. Uses meters."));
4346
PropertyField(m_DistanceScaleFactor, EditorGUIUtility.TrTextContent("Distance Scale Factor", "Dampens the scale up effect HDRP process with distance from the Camera."));
44-
PropertyField(m_MaxDistance, EditorGUIUtility.TrTextContent("Max Distance", "Sets The distance from the Camera at which HDRP begins to fade out Contact Shadows. Uses meters."));
45-
PropertyField(m_FadeDistance, EditorGUIUtility.TrTextContent("Fade Distance", "Sets the distance over which HDRP fades Contact Shadows out when at the Max Distance. Uses meters."));
47+
m_MinDistance.value.floatValue = Mathf.Clamp(m_MinDistance.value.floatValue, 0.0f, m_MaxDistance.value.floatValue);
48+
PropertyField(m_MinDistance, EditorGUIUtility.TrTextContent("Min Distance", "Sets the distance from the camera at which HDRP begins to fade in Contact Shadows. Uses meters."));
49+
PropertyField(m_MaxDistance, EditorGUIUtility.TrTextContent("Max Distance", "Sets the distance from the Camera at which HDRP begins to fade out Contact Shadows. Uses meters."));
50+
m_FadeInDistance.value.floatValue = Mathf.Clamp(m_FadeInDistance.value.floatValue, 0.0f, m_MaxDistance.value.floatValue);
51+
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."));
52+
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."));
4653
PropertyField(m_Opacity, EditorGUIUtility.TrTextContent("Opacity", "Controls the opacity of the Contact Shadow."));
4754
base.OnInspectorGUI();
4855
GUI.enabled = useCustomValue;

com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoop.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3626,8 +3626,12 @@ ContactShadowsParameters PrepareContactShadowsParameters(HDCamera hdCamera, floa
36263626
float contactShadowRange = Mathf.Clamp(m_ContactShadows.fadeDistance.value, 0.0f, m_ContactShadows.maxDistance.value);
36273627
float contactShadowFadeEnd = m_ContactShadows.maxDistance.value;
36283628
float contactShadowOneOverFadeRange = 1.0f / Math.Max(1e-6f, contactShadowRange);
3629+
3630+
float contactShadowMinDist = Mathf.Min(m_ContactShadows.minDistance.value, contactShadowFadeEnd);
3631+
float contactShadowFadeIn = Mathf.Clamp(m_ContactShadows.fadeInDistance.value, 1e-6f, contactShadowFadeEnd);
3632+
36293633
parameters.params1 = new Vector4(m_ContactShadows.length.value, m_ContactShadows.distanceScaleFactor.value, contactShadowFadeEnd, contactShadowOneOverFadeRange);
3630-
parameters.params2 = new Vector4(firstMipOffsetY, 0.0f, 0.0f, 0.0f);
3634+
parameters.params2 = new Vector4(firstMipOffsetY, contactShadowMinDist, contactShadowFadeIn, 0.0f);
36313635
parameters.sampleCount = m_ContactShadows.sampleCount;
36323636

36333637
int deferredShadowTileSize = 16; // Must match DeferreDirectionalShadow.compute

com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ContactShadows.compute

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoopDef.hlsl"
1616
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ContactShadows.hlsl"
1717

18-
// We perform scalarization only for forward rendering as for deferred loads will already be scalar since tiles will match waves and therefore all threads will read from the same tile.
18+
// We perform scalarization all the time here as we don't know if we have clustered data structure or not at this point.
1919
// More info on scalarization: https://flashypixels.wordpress.com/2018/11/10/intro-to-gpu-scalarization-part-2-scalarize-all-the-lights/
20-
#define SCALARIZE_LIGHT_LOOP (defined(PLATFORM_SUPPORTS_WAVE_INTRINSICS) && !defined(LIGHTLOOP_DISABLE_TILE_AND_CLUSTER) && SHADERPASS == SHADERPASS_FORWARD)
20+
#define SCALARIZE_LIGHT_LOOP (defined(PLATFORM_SUPPORTS_WAVE_INTRINSICS) && !defined(LIGHTLOOP_DISABLE_TILE_AND_CLUSTER))
2121

2222
#pragma only_renderers d3d11 playstation xboxone vulkan metal switch
2323

@@ -147,6 +147,9 @@ bool ComputeContactShadow(PositionInputs posInput, float3 direction, inout float
147147
//Here LightDirection is not the light direction but the light position
148148
float rayLength = _ContactShadowLength * max(0.5, posInput.linearDepth * _ContactShadowDistanceScaleFactor);
149149
occluded = ScreenSpaceShadowRayCast(posInput.positionWS, direction, rayLength, posInput.positionSS, fade);
150+
// Fade in
151+
fade *= saturate((posInput.linearDepth - _ContactShadowMinDistance) * rcp(_ContactShadowFadeInEnd));
152+
// Fade out
150153
fade *= saturate((_ContactShadowFadeEnd - posInput.linearDepth) * _ContactShadowFadeOneOverRange);
151154

152155
globalFade = max(globalFade, fade);
@@ -172,7 +175,7 @@ void DeferredContactShadow(uint2 groupThreadId : SV_GroupThreadID, uint2 groupId
172175
PositionInputs posInput = GetPositionInput(pixelCoord.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V, tileCoord);
173176

174177
// discard the shadow if we're on the sky or outside of the contact shadow range
175-
if (depth == UNITY_RAW_FAR_CLIP_VALUE || posInput.linearDepth - _ContactShadowFadeEnd > 1)
178+
if (depth == UNITY_RAW_FAR_CLIP_VALUE || posInput.linearDepth - _ContactShadowFadeEnd > 1 || posInput.linearDepth < _ContactShadowMinDistance)
176179
{
177180
_ContactShadowTextureUAV[COORD_TEXTURE2D_X(pixelCoord)] = 0;
178181

@@ -228,26 +231,35 @@ void DeferredContactShadow(uint2 groupThreadId : SV_GroupThreadID, uint2 groupId
228231
lightStart = startFirstLane;
229232
}
230233

231-
for (uint lightListOffset = 0; lightListOffset < lightCount; lightListOffset++)
234+
uint v_lightIdx = lightStart;
235+
uint v_lightListOffset = 0;
236+
while (v_lightListOffset < lightCount)
232237
{
233-
uint v_lightIdx = FetchIndex(lightStart, lightListOffset);
238+
v_lightIdx = FetchIndex(lightStart, v_lightListOffset);
234239
uint s_lightIdx = ScalarizeElementIndex(v_lightIdx, fastPath);
235240
if (s_lightIdx == -1)
236241
break;
237242

238-
LightData light = FetchLight(s_lightIdx); // Scalar load
243+
LightData s_lightData = FetchLight(s_lightIdx);
239244

240-
if (light.contactShadowMask != 0 && light.isRayTracedContactShadow == 0.0)
245+
// If current scalar and vector light index match, we process the light. The v_lightListOffset for current thread is increased.
246+
// Note that the following should really be ==, however, since helper lanes are not considered by WaveActiveMin, such helper lanes could
247+
// end up with a unique v_lightIdx value that is smaller than s_lightIdx hence being stuck in a loop. All the active lanes will not have this problem.
248+
if (s_lightIdx >= v_lightIdx)
241249
{
242-
// Compute light ray direction:
243-
float3 direction = normalize(light.positionRWS.xyz - posInput.positionWS);
244-
245-
bool occluded = ComputeContactShadow(posInput, direction, globalFade);
246-
247-
// light.contactShadowMask contains one bit at the position of the contact shadow index that will
248-
// be tested in the lightloop, so it insert 1 at the index of the contact shadow if there is a contact shadow
249-
// we take full bits at one multiplied by contact shadow and filter the bit at the contact shadow index.
250-
contactShadowMask |= light.contactShadowMask * occluded;
250+
v_lightListOffset++;
251+
if (s_lightData.contactShadowMask != 0 && s_lightData.isRayTracedContactShadow == 0.0)
252+
{
253+
// Compute light ray direction:
254+
float3 direction = normalize(s_lightData.positionRWS.xyz - posInput.positionWS);
255+
256+
bool occluded = ComputeContactShadow(posInput, direction, globalFade);
257+
258+
// light.contactShadowMask contains one bit at the position of the contact shadow index that will
259+
// be tested in the lightloop, so it insert 1 at the index of the contact shadow if there is a contact shadow
260+
// we take full bits at one multiplied by contact shadow and filter the bit at the contact shadow index.
261+
contactShadowMask |= s_lightData.contactShadowMask * occluded;
262+
}
251263
}
252264
}
253265
}

com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ContactShadows.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,18 @@ public class ContactShadows : VolumeComponentWithQuality
3131
/// </summary>
3232
public MinFloatParameter maxDistance = new MinFloatParameter(50.0f, 0.0f);
3333
/// <summary>
34+
/// The distance from the camera, in meters, at which HDRP begins to fade in Contact Shadows.
35+
/// </summary>
36+
public MinFloatParameter minDistance = new MinFloatParameter(0.0f, 0.0f);
37+
/// <summary>
3438
/// The distance, in meters, over which HDRP fades Contact Shadows out when past the Max Distance.
3539
/// </summary>
3640
public MinFloatParameter fadeDistance = new MinFloatParameter(5.0f, 0.0f);
3741
/// <summary>
42+
/// The distance, in meters, over which HDRP fades Contact Shadows in when past the Min Distance.
43+
/// </summary>
44+
public MinFloatParameter fadeInDistance = new MinFloatParameter(0.0f, 0.0f);
45+
/// <summary>
3846
/// Controls the number of samples HDRP takes along each contact shadow ray. Increasing this value can lead to higher quality.
3947
/// </summary>
4048
public int sampleCount

com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ContactShadows.hlsl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ CBUFFER_END
1111
#define _ContactShadowFadeEnd _ContactShadowParamsParameters.z
1212
#define _ContactShadowFadeOneOverRange _ContactShadowParamsParameters.w
1313
#define _RenderTargetHeight _ContactShadowParamsParameters2.x
14+
#define _ContactShadowMinDistance _ContactShadowParamsParameters2.y
15+
#define _ContactShadowFadeInEnd _ContactShadowParamsParameters2.z

0 commit comments

Comments
 (0)