Skip to content

Contact shadow min distance + fix scalarization code #150

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions com.unity.render-pipelines.high-definition/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Added fabric materials and textures
- Added information for fabric materials in fabric scene
- Added a DisplayInfo attribute to specify a name override and a display order for Volume Component fields (used only in default inspector for now).
- Added Min distance to contact shadows.

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

### Changed
- Improve MIP selection for decals on Transparents
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ Only one Light can cast Contact Shadows at a time. This means that, if you have
| __Enable__ | Enable the checkbox to make HDRP process Contact Shadows for this [Volume](Volumes.html). |
| __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. |
| __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. |
| __Min Distance__ | The distance from the Camera, in meters, at which HDRP begins to fade in Contact Shadows. |
| __Max Distance__ | The distance from the Camera, in meters, at which HDRP begins to fade Contact Shadows out to zero. |
| __Fade Distance__ | The distance, in meters, over which HDRP fades Contact Shadows out when at the __Max Distance__. |
| __Fade In Distance__ | The distance, in meters, over which HDRP fades Contact Shadows in when past the **Min Distance**. |
| __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. |

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ class ContactShadowsEditor : VolumeComponentWithQualityEditor
SerializedDataParameter m_Length;
SerializedDataParameter m_DistanceScaleFactor;
SerializedDataParameter m_MaxDistance;
SerializedDataParameter m_MinDistance;
SerializedDataParameter m_FadeDistance;
SerializedDataParameter m_FadeInDistance;
SerializedDataParameter m_SampleCount;
SerializedDataParameter m_Opacity;


public override void OnEnable()
{
base.OnEnable();
Expand All @@ -26,7 +27,9 @@ public override void OnEnable()
m_Length = Unpack(o.Find(x => x.length));
m_DistanceScaleFactor = Unpack(o.Find(x => x.distanceScaleFactor));
m_MaxDistance = Unpack(o.Find(x => x.maxDistance));
m_MinDistance = Unpack(o.Find(x => x.minDistance));
m_FadeDistance = Unpack(o.Find(x => x.fadeDistance));
m_FadeInDistance = Unpack(o.Find(x => x.fadeInDistance));
m_SampleCount = Unpack(o.Find(x => x.sampleCount));
m_Opacity = Unpack(o.Find(x => x.opacity));
}
Expand All @@ -41,8 +44,12 @@ public override void OnInspectorGUI()
{
PropertyField(m_Length, EditorGUIUtility.TrTextContent("Length", "Controls the length of the rays HDRP uses to calculate Contact Shadows. Uses meters."));
PropertyField(m_DistanceScaleFactor, EditorGUIUtility.TrTextContent("Distance Scale Factor", "Dampens the scale up effect HDRP process with distance from the Camera."));
PropertyField(m_MaxDistance, EditorGUIUtility.TrTextContent("Max Distance", "Sets The distance from the Camera at which HDRP begins to fade out Contact Shadows. Uses meters."));
PropertyField(m_FadeDistance, EditorGUIUtility.TrTextContent("Fade Distance", "Sets the distance over which HDRP fades Contact Shadows out when at the Max Distance. Uses meters."));
m_MinDistance.value.floatValue = Mathf.Clamp(m_MinDistance.value.floatValue, 0.0f, m_MaxDistance.value.floatValue);
PropertyField(m_MinDistance, EditorGUIUtility.TrTextContent("Min Distance", "Sets the distance from the camera at which HDRP begins to fade in Contact Shadows. Uses meters."));
PropertyField(m_MaxDistance, EditorGUIUtility.TrTextContent("Max Distance", "Sets the distance from the Camera at which HDRP begins to fade out Contact Shadows. Uses meters."));
m_FadeInDistance.value.floatValue = Mathf.Clamp(m_FadeInDistance.value.floatValue, 0.0f, m_MaxDistance.value.floatValue);
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."));
base.OnInspectorGUI();
GUI.enabled = useCustomValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3626,8 +3626,12 @@ ContactShadowsParameters PrepareContactShadowsParameters(HDCamera hdCamera, floa
float contactShadowRange = Mathf.Clamp(m_ContactShadows.fadeDistance.value, 0.0f, m_ContactShadows.maxDistance.value);
float contactShadowFadeEnd = m_ContactShadows.maxDistance.value;
float contactShadowOneOverFadeRange = 1.0f / Math.Max(1e-6f, contactShadowRange);

float contactShadowMinDist = Mathf.Min(m_ContactShadows.minDistance.value, contactShadowFadeEnd);
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, 0.0f, 0.0f, 0.0f);
parameters.params2 = new Vector4(firstMipOffsetY, contactShadowMinDist, contactShadowFadeIn, 0.0f);
parameters.sampleCount = m_ContactShadows.sampleCount;

int deferredShadowTileSize = 16; // Must match DeferreDirectionalShadow.compute
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoopDef.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ContactShadows.hlsl"

// 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.
// We perform scalarization all the time here as we don't know if we have clustered data structure or not at this point.
// More info on scalarization: https://flashypixels.wordpress.com/2018/11/10/intro-to-gpu-scalarization-part-2-scalarize-all-the-lights/
#define SCALARIZE_LIGHT_LOOP (defined(PLATFORM_SUPPORTS_WAVE_INTRINSICS) && !defined(LIGHTLOOP_DISABLE_TILE_AND_CLUSTER) && SHADERPASS == SHADERPASS_FORWARD)
#define SCALARIZE_LIGHT_LOOP (defined(PLATFORM_SUPPORTS_WAVE_INTRINSICS) && !defined(LIGHTLOOP_DISABLE_TILE_AND_CLUSTER))

#pragma only_renderers d3d11 playstation xboxone vulkan metal switch

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

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

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

Expand Down Expand Up @@ -228,26 +231,35 @@ void DeferredContactShadow(uint2 groupThreadId : SV_GroupThreadID, uint2 groupId
lightStart = startFirstLane;
}

for (uint lightListOffset = 0; lightListOffset < lightCount; lightListOffset++)
uint v_lightIdx = lightStart;
uint v_lightListOffset = 0;
while (v_lightListOffset < lightCount)
{
uint v_lightIdx = FetchIndex(lightStart, lightListOffset);
v_lightIdx = FetchIndex(lightStart, v_lightListOffset);
uint s_lightIdx = ScalarizeElementIndex(v_lightIdx, fastPath);
if (s_lightIdx == -1)
break;

LightData light = FetchLight(s_lightIdx); // Scalar load
LightData s_lightData = FetchLight(s_lightIdx);

if (light.contactShadowMask != 0 && light.isRayTracedContactShadow == 0.0)
// If current scalar and vector light index match, we process the light. The v_lightListOffset for current thread is increased.
// Note that the following should really be ==, however, since helper lanes are not considered by WaveActiveMin, such helper lanes could
// 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.
if (s_lightIdx >= v_lightIdx)
{
// Compute light ray direction:
float3 direction = normalize(light.positionRWS.xyz - posInput.positionWS);

bool occluded = ComputeContactShadow(posInput, direction, globalFade);

// light.contactShadowMask contains one bit at the position of the contact shadow index that will
// be tested in the lightloop, so it insert 1 at the index of the contact shadow if there is a contact shadow
// we take full bits at one multiplied by contact shadow and filter the bit at the contact shadow index.
contactShadowMask |= light.contactShadowMask * occluded;
v_lightListOffset++;
if (s_lightData.contactShadowMask != 0 && s_lightData.isRayTracedContactShadow == 0.0)
{
// Compute light ray direction:
float3 direction = normalize(s_lightData.positionRWS.xyz - posInput.positionWS);

bool occluded = ComputeContactShadow(posInput, direction, globalFade);

// light.contactShadowMask contains one bit at the position of the contact shadow index that will
// be tested in the lightloop, so it insert 1 at the index of the contact shadow if there is a contact shadow
// we take full bits at one multiplied by contact shadow and filter the bit at the contact shadow index.
contactShadowMask |= s_lightData.contactShadowMask * occluded;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,18 @@ public class ContactShadows : VolumeComponentWithQuality
/// </summary>
public MinFloatParameter maxDistance = new MinFloatParameter(50.0f, 0.0f);
/// <summary>
/// The distance from the camera, in meters, at which HDRP begins to fade in Contact Shadows.
/// </summary>
public MinFloatParameter minDistance = new MinFloatParameter(0.0f, 0.0f);
/// <summary>
/// The distance, in meters, over which HDRP fades Contact Shadows out when past the Max Distance.
/// </summary>
public MinFloatParameter fadeDistance = new MinFloatParameter(5.0f, 0.0f);
/// <summary>
/// The distance, in meters, over which HDRP fades Contact Shadows in when past the Min Distance.
/// </summary>
public MinFloatParameter fadeInDistance = new MinFloatParameter(0.0f, 0.0f);
/// <summary>
/// Controls the number of samples HDRP takes along each contact shadow ray. Increasing this value can lead to higher quality.
/// </summary>
public int sampleCount
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ CBUFFER_END
#define _ContactShadowFadeEnd _ContactShadowParamsParameters.z
#define _ContactShadowFadeOneOverRange _ContactShadowParamsParameters.w
#define _RenderTargetHeight _ContactShadowParamsParameters2.x
#define _ContactShadowMinDistance _ContactShadowParamsParameters2.y
#define _ContactShadowFadeInEnd _ContactShadowParamsParameters2.z