You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#ROBOMERGE-SOURCE: CL 15348315 in //UE5/Release-5.0-EarlyAccess/... #ROBOMERGE-BOT: STARSHIP (Release-5.0-EarlyAccess -> Main) (v771-15082668) [CL 15359818 by daniel wright in ue5-main branch]
209 lines
7.6 KiB
Plaintext
209 lines
7.6 KiB
Plaintext
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
DistanceFieldVisualization.usf
|
|
=============================================================================*/
|
|
|
|
#include "Common.ush"
|
|
#include "DeferredShadingCommon.ush"
|
|
#include "DistanceFieldLightingShared.ush"
|
|
#include "DistanceFieldAOShared.ush"
|
|
#include "GlobalDistanceFieldShared.ush"
|
|
#include "GlobalDistanceFieldUtils.ush"
|
|
|
|
RWTexture2D<float4> RWVisualizeMeshDistanceFields;
|
|
|
|
#define MAX_INTERSECTING_OBJECTS 1024
|
|
groupshared uint IntersectingObjectIndices[MAX_INTERSECTING_OBJECTS];
|
|
|
|
groupshared uint NumIntersectingObjects;
|
|
|
|
void RayTraceThroughTileCulledDistanceFields(float3 WorldRayStart, float3 WorldRayEnd, float MaxRayTime, out float MinRayTime, out float TotalStepsTaken)
|
|
{
|
|
MinRayTime = MaxRayTime;
|
|
TotalStepsTaken = 0;
|
|
|
|
LOOP
|
|
for (uint ListObjectIndex = 0; ListObjectIndex < min(NumIntersectingObjects, (uint)MAX_INTERSECTING_OBJECTS); ListObjectIndex++)
|
|
{
|
|
uint ObjectIndex = IntersectingObjectIndices[ListObjectIndex];
|
|
FDFObjectData DFObjectData = LoadCulledDFObjectData(ObjectIndex);
|
|
|
|
float3 VolumeRayStart = mul(float4(WorldRayStart, 1), DFObjectData.WorldToVolume).xyz;
|
|
float3 VolumeRayEnd = mul(float4(WorldRayEnd, 1), DFObjectData.WorldToVolume).xyz;
|
|
float3 VolumeRayDirection = VolumeRayEnd - VolumeRayStart;
|
|
float VolumeRayLength = length(VolumeRayDirection);
|
|
VolumeRayDirection /= VolumeRayLength;
|
|
|
|
float2 IntersectionTimes = LineBoxIntersect(VolumeRayStart, VolumeRayEnd, -DFObjectData.LocalPositionExtent, DFObjectData.LocalPositionExtent);
|
|
|
|
if (IntersectionTimes.x < IntersectionTimes.y && IntersectionTimes.x < 1)
|
|
{
|
|
float SampleRayTime = IntersectionTimes.x * VolumeRayLength;
|
|
|
|
float MinDistance = 1000000;
|
|
|
|
uint StepIndex = 0;
|
|
uint MaxSteps = 256;
|
|
|
|
LOOP
|
|
for (; StepIndex < MaxSteps; StepIndex++)
|
|
{
|
|
float3 SampleVolumePosition = VolumeRayStart + VolumeRayDirection * SampleRayTime;
|
|
float3 ClampedSamplePosition = clamp(SampleVolumePosition, -DFObjectData.LocalPositionExtent, DFObjectData.LocalPositionExtent);
|
|
float3 VolumeUV = DistanceFieldVolumePositionToUV(ClampedSamplePosition, DFObjectData.UVScale, DFObjectData.UVAdd);
|
|
float DistanceField = SampleMeshDistanceField(VolumeUV, DFObjectData.DistanceFieldMAD).x;
|
|
MinDistance = min(MinDistance, DistanceField);
|
|
|
|
float MinStepSize = 1.0f / (4 * MaxSteps);
|
|
float StepDistance = max(DistanceField, MinStepSize);
|
|
SampleRayTime += StepDistance;
|
|
|
|
// Terminate the trace if we reached a negative area or went past the end of the ray
|
|
if (DistanceField < 0
|
|
|| SampleRayTime > IntersectionTimes.y * VolumeRayLength)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//Result = max(Result, StepIndex / (float)MaxSteps);
|
|
|
|
if (MinDistance * DFObjectData.VolumeScale < 0 || StepIndex == MaxSteps)
|
|
{
|
|
const float NewHitDistance = length(VolumeRayDirection * SampleRayTime * DFObjectData.VolumeToLocalScale);
|
|
MinRayTime = min(MinRayTime, NewHitDistance);
|
|
}
|
|
|
|
TotalStepsTaken += StepIndex;
|
|
}
|
|
}
|
|
}
|
|
|
|
float2 NumGroups;
|
|
|
|
[numthreads(THREADGROUP_SIZEX, THREADGROUP_SIZEY, 1)]
|
|
void VisualizeMeshDistanceFieldCS(
|
|
uint3 GroupId : SV_GroupID,
|
|
uint3 DispatchThreadId : SV_DispatchThreadID,
|
|
uint3 GroupThreadId : SV_GroupThreadID)
|
|
{
|
|
uint ThreadIndex = GroupThreadId.y * THREADGROUP_SIZEX + GroupThreadId.x;
|
|
|
|
float2 ScreenUV = float2((DispatchThreadId.xy * DOWNSAMPLE_FACTOR + View.ViewRectMin.xy + .5f) * View.BufferSizeAndInvSize.zw);
|
|
float2 ScreenPosition = (ScreenUV.xy - View.ScreenPositionScaleBias.wz) / View.ScreenPositionScaleBias.xy;
|
|
|
|
float SceneDepth = CalcSceneDepth(ScreenUV);
|
|
float3 OpaqueWorldPosition = mul(float4(ScreenPosition * SceneDepth, SceneDepth, 1), View.ScreenToWorld).xyz;
|
|
|
|
float TraceDistance = 40000;
|
|
float3 WorldRayStart = View.WorldCameraOrigin;
|
|
float3 WorldRayEnd = WorldRayStart + normalize(OpaqueWorldPosition - View.WorldCameraOrigin) * TraceDistance;
|
|
float3 WorldRayDirection = normalize(WorldRayEnd - WorldRayStart);
|
|
|
|
#if USE_GLOBAL_DISTANCE_FIELD
|
|
|
|
FGlobalSDFTraceInput TraceInput = SetupGlobalSDFTraceInput(WorldRayStart, WorldRayDirection, 0.0f, TraceDistance, 1.0f, 1.0f);
|
|
|
|
FGlobalSDFTraceResult SDFTraceResult = RayTraceGlobalDistanceField(TraceInput);
|
|
|
|
float3 Result = saturate(SDFTraceResult.TotalStepsTaken / 400.0f);
|
|
if (!GlobalSDFTraceResultIsHit(SDFTraceResult))
|
|
{
|
|
// Sky
|
|
Result.xy *= 0.25f;
|
|
}
|
|
|
|
#else
|
|
if (ThreadIndex == 0)
|
|
{
|
|
NumIntersectingObjects = 0;
|
|
}
|
|
|
|
GroupMemoryBarrierWithGroupSync();
|
|
|
|
float3 TileConeVertex;
|
|
float3 TileConeAxis;
|
|
float TileConeAngleCos;
|
|
float TileConeAngleSin;
|
|
|
|
{
|
|
float2 ViewSize = float2(1 / View.ViewToClip[0][0], 1 / View.ViewToClip[1][1]);
|
|
float3 TileCorner00 = normalize(float3((GroupId.x + 0) / NumGroups.x * ViewSize.x * 2 - ViewSize.x, ViewSize.y - (GroupId.y + 0) / NumGroups.y * ViewSize.y * 2, 1));
|
|
float3 TileCorner10 = normalize(float3((GroupId.x + 1) / NumGroups.x * ViewSize.x * 2 - ViewSize.x, ViewSize.y - (GroupId.y + 0) / NumGroups.y * ViewSize.y * 2, 1));
|
|
float3 TileCorner01 = normalize(float3((GroupId.x + 0) / NumGroups.x * ViewSize.x * 2 - ViewSize.x, ViewSize.y - (GroupId.y + 1) / NumGroups.y * ViewSize.y * 2, 1));
|
|
float3 TileCorner11 = normalize(float3((GroupId.x + 1) / NumGroups.x * ViewSize.x * 2 - ViewSize.x, ViewSize.y - (GroupId.y + 1) / NumGroups.y * ViewSize.y * 2, 1));
|
|
|
|
float3 ViewSpaceTileConeAxis = normalize(TileCorner00 + TileCorner10 + TileCorner01 + TileCorner11);
|
|
TileConeAxis = mul(ViewSpaceTileConeAxis, (float3x3)View.ViewToTranslatedWorld);
|
|
TileConeAngleCos = dot(ViewSpaceTileConeAxis, TileCorner00);
|
|
TileConeAngleSin = sqrt(1 - TileConeAngleCos * TileConeAngleCos);
|
|
TileConeVertex = View.WorldCameraOrigin;
|
|
}
|
|
|
|
uint NumCulledObjects = GetCulledNumObjects();
|
|
|
|
LOOP
|
|
for (uint ObjectIndex = ThreadIndex; ObjectIndex < NumCulledObjects; ObjectIndex += THREADGROUP_TOTALSIZE)
|
|
{
|
|
float4 SphereCenterAndRadius = LoadObjectPositionAndRadius(ObjectIndex);
|
|
|
|
BRANCH
|
|
if (SphereIntersectCone(SphereCenterAndRadius, TileConeVertex, TileConeAxis, TileConeAngleCos, TileConeAngleSin))
|
|
{
|
|
uint ListIndex;
|
|
InterlockedAdd(NumIntersectingObjects, 1U, ListIndex);
|
|
|
|
if (ListIndex < MAX_INTERSECTING_OBJECTS)
|
|
{
|
|
IntersectingObjectIndices[ListIndex] = ObjectIndex;
|
|
}
|
|
}
|
|
}
|
|
|
|
GroupMemoryBarrierWithGroupSync();
|
|
|
|
float MinRayTime;
|
|
float TotalStepsTaken;
|
|
|
|
// Trace once to find the distance to first intersection
|
|
RayTraceThroughTileCulledDistanceFields(WorldRayStart, WorldRayEnd, TraceDistance, MinRayTime, TotalStepsTaken);
|
|
|
|
float TempMinRayTime;
|
|
// Recompute the ray end point
|
|
WorldRayEnd = WorldRayStart + WorldRayDirection * MinRayTime;
|
|
// Trace a second time to only accumulate steps taken before the first intersection, improves visualization
|
|
RayTraceThroughTileCulledDistanceFields(WorldRayStart, WorldRayEnd, MinRayTime, TempMinRayTime, TotalStepsTaken);
|
|
|
|
float3 Result = saturate(TotalStepsTaken / 200.0f);
|
|
|
|
if (MinRayTime < TraceDistance)
|
|
{
|
|
Result += .1f;
|
|
}
|
|
else
|
|
{
|
|
// Sky
|
|
Result.z += 0.05f;
|
|
}
|
|
|
|
#endif
|
|
|
|
RWVisualizeMeshDistanceFields[DispatchThreadId.xy] = float4(Result, 0);
|
|
}
|
|
|
|
Texture2D VisualizeDistanceFieldTexture;
|
|
SamplerState VisualizeDistanceFieldSampler;
|
|
|
|
void VisualizeDistanceFieldUpsamplePS(in float4 UVAndScreenPos : TEXCOORD0, out float4 OutColor : SV_Target0)
|
|
{
|
|
// Distance field AO was computed at 0,0 regardless of viewrect min
|
|
float2 DistanceFieldUVs = UVAndScreenPos.xy - View.ViewRectMin.xy * View.BufferSizeAndInvSize.zw;
|
|
|
|
float3 Value = Texture2DSampleLevel(VisualizeDistanceFieldTexture, VisualizeDistanceFieldSampler, DistanceFieldUVs, 0).xyz;
|
|
|
|
// Note: not applying pre-exposure as exposure is skipped in IsAutoExposureDebugMode
|
|
|
|
OutColor = float4(Value, 1);
|
|
}
|