139 lines
5.1 KiB
HLSL
139 lines
5.1 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
/*=============================================================================
|
|
SubstratePublic.ush: Public facing API for external users of Substrate.
|
|
=============================================================================*/
|
|
|
|
#include "/Engine/Private/Substrate/Substrate.ush"
|
|
|
|
#if SUBSTRATE_ENABLED
|
|
|
|
#define SUBSTRATE_ALLOWS_GBUFFER_SAMPLING ((NEEDS_SCENE_TEXTURES && !SCENE_TEXTURES_DISABLED) && SUBSTRATE_MATERIALCONTAINER_IS_VIEWRESOURCE)
|
|
|
|
/** Public facing functions allowing external users access to some Substrate data. */
|
|
|
|
#ifndef SubstratePublicStruct
|
|
#error One must specify the SubstratePublicStruct uniform buffer to fetch data from when using SubstratePuclic.ush
|
|
#endif
|
|
|
|
struct FSubstrateGBuffer
|
|
{
|
|
bool bIsValid;
|
|
|
|
float3 DiffuseColor;
|
|
float3 SpecularColor;
|
|
float3 SubsurfaceColor;
|
|
float3 BaseColor;
|
|
float Specular;
|
|
float Metallic;
|
|
float3 WorldNormal;
|
|
float Opacity;
|
|
float Roughness;
|
|
float MaterialAO;
|
|
float3 ShadingModelColor;
|
|
float ShadingModelID;
|
|
float3 StoredBaseColor;
|
|
float3 StoredSpecular;
|
|
float3 WorldTangent;
|
|
float Anisotropy;
|
|
bool bIsFirstPerson;
|
|
};
|
|
|
|
FSubstrateGBuffer SubstratePublic_GetSubstrateGBufferFromFirstBSDF(uint2 PixelCoord)
|
|
{
|
|
FSubstrateGBuffer SGBuffer = (FSubstrateGBuffer)0;
|
|
SGBuffer.bIsValid = false;
|
|
SGBuffer.WorldNormal = float3(0.0, 0.0, 1.0);
|
|
|
|
#if SUBSTRATE_ALLOWS_GBUFFER_SAMPLING
|
|
FSubstrateAddressing SubstrateAddressing = GetSubstratePixelDataByteOffset(PixelCoord, uint2(View.BufferSizeAndInvSize.xy), SubstratePublicStruct.MaxBytesPerPixel);
|
|
FSubstratePixelHeader SubstratePixelHeader = UnpackSubstrateHeaderIn(SubstratePublicStruct.MaterialTextureArray, SubstrateAddressing, SubstratePublicStruct.TopLayerTexture);
|
|
|
|
BRANCH
|
|
if (SubstratePixelHeader.ClosureCount > 0)
|
|
{
|
|
const FSubstrateSubsurfaceHeader SSSHeader = SubstrateLoadSubsurfaceHeader(SubstratePublicStruct.MaterialTextureArray, SubstratePublicStruct.FirstSliceStoringSubstrateSSSData, SubstrateAddressing.PixelCoords);
|
|
|
|
const bool bSkipSSSMaterialOverride = true; // We do not want the material data to be affected by any override.
|
|
FSubstrateBSDF BSDF = UnpackSubstrateBSDFIn(SubstratePublicStruct.MaterialTextureArray, SubstrateAddressing, SubstratePixelHeader, bSkipSSSMaterialOverride);
|
|
|
|
SGBuffer.bIsValid = true;
|
|
SGBuffer.DiffuseColor = SubstrateGetBSDFDiffuseColor(BSDF);
|
|
SGBuffer.SpecularColor = SubstrateGetBSDFSpecularF0(BSDF);
|
|
SGBuffer.SubsurfaceColor = SubstrateGetBSDFSubSurfaceColor(BSDF);
|
|
SGBuffer.BaseColor = SubstrateGetBSDFBaseColor(BSDF);
|
|
SGBuffer.Specular = SubstrateGetBSDFSpecular(BSDF);
|
|
SGBuffer.Metallic = SubstrateGetBSDFMetallic(BSDF);
|
|
SGBuffer.WorldNormal = SubstrateGetWorldNormal(SubstratePixelHeader, BSDF, SubstrateAddressing);
|
|
SGBuffer.Roughness = SubstrateGetBSDFRoughness(BSDF);
|
|
SGBuffer.MaterialAO = SubstrateGetAO(SubstratePixelHeader);
|
|
SGBuffer.ShadingModelID = SubstrateGetLegacyShadingModels(BSDF);
|
|
SGBuffer.ShadingModelColor = GetShadingModelColor(SGBuffer.ShadingModelID);
|
|
SGBuffer.StoredBaseColor = SubstrateGetBSDFBaseColor(BSDF);
|
|
SGBuffer.StoredSpecular = SubstrateGetBSDFSpecular(BSDF).rrr;
|
|
SGBuffer.WorldTangent = SubstrateGetWorldTangent(SubstratePixelHeader, BSDF, SubstrateAddressing);
|
|
SGBuffer.Anisotropy = SubstrateGetBSDFAnisotropy(BSDF);
|
|
SGBuffer.bIsFirstPerson = SubstratePixelHeader.IsFirstPerson();
|
|
|
|
SGBuffer.Opacity = 0.0f;
|
|
if (SubstrateSubSurfaceHeaderGetSSSType(SSSHeader) != SSS_TYPE_NONE)
|
|
{
|
|
SGBuffer.Opacity = SubstrateSubSurfaceHeaderGetOpacity(SSSHeader);
|
|
}
|
|
else if (BSDF_GETTYPE(BSDF) == SUBSTRATE_BSDF_TYPE_SLAB)
|
|
{
|
|
if (BSDF_GETHASFUZZ(BSDF))
|
|
{
|
|
SGBuffer.Opacity = SLAB_FUZZ_AMOUNT(BSDF); // Cloth
|
|
}
|
|
else if (BSDF_GETHASHAZINESS(BSDF))
|
|
{
|
|
const FHaziness Haziness = UnpackHaziness(SLAB_HAZINESS(BSDF));
|
|
const bool bHazeAsSimpleClearCoat = Haziness.bSimpleClearCoat;
|
|
if (bHazeAsSimpleClearCoat)
|
|
{
|
|
SGBuffer.Opacity = Haziness.Weight; // ClearCoat
|
|
}
|
|
}
|
|
}
|
|
else if (BSDF_GETTYPE(BSDF) == SUBSTRATE_BSDF_TYPE_EYE)
|
|
{
|
|
SGBuffer.Opacity = 1 - EYE_IRISMASK(BSDF); // IrisMask
|
|
}
|
|
else if (BSDF_GETTYPE(BSDF) == SUBSTRATE_BSDF_TYPE_HAIR)
|
|
{
|
|
SGBuffer.Opacity = HAIR_BACKLIT(BSDF); // BackLit
|
|
}
|
|
}
|
|
else if (SubstratePixelHeader.State == 0) // Only Unlit and non written pixels have a state of 0. Those pixels should show up as unlit to respect the legacy behavior.
|
|
{
|
|
SGBuffer.bIsValid = true;
|
|
SGBuffer.ShadingModelID = SHADINGMODELID_UNLIT;
|
|
SGBuffer.ShadingModelColor = GetShadingModelColor(SGBuffer.ShadingModelID);
|
|
}
|
|
#endif
|
|
|
|
return SGBuffer;
|
|
}
|
|
|
|
// Optimised data fetch from the TopLayer texture
|
|
float3 SubstratePublic_GetWorldNormal(uint2 PixelCoord)
|
|
{
|
|
#if SUBSTRATE_ALLOWS_GBUFFER_SAMPLING
|
|
return SubstrateUnpackTopLayerData(SubstratePublicStruct.TopLayerTexture.Load(uint3(PixelCoord, 0))).WorldNormal;
|
|
#else
|
|
return float3(0, 0, 1);
|
|
#endif
|
|
}
|
|
float SubstratePublic_GetRoughness(uint2 PixelCoord)
|
|
{
|
|
#if SUBSTRATE_ALLOWS_GBUFFER_SAMPLING
|
|
return SubstrateUnpackTopLayerData(SubstratePublicStruct.TopLayerTexture.Load(uint3(PixelCoord, 0))).Roughness;
|
|
#else
|
|
return 0.0;
|
|
#endif
|
|
}
|
|
|
|
#endif |