[numthreads( 8 , 8 , 1)]
void TraceFromProbesCS(
uint3 GroupId : SV_GroupID,
uint2 GroupThreadId : SV_GroupThreadID)
{
uint TraceTileIndex = GroupId.y * 128 + GroupId.x;
if (TraceTileIndex < ProbeTraceTileAllocator[0])
{
uint2 TraceTileCoord;
uint TraceTileLevel;
uint ProbeTraceIndex;
UnpackTraceTileInfo(ProbeTraceTileData[TraceTileIndex], TraceTileCoord, TraceTileLevel, ProbeTraceIndex);
uint TraceResolution = (RadianceProbeResolution / 2) << TraceTileLevel;
uint2 ProbeTexelCoord = TraceTileCoord * 8 + GroupThreadId.xy;
float3 ProbeWorldCenter;
uint ClipmapIndex;
uint ProbeIndex;
GetProbeTraceData(ProbeTraceIndex, ProbeWorldCenter, ClipmapIndex, ProbeIndex);
const float3 ProbeTranslatedWorldCenter = ProbeWorldCenter + LWCToFloat( GetPrimaryView() .PreViewTranslation) ;
if (all(ProbeTexelCoord < TraceResolution))
{
float2 ProbeTexelCenter = float2(0.5, 0.5);
float2 ProbeUV = (ProbeTexelCoord + ProbeTexelCenter) / float(TraceResolution);
float3 WorldConeDirection = OctahedronToUnitVector(ProbeUV * 2.0 - 1.0);
float FinalMinTraceDistance = max(MinTraceDistance, GetRadianceProbeTMin(ClipmapIndex));
float FinalMaxTraceDistance = MaxTraceDistance;
float EffectiveStepFactor = StepFactor;
float ConeHalfAngle = acosFast(1.0f - 1.0f / (float)(TraceResolution * TraceResolution));
FConeTraceInput TraceInput;
TraceInput.Setup(
ProbeWorldCenter, ProbeTranslatedWorldCenter, WorldConeDirection,
ConeHalfAngle, MinSampleRadius,
FinalMinTraceDistance, FinalMaxTraceDistance,
EffectiveStepFactor);
TraceInput.bDitheredTransparency = true;
TraceInput.DitherScreenCoord = RadianceProbeResolution * uint2(ProbeIndex & ProbeAtlasResolutionModuloMask, ProbeIndex >> ProbeAtlasResolutionDivideShift) + ProbeTexelCoord;
bool bContinueCardTracing = false;
TraceInput.VoxelTraceStartDistance = CalculateVoxelTraceStartDistance(FinalMinTraceDistance, FinalMaxTraceDistance, MaxMeshSDFTraceDistance, bContinueCardTracing);
FConeTraceResult TraceResult = TraceForProbeTexel(TraceInput);
SharedTraceRadiance[GroupThreadId.y][GroupThreadId.x] = TraceResult.Lighting;
SharedTraceHitDistance[GroupThreadId.y][GroupThreadId.x] = TraceResult.OpaqueHitDistance;
}
GroupMemoryBarrierWithGroupSync();
uint2 ProbeAtlasBaseCoord = RadianceProbeResolution * uint2(ProbeIndex & ProbeAtlasResolutionModuloMask, ProbeIndex >> ProbeAtlasResolutionDivideShift);
if (TraceResolution < RadianceProbeResolution)
{
uint UpsampleFactor = RadianceProbeResolution / TraceResolution;
ProbeAtlasBaseCoord += ( 8 * TraceTileCoord + GroupThreadId.xy) * UpsampleFactor;
float3 Lighting = SharedTraceRadiance[GroupThreadId.y][GroupThreadId.x];
{
for (uint Y = 0; Y < UpsampleFactor; Y++)
{
for (uint X = 0; X < UpsampleFactor; X++)
{
RWRadianceProbeAtlasTexture[ProbeAtlasBaseCoord + uint2(X, Y)] = Lighting;
}
}
}
float HitDistance = min(SharedTraceHitDistance[GroupThreadId.y][GroupThreadId.x], MaxHalfFloat);
for (uint Y = 0; Y < UpsampleFactor; Y++)
{
for (uint X = 0; X < UpsampleFactor; X++)
{
RWDepthProbeAtlasTexture[ProbeAtlasBaseCoord + uint2(X, Y)] = HitDistance;
}
}
}
else
{
uint DownsampleFactor = TraceResolution / RadianceProbeResolution;
uint WriteTileSize = 8 / DownsampleFactor;
if (all(GroupThreadId.xy < WriteTileSize))
{
float3 Lighting = 0;
{
for (uint Y = 0; Y < DownsampleFactor; Y++)
{
for (uint X = 0; X < DownsampleFactor; X++)
{
Lighting += SharedTraceRadiance[GroupThreadId.y * DownsampleFactor + Y][GroupThreadId.x * DownsampleFactor + X];
}
}
}
ProbeAtlasBaseCoord += WriteTileSize * TraceTileCoord + GroupThreadId.xy;
RWRadianceProbeAtlasTexture[ProbeAtlasBaseCoord] = Lighting / (float)(DownsampleFactor * DownsampleFactor);
float HitDistance = MaxHalfFloat;
for (uint Y = 0; Y < DownsampleFactor; Y++)
{
for (uint X = 0; X < DownsampleFactor; X++)
{
HitDistance = min(HitDistance, SharedTraceHitDistance[GroupThreadId.y * DownsampleFactor + Y][GroupThreadId.x * DownsampleFactor + X]);
}
}
RWDepthProbeAtlasTexture[ProbeAtlasBaseCoord] = HitDistance;
}
}
}
}
FConeTraceResult TraceForProbeTexel(FConeTraceInput TraceInput)
{
FConeTraceResult TraceResult;
TraceResult = (FConeTraceResult)0;
TraceResult.Lighting = 0.0;
TraceResult.Transparency = 1.0;
TraceResult.OpaqueHitDistance = TraceInput.MaxTraceDistance;
TraceInput.bZeroRadianceIfRayStartsInsideGeometry = true;
ConeTraceLumenSceneVoxels(TraceInput, TraceResult);
#if ENABLE_DYNAMIC_SKY_LIGHT
if (ReflectionStruct.SkyLightParameters.y > 0)
{
float SkyAverageBrightness = 1.0f;
float Roughness = TanConeAngleToRoughness(tan(TraceInput.ConeAngle));
TraceResult.Lighting = TraceResult.Lighting + GetSkyLightReflection(TraceInput.ConeDirection, Roughness, SkyAverageBrightness) * TraceResult.Transparency;
}
#endif
return TraceResult;
}
void ConeTraceLumenSceneVoxels(
FConeTraceInput TraceInput,
inout FConeTraceResult OutResult)
{
#if SCENE_TRACE_VOXELS
if (TraceInput.VoxelTraceStartDistance < TraceInput.MaxTraceDistance)
{
FConeTraceInput VoxelTraceInput = TraceInput;
VoxelTraceInput.MinTraceDistance = TraceInput.VoxelTraceStartDistance;
FConeTraceResult VoxelTraceResult;
RayTraceGlobalDistanceField(VoxelTraceInput, VoxelTraceResult);
#if !VISIBILITY_ONLY_TRACE
OutResult.Lighting += VoxelTraceResult.Lighting * OutResult.Transparency;
#endif
OutResult.Transparency *= VoxelTraceResult.Transparency;
OutResult.NumSteps += VoxelTraceResult.NumSteps;
OutResult.OpaqueHitDistance = min(OutResult.OpaqueHitDistance, VoxelTraceResult.OpaqueHitDistance);
}
#endif
}
void RayTraceGlobalDistanceField(
FConeTraceInput TraceInput,
inout FConeTraceResult OutResult)
{
FGlobalSDFTraceResult SDFTraceResult;
// Trace SDF ray
{
FGlobalSDFTraceInput SDFTraceInput = SetupGlobalSDFTraceInput(TraceInput.ConeOrigin, TraceInput.ConeDirection, TraceInput.MinTraceDistance, TraceInput.MaxTraceDistance, TraceInput.SDFStepFactor, TraceInput.MinSDFStepFactor);
SDFTraceInput.bDitheredTransparency = TraceInput.bDitheredTransparency;
SDFTraceInput.DitherScreenCoord = TraceInput.DitherScreenCoord;
SDFTraceInput.bExpandSurfaceUsingRayTimeInsteadOfMaxDistance = TraceInput.bExpandSurfaceUsingRayTimeInsteadOfMaxDistance;
SDFTraceInput.InitialMaxDistance = TraceInput.InitialMaxDistance;
SDFTraceResult = RayTraceGlobalDistanceField(SDFTraceInput);
}
float4 LightingAndAlpha = float4(0, 0, 0, 1);
if (GlobalSDFTraceResultIsHit(SDFTraceResult))
{
LightingAndAlpha = EvaluateGlobalDistanceFieldHit(TraceInput, SDFTraceResult);
}
OutResult = (FConeTraceResult)0;
#if !VISIBILITY_ONLY_TRACE
OutResult.Lighting = LightingAndAlpha.rgb;
#endif
OutResult.Transparency = LightingAndAlpha.a;
OutResult.NumSteps = SDFTraceResult.TotalStepsTaken;
OutResult.OpaqueHitDistance = GlobalSDFTraceResultIsHit(SDFTraceResult) ? SDFTraceResult.HitTime : TraceInput.MaxTraceDistance;
OutResult.ExpandSurfaceAmount = SDFTraceResult.ExpandSurfaceAmount;
}
后面与博客内容一致:LumenScreenProbeGather:TraceVoxels_sh15285118586的博客-CSDN博客