65 lines
2.3 KiB
HLSL
65 lines
2.3 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "Common.ush"
|
|
#include "SceneTexturesCommon.ush"
|
|
|
|
// Returns distance along ray that the first hit occurred, or negative on miss
|
|
float CastScreenSpaceShadowRay(
|
|
float3 RayOriginTranslatedWorld, float3 RayDirection, float RayLength, int NumSteps,
|
|
float Dither, float CompareToleranceScale, bool bHairNoShadowLight,
|
|
out float2 HitUV)
|
|
{
|
|
const float4 RayStartClip = mul(float4(RayOriginTranslatedWorld, 1), View.TranslatedWorldToClip);
|
|
const float4 RayDirClip = mul(float4(RayDirection * RayLength, 0), View.TranslatedWorldToClip);
|
|
const float4 RayEndClip = RayStartClip + RayDirClip;
|
|
|
|
const float3 RayStart = RayStartClip.xyz / RayStartClip.w;
|
|
const float3 RayEnd = RayEndClip.xyz / RayEndClip.w;
|
|
|
|
const float3 RayStep = RayEnd - RayStart;
|
|
|
|
const float4 RayDepthClip = RayStartClip + mul(float4(0, 0, RayLength, 0), View.ViewToClip);
|
|
const float3 RayDepth = RayDepthClip.xyz / RayDepthClip.w;
|
|
|
|
const float StepOffset = Dither - 0.5f;
|
|
const float Step = 1.0 / NumSteps;
|
|
|
|
const float CompareTolerance = abs(RayDepth.z - RayStart.z) * Step * CompareToleranceScale;
|
|
|
|
float SampleTime = StepOffset * Step + Step;
|
|
|
|
const float StartDepth = LookupDeviceZ(RayStart.xy * View.ScreenPositionScaleBias.xy + View.ScreenPositionScaleBias.wz);
|
|
|
|
UNROLL
|
|
for (int i = 0; i < NumSteps; i++)
|
|
{
|
|
// SamplePos is in NDC space of the current view
|
|
const float3 SamplePos = RayStart + RayStep * SampleTime;
|
|
const float2 SampleUV = SamplePos.xy * View.ScreenPositionScaleBias.xy + View.ScreenPositionScaleBias.wz;
|
|
const float SampleDepth = LookupDeviceZ(SampleUV);
|
|
|
|
// Avoid self-intersection with the start pixel (exact comparison due to point sampling depth buffer)
|
|
// Exception is made for hair for occluding transmitted light with non-shadow casting light
|
|
if (SampleDepth != StartDepth || bHairNoShadowLight)
|
|
{
|
|
const float DepthDiff = SamplePos.z - SampleDepth;
|
|
const bool bHit = abs(DepthDiff + CompareTolerance) < CompareTolerance;
|
|
|
|
if (bHit)
|
|
{
|
|
HitUV = SampleUV;
|
|
|
|
// Off screen masking, check NDC position against NDC boundary [-1,1]
|
|
bool bValidPos = all(and(-1.0 < SamplePos.xy, SamplePos.xy < 1.0));
|
|
|
|
return bValidPos ? (RayLength * SampleTime) : -1.0;
|
|
}
|
|
}
|
|
|
|
SampleTime += Step;
|
|
}
|
|
|
|
return -1;
|
|
} |