Files
UnrealEngine/Engine/Shaders/Private/Substrate/SubstrateMaterialSampling.ush
2025-05-18 13:04:45 +08:00

115 lines
3.3 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "/Engine/Private/Common.ush"
#include "/Engine/Private/Substrate/Substrate.ush"
#if SUBSTRATE_ENABLED
struct FSubstrateSampledMaterial
{
float3 WorldNormal;
float3 WorldTangent;
float Roughness;
float3 DiffuseAlbedo;
float3 SpecularAlbedo;
float Anisotropy;
float PDF;
uint ClosureIndex;
uint IrradianceAO;
bool bIsSimple;
bool bIsSingle;
bool bIsValid;
bool bIsHair;
bool bIsSLW;
bool bAllowSpatialFilter;
bool bNeedsSeparateSubsurfaceLightAccumulation;
bool bIsFirstPerson;
bool bHasSecondSpecularLobe;
bool bHasBackScattering;
};
FSubstrateSampledMaterial UnpackSampledMaterial(uint4 In)
{
const float4 DataY = UnpackRGBA8(In.y);
const float4 DataZ = UnpackRGBA8(In.z);
FSubstrateSampledMaterial Out;
// Can't use last 8 bit as we store 24bit normal or 32bit normal/tangent
Out.WorldNormal = SubstrateUnpackNormal24(In.x);
Out.WorldTangent = 0;
Out.DiffuseAlbedo = DataY.xyz;
Out.Roughness = DataY.w;
Out.SpecularAlbedo = DataZ.xyz;
const uint Type = BitFieldExtractU32(In.z, 3, 24);
Out.bIsFirstPerson = BitFieldExtractU32(In.z, 1, 27);
Out.bHasSecondSpecularLobe= BitFieldExtractU32(In.z, 1, 28);
Out.bAllowSpatialFilter= BitFieldExtractU32(In.z, 1, 29);
Out.bHasBackScattering = BitFieldExtractU32(In.z, 1, 30);
Out.bNeedsSeparateSubsurfaceLightAccumulation = BitFieldExtractU32(In.z, 1, 31);
Out.bIsValid = Type > 0;
Out.bIsSimple = Type == 1;
Out.bIsSingle = Type == 2;
Out.bIsHair = Type == 4;
Out.bIsSLW = Type == 5;
Out.PDF = Unpack10F(In.w);
Out.ClosureIndex = BitFieldExtractU32(In.w, 3, 10);
Out.IrradianceAO = BitFieldExtractU32(In.w, 8, 16);
uint PackedAniso8bits = BitFieldExtractU32(In.w, 8, 24);
Out.Anisotropy = UnpackR8(PackedAniso8bits & 0xFE);
Out.Anisotropy *= (PackedAniso8bits & 1u) ? 1.f : -1.f;
if (Out.Anisotropy != 0)
{
SubstrateUnpackNormalAndTangent(Out.WorldNormal, Out.WorldTangent, In.x);
}
return Out;
}
uint4 PackSampledMaterial(FSubstrateSampledMaterial In)
{
uint Type = 0;
if (In.bIsSimple) { Type = 1; }
if (In.bIsSingle) { Type = 2; }
if (In.bIsHair) { Type = 4; }
if (In.bIsSLW) { Type = 5; }
if (In.bIsValid && Type == 0) { Type = 3; /*bIsComplex*/ }
uint DataX;
if (In.Anisotropy == 0)
{
DataX = SubstratePackNormal24(In.WorldNormal);
}
else
{
DataX = SubstratePackNormalAndTangent(In.WorldNormal, In.WorldTangent);
}
const uint PackedAniso8bits = (PackR8(abs(In.Anisotropy)) & 0xFE) | (In.Anisotropy > 0 ? 1u : 0u);
const uint DataZ =
((Type & 0x3) << 24) |
((In.bIsFirstPerson ? 0x1 : 0x0) << 27) |
((In.bHasSecondSpecularLobe ? 0x1 : 0x0) << 28) |
((In.bAllowSpatialFilter ? 0x1 : 0x0) << 29) |
((In.bHasBackScattering ? 0x1 : 0x0) << 30) |
((In.bNeedsSeparateSubsurfaceLightAccumulation ? 0x1 : 0x0) << 31);
const uint DataW =
Pack10F(In.PDF) |
((In.ClosureIndex & 0x3u) << 10) |
((In.IrradianceAO & 0xFF) << 16) |
(PackedAniso8bits << 24);
uint4 Out;
Out.x = DataX;
Out.y = PackRGBA8(float4(In.DiffuseAlbedo, In.Roughness));
Out.z = PackRGBA8(float4(In.SpecularAlbedo, 0)) | DataZ;
Out.w = DataW;
return Out;
}
#endif