181 lines
4.7 KiB
HLSL
181 lines
4.7 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "../RayTracing/RayTracingCapsuleLight.ush"
|
|
#include "../RayTracing/RayTracingSphereLight.ush"
|
|
#include "../RayTracing/RayTracingRectLight.ush"
|
|
#include "../RayTracing/RayTracingDirectionalLight.ush"
|
|
|
|
uint2 NumSamplesPerPixelDivideShift;
|
|
|
|
uint2 SampleCoordToDownsampledScreenCoord(uint2 SampleCoord)
|
|
{
|
|
// SampleCoord / NumSamplesPerPixel
|
|
return SampleCoord >> NumSamplesPerPixelDivideShift;
|
|
}
|
|
|
|
uint3 NumSamplesPerVoxelDivideShift;
|
|
|
|
uint3 SampleCoordToDownsampledVolumeCoord(uint3 SampleCoord)
|
|
{
|
|
// SampleCoord / NumSamplesPerVoxel
|
|
return SampleCoord >> NumSamplesPerVoxelDivideShift;
|
|
}
|
|
|
|
uint2 SampleCoordToScreenCoord(uint2 SampleCoord)
|
|
{
|
|
uint2 DownsampledScreenCoord = SampleCoordToDownsampledScreenCoord(SampleCoord);
|
|
return (DownsampledScreenCoord << DownsampleFactorMultShift) + GetSampleScreenCoordJitter(DownsampledScreenCoord);
|
|
}
|
|
|
|
bool GenerateShadowRay(
|
|
FLightShaderParameters LightParameters,
|
|
bool bSpotLight,
|
|
bool bRectLight,
|
|
bool bDirLight,
|
|
float3 TranslatedWorldPosition,
|
|
float3 WorldNormal,
|
|
float2 RandSample,
|
|
out float3 RayOrigin,
|
|
out float3 RayDirection,
|
|
out float RayTMin,
|
|
out float RayTMax)
|
|
{
|
|
float RayPdf = 0.0;
|
|
if (bRectLight)
|
|
{
|
|
return GenerateRectLightOcclusionRay(
|
|
LightParameters,
|
|
TranslatedWorldPosition, WorldNormal,
|
|
RandSample,
|
|
/* out */ RayOrigin,
|
|
/* out */ RayDirection,
|
|
/* out */ RayTMin,
|
|
/* out */ RayTMax,
|
|
/* out */ RayPdf);
|
|
}
|
|
else if (bDirLight)
|
|
{
|
|
GenerateDirectionalLightOcclusionRay(
|
|
LightParameters,
|
|
TranslatedWorldPosition, WorldNormal,
|
|
RandSample,
|
|
/* out */ RayOrigin,
|
|
/* out */ RayDirection,
|
|
/* out */ RayTMin,
|
|
/* out */ RayTMax);
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
// point or spot light
|
|
if (LightParameters.SourceLength > 0.0)
|
|
{
|
|
return GenerateCapsuleLightOcclusionRayWithSolidAngleSampling(
|
|
LightParameters,
|
|
TranslatedWorldPosition, WorldNormal,
|
|
RandSample,
|
|
/* out */ RayOrigin,
|
|
/* out */ RayDirection,
|
|
/* out */ RayTMin,
|
|
/* out */ RayTMax,
|
|
/* out */ RayPdf);
|
|
}
|
|
return GenerateSphereLightOcclusionRayWithSolidAngleSampling(
|
|
LightParameters,
|
|
TranslatedWorldPosition, WorldNormal,
|
|
RandSample,
|
|
/* out */ RayOrigin,
|
|
/* out */ RayDirection,
|
|
/* out */ RayTMin,
|
|
/* out */ RayTMax,
|
|
/* out */ RayPdf);
|
|
}
|
|
}
|
|
|
|
struct FLightSampleTrace
|
|
{
|
|
float3 Direction;
|
|
float Distance;
|
|
};
|
|
|
|
/**
|
|
* Compute shadow ray direction and distance for a given light sample.
|
|
*/
|
|
FLightSampleTrace GetLightSampleTrace(float3 TranslatedWorldPosition, uint LocalLightIndex, float2 LightSampleUV)
|
|
{
|
|
FLightSampleTrace LightSampleTrace;
|
|
LightSampleTrace.Direction = 0.0f;
|
|
LightSampleTrace.Distance = 0.0f;
|
|
|
|
if (LocalLightIndex != MAX_LOCAL_LIGHT_INDEX)
|
|
{
|
|
const FForwardLightData ForwardLightData = GetForwardLightData(LocalLightIndex, 0);
|
|
const FDeferredLightData LightData = ConvertToDeferredLight(ForwardLightData);
|
|
const FLightShaderParameters LightParameters = ConvertToLightShaderParameters(LightData);
|
|
|
|
float3 Unused;
|
|
float Unused2;
|
|
|
|
bool bValid = GenerateShadowRay(
|
|
LightParameters,
|
|
LightData.bSpotLight,
|
|
LightData.bRectLight,
|
|
!LightData.bRadialLight,
|
|
TranslatedWorldPosition,
|
|
float3(0, 0, 0),
|
|
LightSampleUV,
|
|
Unused,
|
|
LightSampleTrace.Direction,
|
|
Unused2,
|
|
LightSampleTrace.Distance);
|
|
if (!bValid)
|
|
{
|
|
// MegaLight pipeline is not really set up to handle invalid samples.
|
|
// Replace what we got with a valid sample so that the rest of the code can
|
|
// still estimate a valid shadow fraction. Forcing the sample to be always
|
|
// occluded would add noise in unshadowed regions, and forcing the sample to
|
|
// count as un-occluded would add light leaks in occluded regions.
|
|
// This seems like the simplest workaround for now.
|
|
float3 ToLight = LightParameters.TranslatedWorldPosition - TranslatedWorldPosition;
|
|
LightSampleTrace.Distance = length(ToLight);
|
|
LightSampleTrace.Direction = ToLight * rcp(LightSampleTrace.Distance);
|
|
}
|
|
}
|
|
|
|
return LightSampleTrace;
|
|
}
|
|
|
|
uint PackTraceTexel(uint2 SampleCoord)
|
|
{
|
|
uint PackedTraceTexel = SampleCoord.y & 0xFFFF;
|
|
PackedTraceTexel |= (SampleCoord.x & 0xFFFF) << 16;
|
|
return PackedTraceTexel;
|
|
}
|
|
|
|
uint2 UnpackTraceTexel(uint PackedTraceTexel)
|
|
{
|
|
uint2 SampleCoord;
|
|
SampleCoord.x = PackedTraceTexel >> 16;
|
|
SampleCoord.y = PackedTraceTexel & 0xFFFF;
|
|
return SampleCoord;
|
|
}
|
|
|
|
uint PackTraceVoxel(uint3 SampleCoord)
|
|
{
|
|
uint PackedTraceVoxel = SampleCoord.z & 0x3FF;
|
|
PackedTraceVoxel |= (SampleCoord.y & 0x3FF) << 10;
|
|
PackedTraceVoxel |= (SampleCoord.x & 0x3FF) << 20;
|
|
return PackedTraceVoxel;
|
|
}
|
|
|
|
uint3 UnpackTraceVoxel(uint PackedTraceVoxel)
|
|
{
|
|
uint3 SampleCoord;
|
|
SampleCoord.x = (PackedTraceVoxel >> 20) & 0x3FF;
|
|
SampleCoord.y = (PackedTraceVoxel >> 10) & 0x3FF;
|
|
SampleCoord.z = PackedTraceVoxel & 0x3FF;
|
|
return SampleCoord;
|
|
} |