77 lines
3.8 KiB
HLSL
77 lines
3.8 KiB
HLSL
#ifndef UTS_SHADOW_EVALUATION
|
|
#define UTS_SHADOW_EVALUATION
|
|
|
|
float3 UtsGetShadowNormal(UtsBSDFData bsdfData)
|
|
{
|
|
#if _MATERIAL_TYPE_FACE
|
|
return normalize(mul(UNITY_MATRIX_M, float4(0.0, 0.0, 1.0, 0.0))).xyz;
|
|
#else
|
|
return bsdfData.geomNormalWS * (1.0 + _ShadowNormalBias);
|
|
#endif
|
|
}
|
|
|
|
// distances = {d, d^2, 1/d, d_proj}, where d_proj = dot(lightToSample, light.forward).
|
|
SHADOW_TYPE UtsEvaluateShadow_Punctual(LightLoopContext lightLoopContext, PositionInputs posInput, LightData light, BuiltinData builtinData, float3 N, float3 L, float4 distances)
|
|
{
|
|
#ifndef LIGHT_EVALUATION_NO_SHADOWS
|
|
float shadow = 1.0;
|
|
float shadowMask = 1.0;
|
|
float NdotL = dot(N, L); // Disable contact shadow and shadow mask when facing away from light (i.e transmission)
|
|
|
|
#ifdef SHADOWS_SHADOWMASK
|
|
// shadowMaskSelector.x is -1 if there is no shadow mask
|
|
// Note that we override shadow value (in case we don't have any dynamic shadow)
|
|
shadow = shadowMask = (light.shadowMaskSelector.x >= 0.0 && NdotL > 0.0) ? dot(BUILTIN_DATA_SHADOW_MASK, light.shadowMaskSelector) : 1.0;
|
|
#endif
|
|
|
|
#if defined(SCREEN_SPACE_SHADOWS_ON) && !defined(_SURFACE_TYPE_TRANSPARENT) && defined(_RECEIVE_SCREEN_SPACE_SHADOW_ON)
|
|
if ((light.screenSpaceShadowIndex & SCREEN_SPACE_SHADOW_INDEX_MASK) != INVALID_SCREEN_SPACE_SHADOW)
|
|
{
|
|
shadow = GetScreenSpaceShadow(posInput, light.screenSpaceShadowIndex);
|
|
shadow = lerp(shadowMask, shadow, light.shadowDimmer);
|
|
}
|
|
else
|
|
#endif
|
|
if ((light.shadowIndex >= 0) && (light.shadowDimmer > 0))
|
|
{
|
|
shadow = GetPunctualShadowAttenuation(lightLoopContext.shadowContext, posInput.positionSS, posInput.positionWS + L * _ShadowDistanceBias, N, light.shadowIndex, L, distances.x, light.lightType == GPULIGHTTYPE_POINT, light.lightType != GPULIGHTTYPE_PROJECTOR_BOX);
|
|
|
|
#ifdef SHADOWS_SHADOWMASK
|
|
// Note: Legacy Unity have two shadow mask mode. ShadowMask (ShadowMask contain static objects shadow and ShadowMap contain only dynamic objects shadow, final result is the minimun of both value)
|
|
// and ShadowMask_Distance (ShadowMask contain static objects shadow and ShadowMap contain everything and is blend with ShadowMask based on distance (Global distance setup in QualitySettigns)).
|
|
// HDRenderPipeline change this behavior. Only ShadowMask mode is supported but we support both blend with distance AND minimun of both value. Distance is control by light.
|
|
// The following code do this.
|
|
// The min handle the case of having only dynamic objects in the ShadowMap
|
|
// The second case for blend with distance is handled with ShadowDimmer. ShadowDimmer is define manually and by shadowDistance by light.
|
|
// With distance, ShadowDimmer become one and only the ShadowMask appear, we get the blend with distance behavior.
|
|
shadow = light.nonLightMappedOnly ? min(shadowMask, shadow) : shadow;
|
|
#endif
|
|
|
|
shadow = lerp(shadowMask, shadow, light.shadowDimmer);
|
|
}
|
|
|
|
// Transparents have no contact shadow information
|
|
#if !defined(_SURFACE_TYPE_TRANSPARENT) && !defined(LIGHT_EVALUATION_NO_CONTACT_SHADOWS)
|
|
{
|
|
// In certain cases (like hair) we allow to force the contact shadow sample.
|
|
#ifdef LIGHT_EVALUATION_CONTACT_SHADOW_DISABLE_NDOTL
|
|
const bool allowContactShadow = true;
|
|
#else
|
|
const bool allowContactShadow = NdotL > 0.0;
|
|
#endif
|
|
|
|
shadow = min(shadow, allowContactShadow ? GetContactShadow(lightLoopContext, light.contactShadowMask, light.isRayTracedContactShadow) : 1.0);
|
|
}
|
|
#endif
|
|
|
|
#ifdef DEBUG_DISPLAY
|
|
if (_DebugShadowMapMode == SHADOWMAPDEBUGMODE_SINGLE_SHADOW && light.shadowIndex == _DebugSingleShadowIndex)
|
|
g_DebugShadowAttenuation = shadow;
|
|
#endif
|
|
return shadow;
|
|
#else // LIGHT_EVALUATION_NO_SHADOWS
|
|
return 1.0;
|
|
#endif
|
|
}
|
|
|
|
#endif |