Files
UnrealEngine/Engine/Shaders/Private/PathTracing/PathTracingInitExtinctionCoefficient.usf
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

84 lines
2.9 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#include "../Common.ush"
#include "PathTracingCommon.ush"
RaytracingAccelerationStructure TLAS;
RWBuffer<float> RWStartingMediumData;
RAY_TRACING_ENTRY_RAYGEN(PathTracingInitExtinctionCoefficientRG)
{
const uint RayFlags = 0;
const uint MissShaderIndex = 0;
const uint InstanceInclusionMask = PATHTRACER_MASK_CAMERA | PATHTRACER_MASK_CAMERA_TRANSLUCENT; // Ignore hair strands, only trace what camera rays can see
FRayDesc UpRay;
UpRay.Origin = PrimaryView.TranslatedWorldCameraOrigin;
UpRay.Direction = float3(0, 0, 1);
UpRay.TMin = 0.0;
UpRay.TMax = RAY_DEFAULT_T_MAX;
float3 StartingSigmaT = 0.0;
float3 StartingSigmaS = 0.0;
float StartingPhaseG = 0;
for (;;)
{
FPackedPathTracingPayload PackedPayload = InitPathTracingPayload(PATHTRACER_SCATTER_CAMERA, 0.0);
// TODO: Should we try to average the result of several paths here? If a material is only partially glass, we may not get a consistent answer here
PackedPayload.SetStochasticSlabRand(0.5);
TraceRay(
TLAS,
RayFlags,
InstanceInclusionMask,
RAY_TRACING_SHADER_SLOT_MATERIAL,
RAY_TRACING_NUM_SHADER_SLOTS,
MissShaderIndex,
UpRay.GetNativeDesc(),
PackedPayload);
#if NEED_TMIN_WORKAROUND // extra safety - discard hit if not conforming
if (PackedPayload.HitT <= UpRay.TMin)
{
PackedPayload.HitT = -1.0;
}
#endif
if (PackedPayload.IsMiss())
{
// we didn't hit anything
break;
}
FPathTracingPayload HitPayload = UnpackPathTracingPayload(PackedPayload, UpRay);
if (HitPayload.IsMaterialSolidGlass())
{
// Found a solid transmissive medium -- pickup the extinction
float3 LocalSigmaT = HitPayload.GetExtinction();
float3 LocalSigmaS = HitPayload.GetGlassAlbedo() * LocalSigmaT;
float PhaseG = HitPayload.GetGlassPhase();
float WeightPrev = max(LobeColorToWeight(StartingSigmaT), 0);
float WeightCurr = max(LobeColorToWeight(LocalSigmaT), 0);
// increase when we leave a medium (that means we must have been inside before)
// decrease when we enter a medium (will be cancelled out when we leave)
StartingSigmaT += HitPayload.IsFrontFace() ? -LocalSigmaT : +LocalSigmaT;
StartingSigmaS += HitPayload.IsFrontFace() ? -LocalSigmaS : +LocalSigmaS;
StartingPhaseG = lerp(StartingPhaseG, PhaseG, MISWeightBalanced(WeightCurr, WeightPrev));
}
// keep tracing
UpRay.TMin = ComputeNewTMin(UpRay.Origin, UpRay.Direction, PackedPayload.HitT);
}
// clamp against 0 in the unlikely case that we only hit front faces of glass on our way up
StartingSigmaT = max(StartingSigmaT, 0.0);
StartingSigmaS = max(StartingSigmaS, 0.0);
RWStartingMediumData[0] = StartingSigmaT.x;
RWStartingMediumData[1] = StartingSigmaT.y;
RWStartingMediumData[2] = StartingSigmaT.z;
RWStartingMediumData[3] = StartingSigmaS.x;
RWStartingMediumData[4] = StartingSigmaS.y;
RWStartingMediumData[5] = StartingSigmaS.z;
RWStartingMediumData[6] = StartingPhaseG;
}