Files
UnrealEngine/Engine/Shaders/Private/Substrate/SubstrateRead.ush
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

231 lines
7.9 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
// Sanity guard.
#ifndef SUBSTRATE_ENABLED
#define SUBSTRATE_ENABLED 1
#error SUBSTRATE_ENABLED needs to be defined
#endif
#if SUBSTRATE_ENABLED
#include "../Common.ush"
#include "Substrate.ush"
#include "/Engine/Private/DeferredShadingCommon.ush"
struct FSubstrateGBufferBSDF
{
FSubstrateBSDF BSDF;
float3x3 BSDFTangentBasis;
float BSDFAO;
};
FSubstrateGBufferBSDF SubstrateReadGBufferBSDF(in FScreenSpaceData ScreenSpaceData)
{
const FGBufferData GBuffer = ScreenSpaceData.GBuffer;
FSubstrateBSDF BSDF = (FSubstrateBSDF)0;
float3x3 BSDFTangentBasis = (float3x3)0;
float BSDFAO = 0.0f;
#if SUBSTRATE_COMPLEXPATH
if (GBuffer.Anisotropy != 0)
{
BSDFTangentBasis[0] = GBuffer.WorldTangent;
BSDFTangentBasis[1] = cross(GBuffer.WorldNormal, GBuffer.WorldTangent);
BSDFTangentBasis[2] = GBuffer.WorldNormal;
}
else
#endif
{
BSDFTangentBasis = GetTangentBasis(GBuffer.WorldNormal);
}
BSDFAO = ScreenSpaceData.AmbientOcclusion;
{
FSubstratePixelFootprint Footprint = SubstrateGetPixelFootprint(1.0f, 1.0f, GBuffer.Curvature);
const float3 Emissive = 0.0f;
const float SpecularProfileId = 0.0f;
const float GlintValue = 1.0f;
const float2 GlintUV = 0.0f;
const float2 GlintUVdx = 0.0f;
const float2 GlintUVdy = 0.0f;
float3 SSSMFP = 0.0f;
float SSSMFPScale = 1.0f;
float SSSPhaseAnisotropy = 0.0f;
float SecondRoughness = 0.0f;
float SecondRoughnessWeight = 0.0f;
float SecondRoughnessAsSimpleClearCoat = 0.0f;
float FuzzAmount = 0.0f;
float3 FuzzColor = 0.0f;
float FuzzRoughness = 0.0f;
uint SSSProfileID = SSS_PROFILE_ID_INVALID;
uint SSSType = SSS_TYPE_NONE;
float ThicknessCm = 1.0f;
bool bIsThinSurface = false;
// Directly use DiffuseColor and SpecularColor (instead of ComputeDiffuseAlbedo() / ComputeF0() with BaseColor, Metallic, Specular),
// as they contain Diffuse/Specular override which are used for view modes.
float3 DiffuseAlbedo = GBuffer.DiffuseColor;
float3 F0 = GBuffer.SpecularColor;
float3 F90 = 1.0f;
float ClearCoatUseSecondNormal = 0.0f;
float3 ClearCoatBottomNormal = GBuffer.WorldNormal;
bool bIsAtTheBottomOfTopology = true;
uint SharedLocalBasisIndex = 0;
uint SharedLocalBasisTypes = 0;
#if SUBSTRATE_COMPLEXPATH
if (GBuffer.ShadingModelID == SHADINGMODELID_HAIR)
{
const float Scatter = GBuffer.Metallic;
const float BackLit = GBuffer.CustomData.b;
BSDF = GetSubstrateHairBSDF(GBuffer.BaseColor, Scatter, GBuffer.Specular, GBuffer.Roughness, BackLit, Emissive, SharedLocalBasisIndex).InlinedBSDF;
}
else if (GBuffer.ShadingModelID == SHADINGMODELID_EYE)
{
SSSProfileID = ExtractSubsurfaceProfileInt(GBuffer);
const float IrisMask = 1.0f - GBuffer.CustomData.w;
float IrisDistance = 0.0;
float3 IrisNormal = GBuffer.WorldNormal;
float3 IrisPlaneNormal = GBuffer.WorldNormal;
#if IRIS_NORMAL
const float2 IrisNormalDelta = float2(GBuffer.CustomData.y, GBuffer.CustomData.z) * 2 - (256.0 / 255.0);
const float2 WorldNormalOct = UnitVectorToOctahedron(GBuffer.WorldNormal);
IrisNormal = OctahedronToUnitVector(WorldNormalOct + IrisNormalDelta);
IrisDistance = 1.0; // Set at 1 in order to let's the mask drive the interpolation. See SubstrateEvaluation.ush.
#else
IrisNormal = OctahedronToUnitVector(GBuffer.CustomData.yz * 2 - 1);
IrisPlaneNormal = IrisNormal;
IrisDistance = GBuffer.StoredMetallic;
#endif
BSDF = GetSubstrateEyeBSDF(DiffuseAlbedo, F0, GBuffer.Roughness, IrisMask, IrisDistance, IrisNormal, IrisPlaneNormal, SSSProfileID, Emissive, SharedLocalBasisIndex).InlinedBSDF;
}
else
#endif
{
#if SUBSTRATE_SINGLEPATH || SUBSTRATE_COMPLEXPATH
if (GBuffer.ShadingModelID == SHADINGMODELID_CLOTH)
{
FuzzColor = ExtractSubsurfaceColor(GBuffer);
FuzzAmount = GBuffer.CustomData.a;
FuzzRoughness = 0.5f; // Fuzz roughness is not stored into the gbuffer. Using GBuffer.Roughness it not ideal as low value, makes most of the fuzz contribution to vanish. Instead hardcode value.
}
else if (GBuffer.ShadingModelID == SHADINGMODELID_SUBSURFACE_PROFILE || GBuffer.ShadingModelID == SHADINGMODELID_PREINTEGRATED_SKIN)
{
SSSType = SSS_TYPE_DIFFUSION; // SSS_TYPE_DIFFUSION_PROFILE will be selected in InternalGetSubstrateSlabBSDF based on SSSProfileID and SSSMFPScale.
SSSMFP = 0;
SSSProfileID = ExtractSubsurfaceProfileInt(GBuffer);
SSSMFPScale = GBuffer.CustomData.a;
SSSPhaseAnisotropy = 0.93f;
}
else if (GBuffer.ShadingModelID == SHADINGMODELID_SUBSURFACE)
{
SSSType = SSS_TYPE_WRAP;
{
// See SubstrateGetBSDFSubSurfaceColor
float3 Extinction = TransmittanceToExtinction(ExtractSubsurfaceColor(GBuffer), SUBSTRATE_SIMPLEVOLUME_THICKNESS_CM * CENTIMETER_TO_METER);
SSSMFP = (1.0f / max(SUBSTRATE_EPSILON, Extinction));
}
SSSPhaseAnisotropy = 1.f - GBuffer.CustomData.a;
SSSMFPScale = 1.0f;
}
else if (GBuffer.ShadingModelID == SHADINGMODELID_TWOSIDED_FOLIAGE)
{
SSSType = SSS_TYPE_TWO_SIDED_WRAP;
{
// See SubstrateGetBSDFSubSurfaceColor
float3 Extinction = TransmittanceToExtinction(ExtractSubsurfaceColor(GBuffer), SUBSTRATE_SIMPLEVOLUME_THICKNESS_CM * CENTIMETER_TO_METER);
SSSMFP = (1.0f / max(SUBSTRATE_EPSILON, Extinction));
}
SSSPhaseAnisotropy = 1.f - GBuffer.CustomData.a;
SSSMFPScale = 1.0f;
}
else if (GBuffer.ShadingModelID == SHADINGMODELID_CLEAR_COAT)
{
#if SUBSTRATE_FASTPATH==0 && CLEAR_COAT_BOTTOM_NORMAL
ClearCoatUseSecondNormal = 1.0f;
const float2 oct1 = ((float2(GBuffer.CustomData.a, GBuffer.CustomData.z) * 4) - (512.0 / 255.0)) + UnitVectorToOctahedron(GBuffer.WorldNormal);
ClearCoatBottomNormal = OctahedronToUnitVector(oct1);
#endif
SecondRoughnessWeight = GBuffer.CustomData.x;
SecondRoughness = GBuffer.CustomData.y;
SecondRoughnessAsSimpleClearCoat = (SecondRoughnessWeight > 0.0f || any(GBuffer.WorldNormal != ClearCoatBottomNormal)) ? 1.0f : 0.0f;
}
#endif
BSDF = InternalGetSubstrateSlabBSDF(
Footprint,
GBuffer.WorldNormal,
DiffuseAlbedo, F0, F90,
GBuffer.Roughness, GBuffer.Anisotropy,
SSSProfileID, true /*bSupportDefaultSSSProfile*/, SSSMFP, SSSMFPScale, SSSPhaseAnisotropy, SSSType,
Emissive,
SecondRoughness, SecondRoughnessWeight, SecondRoughnessAsSimpleClearCoat,
ClearCoatUseSecondNormal, ClearCoatBottomNormal,
FuzzAmount, FuzzColor, FuzzRoughness,
GlintValue, GlintUV, GlintUVdx, GlintUVdy,
SpecularProfileId,
ThicknessCm,
bIsThinSurface,
bIsAtTheBottomOfTopology,
SharedLocalBasisIndex, SharedLocalBasisTypes,
true /*bSupportSSSDiffusion*/).InlinedBSDF;
SLAB_SSSMFP(BSDF) = SanitizeSSSMFP(SLAB_SSSMFP(BSDF));
}
#if SUBSTRATE_INLINE_SHADING && !RAYTRACINGSHADER
BSDF.Coverage = 1;
BSDF.Emissive = 0;
BSDF.ThicknessCm = (SSSType == SSS_TYPE_WRAP || SSSType == SSS_TYPE_TWO_SIDED_WRAP) ? SUBSTRATE_SIMPLEVOLUME_THICKNESS_CM : SUBSTRATE_LAYER_DEFAULT_THICKNESS_CM; // Identity rescaling in InternalGetSubstrateSlabBSDF
BSDF.TmpMFP = SSSMFP;
BSDF.TopLayerDataWeight = 1;
#endif
BSDF.OperatorIndex = 0;
BSDF.LuminanceWeightV = 1.0f;
BSDF.CoverageAboveAlongN = 0.0f;
BSDF.TransmittanceAboveAlongN = 1.0f;
BSDF.bIsBottom = true;
BSDF.bIsTop = true;
BSDF_SETISTOPLAYER(BSDF, 1);
}
FSubstrateGBufferBSDF Out;
Out.BSDF = BSDF;
Out.BSDFTangentBasis = BSDFTangentBasis;
Out.BSDFAO = BSDFAO;
return Out;
}
FSubstrateBSDF UnpackSubstrateBSDFIn(inout FSubstrateAddressing SubstrateAddressing)
{
FSubstrateGBufferBSDF GBufferBSDF = (FSubstrateGBufferBSDF)0;
#if SHADING_PATH_DEFERRED
#if FEATURE_LEVEL >= FEATURE_LEVEL_SM5
FScreenSpaceData ScreenSpaceData = GetScreenSpaceDataUint(SubstrateAddressing.PixelCoords);
#else
const float2 UV = (float2(SubstrateAddressing.PixelCoords) + 0.5f) * View.BufferSizeAndInvSize.zw;
FScreenSpaceData ScreenSpaceData = GetScreenSpaceData(UV);
#endif
GBufferBSDF = SubstrateReadGBufferBSDF(ScreenSpaceData);
#endif
return GBufferBSDF.BSDF;
}
#endif // SUBSTRATE_ENABLED