Files
UnrealEngine/Engine/Shaders/Shared/SubstrateVisualizeDefinitions.h
2025-05-18 13:04:45 +08:00

676 lines
23 KiB
C

// Copyright Epic Games, Inc. All Rights Reserved.
/*================================================================================================
SubstrateVisualise.h: used in ray tracing shaders and C++ code to define common constants
!!! Changing this file requires recompilation of the engine !!!
=================================================================================================*/
#pragma once
#if defined(__cplusplus) || SUBSTRATE_ENABLED
#ifndef __cplusplus
// Change this to force recompilation of all Substrate dependent shaders (for instance https://guidgenerator.com/online-guid-generator.aspx)
#pragma message("UESHADERMETADATA_VERSION E9DF359B-BC55-46BC-B4DF-A5E94467C029")
#include "/Engine/Shared/SubstrateDefinitions.h"
#else
#include "SubstrateDefinitions.h"
#endif
struct FSubsterateDebugClosure
{
int Type;
int bHasWeightL;// = BSDF_GETHASTRANSABOVE(BSDF);
int bHasGreyWeightV;// = BSDF_GETHASGREYWEIGHT_V(BSDF);
int Address; // SubstrateAddressing.CurrentIndex
int NormalID; //BSDF_GETSHAREDLOCALBASISID(BSDF)
int BasisType; // SubstrateGetSharedLocalBasisType(HEADER_GETSHAREDLOCALBASESTYPE(Header.PackedHeader), BSDF_GETSHAREDLOCALBASISID(BSDF));
//////////
// Slabs
int bIsTopLayer; // BSDF_GETISTOPLAYER(BSDF)
int SSSType; // BSDF_GETSSSTYPE(BSDF) != SSS_TYPE_NONE
int bIsThin; // BSDF_GETISTHIN(BSDF)
float LuminanceWeightR, LuminanceWeightG, LuminanceWeightB; // bHasGreyWeightV BSDF.LuminanceWeightV.x or rgb
float TransmittanceAboveAlongNR, TransmittanceAboveAlongNG, TransmittanceAboveAlongNB; // bHasGreyTopTrans BSDF.TransmittanceAboveAlongN.x or rgb
float CoverageAboveAlongN;
float DiffuseR, DiffuseG, DiffuseB;
float F0R, F0G, F0B;
float Roughness;
int bHasF90;
float F90R, F90G, F90B;
int bHasAnisotropy;
float Anisotropy;
int bHasHaziness;
float HazeRoughness;
float HazeWeight;
int HazeSimpleClearCoatMode;
float SSSOpacity;
float SSSMFPR, SSSMFPG, SSSMFPB;
float SSSRescaledMFPR, SSSRescaledMFPG, SSSRescaledMFPB;
float SSSPhase;
float SSSThickness;
float SSSProfileRadius;
int SSSPRofileID;
float FuzzAmount;
float FuzzColorR, FuzzColorG, FuzzColorB;
float FuzzRoughness;
float GlintValue;
float GlintUVDDXx;
float GlintUVDDXy;
float GlintUVDDYx;
float GlintUVDDYy;
int SpecProfileID;
int SpecProfileParameterization;
};
struct FSubstratePixelDebugData
{
int ClosureCount;
int MaterialMode;
int bIsComplexSpecialMaterial;
int OptimisedLegacyMode;
float MaterialAO;
float IndirectIrradiance;
float TopLayerRoughness;
int HasPrecShadowMask;
int HasZeroPrecShadowMask;
int DoesCastContactShadow;
int HasDynamicIndirectShadowCasterRepresentation;
int HasSubsurface;
int LocalBasesCount;
FSubsterateDebugClosure Closures[SUBSTRATE_MAX_CLOSURE_COUNT];
int MemoryDisplayMode;
int MemorySlotA;
int MemorySlotB;
int MemorySlotC;
int MemorySSSData;
int MemoryTotal;
int GPUFrameNumber;
};
#ifndef __cplusplus
uint SubstrateDebugDataSizeInUints;
RWStructuredBuffer<int> SubstrateDebugDataUAV;
struct FSubstrateDebugDataSerializer
{
int WriteIndex;
void Serialize(int Data)
{
if (WriteIndex < SubstrateDebugDataSizeInUints)
{
SubstrateDebugDataUAV[WriteIndex++] = Data;
}
}
void Serialize(float Data)
{
if (WriteIndex < SubstrateDebugDataSizeInUints)
{
SubstrateDebugDataUAV[WriteIndex++] = asuint(Data);
}
}
};
#else
struct FSubstrateDebugDataSerializer
{
int ReadIndex = 0;
int* SubstratePixelDebugData = nullptr;
void Serialize(int& Data)
{
Data = SubstratePixelDebugData[ReadIndex++];
}
void Serialize(float& Data)
{
Data = ((float*)SubstratePixelDebugData)[ReadIndex++];
}
};
#endif
#ifndef __cplusplus
void SerializeSubstratePixelDebugData(in FSubstrateDebugDataSerializer S, in FSubstratePixelDebugData D)
#else
void SerializeSubstratePixelDebugData(FSubstrateDebugDataSerializer& S, FSubstratePixelDebugData& D)
#endif
{
S.Serialize(D.ClosureCount);
#ifdef __cplusplus
// Safe guard to avoid crash in case of readback problem.
D.ClosureCount = FMath::Min(D.ClosureCount, int(SUBSTRATE_MAX_CLOSURE_COUNT));
#endif
S.Serialize(D.MaterialMode);
S.Serialize(D.bIsComplexSpecialMaterial);
S.Serialize(D.OptimisedLegacyMode);
S.Serialize(D.MaterialAO);
S.Serialize(D.IndirectIrradiance);
S.Serialize(D.TopLayerRoughness);
S.Serialize(D.HasPrecShadowMask);
S.Serialize(D.HasZeroPrecShadowMask);
S.Serialize(D.DoesCastContactShadow);
S.Serialize(D.HasDynamicIndirectShadowCasterRepresentation);
S.Serialize(D.HasSubsurface);
S.Serialize(D.LocalBasesCount);
for (int i = 0; i < D.ClosureCount; ++i)
{
S.Serialize(D.Closures[i].Type);
S.Serialize(D.Closures[i].bHasWeightL);
S.Serialize(D.Closures[i].bHasGreyWeightV);
S.Serialize(D.Closures[i].Address);
S.Serialize(D.Closures[i].NormalID);
S.Serialize(D.Closures[i].BasisType);
S.Serialize(D.Closures[i].bIsTopLayer);
S.Serialize(D.Closures[i].SSSType);
S.Serialize(D.Closures[i].bIsThin);
S.Serialize(D.Closures[i].LuminanceWeightR);
S.Serialize(D.Closures[i].LuminanceWeightG);
S.Serialize(D.Closures[i].LuminanceWeightB);
S.Serialize(D.Closures[i].TransmittanceAboveAlongNR);
S.Serialize(D.Closures[i].TransmittanceAboveAlongNG);
S.Serialize(D.Closures[i].TransmittanceAboveAlongNB);
S.Serialize(D.Closures[i].CoverageAboveAlongN);
S.Serialize(D.Closures[i].DiffuseR);
S.Serialize(D.Closures[i].DiffuseG);
S.Serialize(D.Closures[i].DiffuseB);
S.Serialize(D.Closures[i].F0R);
S.Serialize(D.Closures[i].F0G);
S.Serialize(D.Closures[i].F0B);
S.Serialize(D.Closures[i].Roughness);
S.Serialize(D.Closures[i].bHasF90);
S.Serialize(D.Closures[i].F90R);
S.Serialize(D.Closures[i].F90G);
S.Serialize(D.Closures[i].F90B);
S.Serialize(D.Closures[i].bHasAnisotropy);
S.Serialize(D.Closures[i].Anisotropy);
S.Serialize(D.Closures[i].bHasHaziness);
S.Serialize(D.Closures[i].HazeRoughness);
S.Serialize(D.Closures[i].HazeWeight);
S.Serialize(D.Closures[i].HazeSimpleClearCoatMode);
S.Serialize(D.Closures[i].SSSOpacity);
S.Serialize(D.Closures[i].SSSMFPR);
S.Serialize(D.Closures[i].SSSMFPG);
S.Serialize(D.Closures[i].SSSMFPB);
S.Serialize(D.Closures[i].SSSRescaledMFPR);
S.Serialize(D.Closures[i].SSSRescaledMFPG);
S.Serialize(D.Closures[i].SSSRescaledMFPB);
S.Serialize(D.Closures[i].SSSPhase);
S.Serialize(D.Closures[i].SSSThickness);
S.Serialize(D.Closures[i].SSSProfileRadius);
S.Serialize(D.Closures[i].SSSPRofileID);
S.Serialize(D.Closures[i].FuzzAmount);
S.Serialize(D.Closures[i].FuzzColorR);
S.Serialize(D.Closures[i].FuzzColorG);
S.Serialize(D.Closures[i].FuzzColorB);
S.Serialize(D.Closures[i].FuzzRoughness);
S.Serialize(D.Closures[i].GlintValue);
S.Serialize(D.Closures[i].GlintUVDDXx);
S.Serialize(D.Closures[i].GlintUVDDXy);
S.Serialize(D.Closures[i].GlintUVDDYx);
S.Serialize(D.Closures[i].GlintUVDDYy);
S.Serialize(D.Closures[i].SpecProfileID);
S.Serialize(D.Closures[i].SpecProfileParameterization);
}
S.Serialize(D.MemoryDisplayMode);
S.Serialize(D.MemorySlotA);
S.Serialize(D.MemorySlotB);
S.Serialize(D.MemorySlotC);
S.Serialize(D.MemorySSSData);
S.Serialize(D.MemoryTotal);
S.Serialize(D.GPUFrameNumber);
}
#ifndef __cplusplus
#if SUBSTRATE_MATERIALCONTAINER_IS_VIEWRESOURCE
FSubstratePixelDebugData ConvertToSerializableSubstratePixelDebugData(uint2 InCoord, uint GPUFrameNumber)
#else
FSubstratePixelDebugData ConvertToSerializableSubstratePixelDebugData(uint2 InCoord, FSubstrateRaytracingPayload Payload, uint GPUFrameNumber)
#endif
{
FSubstratePixelDebugData Data = (FSubstratePixelDebugData)0;
FSubstrateAddressing SubstrateAddressing = GetSubstratePixelDataByteOffset(InCoord, uint2(View.BufferSizeAndInvSize.xy), Substrate.MaxBytesPerPixel);
const uint FootPrint_Start = SubstrateAddressing.ReadBytes;
#if SUBSTRATE_MATERIALCONTAINER_IS_VIEWRESOURCE
FSubstratePixelHeader Header = UnpackSubstrateHeaderIn(Substrate.MaterialTextureArray, SubstrateAddressing, Substrate.TopLayerTexture);
#else
FSubstratePixelHeader Header = UnpackSubstrateHeaderIn(Payload, SubstrateAddressing, Payload);
#endif
const uint FootPrint_PostHeader = SubstrateAddressing.ReadBytes;
#if SUBSTRATE_MATERIALCONTAINER_IS_VIEWRESOURCE
FSubstrateSubsurfaceHeader SSSHeader = SubstrateLoadSubsurfaceHeader(Substrate.MaterialTextureArray, Substrate.FirstSliceStoringSubstrateSSSData, SubstrateAddressing.PixelCoords);
FSubstrateTopLayerData TopLayerData = SubstrateUnpackTopLayerData(Substrate.TopLayerTexture.Load(uint3(InCoord, 0)));
#else
FSubstrateSubsurfaceHeader SSSHeader = (FSubstrateSubsurfaceHeader)0;
FSubstrateTopLayerData TopLayerData = SubstrateUnpackTopLayerData(Payload.PackedTopLayerData);
#endif
Data.TopLayerRoughness = TopLayerData.Roughness;
const bool bSubstrateMaterial = Header.ClosureCount > 0;
const bool bIsSimpleMaterial = Header.IsSimpleMaterial() || Header.ClosureCount == 0;
const bool bIsSingleMaterial = !Header.IsSimpleMaterial() && Header.IsSingleMaterial();
FSubstrateIrradianceAndOcclusion IrradianceAndOcclusion = SubstrateGetIrradianceAndAO(Header);
Data.ClosureCount = Header.ClosureCount;
Data.MaterialMode = Header.GetMaterialMode();
Data.OptimisedLegacyMode = HEADER_MATERIALMODE_NONE;
if (bIsSingleMaterial)
{
#if SUBSTRATE_DEFERRED_SHADING
Data.OptimisedLegacyMode = (Header.PackedHeader >> (HEADER_SINGLEENCODING_BIT_COUNT)) & HEADER_SINGLE_OPTLEGACYMODE_BIT_MASK;
#endif
}
Data.bIsComplexSpecialMaterial = Header.IsComplexSpecialMaterial();
Data.MaterialAO = IrradianceAndOcclusion.MaterialAO;
Data.IndirectIrradiance = IrradianceAndOcclusion.IndirectIrradiance;
Data.HasPrecShadowMask = Header.HasPrecShadowMask() ? 1 : 0;
Data.HasZeroPrecShadowMask = Header.HasZeroPrecShadowMask() ? 1 : 0;
Data.DoesCastContactShadow = Header.DoesCastContactShadow() ? 1 : 0;
Data.HasDynamicIndirectShadowCasterRepresentation = Header.HasDynamicIndirectShadowCasterRepresentation() ? 1 : 0;
Data.HasSubsurface = Header.HasSubsurface() ? 1 : 0;
#if SUBSTRATE_DEFERRED_SHADING
Data.LocalBasesCount = Header.GetLocalBasesCount();
#endif
LOOP
for(uint i = 0; i < Header.ClosureCount; ++i)
{
// Unpack BSDF data
#if SUBSTRATE_MATERIALCONTAINER_IS_VIEWRESOURCE
FSubstrateBSDF BSDF = UnpackSubstrateBSDF(Substrate.MaterialTextureArray, SubstrateAddressing, Header);
#else
FSubstrateBSDF BSDF = UnpackSubstrateBSDFIn(Payload, SubstrateAddressing, Header);
#endif
Data.Closures[i].Address = SubstrateAddressing.CurrentIndex;
Data.Closures[i].Type = BSDF_GETTYPE(BSDF);
#if SUBSTRATE_DEFERRED_SHADING
Data.Closures[i].NormalID = BSDF_GETSHAREDLOCALBASISID(BSDF);
Data.Closures[i].BasisType = SubstrateGetSharedLocalBasisType(HEADER_GETSHAREDLOCALBASESTYPE(Header.PackedHeader), BSDF_GETSHAREDLOCALBASISID(BSDF));
#endif
Data.Closures[i].bIsTopLayer = BSDF_GETISTOPLAYER(BSDF);
Data.Closures[i].bHasWeightL = BSDF_GETHASTRANSABOVE(BSDF);
Data.Closures[i].bHasGreyWeightV = BSDF_GETHASGREYWEIGHT_V(BSDF);
Data.Closures[i].LuminanceWeightR = BSDF.LuminanceWeightV.r;
Data.Closures[i].LuminanceWeightG = BSDF.LuminanceWeightV.g;
Data.Closures[i].LuminanceWeightB = BSDF.LuminanceWeightV.b;
Data.Closures[i].TransmittanceAboveAlongNR = BSDF.TransmittanceAboveAlongN.r;
Data.Closures[i].TransmittanceAboveAlongNG = BSDF.TransmittanceAboveAlongN.g;
Data.Closures[i].TransmittanceAboveAlongNB = BSDF.TransmittanceAboveAlongN.b;
Data.Closures[i].CoverageAboveAlongN = BSDF.CoverageAboveAlongN;
Data.Closures[i].SSSType = BSDF_GETSSSTYPE(BSDF);
Data.Closures[i].bIsThin = BSDF_GETISTHIN(BSDF);
switch (Data.Closures[i].Type)
{
case SUBSTRATE_BSDF_TYPE_SLAB:
{
Data.Closures[i].DiffuseR = SLAB_DIFFUSEALBEDO(BSDF).r;
Data.Closures[i].DiffuseG = SLAB_DIFFUSEALBEDO(BSDF).g;
Data.Closures[i].DiffuseB = SLAB_DIFFUSEALBEDO(BSDF).b;
Data.Closures[i].F0R = SLAB_F0(BSDF).r;
Data.Closures[i].F0G = SLAB_F0(BSDF).g;
Data.Closures[i].F0B = SLAB_F0(BSDF).b;
Data.Closures[i].Roughness = SLAB_ROUGHNESS(BSDF);
Data.Closures[i].bHasF90 = BSDF_GETHASF90(BSDF);
if (Data.Closures[i].bHasF90)
{
Data.Closures[i].F90R = SLAB_F90(BSDF).r;
Data.Closures[i].F90G = SLAB_F90(BSDF).g;
Data.Closures[i].F90B = SLAB_F90(BSDF).b;
}
else
{
Data.Closures[i].F90R = 1.0f;
Data.Closures[i].F90G = 1.0f;
Data.Closures[i].F90B = 1.0f;
}
Data.Closures[i].bHasAnisotropy = BSDF_GETHASANISOTROPY(BSDF);
if (Data.Closures[i].bHasAnisotropy)
{
Data.Closures[i].Anisotropy = SLAB_ANISOTROPY(BSDF);
}
Data.Closures[i].bHasHaziness = BSDF_GETHASHAZINESS(BSDF);
if (Data.Closures[i].bHasHaziness)
{
FHaziness Haziness = UnpackHaziness(SLAB_HAZINESS(BSDF));
Data.Closures[i].HazeRoughness = Haziness.Roughness;
Data.Closures[i].HazeWeight = Haziness.Weight;
Data.Closures[i].HazeSimpleClearCoatMode = Haziness.bSimpleClearCoat ? 1u : 0u;
}
if (Data.Closures[i].SSSType != SSS_TYPE_NONE || Data.Closures[i].bIsThin)
{
if (Data.Closures[i].SSSType == SSS_TYPE_WRAP || Data.Closures[i].SSSType == SSS_TYPE_TWO_SIDED_WRAP)
{
#if SUBSTRATE_MATERIALCONTAINER_IS_VIEWRESOURCE
Data.Closures[i].SSSOpacity = SubstrateSubSurfaceHeaderGetWrapOpacity(SSSHeader);
#endif
Data.Closures[i].SSSMFPR = SLAB_SSSMFP(BSDF).r;
Data.Closures[i].SSSMFPG = SLAB_SSSMFP(BSDF).g;
Data.Closures[i].SSSMFPB = SLAB_SSSMFP(BSDF).b;
Data.Closures[i].SSSPhase = SLAB_SSSPHASEANISOTROPY(BSDF);
Data.Closures[i].SSSThickness = BSDF_GETTHICKNESSCM(BSDF);
}
else if (Data.Closures[i].SSSType == SSS_TYPE_SIMPLEVOLUME)
{
#if SUBSTRATE_MATERIALCONTAINER_IS_VIEWRESOURCE
Data.Closures[i].SSSOpacity = SubstrateSubSurfaceHeaderGetWrapOpacity(SSSHeader);
#endif
Data.Closures[i].SSSMFPR = SLAB_SSSMFP(BSDF).r;
Data.Closures[i].SSSMFPG = SLAB_SSSMFP(BSDF).g;
Data.Closures[i].SSSMFPB = SLAB_SSSMFP(BSDF).b;
Data.Closures[i].SSSPhase = SLAB_SSSPHASEANISOTROPY(BSDF);
Data.Closures[i].SSSThickness = BSDF_GETTHICKNESSCM(BSDF);
}
else if (Data.Closures[i].SSSType == SSS_TYPE_DIFFUSION_PROFILE)
{
#if SUBSTRATE_MATERIALCONTAINER_IS_VIEWRESOURCE
const uint ProfileId = SubstrateSubSurfaceHeaderGetProfileId(SSSHeader);
const float RadiusScale = SubstrateSubSurfaceHeaderGetProfileRadiusScale(SSSHeader);
const float3 DiffuseMFP = GetSubsurfaceProfileMFPInCm(ProfileId).xyz * RadiusScale;
const float Phase = GetTransmissionProfileParams(ProfileId).ScatteringDistribution;
Data.Closures[i].SSSPRofileID = ProfileId;
Data.Closures[i].SSSProfileRadius = RadiusScale;
Data.Closures[i].SSSMFPR = DiffuseMFP.r;
Data.Closures[i].SSSMFPG = DiffuseMFP.g;
Data.Closures[i].SSSMFPB = DiffuseMFP.b;
Data.Closures[i].SSSPhase = Phase;
#endif
if (Data.Closures[i].bIsThin)
{
Data.Closures[i].SSSThickness = SLAB_SSSPROFILETHICKNESSCM(BSDF);
}
}
else if (Data.Closures[i].SSSType == SSS_TYPE_DIFFUSION)
{
#if SUBSTRATE_MATERIALCONTAINER_IS_VIEWRESOURCE
const float3 OriginalMFP = SubstrateSubSurfaceHeaderGetMFP(SSSHeader);
const float3 RescaledMFP = SLAB_SSSMFP(BSDF);
Data.Closures[i].SSSMFPR = OriginalMFP.r;
Data.Closures[i].SSSMFPG = OriginalMFP.g;
Data.Closures[i].SSSMFPB = OriginalMFP.b;
if (Data.Closures[i].bIsThin)
{
Data.Closures[i].SSSRescaledMFPR = RescaledMFP.r;
Data.Closures[i].SSSRescaledMFPG = RescaledMFP.g;
Data.Closures[i].SSSRescaledMFPB = RescaledMFP.b;
Data.Closures[i].SSSThickness = BSDF_GETTHICKNESSCM(BSDF);
}
#endif
Data.Closures[i].SSSPhase = SLAB_SSSPHASEANISOTROPY(BSDF);
}
}
if (BSDF_GETHASFUZZ(BSDF))
{
Data.Closures[i].FuzzAmount = SLAB_FUZZ_AMOUNT(BSDF);
Data.Closures[i].FuzzColorR = SLAB_FUZZ_COLOR(BSDF).r;
Data.Closures[i].FuzzColorG = SLAB_FUZZ_COLOR(BSDF).g;
Data.Closures[i].FuzzColorB = SLAB_FUZZ_COLOR(BSDF).b;
Data.Closures[i].FuzzRoughness = SLAB_FUZZ_ROUGHNESS(BSDF);
}
if (BSDF_GETHASGLINT(BSDF))
{
Data.Closures[i].GlintValue = SLAB_GLINT_VALUE(BSDF);
Data.Closures[i].GlintUVDDXx = SLAB_GLINT_UVDDX(BSDF).x;
Data.Closures[i].GlintUVDDXy = SLAB_GLINT_UVDDX(BSDF).y;
Data.Closures[i].GlintUVDDYx = SLAB_GLINT_UVDDY(BSDF).x;
Data.Closures[i].GlintUVDDYy = SLAB_GLINT_UVDDY(BSDF).y;
}
else
{
Data.Closures[i].GlintValue = 1.0; // No glint
}
Data.Closures[i].SpecProfileID = -1.0f;
if (BSDF_GETHASSPECPROFILE(BSDF))
{
Data.Closures[i].SpecProfileID = GetSpecularProfileId(SLAB_SPECPROFILEID(BSDF));
Data.Closures[i].SpecProfileParameterization = GetSpecularProfileParameterization(SLAB_SPECPROFILEID(BSDF));
}
}
break;
case SUBSTRATE_BSDF_TYPE_HAIR:
{
// Reusing the slab data to avoid using too many registers in case the compiler has trouble optimising
Data.Closures[i].DiffuseR = HAIR_BASECOLOR(BSDF).r;
Data.Closures[i].DiffuseG = HAIR_BASECOLOR(BSDF).g;
Data.Closures[i].DiffuseB = HAIR_BASECOLOR(BSDF).b;
Data.Closures[i].F0R = HAIR_SPECULAR(BSDF);
Data.Closures[i].Roughness = HAIR_ROUGHNESS(BSDF);
Data.Closures[i].F90R = HAIR_SCATTER(BSDF);
Data.Closures[i].F90G = HAIR_BACKLIT(BSDF);
Data.Closures[i].F90B = HAIR_COMPLEXTRANSMITTANCE(BSDF);
}
break;
case SUBSTRATE_BSDF_TYPE_EYE:
{
// Reusing the slab data to avoid using too many registers in case the compiler has trouble optimising
Data.Closures[i].DiffuseR = EYE_DIFFUSEALBEDO(BSDF).r;
Data.Closures[i].DiffuseG = EYE_DIFFUSEALBEDO(BSDF).g;
Data.Closures[i].DiffuseB = EYE_DIFFUSEALBEDO(BSDF).b;
Data.Closures[i].F0R = EYE_F0(BSDF);
Data.Closures[i].Roughness = EYE_ROUGHNESS(BSDF);
Data.Closures[i].F90R = EYE_IRISMASK(BSDF);
Data.Closures[i].F90G = EYE_IRISDISTANCE(BSDF);
Data.Closures[i].SSSMFPR = EYE_IRISNORMAL(BSDF).x;
Data.Closures[i].SSSMFPG = EYE_IRISNORMAL(BSDF).y;
Data.Closures[i].SSSMFPB = EYE_IRISNORMAL(BSDF).z;
Data.Closures[i].SSSRescaledMFPR = EYE_IRISPLANENORMAL(BSDF).x;
Data.Closures[i].SSSRescaledMFPG = EYE_IRISPLANENORMAL(BSDF).y;
Data.Closures[i].SSSRescaledMFPB = EYE_IRISPLANENORMAL(BSDF).z;
#if SUBSTRATE_MATERIALCONTAINER_IS_VIEWRESOURCE
const bool bHasSSS = Header.HasSubsurface();
const bool bIsValid = SubstrateSubSurfaceHeaderGetIsValid(SSSHeader);
const bool bIsProfile = SubstrateSubSurfaceHeaderGetIsProfile(SSSHeader);
Data.Closures[i].SSSPRofileID = -1;
if (bHasSSS && bIsValid && bIsProfile)
{
Data.Closures[i].SSSPRofileID = SubstrateSubSurfaceHeaderGetProfileId(SSSHeader);
}
#endif
}
break;
case SUBSTRATE_BSDF_TYPE_SINGLELAYERWATER:
{
// Reusing the slab data to avoid using too many registers in case the compiler has trouble optimising
Data.Closures[i].DiffuseR = SLW_BASECOLOR(BSDF).r;
Data.Closures[i].DiffuseG = SLW_BASECOLOR(BSDF).g;
Data.Closures[i].DiffuseB = SLW_BASECOLOR(BSDF).b;
Data.Closures[i].F0R = SLW_SPECULAR(BSDF).r;
Data.Closures[i].F0G = SLW_METALLIC(BSDF).r;
Data.Closures[i].Roughness = SLW_ROUGHNESS(BSDF);
Data.Closures[i].SSSOpacity = SLW_TOPMATERIALOPACITY(BSDF);
}
break;
default:
{
// Error
}
break;
}
}
const uint FootPrint_PostBSDFs = SubstrateAddressing.ReadBytes;
// Output memory reads
Data.MemoryDisplayMode = 0;
{
const bool bHasSSSData = SubstrateSubSurfaceHeaderGetIsValid(SSSHeader);
const uint TopLayerDataBytes = 4;
const uint SSSDataBytes = 8;
const bool bSubstrateMaterial = Header.ClosureCount > 0;
const bool bIsSimpleMaterial = Header.IsSimpleMaterial() || Header.ClosureCount == 0;
const bool bIsSingleMaterial = !Header.IsSimpleMaterial() && Header.IsSingleMaterial();
const uint HeaderSize = FootPrint_PostHeader - FootPrint_Start;
const uint BSDFsSize = FootPrint_PostBSDFs - FootPrint_PostHeader;
const uint TotalSize = (FootPrint_PostBSDFs - FootPrint_Start) + (bHasSSSData ? SSSDataBytes : 0);
if (Header.ClosureCount > 0)
{
if (bIsSimpleMaterial || Header.IsSingleLayerWater())
{
Data.MemoryDisplayMode = 1;
Data.MemorySlotA = HeaderSize + BSDFsSize - TopLayerDataBytes; // Header+BSDF
Data.MemorySlotB = TopLayerDataBytes; // TopNormalTex
}
else if (bIsSingleMaterial || Header.IsEye() || Header.IsHair())
{
Data.MemoryDisplayMode = 2;
Data.MemorySlotA = HeaderSize - TopLayerDataBytes; // Header
Data.MemorySlotB = TopLayerDataBytes; // TopNormalTex
Data.MemorySlotC = BSDFsSize; // BSDF
}
else
{
Data.MemoryDisplayMode = 3;
Data.MemorySlotA = HeaderSize; // Header+Norm
Data.MemorySlotB = BSDFsSize; // BSDFs
}
if (bHasSSSData)
{
Data.MemorySSSData = SSSDataBytes; // SSS Data
}
}
Data.MemoryTotal = TotalSize;
}
Data.GPUFrameNumber = asint(GPUFrameNumber);
return Data;
}
#if SUBSTRATE_MATERIALCONTAINER_IS_VIEWRESOURCE
void SerializeSubstratePixelDebugDataEntry(uint2 InCoord, uint GPUFrameNumber)
#else
void SerializeSubstratePixelDebugDataEntry(uint2 InCoord, FSubstrateRaytracingPayload Payload, uint GPUFrameNumber)
#endif
{
// Convert Substrate GBuffer into the CPU/GPU common data to serialize.
#if SUBSTRATE_MATERIALCONTAINER_IS_VIEWRESOURCE
FSubstratePixelDebugData Data = ConvertToSerializableSubstratePixelDebugData(InCoord, GPUFrameNumber);
#else
FSubstratePixelDebugData Data = ConvertToSerializableSubstratePixelDebugData(InCoord, Payload, GPUFrameNumber);
#endif
// And serialise it.
FSubstrateDebugDataSerializer S = (FSubstrateDebugDataSerializer)0;
SerializeSubstratePixelDebugData(S, Data);
}
void SerializeNullPixelDebugDataEntry()
{
FSubstratePixelDebugData Data = (FSubstratePixelDebugData)0;
FSubstrateDebugDataSerializer S = (FSubstrateDebugDataSerializer)0;
SerializeSubstratePixelDebugData(S, Data);
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
struct FSubstrateSystemInfoData
{
int TileCount[SUBSTRATE_TILE_TYPE_COUNT];
};
#ifndef __cplusplus
void SerializeSubstrateSystemInfoDebugData(in FSubstrateDebugDataSerializer S, in FSubstrateSystemInfoData D)
#else
void SerializeSubstrateSystemInfoDebugData(FSubstrateDebugDataSerializer& S, FSubstrateSystemInfoData& D)
#endif
{
for (int i = 0; i < SUBSTRATE_TILE_TYPE_COUNT; ++i)
{
S.Serialize(D.TileCount[i]);
}
}
#ifndef __cplusplus
uint GetTileCount(uint InType);
void ConvertToSerializableSubstratePixelDebugData()
{
FSubstrateSystemInfoData Data = (FSubstrateSystemInfoData)0;
// Setup the system info to send to the CPU for debug print
for (int i = 0; i < SUBSTRATE_TILE_TYPE_COUNT; ++i)
{
Data.TileCount[i] = GetTileCount(i);
}
// And serialise it.
FSubstrateDebugDataSerializer S = (FSubstrateDebugDataSerializer)0;
SerializeSubstrateSystemInfoDebugData(S, Data);
}
#endif
#endif // defined(__cplusplus) || SUBSTRATE_ENABLED