Files
UnrealEngineUWP/Engine/Shaders/Private/Strata/StrataVisualize.usf
Charles deRousiers b369cdd7dd Fix Strata visualization name typo
#rb none
#jira none
#preflight shader

[CL 20449271 by Charles deRousiers in ue5-main branch]
2022-06-01 04:16:30 -04:00

1272 lines
43 KiB
Plaintext

// Copyright Epic Games, Inc. All Rights Reserved.
#include "/Engine/Private/Common.ush"
#include "/Engine/Private/DeferredShadingCommon.ush"
#if defined(SHADER_DEBUGSTRATATREE_PS) || defined(SHADER_DEBUGSTRATATREE_CS)
#define STRATA_INLINE_SHADING 1
#else
#define STRATA_INLINE_SHADING 0
#endif
#define STRATA_SSS_MATERIAL_OVERRIDE 0
#define STRATA_SSS_TRANSMISSION 0 // Disable for now, as the SSS profile texture need to be bound
#include "/Engine/Private/Strata/StrataEvaluation.ush"
#include "/Engine/Private/Strata/StrataTile.ush"
#include "/Engine/Private/ShaderPrint.ush"
#include "../ColorMap.ush"
// This is for the fxc compiler to compile faster.
#define STRATA_VIZ_MAX_BSDF 2
void DrawReferentialTWS(float3 P /*In Translated World Space*/, float3 X, float3 Y, float3 N, float3 InColor)
{
const float Size = 10.f;
const float SizeWithTip = 12.0f;
const float4 Color = float4(InColor, 1);
const float4 ColorX = float4(1, 0, 0, 1);
const float4 ColorY = float4(0, 1, 0, 1);
const float4 ColorZ = float4(0, 0, 1, 1);
// Core
AddLineTWS(P, P + X * Size, Color, Color);
AddLineTWS(P, P + Y * Size, Color, Color);
AddLineTWS(P, P + N * Size, Color, Color);
// Tips
AddLineTWS(P + X * Size, P + X * SizeWithTip, ColorX, ColorX);
AddLineTWS(P + Y * Size, P + Y * SizeWithTip, ColorY, ColorY);
AddLineTWS(P + N * Size, P + N * SizeWithTip, ColorZ, ColorZ);
}
void AddDrawPixelFootprint(float3 P, float3 dPdx, float3 dPdy, float2 Scale, bool bNormalize, float4 Color)
{
const float3 T = (bNormalize ? normalize(dPdx) : dPdx) * Scale.x;
const float3 B = (bNormalize ? normalize(dPdy) : dPdy) * Scale.y;
const float3 N = normalize(cross(T, B));
const float3 WP0 = P - T - B;
const float3 WP1 = P + T - B;
const float3 WP2 = P + T + B;
const float3 WP3 = P - T + B;
AddLineTWS(WP0, WP1, Color);
AddLineTWS(WP1, WP2, Color);
AddLineTWS(WP2, WP3, Color);
AddLineTWS(WP3, WP0, Color);
}
void DrawPixelFootprint(float3 P, float3 dPdx, float3 dPdy, uint2 PixelCoord)
{
const FStrataSubsurfaceHeader SSSHeader = StrataLoadSubsurfaceHeader(Strata.SSSTexture, PixelCoord);
const uint SubsurfaceProfileInt = StrataSubSurfaceHeaderGetProfileId(SSSHeader);
const bool bIsValid = StrataSubSurfaceHeaderGetIsValid(SSSHeader);
const bool bIsProfile = StrataSubSurfaceHeaderGetIsProfile(SSSHeader);
const float PixelRadiusScale = StrataSubSurfaceHeaderGetProfileRadiusScale(SSSHeader);
if (bIsValid)
{
float3 MFP = 0;
if (bIsProfile)
{
MFP = GetSubsurfaceProfileMFPInCm(StrataSubSurfaceHeaderGetProfileId(SSSHeader)).xyz * StrataSubSurfaceHeaderGetProfileRadiusScale(SSSHeader);
}
else
{
MFP = StrataSubSurfaceHeaderGetMFP(SSSHeader);
}
FStrataPixelFootprint Footprint = StrataGetPixelFootprint(P);
AddDrawPixelFootprint(P, dPdx, dPdy, 0.5f, false, ColorRed);
AddDrawPixelFootprint(P, dPdx, dPdy, Footprint.PixelRadiusInWorldSpace, true, ColorOrange);
AddDrawPixelFootprint(P, dPdx, dPdy, max3(MFP.x, MFP.y, MFP.z), true, ColorCyan);
// Normal
const float3 N = normalize(cross(normalize(dPdx), normalize(dPdy)));
AddLineTWS(P, P + N * 10.f, ColorBlue);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Material Print
#if SHADER_MATERIALPRINT
uint BSDFIndex;
RWBuffer<uint> RWPositionOffsetBuffer;
// View mode:
// 1: Plot a single pixel
// 2: Color code the number of BSDFs (green -> red)
// 3: Add layer visualization
void PrintBool(inout FShaderPrintContext Ctx, bool In, FFontColor InColor)
{
if (In)
{
Print(Ctx, TEXT("Yes "), FontGreen);
}
else
{
Print(Ctx, TEXT("No "), FontRed);
}
}
void PrintPixelType(inout FShaderPrintContext Ctx, bool bIsSimpleMaterial, bool bIsSingleMaterial, FFontColor InColor)
{
if (bIsSimpleMaterial) Print(Ctx, TEXT("Simple "), InColor);
else if (bIsSingleMaterial) Print(Ctx, TEXT("Single "), InColor);
else Print(Ctx, TEXT("Complex "), InColor);
}
void PrintSSSType(inout FShaderPrintContext Ctx, uint SSSType, FFontColor InColor)
{
if (SSSType == SSS_TYPE_WRAP) Print(Ctx, TEXT("Wrap"), InColor);
else if (SSSType == SSS_TYPE_DIFFUSION) Print(Ctx, TEXT("Diffusion"), InColor);
else if (SSSType == SSS_TYPE_DIFFUSION_PROFILE) Print(Ctx, TEXT("Diffusion Profile"), InColor);
else /* (SSSType == SSS_TYPE_INVALID) */ Print(Ctx, TEXT("Invalid"), InColor);
}
void PrintBSDF(inout FShaderPrintContext Context, inout FStrataAddressing StrataAddressing, FStrataPixelHeader Header, float3 WorldPosition, float3 V)
{
const FFontColor FontBSDF = FontSilver;
const FFontColor FontBSDFType = FontEmerald;
const FFontColor FontBSDFStateName= FontWhite;
const FFontColor FontBSDFPropName = FontOrange;
const FFontColor FontBSDFPropValu = FontWhite;
const FStrataBSDF BSDF = UnpackStrataBSDFIn(Strata.MaterialTextureArray, StrataAddressing, Header);
// Draw Referential
{
const float3 DummyL = float3(0, 0, 1);
FStrataBSDFContext BSDFContext = StrataCreateBSDFContext(Header, BSDF, StrataAddressing, V, DummyL);
DrawReferentialTWS(WorldPosition, BSDFContext.X, BSDFContext.Y, BSDFContext.N, float3(1, 1, 0));
}
switch (BSDF_GETTYPE(BSDF))
{
case STRATA_BSDF_TYPE_SLAB:
{
const bool bWeightL = BSDF_GETHASTRANSABOVE(BSDF);
const bool bGreyWeightV = BSDF_GETHASGREYWEIGHT_V(BSDF);
const bool bGreyTopTrans = BSDF.TransmittanceAboveAlongN.x == BSDF.TransmittanceAboveAlongN.y && BSDF.TransmittanceAboveAlongN.x == BSDF.TransmittanceAboveAlongN.z;
Print(Context, TEXT("Slab "), FontBSDFType);
Newline(Context);
Print(Context, TEXT(" NormalID Aniso TopLayer Scattering SingleScatt. IsThin WeightV "), FontBSDFStateName);
if (!bGreyWeightV)
{
Print(Context, TEXT(" "), FontBSDFStateName);
}
if (bWeightL)
{
Print(Context, TEXT("WeightL"), FontBSDFStateName);
}
Newline(Context);
Print(Context, TEXT(" "), FontSilver);
Print(Context, BSDF_GETSHAREDLOCALBASISID(BSDF), FontBSDF, 2, 1); Print(Context, TEXT(" "), FontSilver);
PrintBool(Context, BSDF_GETHASANISOTROPY(BSDF), FontBSDF); Print(Context, TEXT(" "), FontSilver);
PrintBool(Context, BSDF_GETISTOPLAYER(BSDF), FontBSDF); Print(Context, TEXT(" "), FontSilver);
PrintBool(Context, BSDF_GETSSSTYPE(BSDF) != SSS_TYPE_INVALID, FontBSDF); Print(Context, TEXT(" "), FontSilver);
PrintBool(Context, BSDF_GETISSIMPLEVOLUME(BSDF), FontBSDF); Print(Context, TEXT(" "), FontSilver);
PrintBool(Context, BSDF_GETISTHIN(BSDF), FontBSDF); Print(Context, TEXT(" "), FontSilver);
// View Weight
{
if (bGreyWeightV)
{
Print(Context, BSDF.LuminanceWeightV.x, FontSilver, 6, 4);
}
else
{
Print(Context, BSDF.LuminanceWeightV.r, FontLightRed, 6, 4);
Print(Context, BSDF.LuminanceWeightV.g, FontLightGreen, 6, 4);
Print(Context, BSDF.LuminanceWeightV.b, FontLightBlue, 6, 4);
}
}
// Lighy weight
if (bGreyTopTrans)
{
Print(Context, TEXT(" "), FontSilver);
if (bGreyTopTrans)
{
Print(Context, BSDF.TransmittanceAboveAlongN.x, FontSilver);
}
else
{
Print(Context, BSDF.TransmittanceAboveAlongN.r, FontLightRed, 6, 4);
Print(Context, BSDF.TransmittanceAboveAlongN.g, FontLightGreen, 6, 4);
Print(Context, BSDF.TransmittanceAboveAlongN.b, FontLightBlue, 6, 4);
}
}
Newline(Context);
Print(Context, TEXT(" Diffuse "), FontBSDFPropName); Print(Context, SLAB_DIFFUSEALBEDO(BSDF), FontBSDFPropValu); Newline(Context);
const bool bGreyF0 = SLAB_F0(BSDF).x == SLAB_F0(BSDF).y && SLAB_F0(BSDF).x == SLAB_F0(BSDF).z;
if (bGreyF0)
{
Print(Context, TEXT(" F0 "), FontBSDFPropName); Print(Context, SLAB_F0(BSDF).x, FontBSDFPropValu); Newline(Context);
}
else
{
Print(Context, TEXT(" F0 "), FontBSDFPropName); Print(Context, SLAB_F0(BSDF), FontBSDFPropValu); Newline(Context);
}
if (BSDF_GETHASF90(BSDF))
{
const bool bGreyF90 = SLAB_F90(BSDF).x == SLAB_F90(BSDF).y && SLAB_F90(BSDF).x == SLAB_F90(BSDF).z;
if (bGreyF90)
{
Print(Context, TEXT(" F90 "), FontBSDFPropName); Print(Context, SLAB_F90(BSDF).x, FontBSDFPropValu); Newline(Context);
}
else
{
Print(Context, TEXT(" F90 "), FontBSDFPropName); Print(Context, SLAB_F90(BSDF), FontBSDFPropValu); Newline(Context);
}
}
Print(Context, TEXT(" Roughness "), FontBSDFPropName); Print(Context, SLAB_ROUGHNESS(BSDF), FontBSDFPropValu); Newline(Context);
if (BSDF_GETHASANISOTROPY(BSDF))
{
Print(Context, TEXT(" Anisotropy "), FontBSDFPropName); Print(Context, SLAB_ANISOTROPY(BSDF), FontBSDFPropValu); Newline(Context);
}
if (BSDF_GETHASHAZINESS(BSDF))
{
Print(Context, TEXT(" Haziness "), FontBSDFPropName); Print(Context, SLAB_HAZINESS(BSDF), FontBSDFPropValu); Newline(Context);
}
if (BSDF_GETSSSTYPE(BSDF) != SSS_TYPE_INVALID || BSDF_GETISSIMPLEVOLUME(BSDF) || BSDF_GETISTHIN(BSDF))
{
const FStrataSubsurfaceHeader SSSHeader = StrataLoadSubsurfaceHeader(Strata.SSSTexture, StrataAddressing.PixelCoords);
const uint SSSType = StrataSubSurfaceHeaderGetSSSType(SSSHeader);
const float Opacity = StrataSubSurfaceHeaderGetWrapOpacity(SSSHeader);
Print(Context, TEXT(" SSS Type "), FontBSDFPropName); PrintSSSType(Context, SSSType, FontYellow); Newline(Context);
Print(Context, TEXT(" SSS Opacity "), FontBSDFPropName); Print(Context, Opacity, FontBSDFPropValu); Newline(Context);
if (BSDF_GETSSSTYPE(BSDF) == SSS_TYPE_DIFFUSION_PROFILE && BSDF_GETISSIMPLEVOLUME(BSDF) == 0)
{
Print(Context, TEXT(" SSS ID. "), FontBSDFPropName); Print(Context, SLAB_SSSPROFILEID(BSDF), FontBSDFPropValu); Newline(Context);
Print(Context, TEXT(" SSS Radius "), FontBSDFPropName); Print(Context, SLAB_SSSPROFILERADIUSSCALE(BSDF), FontBSDFPropValu); Newline(Context);
}
else
{
Print(Context, TEXT(" SSS MFP "), FontBSDFPropName); Print(Context, SLAB_SSSMFP(BSDF), FontBSDFPropValu); Newline(Context);
}
Print(Context, TEXT(" SSS Phase "), FontBSDFPropName); Print(Context, SLAB_SSSPHASEANISOTROPY(BSDF), FontBSDFPropValu); Newline(Context);
} // SSS
if (BSDF_GETHASFUZZ(BSDF))
{
Print(Context, TEXT(" Fuzz Amount "), FontBSDFPropName); Print(Context, SLAB_FUZZ_AMOUNT(BSDF), FontBSDFPropValu); Newline(Context);
Print(Context, TEXT(" Fuzz Color "), FontBSDFPropName); Print(Context, SLAB_FUZZ_COLOR(BSDF), FontBSDFPropValu); Newline(Context);
}
}
break;
case STRATA_BSDF_TYPE_HAIR:
{
Print(Context, TEXT("Hair"), FontBSDFType);
Newline(Context);
Print(Context, TEXT(" NormalID Aniso IsTopLayer LuminanceWeight"), FontBSDF);
Newline(Context);
Print(Context, BSDF_GETSHAREDLOCALBASISID(BSDF), FontBSDF);
PrintBool(Context, BSDF_GETHASANISOTROPY(BSDF), FontBSDF);
PrintBool(Context, BSDF_GETISTOPLAYER(BSDF), FontBSDF);
if (BSDF_GETHASGREYWEIGHT_V(BSDF))
{
Print(Context, BSDF.LuminanceWeightV.x, FontSilver);
}
else
{
Print(Context, BSDF.LuminanceWeightV.r, FontLightRed);
Print(Context, BSDF.LuminanceWeightV.g, FontLightGreen);
Print(Context, BSDF.LuminanceWeightV.b, FontLightBlue);
}
Newline(Context);
Print(Context, TEXT(" BaseColor "), FontBSDFPropName); Print(Context, HAIR_BASECOLOR(BSDF), FontBSDFPropValu); Newline(Context);
Print(Context, TEXT(" Specular "), FontBSDFPropName); Print(Context, HAIR_SPECULAR(BSDF), FontBSDFPropValu); Newline(Context);
Print(Context, TEXT(" Roughness "), FontBSDFPropName); Print(Context, HAIR_ROUGHNESS(BSDF), FontBSDFPropValu); Newline(Context);
Print(Context, TEXT(" Scatter "), FontBSDFPropName); Print(Context, HAIR_SCATTER(BSDF), FontBSDFPropValu); Newline(Context);
Print(Context, TEXT(" Backlit "), FontBSDFPropName); Print(Context, HAIR_BACKLIT(BSDF), FontBSDFPropValu); Newline(Context);
Print(Context, TEXT(" Has Transmittance "), FontBSDFPropName); Print(Context, HAIR_COMPLEXTRANSMITTANCE(BSDF), FontBSDFPropValu); Newline(Context);
}
break;
case STRATA_BSDF_TYPE_SINGLELAYERWATER:
{
Print(Context, TEXT("Water"), FontBSDFType);
Newline(Context);
Print(Context, TEXT(" BaseColor "), FontBSDFPropName); Print(Context, SLW_BASECOLOR(BSDF), FontBSDFPropValu); Newline(Context);
Print(Context, TEXT(" Metallic "), FontBSDFPropName); Print(Context, SLW_METALLIC(BSDF), FontBSDFPropValu); Newline(Context);
Print(Context, TEXT(" Specular "), FontBSDFPropName); Print(Context, SLW_SPECULAR(BSDF), FontBSDFPropValu); Newline(Context);
Print(Context, TEXT(" Roughness "), FontBSDFPropName); Print(Context, SLW_ROUGHNESS(BSDF), FontBSDFPropValu); Newline(Context);
Print(Context, TEXT(" Top Material Opacity "), FontBSDFPropName); Print(Context, SLW_TOPMATERIALOPACITY(BSDF), FontBSDFPropValu); Newline(Context);
}
break;
default:
{
Print(Context, TEXT("Error"), FontRed);
}
break;
}
Newline(Context);
}
void PrintPixel(uint2 InCoord, float3 InWorldPosition, float3 V)
{
FShaderPrintContext Context;
if (BSDFIndex > 0)
{
float2 PrintOffset;
PrintOffset.x = asfloat(RWPositionOffsetBuffer[0]);
PrintOffset.y = asfloat(RWPositionOffsetBuffer[1]);
Context = InitShaderPrintContext(true, PrintOffset);
}
else
{
Context = InitShaderPrintContext(true, uint2(50, 50));
}
FStrataAddressing StrataAddressing = GetStrataPixelDataByteOffset(InCoord, uint2(View.BufferSizeAndInvSize.xy), Strata.MaxBytesPerPixel);
const uint FootPrint_Start = StrataAddressing.ReadBytes;
FStrataPixelHeader Header = UnpackStrataHeaderIn(Strata.MaterialTextureArray, StrataAddressing, Strata.TopLayerTexture);
const uint FootPrint_PostHeader = StrataAddressing.ReadBytes;
const FFontColor FontBSDFCount = FontEmerald;
const FFontColor FontHeaderStateName = FontWhite;
const FFontColor FontHeaderPropName = FontWhite;
const FFontColor FontHeaderPropValue = FontSilver;
// Header
if (BSDFIndex < Header.BSDFCount && BSDFIndex == 0)
{
const FStrataTopLayerData TopLayerData = StrataUnpackTopLayerData(Strata.TopLayerTexture.Load(uint3(InCoord, 0)));
const bool bStrataMaterial = Header.BSDFCount > 0;
const bool bIsSimpleMaterial = IsSimpleMaterial(Header) || Header.BSDFCount == 0;
const bool bIsSingleMaterial = !IsSimpleMaterial(Header) && IsSingleMaterial(Header);
Print(Context, Header.BSDFCount, FontBSDFCount, 2, 0);
Print(Context, TEXT("BSDF"), FontBSDFCount);
Print(Context, TEXT(" - "), FontWhite);
PrintPixelType(Context, bIsSimpleMaterial, bIsSingleMaterial, FontLightRed);
Newline(Context);
Print(Context, TEXT(" AO TopRoughness PreShadow ZeroShadow ContacShadow Ind.Occluder IsWater HasSSS"), FontHeaderStateName);
Newline(Context);
Print(Context, TEXT(" "));
Print(Context, StrataGetAO(Header), FontHeaderPropValue, 5, 3); Print(Context, TEXT(" "));
Print(Context, TopLayerData.Roughness, FontHeaderPropValue, 5, 3); Print(Context, TEXT(" "));
PrintBool(Context, HasPrecShadowMask(Header), FontHeaderPropValue); Print(Context, TEXT(" "));
PrintBool(Context, HasZeroPrecShadowMask(Header), FontHeaderPropValue); Print(Context, TEXT(" "));
PrintBool(Context, DoesCastContactShadow(Header), FontHeaderPropValue); Print(Context, TEXT(" "));
PrintBool(Context, HasDynamicIndirectShadowCasterRepresentation(Header), FontHeaderPropValue); Print(Context, TEXT(" "));
PrintBool(Context, IsSingleLayerWater(Header), FontHeaderPropValue); Print(Context, TEXT(" "));
PrintBool(Context, HasSubsurface(Header), FontHeaderPropValue);
Newline(Context);
Newline(Context);
}
// BSDFs
if (BSDFIndex < Header.BSDFCount)
{
if (BSDFIndex > 0)
{
const uint AddressOffset = UnpackBSDFOffsetAtIndex(Strata.BSDFOffsetTexture[InCoord], BSDFIndex, Header.BSDFCount);
StrataSeekBSDF(StrataAddressing, AddressOffset);
}
PrintBSDF(Context, StrataAddressing, Header, InWorldPosition, V);
RWPositionOffsetBuffer[0] = asuint(Context.Pos.x);
RWPositionOffsetBuffer[1] = asuint(Context.Pos.y);
}
// Memory footprint
if (BSDFIndex+1 == Header.BSDFCount)
{
const bool bStrataMaterial = Header.BSDFCount > 0;
const bool bIsSimpleMaterial = IsSimpleMaterial(Header) || Header.BSDFCount == 0;
const bool bIsSingleMaterial = !IsSimpleMaterial(Header) && IsSingleMaterial(Header);
const uint FootPrint_PostBSDFs = StrataAddressing.ReadBytes;
const uint HeaderSize = FootPrint_PostHeader - FootPrint_Start;
const uint BSDFsSize = FootPrint_PostBSDFs - FootPrint_PostHeader;
const uint TotalSize = FootPrint_PostBSDFs - FootPrint_Start;
const uint TopLayerDataBytes = 4; // bytes
Print(Context, TEXT("Memory"), FontEmerald); Newline(Context);
if (bIsSingleMaterial)
{
Print(Context, TEXT(" Header "), FontSilver); Print(Context, HeaderSize - TopLayerDataBytes, FontSilver, 3, 0); Print(Context, TEXT("bytes"), FontSilver); Newline(Context);
Print(Context, TEXT(" TopNormalTex "), FontSilver); Print(Context, TopLayerDataBytes, FontSilver, 3, 0); Print(Context, TEXT("bytes"), FontSilver); Newline(Context);
Print(Context, TEXT(" BSDF "), FontSilver); Print(Context, BSDFsSize, FontSilver, 3, 0); Print(Context, TEXT("bytes"), FontSilver); Newline(Context);
}
else if (bIsSimpleMaterial)
{
Print(Context, TEXT(" Header+BSDF "), FontSilver); Print(Context, HeaderSize + BSDFsSize - TopLayerDataBytes, FontSilver, 3, 0); Print(Context, TEXT("bytes"), FontSilver); Newline(Context);
Print(Context, TEXT(" TopNormalTex "), FontSilver); Print(Context, TopLayerDataBytes, FontSilver, 3, 0); Print(Context, TEXT("bytes"), FontSilver); Newline(Context);
}
else
{
Print(Context, TEXT(" Header+Norm "), FontSilver); Print(Context, HeaderSize, FontSilver, 3, 0); Print(Context, TEXT("bytes"), FontSilver); Newline(Context);
Print(Context, TEXT(" BSDFs "), FontSilver); Print(Context, BSDFsSize, FontSilver, 3, 0); Print(Context, TEXT("bytes"), FontSilver); Newline(Context);
}
Print(Context, TEXT(" Total "), FontOrange); Print(Context, TotalSize, FontOrange, 3, 0); Print(Context, TEXT("bytes"), FontOrange); Newline(Context);
}
}
[numthreads(1, 1, 1)]
void MaterialPrintInfoCS(uint3 DispatchThreadId : SV_DispatchThreadID)
{
const uint2 PixelPos = (float2(View.CursorPosition) * View.ViewResolutionFraction);
const float2 BufferUV = SvPositionToBufferUV(float4(PixelPos + 0.5f, 0, 0));
const float2 ScreenPosition = SvPositionToScreenPosition(float4(PixelPos, 0.5f, 1)).xy;
const float DeviceZ = SampleDeviceZFromSceneTextures(BufferUV);
const float SceneDepth = ConvertFromDeviceZ(DeviceZ);
const float3 WorldPosition = mul(float4(ScreenPosition * SceneDepth, SceneDepth, 1), PrimaryView.ScreenToTranslatedWorld).xyz;
const float3 V = -normalize(WorldPosition - PrimaryView.TranslatedWorldCameraOrigin);
PrintPixel(PixelPos, WorldPosition, V);
}
#endif // SHADER_MATERIALPRINT
///////////////////////////////////////////////////////////////////////////////////////////////////
// Material Visualize
#if SHADER_MATERIALVISUALIZE
uint ViewMode;
void VisualizeMaterialPS(
float4 SVPos : SV_POSITION,
out float4 OutColor : SV_Target0)
{
const uint2 PixelPos = uint2(SVPos.xy);
float2 BufferUV = SvPositionToBufferUV(float4(PixelPos, SVPos.zw));
const float2 ScreenPosition = SvPositionToScreenPosition(SVPos).xy;
const float2 ScreenMaterialPosition = SvPositionToScreenPosition(float4(PixelPos, 0.5f, 1)).xy;
float DeviceZ = SampleDeviceZFromSceneTextures(BufferUV);
float SceneDepth = ConvertFromDeviceZ(DeviceZ);
const float3 WorldPosition = mul(float4(ScreenMaterialPosition * SceneDepth, SceneDepth, 1), PrimaryView.ScreenToTranslatedWorld).xyz;
const float3 V = -normalize(WorldPosition - PrimaryView.TranslatedWorldCameraOrigin);
FStrataAddressing StrataAddressing = GetStrataPixelDataByteOffset(PixelPos, uint2(View.BufferSizeAndInvSize.xy), Strata.MaxBytesPerPixel);
FStrataPixelHeader Header = UnpackStrataHeaderIn(Strata.MaterialTextureArray, StrataAddressing, Strata.TopLayerTexture);
bool bStrataMaterial = Header.BSDFCount > 0;
OutColor = 0;
// BSDF count
if (ViewMode == 2)
{
OutColor.w = 0.1f;
if (Header.BSDFCount > 0)
{
const float BSDFCost = saturate(float(Header.BSDFCount) / 4.f);
OutColor.xyz = ColorMapTurbo(BSDFCost);
}
}
else
{
OutColor = float4(0.0f, 0.0f, 0.0f, 1.0f);
}
}
#endif // SHADER_MATERIALVISUALIZE
///////////////////////////////////////////////////////////////////////////////////////////////////
// Material Visualize
#define BSDF_ELEMENT_SIZE 210
#define BSDF_ELEMENT_STARTX 100.0f + 450.0f
#define BSDF_ELEMENT_STARTY 100
#if SHADER_DEBUGSTRATATREE_PS || SHADER_DEBUGSTRATATREE_CS
#define TREE_MAX_DEPTH 4
#define TREE_START_POS float2(1300, 350)
#define TREE_BRANCH float2(200, 75)
#define TREE_COLOR float4(0.8, 0.8, 0.8, 1.0)
#define TREE_NODE_RADIUS 20.0
float2 GetBranchOffset(FStrataOperator Op, bool bIsLeft)
{
if (Op.Type == STRATA_OPERATOR_WEIGHT || Op.Type == STRATA_OPERATOR_THINFILM)
{
return float2(0, TREE_BRANCH.y);
}
return TREE_BRANCH * (bIsLeft ? float2(-1, 1) : float2(1, 1));
}
#endif // SHADER_DEBUGSTRATATREE_PS || SHADER_DEBUGSTRATATREE_CS
#if SHADER_DEBUGSTRATATREE_CS
[numthreads(1, 1, 1)]
void MaterialDebugStrataTreeCS(uint3 DispatchThreadId : SV_DispatchThreadID)
{
const uint2 PixelPos = (float2(View.CursorPosition) * View.ViewResolutionFraction);
FStrataAddressing StrataAddressing = GetStrataPixelDataByteOffset(PixelPos, uint2(View.BufferSizeAndInvSize.xy), Strata.MaxBytesPerPixel);
FStrataPixelHeader Header = UnpackStrataHeaderIn(Strata.MaterialTextureArray, StrataAddressing, Strata.TopLayerTexture);
if (Header.BSDFCount > 0)
{
const int SliceStoringDebugStrataTree = Strata.SliceStoringDebugStrataTree + STRATA_BASE_PASS_MRT_OUTPUT_COUNT;
FStrataTreeHeader StrataTreeHeader = (FStrataTreeHeader)0;
StrataUnpackInStrataTreeHeader(
Strata.MaterialTextureArray,
StrataTreeHeader,
SliceStoringDebugStrataTree);
FShaderPrintContext Context;
Context = InitShaderPrintContext(true, uint2(50, 50));
const int BSDFCount = StrataTreeHeader.BSDFCount;
Print(Context, BSDFCount, FontYellow, 2, 0);
Print(Context, TEXT("BSDFs"), FontYellow);
if (StrataTreeHeader.ConvertedFromLegacy)
{
Print(Context, TEXT(" (Converted from legacy material)"), FontOrange);
}
Newline(Context);
Print(Context, StrataTreeHeader.OperatorCount, FontWhite, 2, 0);
Print(Context, TEXT("Operators"), FontWhite);
#define MAX_LAYER_COUNT 4
float LayerAccCoverage[MAX_LAYER_COUNT];
{
for (int i = 0; i < MAX_LAYER_COUNT; ++i)
{
LayerAccCoverage[i] = 0.0f;
}
}
Context = InitShaderPrintContext(true, uint2(50, BSDF_ELEMENT_STARTY));
{
#if STRATA_COMPILER == 1
LOOP
#else
StrataTreeHeader.OperatorCount = min(StrataTreeHeader.OperatorCount, 2);
STRATA_UNROLL_N(2)
#endif
for (int i = 0; i < StrataTreeHeader.OperatorCount; i++)
{
FStrataOperator Op = StrataUnpackInStrataTreeOperator(
i,
Strata.MaterialTextureArray,
StrataTreeHeader,
SliceStoringDebugStrataTree);
Print(Context, TEXT("OperatorIndex = "), FontCyan);
Print(Context, i, FontCyan, 2, 0);
Newline(Context);
Print(Context, TEXT("ParentIndex = "), FontWhite);
Print(Context, Op.ParentIndex, FontWhite, 2, 0);
Newline(Context);
Print(Context, TEXT("LayerDepth = "), FontWhite);
Print(Context, Op.LayerDepth, FontWhite, 2, 0);
Newline(Context);
Print(Context, TEXT("MaxDistanceFromLeaves = "), FontWhite);
Print(Context, Op.MaxDistanceFromLeaves, FontWhite, 2, 0);
Newline(Context);
Print(Context, TEXT("Type = "), FontWhite);
if (Op.Type == STRATA_OPERATOR_WEIGHT)
{
Print(Context, TEXT("WEIGHT"), FontWhite);
}
else if (Op.Type == STRATA_OPERATOR_VERTICAL)
{
Print(Context, TEXT("VERTICAL"), FontWhite);
}
else if (Op.Type == STRATA_OPERATOR_HORIZONTAL)
{
Print(Context, TEXT("HORIZONTAL"), FontWhite);
}
else if (Op.Type == STRATA_OPERATOR_ADD)
{
Print(Context, TEXT("ADD"), FontWhite);
}
else if (Op.Type == STRATA_OPERATOR_BSDF)
{
Print(Context, TEXT("BSDF"), FontWhite);
}
else if (Op.Type == STRATA_OPERATOR_BSDF_LEGACY)
{
Print(Context, TEXT("BSDF_LEGACY"), FontWhite);
}
else if (Op.Type == STRATA_OPERATOR_THINFILM)
{
Print(Context, TEXT("THINFILM"), FontWhite);
}
else
{
Print(Context, TEXT("UNKOWN"), FontWhite);
}
Newline(Context);
if (Op.Type == STRATA_OPERATOR_BSDF)
{
Print(Context, TEXT("BSDFIndex = "), FontYellow);
Print(Context, Op.LeftIndex, FontYellow, 2, 0);
}
else
{
Print(Context, TEXT("LeftIndex = "), FontWhite);
Print(Context, Op.LeftIndex, FontWhite, 2, 0);
}
Newline(Context);
Print(Context, TEXT("RightIndex = "), FontWhite);
Print(Context, Op.RightIndex, FontWhite, 2, 0);
Newline(Context);
Print(Context, TEXT("Weight = "), FontWhite);
Print(Context, Op.Weight, FontWhite, 5, 2);
Newline(Context);
Print(Context, TEXT("Coverage = "), FontWhite);
Print(Context, Op.Coverage, FontWhite, 5, 2);
Newline(Context);
Newline(Context);
}
}
{
#if STRATA_COMPILER == 1
LOOP
#else
StrataTreeHeader.BSDFCount = min(StrataTreeHeader.BSDFCount, 2);
STRATA_UNROLL_N(2)
#endif
for (int i = 0; i < StrataTreeHeader.BSDFCount; i++)
{
FStrataBSDF BSDF = StrataUnpackInStrataTreeBSDF(
i,
Strata.MaterialTextureArray,
StrataTreeHeader,
SliceStoringDebugStrataTree);
const bool bActive = any(BSDF.LuminanceWeightV > 0.0);
FFontColor BSDFFont = FontDarkRed;
Context = InitShaderPrintContext(true, uint2(300, BSDF_ELEMENT_STARTY + BSDF_ELEMENT_SIZE * i));
Print(Context, TEXT("BSDFIndex = "), FontYellow);
Print(Context, i, FontYellow, 2, 0);
if (!bActive)
{
Print(Context, TEXT("DISABLED"), FontDarkRed);
}
else
{
BSDFFont = FontWhite;
}
Newline(Context);
Print(Context, TEXT("OperatorIndex = "), FontCyan);
Print(Context, BSDF.OperatorIndex, FontCyan, 2, 0);
Newline(Context);
Print(Context, TEXT("Coverage = "), BSDFFont);
Print(Context, BSDF.Coverage, BSDFFont, 5, 2);
Newline(Context);
Print(Context, TEXT("LumWghtV = "), BSDFFont);
Print(Context, BSDF.LuminanceWeightV.r, FontLightRed, 5, 2);
Print(Context, BSDF.LuminanceWeightV.g, FontLightGreen, 5, 2);
Print(Context, BSDF.LuminanceWeightV.b, FontLightBlue, 5, 2);
Newline(Context);
Print(Context, TEXT("TopTrans = "), BSDFFont);
Print(Context, BSDF.TransmittanceAboveAlongN.r, FontLightRed, 5, 2);
Print(Context, BSDF.TransmittanceAboveAlongN.g, FontLightGreen, 5, 2);
Print(Context, BSDF.TransmittanceAboveAlongN.b, FontLightBlue, 5, 2);
Newline(Context);
Print(Context, TEXT("BotTrans = "), BSDFFont);
Print(Context, BSDF.TransmittanceBelowAlongN.r, FontLightRed, 5, 2);
Print(Context, BSDF.TransmittanceBelowAlongN.g, FontLightGreen, 5, 2);
Print(Context, BSDF.TransmittanceBelowAlongN.b, FontLightBlue, 5, 2);
Newline(Context);
Print(Context, TEXT("Diffuse = "), BSDFFont);
const float3 BSDFDiffuse = StrataGetBSDFDiffuseColor(BSDF);
Print(Context, BSDFDiffuse.r, FontLightRed, 5, 2);
Print(Context, BSDFDiffuse.g, FontLightGreen, 5, 2);
Print(Context, BSDFDiffuse.b, FontLightBlue, 5, 2);
Newline(Context);
}
}
Context = InitShaderPrintContext(true, uint2(675, BSDF_ELEMENT_STARTY - 50));
Print(Context, TEXT("BSDF visualization"), FontWhite);
Context = InitShaderPrintContext(true, uint2(1165, BSDF_ELEMENT_STARTY - 50));
Print(Context, TEXT("Topology"), FontWhite);
// Debug print the strata tree only for DXC for the sake of compilation performance.
#if STRATA_COMPILER
uint NodeIndexStack[TREE_MAX_DEPTH];
uint ChildrenVisitedStack[TREE_MAX_DEPTH]; // 0:none, 1:left, 2:left&right
float2 PrintPosStack[TREE_MAX_DEPTH];
int StackPtr = 0;
NodeIndexStack[StackPtr] = StrataTreeHeader.RootOperatorIndex;
ChildrenVisitedStack[StackPtr] = 0;
PrintPosStack[StackPtr] = TREE_START_POS;
while (StackPtr >= 0)
{
uint OperatorIndex = NodeIndexStack[StackPtr];
FStrataOperator Op = StrataUnpackInStrataTreeOperator(
OperatorIndex,
Strata.MaterialTextureArray,
StrataTreeHeader,
SliceStoringDebugStrataTree);
Context = InitShaderPrintContext(true, uint2(PrintPosStack[StackPtr]));
if (Op.Type == STRATA_OPERATOR_WEIGHT)
{
Print(Context, TEXT("W"), FontWhite);
}
else if (Op.Type == STRATA_OPERATOR_VERTICAL)
{
Print(Context, TEXT("V"), FontWhite);
}
else if (Op.Type == STRATA_OPERATOR_HORIZONTAL)
{
Print(Context, TEXT("H"), FontWhite);
}
else if (Op.Type == STRATA_OPERATOR_ADD)
{
Print(Context, TEXT("A"), FontWhite);
}
else if (Op.Type == STRATA_OPERATOR_BSDF)
{
Context = InitShaderPrintContext(true, uint2(PrintPosStack[StackPtr]) - uint2(3,0));
Print(Context, TEXT("B"), FontYellow);
Print(Context, Op.LeftIndex, FontYellow);
}
else if (Op.Type == STRATA_OPERATOR_BSDF_LEGACY)
{
Print(Context, TEXT("BL"), FontWhite);
}
else if (Op.Type == STRATA_OPERATOR_THINFILM)
{
Print(Context, TEXT("TF"), FontWhite);
}
else
{
Print(Context, TEXT("UNKOWN"), FontWhite);
}
const float2 ParentPrintPos = PrintPosStack[StackPtr];
AddCircleSS(Context, ParentPrintPos, TREE_NODE_RADIUS, TREE_COLOR);
if (Op.LayerDepth == TREE_MAX_DEPTH - 1 || Op.Type == STRATA_OPERATOR_BSDF || Op.Type == STRATA_OPERATOR_BSDF_LEGACY)
{
StackPtr--;
continue;
}
if (ChildrenVisitedStack[StackPtr] == 0)
{
if (Op.LeftIndex >= 0)
{
ChildrenVisitedStack[StackPtr] = 1;
StackPtr++;
NodeIndexStack[StackPtr] = Op.LeftIndex;
ChildrenVisitedStack[StackPtr] = 0;
const float2 BranchOffset = GetBranchOffset(Op, true);
const float2 BranchOffsetNorm = normalize(BranchOffset);
PrintPosStack[StackPtr] = ParentPrintPos + BranchOffset;
AddLineSS(Context, ParentPrintPos + TREE_NODE_RADIUS * BranchOffsetNorm, PrintPosStack[StackPtr] - TREE_NODE_RADIUS * BranchOffsetNorm, TREE_COLOR);
}
else if (Op.RightIndex >= 0)
{
ChildrenVisitedStack[StackPtr] = 2;
StackPtr++;
NodeIndexStack[StackPtr] = Op.RightIndex;
ChildrenVisitedStack[StackPtr] = 0;
const float2 BranchOffset = GetBranchOffset(Op, false);
const float2 BranchOffsetNorm = normalize(BranchOffset);
PrintPosStack[StackPtr] = ParentPrintPos + BranchOffset;
AddLineSS(Context, ParentPrintPos + TREE_NODE_RADIUS * BranchOffsetNorm, PrintPosStack[StackPtr] - TREE_NODE_RADIUS * BranchOffsetNorm, TREE_COLOR);
}
else
{
StackPtr--;
}
}
else if (ChildrenVisitedStack[StackPtr] == 1)
{
if (Op.RightIndex >= 0)
{
ChildrenVisitedStack[StackPtr] = 2;
StackPtr++;
NodeIndexStack[StackPtr] = Op.RightIndex;
ChildrenVisitedStack[StackPtr] = 0;
const float2 BranchOffset = GetBranchOffset(Op, false);
const float2 BranchOffsetNorm = normalize(BranchOffset);
PrintPosStack[StackPtr] = ParentPrintPos + BranchOffset;
AddLineSS(Context, ParentPrintPos + TREE_NODE_RADIUS * BranchOffsetNorm, PrintPosStack[StackPtr] - TREE_NODE_RADIUS * BranchOffsetNorm, TREE_COLOR);
}
else
{
StackPtr--;
}
}
else
{
StackPtr--;
}
}
#endif // STRATA_COMPILER
}
}
#endif // SHADER_DEBUGSTRATATREE_CS
#if SHADER_DEBUGSTRATATREE_PS
#include "../DeferredShadingCommon.ush"
#define SUPPORT_CONTACT_SHADOWS 0
#include "../DeferredLightingCommon.ush"
#include "StrataEvaluation.ush"
// These defines are needed for environment lighting in StrataLightingCommon
#define ENABLE_DYNAMIC_SKY_LIGHT 1
#define ENABLE_SKY_LIGHT 1
#define SUPPORT_DFAO_INDIRECT_OCCLUSION 0
#define STRATA_FASTPATH 0
#define REFLECTION_COMPOSITE_USE_BLENDED_REFLECTION_CAPTURES 0
#include "../ReflectionEnvironmentShared.ush"
#include "../SkyLightingDiffuseShared.ush"
#include "../ReflectionEnvironmentComposite.ush"
#define USE_STRATA_ENV_LIGHTING_COMMON 1
#define USE_STRATA_FORWARD_LIGHTING_COMMON 1
#include "StrataLightingCommon.ush"
float4 GetBackgroundCheckboardColor(float2 UV)
{
const float Count = 16.0f;
uint2 UVi = uint2(UV * Count);
bool bIsBlack = (UVi.x % 2) > 0 ? true : false;
bIsBlack = (UVi.y % 2) > 0 ? !bIsBlack : bIsBlack;
const float3 Color = (bIsBlack ? 0.04 : 0.18);
return float4(Color, 0.0);
}
// Updated from http://jcgt.org/published/0007/03/04/
bool slabs(float3 p0, float3 p1, float3 rayOrigin, float3 invRaydir, out float outTMin, out float outTMax)
{
float3 t0 = (p0 - rayOrigin) * invRaydir;
float3 t1 = (p1 - rayOrigin) * invRaydir;
float3 tmin = min(t0, t1), tmax = max(t0, t1);
float maxtmin = max(max(tmin.x, tmin.y), tmin.z);
float mintmax = min(min(tmax.x, tmax.y), tmax.z);
outTMin = maxtmin;
outTMax = mintmax;
return maxtmin <= mintmax;
}
void EvaluateLighting(
in FStrataBSDF BSDF,
in float3 V,
in float3x3 TangentBasis,
in float ThicknessRatio,
inout float4 OutColor)
{
float3 AbsoluteWorldPosition = LWCHackToFloat(PrimaryView.WorldCameraOrigin);
float3 TranslatedWorldPosition = PrimaryView.TranslatedWorldCameraOrigin;
float SceneDepth = 0.0;
const float3 N = TangentBasis[2];
if (BSDF_GETISSIMPLEVOLUME(BSDF))
{
// Apply transmittance on the background
float3 DiffuseColor = SLAB_DIFFUSEALBEDO(BSDF);
FParticipatingMedia PM = StrataSlabCreateParticipatingMedia(DiffuseColor, SLAB_SSSMFP(BSDF));
const float3 Transmittance = IsotropicMediumSlabTransmittance(PM, ThicknessRatio * STRATA_SIMPLEVOLUME_THICKNESS_M, 1.f);
OutColor.rgb *= Transmittance * BSDF.Coverage + (1.0f - BSDF.Coverage);
}
else
{
OutColor.rgb *= 0.0f;
}
// Patch the BSDF to appear as a top layer
BSDF.LuminanceWeightV = 1.0f;
BSDF.TransmittanceAboveAlongN = 1.0f;
BSDF.TransmittanceBelowAlongN = 1.0f;
BSDF.bIsBottom = true;
BSDF.bIsTop = true;
BSDF.Coverage = 1.0f;
// Create a head that will map to a single BSDF
FStrataPixelHeader StrataPixelHeader = InitialiseStrataPixelHeader();
StrataPixelHeader.BSDFCount = 1;
FStrataIntegrationSettings Settings = InitStrataIntegrationSettings();
FStrataAddressing NullStrataAddressing = (FStrataAddressing)0;
// Apply emissive
OutColor.rgb += BSDF_GETEMISSIVE(BSDF) * View.PreExposure;
// Apply a white directional light
if (ForwardLightData.HasDirectionalLight)
{
FDeferredLightData DirLightData = (FDeferredLightData)0;
DirLightData.Color = ForwardLightData.DirectionalLightColor;
DirLightData.FalloffExponent = 0;
DirLightData.Direction = ForwardLightData.DirectionalLightDirection;
DirLightData.DistanceFadeMAD = ForwardLightData.DirectionalLightDistanceFadeMAD;
DirLightData.bRadialLight = false;
DirLightData.SpecularScale = 1;
float4 DirLightAttenuation = float4(1, 1, 1, 1);
DirLightData.ShadowedBits = 1;
DirLightData.ShadowMapChannelMask.x = 1;
DirLightData.HairTransmittance = InitHairTransmittanceData();
float Dither = 0.0f;
float3 ToLight = DirLightData.Direction;
float LightMask = 1.0f;
FRectTexture RectTexture = InitRectTexture();
uint LightChannelMask = 0xFFFFFFFF;
uint PrimitiveLightingChannelMask = LightChannelMask;
float3 BSDFColoredVisibility = 1.0f;
FStrataBSDFContext StrataBSDFContext = StrataCreateBSDFContext(TangentBasis, BSDF, V, ToLight);
bool bEvaluateHasBeenExecuted = false;
FStrataEvaluateResult BSDFEvaluate = (FStrataEvaluateResult)0;
float3 DirLightLuminance = StrataForwardLightingCommon(
Dither,
Settings,
DirLightData,
ToLight,
LightMask,
DirLightAttenuation,
RectTexture,
LightChannelMask,
PrimitiveLightingChannelMask,
TranslatedWorldPosition,
SceneDepth,
BSDFColoredVisibility,
StrataPixelHeader,
StrataBSDFContext,
bEvaluateHasBeenExecuted,
BSDFEvaluate);
OutColor.rgb += DirLightLuminance * View.PreExposure;
}
// Apply the sky box
{
float3 ToLight = V;
FStrataBSDFContext StrataBSDFContext = StrataCreateBSDFContext(TangentBasis, BSDF, V, ToLight);
const bool bEnableSpecular = ReflectionStruct.SkyLightParameters.y > 0.0f;
FStrataEnvLightResult StrataEnvLight = StrataEvaluateForEnvLight(StrataBSDFContext, bEnableSpecular, Settings);
float SSRReductionFactor = 0.0;
float3 DiffuseLighting = 0.0;
float3 SpecularLighting = 0.0;
StrataEnvLightingCommon(
StrataEnvLight,
StrataPixelHeader,
StrataBSDFContext,
BSDF,
N, //in float3 BentNormal,
1.0,//in float3 BSDFThroughput,
0, //in uint CaptureDataStartIndex,
0, //in uint NumCulledReflectionCaptures,
1.0,//in float ScreenAmbientOcclusion,
1.0,//in float CloudVolumetricAOShadow,
1.0,//in float TopLayerSpecularContributionFactor,
TranslatedWorldPosition,
1.0,//in float CombinedScreenAndMaterialAO,
SSRReductionFactor,
DiffuseLighting,
SpecularLighting);
OutColor.rgb += (DiffuseLighting + SpecularLighting) * View.PreExposure;;
}
}
void GetMaterialOnCube(
in float4 SVPos,
in float2 Pos,
in float Size,
in FStrataBSDF BSDF,
inout float4 OutColor)
{
const float2 PixelPos = SVPos.xy;
if (BSDF_GETTYPE(BSDF) == STRATA_BSDF_TYPE_SLAB && all(PixelPos > Pos) && all(PixelPos < (Pos + Size)))
{
const float2 UV = (PixelPos - Pos) / Size;
OutColor = GetBackgroundCheckboardColor(UV);
const float3 RayO = -View.ViewForward*1.2;
const float3 RayD = View.ViewForward + 1.0 * (UV.x - 0.5) * View.ViewRight - 1.0 * (UV.y - 0.5) * View.ViewUp;
float3 V = -RayD;
float2 Hit;
const float CubeSize = 0.25;
bool bIntersection = slabs(-CubeSize, CubeSize, RayO, 1/RayD, Hit.x, Hit.y);
if (bIntersection)
{
float3 P = RayO + RayD * Hit.x;
float3 N = normalize(P);
float3 AbsN = abs(N);
N = AbsN.x > AbsN.y && AbsN.x > AbsN.z ? float3(1 * sign(N.x), 0, 0) : N;
N = AbsN.y > AbsN.z && AbsN.y > AbsN.x ? float3(0, 1 * sign(N.y), 0) : N;
N = AbsN.z > AbsN.x && AbsN.z > AbsN.y ? float3(0, 0, 1 * sign(N.z)) : N;
const float ThicknessRatio = abs(Hit.y - Hit.x) / CubeSize;
float3x3 TangentBasis;
TangentBasis[2] = N;
TangentBasis[0] = AbsN.x > AbsN.y && AbsN.x > AbsN.z ? float3(0, 1, 0) : (AbsN.y > AbsN.z && AbsN.y > AbsN.x ? float3(0, 0, 1) : float3(1, 0, 0));
TangentBasis[1] = AbsN.x > AbsN.y && AbsN.x > AbsN.z ? float3(0, 0, 1) : (AbsN.y > AbsN.z && AbsN.y > AbsN.x ? float3(1, 0, 0) : float3(0, 1, 0));
EvaluateLighting(
BSDF,
V,
TangentBasis,
ThicknessRatio,
OutColor);
}
}
}
void GetMaterialOnSphere(
in float4 SVPos,
in float2 Pos,
in float Size,
in FStrataBSDF BSDF,
inout float4 OutColor)
{
const float2 PixelPos = SVPos.xy;
if (BSDF_GETTYPE(BSDF) == STRATA_BSDF_TYPE_SLAB && all(PixelPos > Pos) && all(PixelPos < (Pos + Size)))
{
const float2 UV = (PixelPos - Pos) / Size;
OutColor = GetBackgroundCheckboardColor(UV);
float3 V = -View.ViewForward;
const float3 RayO = V + (UV.x-0.5) * View.ViewRight + -(UV.y-0.5) * View.ViewUp;
const float3 RayD = -V;
const float4 Sphere = float4(0.0f, 0.0f, 0.f, 0.48);
const float2 Hit = RayIntersectSphere(RayO, RayD, Sphere);
if (Hit.x >= 0)
{
float3 P = RayO + RayD * Hit.x;
float3 N = normalize(P - Sphere.xyz);
const float ThicknessRatio = (Hit.y - Hit.x) / Sphere.w;
float3x3 TangentBasis;
TangentBasis[2] = N;
TangentBasis[0] = normalize(N * float3(1, 0, 0));
TangentBasis[1] = cross(N, TangentBasis[0]);
TangentBasis[0] = -cross(N, TangentBasis[1]);
EvaluateLighting(
BSDF,
V,
TangentBasis,
ThicknessRatio,
OutColor);
}
}
}
void GetMaterialSlice(
in float4 SVPos,
in float2 Pos,
in float2 Size,
in FStrataBSDF BSDF,
inout float4 OutColor)
{
const float2 PixelPos = SVPos.xy;
if (BSDF_GETTYPE(BSDF) == STRATA_BSDF_TYPE_SLAB && all(int2(PixelPos) > int2(Pos)) && all(int2(PixelPos) < int2(Pos + Size)))
{
const float2 UV = (PixelPos - Pos) / Size;
OutColor = GetBackgroundCheckboardColor((PixelPos - Pos) / Size.x);
// View and normal along up.
float3 V = float3(0, 0, 1);
float3 N = float3(0, 0, 1);
const float ThicknessRatio = 1.0;
float3x3 TangentBasis;
TangentBasis[2] = N;
TangentBasis[0] = float3(1, 0, 0);
TangentBasis[1] = float3(0, 1, 0);
EvaluateLighting(
BSDF,
V,
TangentBasis,
ThicknessRatio,
OutColor);
}
else
{
OutColor = 0;
}
}
void MaterialDebugStrataTreePS(
float4 SVPos : SV_POSITION,
out float4 OutColor : SV_Target0)
{
OutColor = float4(0.0f, 0.0f, 0.0f, 1.0f);
FStrataAddressing StrataAddressing = GetStrataPixelDataByteOffset((float2(View.CursorPosition) * View.ViewResolutionFraction), uint2(View.BufferSizeAndInvSize.xy), Strata.MaxBytesPerPixel);
FStrataPixelHeader Header = UnpackStrataHeaderIn(Strata.MaterialTextureArray, StrataAddressing, Strata.TopLayerTexture);
if (Header.BSDFCount > 0)
{
const float2 PixelPos = SVPos.xy;
OutColor = float4(0.0f, 0.0f, 0.0f, PixelPos.x < 540.0f ? 0.5f : 1.0f); // Background
if (int(PixelPos.x) == 280 && int(PixelPos.y) > 90)
{
OutColor = float4(1.0f, 1.0f, 1.0f, 0.5f); // Operator/BSDF separator
}
const int SliceStoringDebugStrataTree = Strata.SliceStoringDebugStrataTree + STRATA_BASE_PASS_MRT_OUTPUT_COUNT;
FStrataTreeHeader StrataTreeHeader = (FStrataTreeHeader)0;
StrataUnpackInStrataTreeHeader(
Strata.MaterialTextureArray,
StrataTreeHeader,
SliceStoringDebugStrataTree);
float2 Pos = float2(BSDF_ELEMENT_STARTX, BSDF_ELEMENT_STARTY);
const float MaterialPanelSize = 200.0f;
// STRATA_TODO: read BSDF and Operators "on the fly".
{
#if STRATA_COMPILER == 1
LOOP
#else
StrataTreeHeader.BSDFCount = min(StrataTreeHeader.BSDFCount, 2);
STRATA_UNROLL_N(2)
#endif
for (int i = 0; i < StrataTreeHeader.BSDFCount; i++)
{
FStrataBSDF BSDF = StrataUnpackInStrataTreeBSDF(
i,
Strata.MaterialTextureArray,
StrataTreeHeader,
SliceStoringDebugStrataTree);
//if (BSDF.Coverage > 0.0f)
{
GetMaterialOnSphere(
SVPos,
Pos,
MaterialPanelSize,
BSDF,
OutColor);
GetMaterialOnCube(
SVPos,
Pos + float2(MaterialPanelSize + 10.0f, 0.0f),
MaterialPanelSize,
BSDF,
OutColor);
Pos.y += MaterialPanelSize + 10.0f;
}
}
}
#define MAX_LAYER_COUNT 4
float LayerAccCoverage[MAX_LAYER_COUNT];
{
for (int i = 0; i < MAX_LAYER_COUNT; ++i)
{
LayerAccCoverage[i] = 0.0f;
}
}
float2 MatTopOrigin = float2(BSDF_ELEMENT_STARTX + 450, BSDF_ELEMENT_STARTY);// float2(BSDF_ELEMENT_STARTX, 550);
float2 MatTopLayerSize = float2(410, 100);
// This is a really basic material topology debug. STRATA_TODO would be to draw the material graph itself with anottation
{
#if STRATA_COMPILER == 1
LOOP
#else
StrataTreeHeader.BSDFCount = min(StrataTreeHeader.BSDFCount, 2);
STRATA_UNROLL_N(2)
#endif
for (int i = 0; i < StrataTreeHeader.BSDFCount; i++)
{
FStrataBSDF BSDF = StrataUnpackInStrataTreeBSDF(
i,
Strata.MaterialTextureArray,
StrataTreeHeader,
SliceStoringDebugStrataTree);
FStrataOperator Op = StrataUnpackInStrataTreeOperator(
BSDF.OperatorIndex,
Strata.MaterialTextureArray,
StrataTreeHeader,
SliceStoringDebugStrataTree);
const uint LayerDepth = Op.LayerDepth;
if (LayerDepth < MAX_LAYER_COUNT)
{
// Draw the slab information
float2 LayerOrigin = MatTopOrigin + MatTopLayerSize.xy * float2(LayerAccCoverage[LayerDepth], LayerDepth);
float2 SlabSize = MatTopLayerSize.xy * float2(BSDF.Coverage, 1.0);
if (BSDF_GETTYPE(BSDF) == STRATA_BSDF_TYPE_SLAB && all(int2(PixelPos) >= int2(LayerOrigin)) && all(int2(PixelPos) <= int2(LayerOrigin + SlabSize)))
{
GetMaterialSlice(
SVPos,
LayerOrigin,
SlabSize,
BSDF,
OutColor);
}
LayerAccCoverage[LayerDepth] += BSDF.Coverage;
}
}
}
}
OutColor = float4(pow(OutColor.rgb, 1.0 / 2.2), OutColor.a);
}
#endif // SHADER_DEBUGSTRATATREE_PS