Files
UnrealEngine/Engine/Shaders/Private/Lumen/LumenShortRangeAOHardwareRayTracing.usf
2025-05-18 13:04:45 +08:00

158 lines
4.4 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#define SUBSTRATE_MATERIALCONTAINER_IS_VIEWRESOURCE 1
#include "../Common.ush"
#include "LumenMaterial.ush"
#include "../DeferredShadingCommon.ush"
#include "../BRDF.ush"
#include "../MonteCarlo.ush"
#include "../BlueNoise.ush"
#include "../ShadingModelsSampling.ush"
#include "../SceneTextureParameters.ush"
#include "../RayTracing/RayTracingCommon.ush"
#include "../RayTracing/RayTracingDeferredShadingCommon.ush"
#include "LumenHairTracing.ush"
#include "LumenPosition.ush"
#include "LumenScreenProbeCommon.ush"
#include "LumenScreenSpaceBentNormal.ush"
#ifndef THREADGROUP_SIZE
#define THREADGROUP_SIZE 1
#endif
RaytracingAccelerationStructure TLAS;
#if OUTPUT_BENT_NORMAL
RWTexture2DArray<uint> RWShortRangeAO;
#else
RWTexture2DArray<UNORM float> RWShortRangeAO;
#endif
#if DOWNSAMPLE_FACTOR != 1
RWTexture2D<float> RWDownsampledSceneDepth;
RWTexture2D<UNORM float3> RWDownsampledSceneWorldNormal;
#endif
uint NumRays;
float NormalBias;
float MaxScreenTraceFraction;
uint2 ShortRangeAOViewMin;
uint2 ShortRangeAOViewSize;
RAY_TRACING_ENTRY_RAYGEN(LumenShortRangeAOHardwareRayTracing)
{
const uint2 DispatchThreadId = DispatchRaysIndex().xy;
const uint2 GroupId = DispatchThreadId / 8;
const uint2 GroupThreadId = DispatchThreadId % 8;
const FLumenMaterialCoord Coord = GetLumenMaterialCoordDownsampled(DispatchThreadId, GroupId, GroupThreadId, DOWNSAMPLE_FACTOR, ShortRangeAOViewMin, ShortRangeAOViewSize);
const uint3 ShortRangeAOCoord = Coord.DownsampledCoord;
if (Coord.bIsValid)
{
const float2 ScreenUV = (Coord.SvPosition + .5f) * View.BufferSizeAndInvSize.zw;
const float SceneDepth = CalcSceneDepth(ScreenUV);
const float DummyMaxRoughnessToTrace = 0.5f;
const FLumenMaterialData Material = ReadMaterialData(Coord, DummyMaxRoughnessToTrace);
if (IsValid(Material))
{
float3 TranslatedWorldPosition = GetTranslatedWorldPositionFromScreenUV(ScreenUV, SceneDepth);
float3x3 TangentBasis = GetTangentBasis(Material.WorldNormal);
float TraceDistance = MaxScreenTraceFraction * 2.0 * GetScreenRayLengthMultiplierForProjectionType(SceneDepth).x;
float AmbientOcclusion = 0.0f;
float3 UnoccludedSum = 0;
float3 BentNormal = 0;
for (uint PixelRayIndex = 0; PixelRayIndex < NumRays; PixelRayIndex++)
{
float2 UniformRandom = BlueNoiseVec2(Coord.SvPosition, ScreenProbeGatherStateFrameIndex * NumRays + PixelRayIndex);
float4 HemisphereSample = CosineSampleHemisphere(UniformRandom);
float3 RayDirection = mul(HemisphereSample.xyz, TangentBasis);
float DirectionVisible = 1;
{
FRayDesc Ray;
Ray.Origin = TranslatedWorldPosition;
Ray.TMin = 0;
Ray.Direction = RayDirection;
Ray.TMax = TraceDistance;
ApplyCameraRelativeDepthBias(Ray, Coord.SvPosition, ConvertToDeviceZ(SceneDepth), Material.WorldNormal, NormalBias);
uint RayFlags = RAY_FLAG_SKIP_CLOSEST_HIT_SHADER | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH;
const uint InstanceInclusionMask = RAY_TRACING_MASK_OPAQUE;
FMinimalPayload MinimalPayload = TraceVisibilityRay(
TLAS,
RayFlags,
InstanceInclusionMask,
Ray);
bool bHit = MinimalPayload.IsHit();
#if USE_HAIRSTRANDS_VOXEL
if (!bHit)
{
bool bHairHit;
float HairTransparency;
float HairHitT;
uint2 NoiseCoord = Coord.SvPosition * uint2(NumRays, 1) + uint2(PixelRayIndex, 0);
TraceHairVoxels(
NoiseCoord,
SceneDepth,
TranslatedWorldPosition,
RayDirection,
TraceDistance,
false,
bHairHit,
HairTransparency,
HairHitT);
bHit = bHairHit && HairHitT < TraceDistance;
}
#endif
DirectionVisible = bHit ? 0.0f : 1.0f;
}
UnoccludedSum += RayDirection;
BentNormal += RayDirection * DirectionVisible;
AmbientOcclusion += DirectionVisible;
}
float NormalizeFactor = length(UnoccludedSum);
if (NormalizeFactor > 0)
{
BentNormal /= NormalizeFactor;
}
AmbientOcclusion /= NumRays;
// Debug passthrough
//BentNormal = Material.WorldNormal;
#if OUTPUT_BENT_NORMAL
RWShortRangeAO[ShortRangeAOCoord] = PackScreenBentNormal(BentNormal);
#else
RWShortRangeAO[ShortRangeAOCoord] = AmbientOcclusion;
#endif
#if DOWNSAMPLE_FACTOR != 1
if (ShortRangeAOCoord.z == 0)
{
RWDownsampledSceneDepth[ShortRangeAOCoord.xy] = SceneDepth;
RWDownsampledSceneWorldNormal[ShortRangeAOCoord.xy] = Material.WorldNormal;
}
#endif
}
}
}