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

142 lines
5.9 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
LumenFrontLayerTranslucency.usf
=============================================================================*/
#include "../Common.ush"
#include "../BRDF.ush"
// Material pass reroutes
#define SceneTexturesStruct LumenFrontLayerTranslucencyGBufferPass.SceneTextures
#include "/Engine/Generated/Material.ush"
#include "/Engine/Generated/VertexFactory.ush"
struct FLumenFrontLayerTranslucencyGBufferInterpolantsVSToPS
{
};
struct FLumenFrontLayerTranslucencyGBufferVSToPS
{
FVertexFactoryInterpolantsVSToPS FactoryInterpolants;
FLumenFrontLayerTranslucencyGBufferInterpolantsVSToPS PassInterpolants;
INVARIANT_OUTPUT float4 Position : SV_POSITION;
};
void MainVS(
FVertexFactoryInput Input,
out FLumenFrontLayerTranslucencyGBufferVSToPS Output
)
{
uint EyeIndex = 0;
ResolvedView = ResolveView();
FVertexFactoryIntermediates VFIntermediates = GetVertexFactoryIntermediates(Input);
float4 WorldPositionExcludingWPO = VertexFactoryGetWorldPosition(Input, VFIntermediates);
float4 WorldPosition = WorldPositionExcludingWPO;
float4 ClipSpacePosition;
float3x3 TangentToLocal = VertexFactoryGetTangentToLocal(Input, VFIntermediates);
FMaterialVertexParameters VertexParameters = GetMaterialVertexParameters(Input, VFIntermediates, WorldPosition.xyz, TangentToLocal);
ISOLATE
{
WorldPosition.xyz += GetMaterialWorldPositionOffset(VertexParameters);
ApplyMaterialFirstPersonTransform(VertexParameters, WorldPosition.xyz);
float4 RasterizedWorldPosition = VertexFactoryGetRasterizedWorldPosition(Input, VFIntermediates, WorldPosition);
ClipSpacePosition = INVARIANT(mul(RasterizedWorldPosition, ResolvedView.TranslatedWorldToClip));
Output.Position = INVARIANT(ClipSpacePosition);
}
Output.FactoryInterpolants = VertexFactoryGetInterpolantsVSToPS(Input, VFIntermediates, VertexParameters);
}
void MainPS(
FVertexFactoryInterpolantsVSToPS Interpolants,
FLumenFrontLayerTranslucencyGBufferInterpolantsVSToPS PassInterpolants,
in INPUT_POSITION_QUALIFIERS float4 SvPosition : SV_Position
OPTIONAL_IsFrontFace,
out float4 OutTarget0 : SV_Target0
OPTIONAL_OutDepthConservative)
{
ResolvedView = ResolveView();
FMaterialPixelParameters MaterialParameters = GetMaterialPixelParameters(Interpolants, SvPosition);
FPixelMaterialInputs PixelMaterialInputs;
{
float4 ScreenPosition = SvPositionToResolvedScreenPosition(SvPosition);
float3 TranslatedWorldPosition = SvPositionToResolvedTranslatedWorld(SvPosition);
CalcMaterialParametersEx(MaterialParameters, PixelMaterialInputs, SvPosition, ScreenPosition, bIsFrontFace, TranslatedWorldPosition, TranslatedWorldPosition);
}
float3 WorldNormal = MaterialParameters.WorldNormal;
float Roughness = GetMaterialRoughness(PixelMaterialInputs);
#if TEMPLATE_USES_SUBSTRATE
{
const float3 V = MaterialParameters.CameraVector;
const float3 L = MaterialParameters.WorldNormal;
// Initialise a Substrate header with normal in registers
FSubstrateData SubstrateData = PixelMaterialInputs.GetFrontSubstrateData();
FSubstratePixelHeader SubstratePixelHeader = MaterialParameters.GetFrontSubstrateHeader();
SubstratePixelHeader.IrradianceAO.MaterialAO = GetMaterialAmbientOcclusion(PixelMaterialInputs);
float TotalCoverage = 1.f;
if (SubstratePixelHeader.SubstrateTree.BSDFCount > 0)
{
const FSubstrateIntegrationSettings Settings = InitSubstrateIntegrationSettings(false /*bForceFullyRough*/, true /*bRoughDiffuseEnabled*/, 0 /*PeelLayersAboveDepth*/, false/*bRoughnessTracking*/);
float3 TotalTransmittancePreCoverage = 0;
SubstratePixelHeader.SubstrateUpdateTree(SubstrateData, V, Settings, TotalCoverage, TotalTransmittancePreCoverage);
// Clip pixels that will never receive any lumen front material reflections.
// We cannot generalise and use GetMaterialClippingVelocity for that because this function clips with a 1/255 threshold...that can result in NaN refelctions if some pixels are not genrated correctly.
clip(TotalCoverage <= 0.0f ? -1.0f : 1.0f);
// Extract averaged normal and roughness
WorldNormal = 0;
Roughness = 0;
float TopLayerTotalWeight = 0.0f;
SUBSTRATE_UNROLL_N(SUBSTRATE_CLAMPED_CLOSURE_COUNT)
for (int BSDFIdx = 0; BSDFIdx < SubstratePixelHeader.SubstrateTree.BSDFCount; ++BSDFIdx)
{
#define CurrentBSDF SubstratePixelHeader.SubstrateTree.BSDFs[BSDFIdx]
if (SubstrateIsBSDFVisible(CurrentBSDF))
{
FSubstrateAddressing NullSubstrateAddressing = (FSubstrateAddressing)0; // Fake unused in SubstrateCreateBSDFContext when using Forward inline shading
FSubstrateBSDFContext SubstrateBSDFContext = SubstrateCreateBSDFContext(SubstratePixelHeader, CurrentBSDF, NullSubstrateAddressing, V, L);
const float Weight = Luminance(CurrentBSDF.LuminanceWeightV);
WorldNormal += Weight * SubstrateBSDFContext.N;
TopLayerTotalWeight += CurrentBSDF.TopLayerDataWeight;
Roughness += CurrentBSDF.TopLayerDataWeight * SubstrateGetBSDFRoughness(CurrentBSDF);
}
#undef CurrentBSDF
}
if (any(WorldNormal != 0))
{
WorldNormal = normalize(WorldNormal);
}
Roughness = TopLayerTotalWeight > 0.0f ? Roughness / TopLayerTotalWeight : 0.0f;
}
}
#else
// Thin translucent materials are assumed to always have a coverage of 1.
#if !MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT
clip(PixelMaterialInputs.Opacity <= 0.0f ? -1.0f : 1.0f);
#endif
#endif // TEMPLATE_USES_SUBSTRATE
GetMaterialCoverageAndClipping(MaterialParameters, PixelMaterialInputs);
#if OUTPUT_PIXEL_DEPTH_OFFSET
ApplyPixelDepthOffsetToMaterialParameters(MaterialParameters, PixelMaterialInputs, OutDepth);
#endif
// We store (1+roughness*65534)/65535 to make sure w is always greater that 0 where we write which then signifies we need lumen high quality reflections.
// The render target is 16-bit unorm and we will still get enough accuracy.
OutTarget0 = float4(EncodeNormal(WorldNormal), (1.0f + Roughness * 65534.0f) / 65535.0f);
}