142 lines
5.9 KiB
HLSL
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);
|
|
} |