Files
UnrealEngine/Engine/Source/Runtime/Renderer/Private/HairStrands/HairStrandsDebug.cpp
2025-05-18 13:04:45 +08:00

1342 lines
61 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "HairStrandsDebug.h"
#include "HairStrandsInterface.h"
#include "HairStrandsDeepShadow.h"
#include "HairStrandsUtils.h"
#include "HairStrandsVoxelization.h"
#include "HairStrandsRendering.h"
#include "HairStrandsVisibility.h"
#include "HairStrandsInterface.h"
#include "HairStrandsTile.h"
#include "HairStrandsData.h"
#include "Shader.h"
#include "GlobalShader.h"
#include "ShaderParameters.h"
#include "ShaderParameterStruct.h"
#include "RenderGraphUtils.h"
#include "PostProcess/PostProcessing.h"
#include "PostProcess/SceneFilterRendering.h"
#include "PostProcess/SceneRenderTargets.h"
#include "SceneTextureParameters.h"
#include "DynamicPrimitiveDrawing.h"
#include "CanvasTypes.h"
#include "ShaderPrintParameters.h"
#include "RenderGraphUtils.h"
#include "ShaderPrint.h"
#include "ScreenPass.h"
#include "ScenePrivate.h"
#include "UnrealEngine.h"
#include "DataDrivenShaderPlatformInfo.h"
#include "GroomVisualizationData.h"
static int32 GDeepShadowDebugIndex = 0;
static float GDeepShadowDebugScale = 20;
static FAutoConsoleVariableRef CVarDeepShadowDebugDomIndex(TEXT("r.HairStrands.DeepShadow.DebugDOMIndex"), GDeepShadowDebugIndex, TEXT("Index of the DOM texture to draw"));
static FAutoConsoleVariableRef CVarDeepShadowDebugDomScale(TEXT("r.HairStrands.DeepShadow.DebugDOMScale"), GDeepShadowDebugScale, TEXT("Scaling value for the DeepOpacityMap when drawing the deep shadow stats"));
static int32 GHairStrandsDebugPlotBsdf = 0;
static FAutoConsoleVariableRef CVarHairStrandsDebugBSDF(TEXT("r.HairStrands.PlotBsdf"), GHairStrandsDebugPlotBsdf, TEXT("Debug view for visualizing hair BSDF."));
static float GHairStrandsDebugPlotBsdfRoughness = 0.3f;
static FAutoConsoleVariableRef CVarHairStrandsDebugBSDFRoughness(TEXT("r.HairStrands.PlotBsdf.Roughness"), GHairStrandsDebugPlotBsdfRoughness, TEXT("Change the roughness of the debug BSDF plot."));
static float GHairStrandsDebugPlotBsdfBaseColor = 1;
static FAutoConsoleVariableRef CVarHairStrandsDebugBSDFAbsorption(TEXT("r.HairStrands.PlotBsdf.BaseColor"), GHairStrandsDebugPlotBsdfBaseColor, TEXT("Change the base color / absorption of the debug BSDF plot."));
static float GHairStrandsDebugPlotBsdfExposure = 1.1f;
static FAutoConsoleVariableRef CVarHairStrandsDebugBSDFExposure(TEXT("r.HairStrands.PlotBsdf.Exposure"), GHairStrandsDebugPlotBsdfExposure, TEXT("Change the exposure of the plot."));
static int32 GHairVirtualVoxel_DebugTraversalType = 0;
static FAutoConsoleVariableRef CVarHairVirtualVoxel_DebugTraversalType(TEXT("r.HairStrands.Voxelization.Virtual.DebugTraversalType"), GHairVirtualVoxel_DebugTraversalType, TEXT("Traversal mode (0:linear, 1:mip) for debug voxel visualization."));
static bool TryEnableShaderDrawAndShaderPrint(const FViewInfo& View, uint32 ResquestedShaderDrawElements, uint32 RequestedShaderPrintElements)
{
// Force ShaderPrint on.
ShaderPrint::SetEnabled(true);
ShaderPrint::RequestSpaceForCharacters(RequestedShaderPrintElements);
ShaderPrint::RequestSpaceForLines(ResquestedShaderDrawElements);
return ShaderPrint::IsEnabled(View.ShaderPrintData);
}
FHairStrandsDebugData::FPlotData FHairStrandsDebugData::CreatePlotData(FRDGBuilder& GraphBuilder)
{
FHairStrandsDebugData::FPlotData Out;
Out.ShadingPointBuffer = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(ShadingInfo), MaxShadingPointCount), TEXT("Hair.DebugShadingPoint"));
Out.ShadingPointCounter = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32), 1), TEXT("Hair.DebugShadingPointCounter"));
Out.SampleBuffer = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(Sample), MaxSampleCount), TEXT("Hair.DebugSample"));
Out.SampleCounter = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32), 1), TEXT("Hair.DebugSampleCounter"));
AddClearUAVPass(GraphBuilder, GraphBuilder.CreateUAV(Out.ShadingPointCounter, PF_R32_UINT), 0u);
AddClearUAVPass(GraphBuilder, GraphBuilder.CreateUAV(Out.SampleCounter, PF_R32_UINT), 0u);
return Out;
}
void FHairStrandsDebugData::SetParameters(FRDGBuilder& GraphBuilder, const FHairStrandsDebugData::FPlotData& In, FHairStrandsDebugData::FWriteParameters& Out)
{
Out.Debug_MaxSampleCount = FHairStrandsDebugData::MaxSampleCount;
Out.Debug_MaxShadingPointCount = FHairStrandsDebugData::MaxShadingPointCount;
Out.Debug_ShadingPointBuffer = GraphBuilder.CreateUAV(In.ShadingPointBuffer);
Out.Debug_ShadingPointCounter = GraphBuilder.CreateUAV(In.ShadingPointCounter, PF_R32_UINT);
Out.Debug_SampleBuffer = GraphBuilder.CreateUAV(In.SampleBuffer);
Out.Debug_SampleCounter = GraphBuilder.CreateUAV(In.SampleCounter, PF_R32_UINT);
}
void FHairStrandsDebugData::SetParameters(FRDGBuilder& GraphBuilder, const FHairStrandsDebugData::FPlotData& In, FHairStrandsDebugData::FReadParameters& Out)
{
Out.Debug_MaxSampleCount = FHairStrandsDebugData::MaxSampleCount;
Out.Debug_MaxShadingPointCount = FHairStrandsDebugData::MaxShadingPointCount;
Out.Debug_ShadingPointBuffer = GraphBuilder.CreateSRV(In.ShadingPointBuffer);
Out.Debug_ShadingPointCounter = GraphBuilder.CreateSRV(In.ShadingPointCounter, PF_R32_UINT);
Out.Debug_SampleBuffer = GraphBuilder.CreateSRV(In.SampleBuffer);
Out.Debug_SampleCounter = GraphBuilder.CreateSRV(In.SampleCounter, PF_R32_UINT);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
class FHairPrintLODInfoCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FHairPrintLODInfoCS);
SHADER_USE_PARAMETER_STRUCT(FHairPrintLODInfoCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER(FIntPoint, MaxResolution)
SHADER_PARAMETER(FVector3f, GroupColor)
SHADER_PARAMETER(uint32, GroupIndex)
SHADER_PARAMETER(uint32, GeometryType)
SHADER_PARAMETER(uint32, CurveCount)
SHADER_PARAMETER(uint32, PointCount)
SHADER_PARAMETER(float, CoverageScale)
SHADER_PARAMETER(float, ScreenSize)
SHADER_PARAMETER(float, LOD)
SHADER_PARAMETER_STRUCT_INCLUDE(ShaderPrint::FShaderParameters, ShaderPrintUniformBuffer)
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return IsHairStrandsSupported(EHairStrandsShaderType::All, Parameters.Platform) && ShaderPrint::IsSupported(Parameters.Platform);
}
static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters) { return EShaderPermutationPrecacheRequest::NotPrecached; }
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
// Skip optimization for avoiding long compilation time due to large UAV writes
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
ShaderPrint::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.CompilerFlags.Add(CFLAG_Debug);
OutEnvironment.SetDefine(TEXT("SHADER_LOD_INFO"), 1);
}
};
IMPLEMENT_GLOBAL_SHADER(FHairPrintLODInfoCS, "/Engine/Private/HairStrands/HairStrandsDebug.usf", "MainCS", SF_Compute);
static void AddPrintLODInfoPass(
FRDGBuilder& GraphBuilder,
const FViewInfo& View,
const FHairGroupPublicData* Data)
{
if (!ShaderPrint::IsSupported(View.GetShaderPlatform()))
{
return;
}
// Force ShaderPrint on.
ShaderPrint::SetEnabled(true);
ShaderPrint::RequestSpaceForCharacters(2000);
if (!ShaderPrint::IsEnabled(View.ShaderPrintData))
{
return;
}
const uint32 GroupIndex = Data->GetGroupIndex();
const FLinearColor GroupColor = Data->DebugGroupColor;
const uint32 IntLODIndex = Data->LODIndex;
FHairPrintLODInfoCS::FParameters* Parameters = GraphBuilder.AllocParameters<FHairPrintLODInfoCS::FParameters>();
Parameters->MaxResolution = FIntPoint(View.ViewRect.Width(), View.ViewRect.Height());
Parameters->GroupIndex = GroupIndex;
Parameters->LOD = Data->LODIndex;
Parameters->GroupColor = FVector3f(GroupColor.R, GroupColor.G, GroupColor.B);
Parameters->ScreenSize = Data->DebugScreenSize;
Parameters->CurveCount = Data->GetActiveStrandsCurveCount();
Parameters->PointCount = Data->GetActiveStrandsPointCount();
Parameters->CoverageScale = Data->GetActiveStrandsCoverageScale();
switch (Data->VFInput.GeometryType)
{
case EHairGeometryType::Strands: Parameters->GeometryType = 0; break;
case EHairGeometryType::Cards : Parameters->GeometryType = 1; break;
case EHairGeometryType::Meshes : Parameters->GeometryType = 2; break;
}
ShaderPrint::SetParameters(GraphBuilder, View.ShaderPrintData, Parameters->ShaderPrintUniformBuffer);
TShaderMapRef<FHairPrintLODInfoCS> ComputeShader(View.ShaderMap);
ClearUnusedGraphResources(ComputeShader, Parameters);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("HairStrands::PrintLODInfo(%d/%d)", Parameters->GroupIndex, Parameters->GroupIndex),
ComputeShader,
Parameters,
FIntVector(1, 1, 1));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
class FHairDebugPrintCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FHairDebugPrintCS);
SHADER_USE_PARAMETER_STRUCT(FHairDebugPrintCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER(FIntPoint, GroupSize)
SHADER_PARAMETER(FIntPoint, MaxResolution)
SHADER_PARAMETER(uint32, FastResolveMask)
SHADER_PARAMETER(uint32, HairMacroGroupCount)
SHADER_PARAMETER(uint32, HairVisibilityNodeGroupSize)
SHADER_PARAMETER(uint32, AllocatedSampleCount)
SHADER_PARAMETER(uint32, HairInstanceCount)
SHADER_PARAMETER(float, ResolutionScale)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint>, HairInstanceDataBuffer)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<int>, InstanceAABBBuffer)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, HairCountTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, HairCountUintTexture)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint>, HairVisibilityIndirectArgsBuffer)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, HairMacroGroupAABBBuffer)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, HairMacroGroupVoxelAlignedAABBBuffer)
SHADER_PARAMETER_RDG_TEXTURE_SRV(Texture2D, StencilTexture)
SHADER_PARAMETER_SAMPLER(SamplerState, LinearSampler)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSceneUniformParameters, Scene)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
SHADER_PARAMETER_STRUCT_INCLUDE(ShaderPrint::FShaderParameters, ShaderPrintUniformBuffer)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FHairStrandsViewUniformParameters, HairStrands)
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsHairStrandsSupported(EHairStrandsShaderType::Strands, Parameters.Platform) && ShaderPrint::IsSupported(Parameters.Platform); }
static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters) { return EShaderPermutationPrecacheRequest::NotPrecached; }
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
// Skip optimization for avoiding long compilation time due to large UAV writes
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.CompilerFlags.Add(CFLAG_Debug);
OutEnvironment.SetDefine(TEXT("SHADER_PRINT"), 1);
OutEnvironment.SetDefine(TEXT("VF_SUPPORTS_PRIMITIVE_SCENE_DATA"), 1);
}
};
IMPLEMENT_GLOBAL_SHADER(FHairDebugPrintCS, "/Engine/Private/HairStrands/HairStrandsDebug.usf", "MainCS", SF_Compute);
static void AddDebugHairPrintPass(
FRDGBuilder& GraphBuilder,
const FScene* Scene,
const FViewInfo* View,
const EGroomViewMode ViewMode,
const FHairStrandsVisibilityData& VisibilityData,
const FHairStrandsMacroGroupDatas& MacroGroupDatas,
const FHairStrandsMacroGroupResources& MacroGroupResources,
FRDGTextureSRVRef InStencilTexture)
{
if (!Scene || !View || !View->HairStrandsViewData.UniformBuffer || !InStencilTexture) return;
if (!ShaderPrint::IsSupported(View->GetShaderPlatform()))
{
return;
}
if (!TryEnableShaderDrawAndShaderPrint(*View, MacroGroupResources.MacroGroupCount * 32u, 8192u))
{
return;
}
struct FData
{
uint32 PrimitiveID = ~0;
uint32 RegisteredIndex = ~0;
uint32 GeometryType = 0;
uint32 Pad0 = 0;
FVector4f InstanceScreenSphereBound = FVector4f::Zero();
};
// Build mapping Instance -> PrimitiveID to fetch primitive data (i.e., transform & co)
const uint32 MacroGroupCount = MacroGroupDatas.Num();
TArray<FData> InstanceDatas;
InstanceDatas.Reserve(MacroGroupCount * 4u);
for (uint32 MacroGroupIndex = 0; MacroGroupIndex < MacroGroupCount; ++MacroGroupIndex)
{
const FHairStrandsMacroGroupData& MacroGroup = MacroGroupDatas[MacroGroupIndex];
for (const FHairStrandsMacroGroupData::PrimitiveInfo& PrimitiveInfo : MacroGroup.PrimitivesInfos)
{
if (PrimitiveInfo.PrimitiveSceneProxy)
{
FData& InstanceData = InstanceDatas.AddDefaulted_GetRef();
InstanceData.PrimitiveID = ~0u;
if (const FPrimitiveSceneInfo* SceneInfo = PrimitiveInfo.PrimitiveSceneProxy->GetPrimitiveSceneInfo())
{
InstanceData.PrimitiveID = SceneInfo->GetIndex();
}
FHairStrandsInstance* Instance = PrimitiveInfo.PublicDataPtr->Instance;
check(Instance);
const float MaxRectSizeInPixels = FMath::Min(View->UnscaledViewRect.Height(), View->UnscaledViewRect.Width());
const float ContinousLODRadius = PrimitiveInfo.PublicDataPtr->ContinuousLODScreenSize * MaxRectSizeInPixels * 0.5f; // Diameter->Radius
InstanceData.GeometryType = Instance->GetHairGeometry();
InstanceData.RegisteredIndex = Instance->RegisteredIndex;
InstanceData.InstanceScreenSphereBound = FVector4f(PrimitiveInfo.PublicDataPtr->ContinuousLODScreenPos.X, PrimitiveInfo.PublicDataPtr->ContinuousLODScreenPos.Y, 0.f, ContinousLODRadius);
}
else
{
InstanceDatas.AddDefaulted();
}
}
}
FRDGBufferRef InstanceDataBuffer = CreateVertexBuffer(GraphBuilder, TEXT("Hair.Debug.InstanceDatas"), FRDGBufferDesc::CreateBufferDesc(sizeof(FData), InstanceDatas.Num()), InstanceDatas.GetData(), sizeof(FData) * InstanceDatas.Num());
FRDGTextureRef ViewHairCountTexture = VisibilityData.ViewHairCountTexture ? VisibilityData.ViewHairCountTexture : GSystemTextures.GetBlackDummy(GraphBuilder);
FRDGTextureRef ViewHairCountUintTexture = VisibilityData.ViewHairCountUintTexture ? VisibilityData.ViewHairCountUintTexture : GSystemTextures.GetBlackDummy(GraphBuilder);
const FIntRect Viewport = View->ViewRect;
const FIntPoint Resolution(Viewport.Width(), Viewport.Height());
FHairDebugPrintCS::FParameters* Parameters = GraphBuilder.AllocParameters<FHairDebugPrintCS::FParameters>();
Parameters->ResolutionScale = float(View->ViewRect.Width()) / float(View->UnscaledViewRect.Width());
Parameters->Scene = View->GetSceneUniforms().GetBuffer(GraphBuilder);
Parameters->HairInstanceCount = InstanceDatas.Num();
Parameters->HairInstanceDataBuffer = GraphBuilder.CreateSRV(InstanceDataBuffer, PF_R32_UINT);
Parameters->InstanceAABBBuffer = Scene->HairStrandsSceneData.TransientResources->GroupAABBSRV;
Parameters->GroupSize = GetVendorOptimalGroupSize2D();
Parameters->ViewUniformBuffer = View->ViewUniformBuffer;
Parameters->MaxResolution = VisibilityData.CoverageTexture ? VisibilityData.CoverageTexture->Desc.Extent : FIntPoint(0,0);
Parameters->AllocatedSampleCount = VisibilityData.MaxNodeCount;
Parameters->FastResolveMask = STENCIL_TEMPORAL_RESPONSIVE_AA_MASK;
Parameters->HairCountTexture = ViewHairCountTexture;
Parameters->HairCountUintTexture = ViewHairCountUintTexture;
Parameters->HairVisibilityIndirectArgsBuffer = GraphBuilder.CreateSRV(VisibilityData.NodeIndirectArg, PF_R32_UINT);
Parameters->HairVisibilityNodeGroupSize = VisibilityData.NodeGroupSize;
Parameters->StencilTexture = InStencilTexture;
Parameters->LinearSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
Parameters->HairMacroGroupCount = MacroGroupResources.MacroGroupCount;
Parameters->HairStrands = View->HairStrandsViewData.UniformBuffer;
Parameters->HairMacroGroupAABBBuffer = GraphBuilder.CreateSRV(MacroGroupResources.MacroGroupAABBsBuffer, PF_R32_SINT);
Parameters->HairMacroGroupVoxelAlignedAABBBuffer = GraphBuilder.CreateSRV(MacroGroupResources.MacroGroupVoxelAlignedAABBsBuffer, PF_R32_SINT);
ShaderPrint::SetParameters(GraphBuilder, View->ShaderPrintData, Parameters->ShaderPrintUniformBuffer);
TShaderMapRef<FHairDebugPrintCS> ComputeShader(View->ShaderMap);
ClearUnusedGraphResources(ComputeShader, Parameters);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("HairStrands::DebugPrint"),
ComputeShader,
Parameters,
FIntVector(1, 1, 1));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
class FHairDebugShadowCullingCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FHairDebugShadowCullingCS);
SHADER_USE_PARAMETER_STRUCT(FHairDebugShadowCullingCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER(uint32, InstanceCount)
SHADER_PARAMETER(FVector3f, LightCenter)
SHADER_PARAMETER(FVector3f, LightExtent)
SHADER_PARAMETER(FMatrix44f, LightToWorld)
SHADER_PARAMETER(FMatrix44f, ViewWorldToProj)
SHADER_PARAMETER(FMatrix44f, ViewProjToWorld)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, InstanceBoundInWorldSpace)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, InstanceBoundInLightSpace)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, InstanceIntersection)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
SHADER_PARAMETER_STRUCT_INCLUDE(ShaderPrint::FShaderParameters, ShaderPrintUniformBuffer)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FHairStrandsViewUniformParameters, HairStrands)
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsHairStrandsSupported(EHairStrandsShaderType::Strands, Parameters.Platform) && ShaderPrint::IsSupported(Parameters.Platform); }
static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters) { return EShaderPermutationPrecacheRequest::NotPrecached; }
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
// Skip optimization for avoiding long compilation time due to large UAV writes
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.CompilerFlags.Add(CFLAG_Debug);
OutEnvironment.SetDefine(TEXT("SHADER_SHADOW_CULLING"), 1);
}
};
IMPLEMENT_GLOBAL_SHADER(FHairDebugShadowCullingCS, "/Engine/Private/HairStrands/HairStrandsDebug.usf", "MainCS", SF_Compute);
static void AddDebugHairShadowCullingPass(
FRDGBuilder& GraphBuilder,
const FScene* Scene,
const FViewInfo* View)
{
if (!Scene || !View || !View->HairStrandsViewData.UniformBuffer) return;
if (!ShaderPrint::IsSupported(View->GetShaderPlatform()))
{
return;
}
const uint32 LightCount = View->HairStrandsViewData.DebugData.CullData.DirectionalLights.Num();
uint32 InstanceCount = 0;
for (auto It : View->HairStrandsViewData.DebugData.CullData.DirectionalLights)
{
InstanceCount += It.InstanceBoundInLightSpace.Num();
}
if (LightCount == 0 || InstanceCount == 0)
{
return;
}
if (!TryEnableShaderDrawAndShaderPrint(*View, 2000u, 2000u))
{
return;
}
auto CreateBoundBuffer = [&](const TArray<FHairStrandsDebugData::FCullData::FBound>& In)
{
TArray<float> Bound; Bound.Reserve(In.Num() * 6);
for (auto& B : In)
{
Bound.Add(B.Min.X);
Bound.Add(B.Min.Y);
Bound.Add(B.Min.Z);
Bound.Add(B.Max.X);
Bound.Add(B.Max.Y);
Bound.Add(B.Max.Z);
}
return CreateVertexBuffer(GraphBuilder, TEXT("Hair.Debug.InstanceBounds"), FRDGBufferDesc::CreateBufferDesc(4, Bound.Num()), Bound.GetData(), 4u * Bound.Num());
};
uint32 LightIndex = 0;
for (auto It : View->HairStrandsViewData.DebugData.CullData.DirectionalLights)
{
FRDGBufferRef InstanceBoundInLightSpaceBuffer = CreateBoundBuffer(It.InstanceBoundInLightSpace);
FRDGBufferRef InstanceBoundInWorldSpaceBuffer = CreateBoundBuffer(It.InstanceBoundInWorldSpace);
FRDGBufferRef InstanceIntersectionBuffer = CreateVertexBuffer(GraphBuilder, TEXT("Hair.Debug.InstanceIntersection"), FRDGBufferDesc::CreateBufferDesc(4, It.InstanceIntersection.Num()), It.InstanceIntersection.GetData(), 4u * It.InstanceIntersection.Num());
FHairDebugShadowCullingCS::FParameters* Parameters = GraphBuilder.AllocParameters<FHairDebugShadowCullingCS::FParameters>();
Parameters->InstanceCount = InstanceCount;
Parameters->LightCenter = It.Center;
Parameters->LightExtent = It.Extent;
Parameters->LightToWorld = FMatrix44f(It.LightToWorld);
Parameters->ViewWorldToProj = FMatrix44f(View->ViewMatrices.GetViewProjectionMatrix());
Parameters->ViewProjToWorld = FMatrix44f(View->ViewMatrices.GetInvViewProjectionMatrix());
Parameters->InstanceBoundInLightSpace = GraphBuilder.CreateSRV(InstanceBoundInLightSpaceBuffer, PF_R32_FLOAT);
Parameters->InstanceBoundInWorldSpace = GraphBuilder.CreateSRV(InstanceBoundInWorldSpaceBuffer, PF_R32_FLOAT);
Parameters->InstanceIntersection = GraphBuilder.CreateSRV(InstanceIntersectionBuffer, PF_R32_UINT);
Parameters->ViewUniformBuffer = View->ViewUniformBuffer;
ShaderPrint::SetParameters(GraphBuilder, View->ShaderPrintData, Parameters->ShaderPrintUniformBuffer);
Parameters->HairStrands = View->HairStrandsViewData.UniformBuffer;
TShaderMapRef<FHairDebugShadowCullingCS> ComputeShader(View->ShaderMap);
ClearUnusedGraphResources(ComputeShader, Parameters);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("HairStrands::DebugShadowCulling(%d/%d)", LightIndex++, LightCount),
ComputeShader,
Parameters,
FIntVector(1, 1, 1));
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
class FHairDebugPS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FHairDebugPS);
SHADER_USE_PARAMETER_STRUCT(FHairDebugPS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER(FVector2f, OutputResolution)
SHADER_PARAMETER(uint32, FastResolveMask)
SHADER_PARAMETER(uint32, DebugMode)
SHADER_PARAMETER(int32, SampleIndex)
SHADER_PARAMETER(uint32, MaxSampleCount)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, HairCountTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, HairCountUintTexture)
SHADER_PARAMETER_RDG_TEXTURE_SRV(Texture2D, DepthStencilTexture)
SHADER_PARAMETER_SAMPLER(SamplerState, LinearSampler)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FHairStrandsViewUniformParameters, HairStrands)
RENDER_TARGET_BINDING_SLOTS()
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsHairStrandsSupported(EHairStrandsShaderType::Strands, Parameters.Platform); }
static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters) { return EShaderPermutationPrecacheRequest::NotPrecached; }
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("SHADER_DEBUG_MODE"), 1);
}
};
IMPLEMENT_GLOBAL_SHADER(FHairDebugPS, "/Engine/Private/HairStrands/HairStrandsDebug.usf", "MainPS", SF_Pixel);
static void AddDebugHairPass(
FRDGBuilder& GraphBuilder,
const FViewInfo* View,
const EGroomViewMode InDebugMode,
const FHairStrandsVisibilityData& VisibilityData,
FRDGTextureSRVRef InDepthStencilTexture,
FRDGTextureRef& OutTarget)
{
check(OutTarget);
check(InDebugMode == EGroomViewMode::TAAResolveType ||
InDebugMode == EGroomViewMode::SamplePerPixel ||
InDebugMode == EGroomViewMode::CoverageType ||
InDebugMode == EGroomViewMode::Coverage ||
InDebugMode == EGroomViewMode::MaterialDepth ||
InDebugMode == EGroomViewMode::MaterialBaseColor ||
InDebugMode == EGroomViewMode::MaterialRoughness ||
InDebugMode == EGroomViewMode::MaterialSpecular ||
InDebugMode == EGroomViewMode::MaterialTangent);
if (!VisibilityData.CoverageTexture || !VisibilityData.NodeIndex || !VisibilityData.NodeData) return;
if (InDebugMode == EGroomViewMode::TAAResolveType && !InDepthStencilTexture) return;
const FIntRect Viewport = View->ViewRect;
const FIntPoint Resolution(Viewport.Width(), Viewport.Height());
uint32 InternalDebugMode = 0;
switch (InDebugMode)
{
case EGroomViewMode::SamplePerPixel: InternalDebugMode = 0; break;
case EGroomViewMode::CoverageType: InternalDebugMode = 1; break;
case EGroomViewMode::TAAResolveType: InternalDebugMode = 2; break;
case EGroomViewMode::Coverage: InternalDebugMode = 3; break;
case EGroomViewMode::MaterialDepth: InternalDebugMode = 4; break;
case EGroomViewMode::MaterialBaseColor: InternalDebugMode = 5; break;
case EGroomViewMode::MaterialRoughness: InternalDebugMode = 6; break;
case EGroomViewMode::MaterialSpecular: InternalDebugMode = 7; break;
case EGroomViewMode::MaterialTangent: InternalDebugMode = 8; break;
};
FHairDebugPS::FParameters* Parameters = GraphBuilder.AllocParameters<FHairDebugPS::FParameters>();
Parameters->ViewUniformBuffer = View->ViewUniformBuffer;
Parameters->OutputResolution = Resolution;
Parameters->FastResolveMask = STENCIL_TEMPORAL_RESPONSIVE_AA_MASK;
Parameters->HairStrands = View->HairStrandsViewData.UniformBuffer;
Parameters->DepthStencilTexture = InDepthStencilTexture;
Parameters->LinearSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
Parameters->DebugMode = InternalDebugMode;
Parameters->SampleIndex = 0;
Parameters->RenderTargets[0] = FRenderTargetBinding(OutTarget, ERenderTargetLoadAction::ELoad, 0);
TShaderMapRef<FScreenVS> VertexShader(View->ShaderMap);
TShaderMapRef<FHairDebugPS> PixelShader(View->ShaderMap);
ClearUnusedGraphResources(PixelShader, Parameters);
GraphBuilder.AddPass(
RDG_EVENT_NAME("HairStrands::DebugMode(%s)", GetGroomViewModeName(InDebugMode)),
Parameters,
ERDGPassFlags::Raster,
[Parameters, VertexShader, PixelShader, Viewport, Resolution](FRDGAsyncTask, FRHICommandList& RHICmdList)
{
FGraphicsPipelineStateInitializer GraphicsPSOInit;
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
GraphicsPSOInit.BlendState = TStaticBlendState<CW_RGBA, BO_Add, BF_SourceAlpha, BF_InverseSourceAlpha, BO_Add, BF_One, BF_Zero>::GetRHI();
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<>::GetRHI();
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always>::GetRHI();
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI;
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader();
GraphicsPSOInit.PrimitiveType = PT_TriangleList;
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0);
RHICmdList.SetViewport(Viewport.Min.X, Viewport.Min.Y, 0.0f, Viewport.Max.X, Viewport.Max.Y, 1.0f);
SetShaderParameters(RHICmdList, PixelShader, PixelShader.GetPixelShader(), *Parameters);
DrawRectangle(
RHICmdList,
0, 0,
Viewport.Width(), Viewport.Height(),
Viewport.Min.X, Viewport.Min.Y,
Viewport.Width(), Viewport.Height(),
Viewport.Size(),
Resolution,
VertexShader,
EDRF_UseTriangleOptimization);
});
}
///////////////////////////////////////////////////////////////////////////////////////////////////
class FDeepShadowVisualizePS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FDeepShadowVisualizePS);
SHADER_USE_PARAMETER_STRUCT(FDeepShadowVisualizePS, FGlobalShader);
class FOutputType : SHADER_PERMUTATION_INT("PERMUTATION_OUTPUT_TYPE", 2);
using FPermutationDomain = TShaderPermutationDomain<FOutputType>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER(float, DomScale)
SHADER_PARAMETER(FVector2f, OutputResolution)
SHADER_PARAMETER(FVector2f, InvOutputResolution)
SHADER_PARAMETER(FIntVector4, HairViewRect)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DeepShadowDepthTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DeepShadowLayerTexture)
SHADER_PARAMETER_SAMPLER(SamplerState, LinearSampler)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
RENDER_TARGET_BINDING_SLOTS()
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsHairStrandsSupported(EHairStrandsShaderType::Strands, Parameters.Platform); }
static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters) { return EShaderPermutationPrecacheRequest::NotPrecached; }
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("SHADER_VISUALIZEDOM"), 1);
}
};
IMPLEMENT_GLOBAL_SHADER(FDeepShadowVisualizePS, "/Engine/Private/HairStrands/HairStrandsDebug.usf", "VisualizeDomPS", SF_Pixel);
static void AddDebugDeepShadowTexturePass(
FRDGBuilder& GraphBuilder,
const FViewInfo* View,
const FIntRect& HairViewRect,
const FHairStrandsDeepShadowData* ShadowData,
const FHairStrandsDeepShadowResources* Resources,
FRDGTextureRef& OutTarget)
{
check(OutTarget);
const FIntRect Viewport = View->ViewRect;
const FIntPoint Resolution(Viewport.Width(), Viewport.Height());
FDeepShadowVisualizePS::FParameters* Parameters = GraphBuilder.AllocParameters<FDeepShadowVisualizePS::FParameters>();
Parameters->DomScale = GDeepShadowDebugScale;
Parameters->OutputResolution = Resolution;
Parameters->InvOutputResolution = FVector2f(1.f / Resolution.X, 1.f / Resolution.Y);
Parameters->DeepShadowDepthTexture = Resources ? Resources->DepthAtlasTexture : nullptr;
Parameters->DeepShadowLayerTexture = Resources ? Resources->LayersAtlasTexture : nullptr;
Parameters->LinearSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
Parameters->HairViewRect = FIntVector4(HairViewRect.Min.X, HairViewRect.Min.Y, HairViewRect.Width(), HairViewRect.Height());
Parameters->RenderTargets[0] = FRenderTargetBinding(OutTarget, ERenderTargetLoadAction::ELoad, 0);
TShaderMapRef<FScreenVS> VertexShader(View->ShaderMap);
FDeepShadowVisualizePS::FPermutationDomain PermutationVector;
PermutationVector.Set<FDeepShadowVisualizePS::FOutputType>(ShadowData ? 0 : 1);
TShaderMapRef<FDeepShadowVisualizePS> PixelShader(View->ShaderMap, PermutationVector);
ClearUnusedGraphResources(PixelShader, Parameters);
GraphBuilder.AddPass(
ShadowData ? RDG_EVENT_NAME("DebugDeepShadowTexture") : RDG_EVENT_NAME("DebugHairViewRect"),
Parameters,
ERDGPassFlags::Raster,
[Parameters, VertexShader, PixelShader, Viewport, Resolution](FRDGAsyncTask, FRHICommandList& RHICmdList)
{
FGraphicsPipelineStateInitializer GraphicsPSOInit;
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
GraphicsPSOInit.BlendState = TStaticBlendState<CW_RGBA, BO_Add, BF_One, BF_Zero, BO_Add, BF_One, BF_Zero>::GetRHI();
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<>::GetRHI();
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always>::GetRHI();
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI;
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader();
GraphicsPSOInit.PrimitiveType = PT_TriangleList;
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0);
RHICmdList.SetViewport(Viewport.Min.X, Viewport.Min.Y, 0.0f, Viewport.Max.X, Viewport.Max.Y, 1.0f);
SetShaderParameters(RHICmdList, PixelShader, PixelShader.GetPixelShader(), *Parameters);
DrawRectangle(
RHICmdList,
0, 0,
Viewport.Width(), Viewport.Height(),
Viewport.Min.X, Viewport.Min.Y,
Viewport.Width(), Viewport.Height(),
Viewport.Size(),
Resolution,
VertexShader,
EDRF_UseTriangleOptimization);
});
}
///////////////////////////////////////////////////////////////////////////////////////////////////
class FDeepShadowInfoCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FDeepShadowInfoCS);
SHADER_USE_PARAMETER_STRUCT(FDeepShadowInfoCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FSceneTextureParameters, SceneTextures)
SHADER_PARAMETER_STRUCT_INCLUDE(ShaderPrint::FShaderParameters, ShaderPrintParameters)
SHADER_PARAMETER(FVector2f, OutputResolution)
SHADER_PARAMETER(uint32, AllocatedSlotCount)
SHADER_PARAMETER(uint32, MacroGroupCount)
SHADER_PARAMETER(uint32, bViewRectOptimizeEnabled)
SHADER_PARAMETER(uint32, bVoxelizationEnabled)
SHADER_PARAMETER(FIntPoint, AtlasResolution)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, MacroGroupAABBBuffer)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, ShadowViewInfoBuffer)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, OutputTexture)
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsHairStrandsSupported(EHairStrandsShaderType::Strands, Parameters.Platform) && ShaderPrint::IsSupported(Parameters.Platform); }
static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters) { return EShaderPermutationPrecacheRequest::NotPrecached; }
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
ShaderPrint::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.CompilerFlags.Add(CFLAG_Debug);
OutEnvironment.SetDefine(TEXT("SHADER_DOMINFO"), 1);
}
};
IMPLEMENT_GLOBAL_SHADER(FDeepShadowInfoCS, "/Engine/Private/HairStrands/HairStrandsDebug.usf", "MainCS", SF_Compute);
static void AddDeepShadowInfoPass(
FRDGBuilder& GraphBuilder,
const FViewInfo& View,
const FHairStrandsDeepShadowResources& DeepShadowResources,
const FHairStrandsMacroGroupResources& MacroGroupResources,
FRDGTextureRef& OutputTexture)
{
if (!ShaderPrint::IsSupported(View.GetShaderPlatform()))
{
return;
}
if (DeepShadowResources.TotalAtlasSlotCount == 0)
{
return;
}
if (!TryEnableShaderDrawAndShaderPrint(View, DeepShadowResources.TotalAtlasSlotCount * 64, 2000))
{
return;
}
FSceneTextureParameters SceneTextures = GetSceneTextureParameters(GraphBuilder, View);
const FIntPoint Resolution(OutputTexture->Desc.Extent);
FDeepShadowInfoCS::FParameters* Parameters = GraphBuilder.AllocParameters<FDeepShadowInfoCS::FParameters>();
Parameters->ViewUniformBuffer = View.ViewUniformBuffer;
Parameters->OutputResolution = Resolution;
Parameters->AllocatedSlotCount = DeepShadowResources.TotalAtlasSlotCount;
Parameters->MacroGroupCount = MacroGroupResources.MacroGroupCount;
Parameters->SceneTextures = SceneTextures;
Parameters->bViewRectOptimizeEnabled = IsHairStrandsViewRectOptimEnable() ? 1u : 0u;
Parameters->bVoxelizationEnabled = View.HairStrandsViewData.VirtualVoxelResources.IsValid() ? 1u : 0u;
Parameters->AtlasResolution = View.HairStrandsViewData.DeepShadowResources.DepthAtlasTexture->Desc.Extent;
Parameters->MacroGroupAABBBuffer = GraphBuilder.CreateSRV(MacroGroupResources.MacroGroupAABBsBuffer, PF_R32_SINT);
Parameters->ShadowViewInfoBuffer = GraphBuilder.CreateSRV(DeepShadowResources.DeepShadowViewInfoBuffer);
ShaderPrint::SetParameters(GraphBuilder, View.ShaderPrintData, Parameters->ShaderPrintParameters);
Parameters->OutputTexture = GraphBuilder.CreateUAV(OutputTexture);
TShaderMapRef<FDeepShadowInfoCS> ComputeShader(View.ShaderMap);
FComputeShaderUtils::AddPass(GraphBuilder, RDG_EVENT_NAME("HairStrands::DeepShadowDebugInfo"), ComputeShader, Parameters, FIntVector(1, 1, 1));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
class FVoxelVirtualRaymarchingCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FVoxelVirtualRaymarchingCS);
SHADER_USE_PARAMETER_STRUCT(FVoxelVirtualRaymarchingCS, FGlobalShader);
class FTraversalType : SHADER_PERMUTATION_INT("PERMUTATION_TRAVERSAL", 2);
using FPermutationDomain = TShaderPermutationDomain<FTraversalType>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FSceneTextureParameters, SceneTextures)
SHADER_PARAMETER_STRUCT_INCLUDE(ShaderPrint::FShaderParameters, ShaderPrintParameters)
SHADER_PARAMETER(FVector2f, OutputResolution)
SHADER_PARAMETER(uint32, MacroGroupId)
SHADER_PARAMETER(uint32, MacroGroupCount)
SHADER_PARAMETER(uint32, MaxTotalPageIndexCount)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SceneDepthBeforeCompositionTexture)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FVirtualVoxelParameters, VirtualVoxel)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, TotalValidPageCounter)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, OutputTexture)
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsHairStrandsSupported(EHairStrandsShaderType::Strands, Parameters.Platform) && ShaderPrint::IsSupported(Parameters.Platform); }
static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters) { return EShaderPermutationPrecacheRequest::NotPrecached; }
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
// Skip optimization for avoiding long compilation time due to large UAV writes
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.CompilerFlags.Add(CFLAG_Debug);
OutEnvironment.SetDefine(TEXT("SHADER_VOXEL_DEBUG"), 1);
}
};
IMPLEMENT_GLOBAL_SHADER(FVoxelVirtualRaymarchingCS, "/Engine/Private/HairStrands/HairStrandsVoxelDebug.usf", "MainCS", SF_Compute);
static void AddVoxelPageRaymarchingPass(
FRDGBuilder& GraphBuilder,
const FViewInfo& View,
const FHairStrandsMacroGroupDatas& MacroGroupDatas,
const FHairStrandsVoxelResources& VoxelResources,
FRDGTextureRef& OutputTexture)
{
if (!ShaderPrint::IsSupported(View.GetShaderPlatform()))
{
return;
}
if (!TryEnableShaderDrawAndShaderPrint(View, 4000, 2000))
{
return;
}
FSceneTextureParameters SceneTextures = GetSceneTextureParameters(GraphBuilder, View);
const FIntPoint Resolution(OutputTexture->Desc.Extent);
for (const FHairStrandsMacroGroupData& MacroGroupData : MacroGroupDatas)
{
FVoxelVirtualRaymarchingCS::FParameters* Parameters = GraphBuilder.AllocParameters<FVoxelVirtualRaymarchingCS::FParameters>();
Parameters->ViewUniformBuffer = View.ViewUniformBuffer;
Parameters->OutputResolution = Resolution;
Parameters->SceneTextures = SceneTextures;
Parameters->MacroGroupId = MacroGroupData.MacroGroupId;
Parameters->MacroGroupCount = MacroGroupDatas.Num();
Parameters->MaxTotalPageIndexCount = VoxelResources.Parameters.Common.PageIndexCount;
Parameters->VirtualVoxel = VoxelResources.UniformBuffer;
Parameters->TotalValidPageCounter = GraphBuilder.CreateSRV(VoxelResources.PageIndexGlobalCounter, PF_R32_UINT);
ShaderPrint::SetParameters(GraphBuilder, View.ShaderPrintData, Parameters->ShaderPrintParameters);
Parameters->OutputTexture = GraphBuilder.CreateUAV(OutputTexture);
Parameters->SceneDepthBeforeCompositionTexture = View.HairStrandsViewData.DebugData.Common.SceneDepthTextureBeforeCompsition;
if (Parameters->SceneDepthBeforeCompositionTexture == nullptr)
{
Parameters->SceneDepthBeforeCompositionTexture = SceneTextures.SceneDepthTexture;
}
FVoxelVirtualRaymarchingCS::FPermutationDomain PermutationVector;
PermutationVector.Set<FVoxelVirtualRaymarchingCS::FTraversalType>(GHairVirtualVoxel_DebugTraversalType > 0 ? 1 : 0);
TShaderMapRef<FVoxelVirtualRaymarchingCS> ComputeShader(View.ShaderMap, PermutationVector);
const FIntVector DispatchCount = DispatchCount.DivideAndRoundUp(FIntVector(OutputTexture->Desc.Extent.X, OutputTexture->Desc.Extent.Y, 1), FIntVector(8, 8, 1));
FComputeShaderUtils::AddPass(GraphBuilder, RDG_EVENT_NAME("HairStrands::VoxelVirtualRaymarching"), ComputeShader, Parameters, DispatchCount);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
class FDebugHairTangentCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FDebugHairTangentCS);
SHADER_USE_PARAMETER_STRUCT(FDebugHairTangentCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSceneTextureUniformParameters, SceneTextures)
SHADER_PARAMETER_STRUCT_INCLUDE(ShaderPrint::FShaderParameters, ShaderPrint)
SHADER_PARAMETER(FVector2f, OutputResolution)
SHADER_PARAMETER(FIntPoint, TileCount)
SHADER_PARAMETER(uint32, TileSize)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
SHADER_PARAMETER_SAMPLER(SamplerState, BilinearTextureSampler)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FHairStrandsViewUniformParameters, HairStrands)
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsHairStrandsSupported(EHairStrandsShaderType::Strands, Parameters.Platform) && ShaderPrint::IsSupported(Parameters.Platform); }
static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters) { return EShaderPermutationPrecacheRequest::NotPrecached; }
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("SHADER_TANGENT"), 1);
}
};
IMPLEMENT_GLOBAL_SHADER(FDebugHairTangentCS, "/Engine/Private/HairStrands/HairStrandsDebug.usf", "MainCS", SF_Compute);
static void AddDebugHairTangentPass(
FRDGBuilder& GraphBuilder,
const FViewInfo& View,
const FSceneTextures& SceneTextures,
FRDGTextureRef& OutputTexture)
{
if (!ShaderPrint::IsSupported(View.GetShaderPlatform()))
{
return;
}
if (!TryEnableShaderDrawAndShaderPrint(View, 64000u, 1000u))
{
return;
}
FDebugHairTangentCS::FParameters* Parameters = GraphBuilder.AllocParameters<FDebugHairTangentCS::FParameters>();
Parameters->ViewUniformBuffer = View.ViewUniformBuffer;
Parameters->HairStrands = View.HairStrandsViewData.UniformBuffer;
Parameters->OutputResolution = OutputTexture->Desc.Extent;
Parameters->TileSize = 8;
Parameters->TileCount = FIntPoint(FMath::FloorToInt(Parameters->OutputResolution.X / Parameters->TileSize), FMath::FloorToInt(Parameters->OutputResolution.X / Parameters->TileSize));
Parameters->SceneTextures = SceneTextures.UniformBuffer;
Parameters->BilinearTextureSampler = TStaticSamplerState<SF_Bilinear>::GetRHI();
ShaderPrint::SetParameters(GraphBuilder, View.ShaderPrintData, Parameters->ShaderPrint);
const FIntVector DispatchCount = DispatchCount.DivideAndRoundUp(FIntVector(OutputTexture->Desc.Extent.X, OutputTexture->Desc.Extent.Y, 1), FIntVector(8, 8, 1));
ShaderPrint::RequestSpaceForLines(DispatchCount.X * DispatchCount.Y);
TShaderMapRef<FDebugHairTangentCS> ComputeShader(View.ShaderMap);
FComputeShaderUtils::AddPass(GraphBuilder, RDG_EVENT_NAME("HairStrands::DebugTangentCS"), ComputeShader, Parameters, DispatchCount);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
class FHairStrandsPlotBSDFPS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FHairStrandsPlotBSDFPS);
SHADER_USE_PARAMETER_STRUCT(FHairStrandsPlotBSDFPS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER(FIntPoint, InputCoord)
SHADER_PARAMETER(FIntPoint, OutputOffset)
SHADER_PARAMETER(FIntPoint, OutputResolution)
SHADER_PARAMETER(FIntPoint, MaxResolution)
SHADER_PARAMETER(uint32, HairComponents)
SHADER_PARAMETER(float, Roughness)
SHADER_PARAMETER(float, BaseColor)
SHADER_PARAMETER(float, Exposure)
RENDER_TARGET_BINDING_SLOTS()
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsHairStrandsSupported(EHairStrandsShaderType::Tool, Parameters.Platform); }
static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters) { return EShaderPermutationPrecacheRequest::NotPrecached; }
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("SHADER_PLOTBSDF"), 1);
}
};
IMPLEMENT_GLOBAL_SHADER(FHairStrandsPlotBSDFPS, "/Engine/Private/HairStrands/HairStrandsDebug.usf", "MainPS", SF_Pixel);
static void AddPlotBSDFPass(
FRDGBuilder& GraphBuilder,
const FViewInfo& View,
FRDGTextureRef& OutputTexture)
{
FSceneTextureParameters SceneTextures = GetSceneTextureParameters(GraphBuilder, View);
const FIntPoint Resolution(OutputTexture->Desc.Extent);
FHairStrandsPlotBSDFPS::FParameters* Parameters = GraphBuilder.AllocParameters<FHairStrandsPlotBSDFPS::FParameters>();
Parameters->InputCoord = View.CursorPos;
Parameters->OutputOffset = FIntPoint(10,100);
Parameters->OutputResolution = FIntPoint(256, 256);
Parameters->MaxResolution = OutputTexture->Desc.Extent;
Parameters->HairComponents = ToBitfield(GetHairComponents());
Parameters->Roughness = GHairStrandsDebugPlotBsdfRoughness;
Parameters->BaseColor = GHairStrandsDebugPlotBsdfBaseColor;
Parameters->Exposure = GHairStrandsDebugPlotBsdfExposure;
Parameters->RenderTargets[0] = FRenderTargetBinding(OutputTexture, ERenderTargetLoadAction::ELoad);
const FIntPoint OutputResolution = SceneTextures.SceneDepthTexture->Desc.Extent;
TShaderMapRef<FScreenVS> VertexShader(View.ShaderMap);
TShaderMapRef<FHairStrandsPlotBSDFPS> PixelShader(View.ShaderMap);
const FGlobalShaderMap* GlobalShaderMap = View.ShaderMap;
const FIntRect Viewport = View.ViewRect;
ClearUnusedGraphResources(PixelShader, Parameters);
GraphBuilder.AddPass(
RDG_EVENT_NAME("HairStrands::BsdfPlot"),
Parameters,
ERDGPassFlags::Raster,
[Parameters, VertexShader, PixelShader, Viewport, Resolution](FRDGAsyncTask, FRHICommandList& RHICmdList)
{
FGraphicsPipelineStateInitializer GraphicsPSOInit;
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
GraphicsPSOInit.BlendState = TStaticBlendState<CW_RGBA, BO_Add, BF_One, BF_Zero, BO_Add, BF_One, BF_Zero>::GetRHI();
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<>::GetRHI();
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always>::GetRHI();
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI;
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader();
GraphicsPSOInit.PrimitiveType = PT_TriangleList;
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0);
RHICmdList.SetViewport(Viewport.Min.X, Viewport.Min.Y, 0.0f, Viewport.Max.X, Viewport.Max.Y, 1.0f);
SetShaderParameters(RHICmdList, PixelShader, PixelShader.GetPixelShader(), *Parameters);
DrawRectangle(
RHICmdList,
0, 0,
Viewport.Width(), Viewport.Height(),
Viewport.Min.X, Viewport.Min.Y,
Viewport.Width(), Viewport.Height(),
Viewport.Size(),
Resolution,
VertexShader,
EDRF_UseTriangleOptimization);
});
}
///////////////////////////////////////////////////////////////////////////////////////////////////
class FHairStrandsPlotSamplePS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FHairStrandsPlotSamplePS);
SHADER_USE_PARAMETER_STRUCT(FHairStrandsPlotSamplePS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FHairStrandsDebugData::FReadParameters, DebugData)
SHADER_PARAMETER(FIntPoint, OutputOffset)
SHADER_PARAMETER(FIntPoint, OutputResolution)
SHADER_PARAMETER(FIntPoint, MaxResolution)
SHADER_PARAMETER(uint32, HairComponents)
SHADER_PARAMETER(float, Exposure)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
RENDER_TARGET_BINDING_SLOTS()
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsHairStrandsSupported(EHairStrandsShaderType::Tool, Parameters.Platform); }
static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters) { return EShaderPermutationPrecacheRequest::NotPrecached; }
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("SHADER_PLOTSAMPLE"), 1);
}
};
IMPLEMENT_GLOBAL_SHADER(FHairStrandsPlotSamplePS, "/Engine/Private/HairStrands/HairStrandsDebug.usf", "MainPS", SF_Pixel);
static void AddPlotSamplePass(
FRDGBuilder& GraphBuilder,
const FViewInfo& View,
const FHairStrandsDebugData::FPlotData& DebugData,
FRDGTextureRef& OutputTexture)
{
FSceneTextureParameters SceneTextures = GetSceneTextureParameters(GraphBuilder, View);
const FIntPoint Resolution(OutputTexture->Desc.Extent);
FHairStrandsPlotSamplePS::FParameters* Parameters = GraphBuilder.AllocParameters<FHairStrandsPlotSamplePS::FParameters>();
FHairStrandsDebugData::SetParameters(GraphBuilder, DebugData, Parameters->DebugData);
Parameters->ViewUniformBuffer = View.ViewUniformBuffer;
Parameters->OutputOffset = FIntPoint(100, 100);
Parameters->OutputResolution = FIntPoint(256, 256);
Parameters->MaxResolution = OutputTexture->Desc.Extent;
Parameters->HairComponents = ToBitfield(GetHairComponents());
Parameters->Exposure = GHairStrandsDebugPlotBsdfExposure;
Parameters->RenderTargets[0] = FRenderTargetBinding(OutputTexture, ERenderTargetLoadAction::ELoad);
const FIntPoint OutputResolution = SceneTextures.SceneDepthTexture->Desc.Extent;
TShaderMapRef<FScreenVS> VertexShader(View.ShaderMap);
TShaderMapRef<FHairStrandsPlotSamplePS> PixelShader(View.ShaderMap);
const FGlobalShaderMap* GlobalShaderMap = View.ShaderMap;
const FIntRect Viewport = View.ViewRect;
ClearUnusedGraphResources(PixelShader, Parameters);
GraphBuilder.AddPass(
RDG_EVENT_NAME("HairStrands::SamplePlot"),
Parameters,
ERDGPassFlags::Raster,
[Parameters, VertexShader, PixelShader, Viewport, Resolution](FRDGAsyncTask, FRHICommandList& RHICmdList)
{
FGraphicsPipelineStateInitializer GraphicsPSOInit;
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
GraphicsPSOInit.BlendState = TStaticBlendState<CW_RGBA, BO_Add, BF_One, BF_Zero, BO_Add, BF_One, BF_Zero>::GetRHI();
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<>::GetRHI();
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always>::GetRHI();
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI;
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader();
GraphicsPSOInit.PrimitiveType = PT_TriangleList;
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0);
RHICmdList.SetViewport(Viewport.Min.X, Viewport.Min.Y, 0.0f, Viewport.Max.X, Viewport.Max.Y, 1.0f);
SetShaderParameters(RHICmdList, PixelShader, PixelShader.GetPixelShader(), *Parameters);
DrawRectangle(
RHICmdList,
0, 0,
Viewport.Width(), Viewport.Height(),
Viewport.Min.X, Viewport.Min.Y,
Viewport.Width(), Viewport.Height(),
Viewport.Size(),
Resolution,
VertexShader,
EDRF_UseTriangleOptimization);
});
}
///////////////////////////////////////////////////////////////////////////////////////////////////
class FHairVisibilityDebugPPLLCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FHairVisibilityDebugPPLLCS);
SHADER_USE_PARAMETER_STRUCT(FHairVisibilityDebugPPLLCS, FGlobalShader);
using FPermutationDomain = TShaderPermutationDomain<>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
SHADER_PARAMETER(float, PPLLMeanListElementCountPerPixel)
SHADER_PARAMETER(float, PPLLMaxTotalListElementCount)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, PPLLCounter)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, PPLLNodeIndex)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, PPLLNodeData)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, SceneColorTextureUAV)
SHADER_PARAMETER_STRUCT_INCLUDE(ShaderPrint::FShaderParameters, ShaderPrintParameters)
END_SHADER_PARAMETER_STRUCT()
static FPermutationDomain RemapPermutation(FPermutationDomain PermutationVector)
{
return PermutationVector;
}
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return IsHairStrandsSupported(EHairStrandsShaderType::Tool, Parameters.Platform) && ShaderPrint::IsSupported(Parameters.Platform);
}
static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters) { return EShaderPermutationPrecacheRequest::NotPrecached; }
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("SHADER_PPLL_DEBUG"), 1);
// Skip optimization for avoiding long compilation time due to large UAV writes
OutEnvironment.CompilerFlags.Add(CFLAG_Debug);
}
};
IMPLEMENT_GLOBAL_SHADER(FHairVisibilityDebugPPLLCS, "/Engine/Private/HairStrands/HairStrandsDebug.usf", "VisibilityDebugPPLLCS", SF_Compute);
///////////////////////////////////////////////////////////////////////////////////////////////////
uint32 GetHairStrandsMeanSamplePerPixel(EShaderPlatform In);
static void InternalRenderHairStrandsDebugInfo(
FRDGBuilder& GraphBuilder,
FScene* Scene,
FViewInfo& View,
FHairStrandsBookmarkParameters& Params)
{
if (!ShaderPrint::IsSupported(View.GetShaderPlatform()))
{
return;
}
if (!Params.HasInstances())
{
return;
}
const float YStep = 14;
const float ColumnWidth = 200;
RDG_EVENT_SCOPE(GraphBuilder, "HairStrandsDebug");
// Only render debug information for the main view
const FSceneTextures& SceneTextures = View.GetSceneTextures();
// Bookmark for calling debug rendering from the plugin
{
const FSceneView* View0 = Params.View;
FShaderPrintData* View0ShaderPrintData = Params.ShaderPrintData;
Params.View = &View;
Params.ShaderPrintData = &View.ShaderPrintData;
RunHairStrandsBookmark(GraphBuilder, EHairStrandsBookmark::ProcessDebug, Params);
Params.View = View0;
Params.ShaderPrintData = View0ShaderPrintData;
}
const EGroomViewMode ViewMode = GetGroomViewMode(View);
// Display tangent vector for strands/cards/meshes
if (ViewMode == EGroomViewMode::Tangent)
{
AddDebugHairTangentPass(GraphBuilder, View, SceneTextures, Params.SceneColorTexture);
}
// Draw LOD info
for (const FMeshBatchAndRelevance& Mesh : View.HairStrandsMeshElements)
{
const FHairGroupPublicData* GroupData = HairStrands::GetHairData(Mesh.Mesh);
if (GroupData->bDebugDrawLODInfo)
{
AddPrintLODInfoPass(GraphBuilder, View, GroupData);
}
}
for (const FMeshBatchAndRelevance& Mesh : View.HairCardsMeshElements)
{
const FHairGroupPublicData* GroupData = HairStrands::GetHairData(Mesh.Mesh);
if (GroupData->bDebugDrawLODInfo)
{
AddPrintLODInfoPass(GraphBuilder, View, GroupData);
}
}
// Pass this point, all debug rendering concern only hair strands data
if (!HairStrands::HasViewHairStrandsData(View))
{
return;
}
const FScreenPassRenderTarget SceneColor(Params.SceneColorTexture, View.ViewRect, ERenderTargetLoadAction::ELoad);
const FHairStrandsViewData& HairData = View.HairStrandsViewData;
if (GHairStrandsDebugPlotBsdf > 0 || HairData.DebugData.IsPlotDataValid())
{
if (GHairStrandsDebugPlotBsdf > 0)
{
AddPlotBSDFPass(GraphBuilder, View, Params.SceneColorTexture);
}
if (HairData.DebugData.IsPlotDataValid())
{
AddPlotSamplePass(GraphBuilder, View, HairData.DebugData.PlotData, Params.SceneColorTexture);
}
}
float ClusterY = 38;
if (View.HairStrandsViewData.DebugData.CullData.bIsValid)
{
AddDebugHairShadowCullingPass(GraphBuilder, Scene, &View);
}
if (ViewMode == EGroomViewMode::MacroGroups)
{
AddDebugHairPrintPass(GraphBuilder, Scene, &View, ViewMode, HairData.VisibilityData, HairData.MacroGroupDatas, HairData.MacroGroupResources, SceneTextures.Stencil);
}
if (ViewMode == EGroomViewMode::DeepOpacityMaps)
{
for (const FHairStrandsMacroGroupData& MacroGroup : HairData.MacroGroupDatas)
{
if (!HairData.DeepShadowResources.DepthAtlasTexture || !HairData.DeepShadowResources.LayersAtlasTexture)
{
continue;
}
for (const FHairStrandsDeepShadowData& DeepShadowData : MacroGroup.DeepShadowDatas)
{
const uint32 DomIndex = GDeepShadowDebugIndex;
if (DeepShadowData.AtlasSlotIndex != DomIndex)
continue;
AddDebugDeepShadowTexturePass(GraphBuilder, &View, FIntRect(), &DeepShadowData, &HairData.DeepShadowResources, Params.SceneColorTexture);
}
}
}
// View Rect
if (IsHairStrandsViewRectOptimEnable() && ViewMode == EGroomViewMode::MacroGroupScreenRect)
{
for (const FHairStrandsMacroGroupData& MacroGroupData : HairData.MacroGroupDatas)
{
AddDebugDeepShadowTexturePass(GraphBuilder, &View, MacroGroupData.ScreenRect, nullptr, nullptr, Params.SceneColorTexture);
}
const FIntRect TotalRect = ComputeVisibleHairStrandsMacroGroupsRect(View, View.ViewRect, HairData.MacroGroupDatas);
AddDebugDeepShadowTexturePass(GraphBuilder, &View, TotalRect, nullptr, nullptr, Params.SceneColorTexture);
}
// Render Frustum for all lights & macro groups
{
if ((ViewMode == EGroomViewMode::LightBounds || ViewMode == EGroomViewMode::DeepOpacityMaps))
{
AddDeepShadowInfoPass(GraphBuilder, View, HairData.DeepShadowResources, HairData.MacroGroupResources, Params.SceneColorTexture);
}
}
const bool bRunDebugPass =
ViewMode == EGroomViewMode::TAAResolveType ||
ViewMode == EGroomViewMode::SamplePerPixel ||
ViewMode == EGroomViewMode::CoverageType ||
ViewMode == EGroomViewMode::Coverage ||
ViewMode == EGroomViewMode::MaterialDepth ||
ViewMode == EGroomViewMode::MaterialBaseColor ||
ViewMode == EGroomViewMode::MaterialRoughness ||
ViewMode == EGroomViewMode::MaterialSpecular ||
ViewMode == EGroomViewMode::MaterialTangent;
if (bRunDebugPass)
{
AddDebugHairPass(GraphBuilder, &View, ViewMode, HairData.VisibilityData, SceneTextures.Stencil, Params.SceneColorTexture);
AddDebugHairPrintPass(GraphBuilder, Scene, &View, ViewMode, HairData.VisibilityData, HairData.MacroGroupDatas, HairData.MacroGroupResources, SceneTextures.Stencil);
}
else if (ViewMode == EGroomViewMode::Tile)
{
check(HairData.VisibilityData.TileData.IsValid());
AddHairStrandsDebugTilePass(GraphBuilder, View, Params.SceneColorTexture, HairData.VisibilityData.TileData);
}
const bool bIsVoxelMode = ViewMode == EGroomViewMode::VoxelsDensity;
if (bIsVoxelMode)
{
if (HairData.VirtualVoxelResources.IsValid())
{
AddVoxelPageRaymarchingPass(GraphBuilder, View, HairData.MacroGroupDatas, HairData.VirtualVoxelResources, Params.SceneColorTexture);
}
}
if (HairData.DebugData.IsPPLLDataValid()) // Check if PPLL rendering is used and its debug view is enabled.
{
// Force ShaderPrint on.
ShaderPrint::SetEnabled(true);
ShaderPrint::RequestSpaceForCharacters(256);
const FIntPoint PPLLResolution = HairData.DebugData.PPLLData.NodeIndexTexture->Desc.Extent;
FHairVisibilityDebugPPLLCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FHairVisibilityDebugPPLLCS::FParameters>();
PassParameters->PPLLMeanListElementCountPerPixel = GetHairStrandsMeanSamplePerPixel(View.GetShaderPlatform());
PassParameters->PPLLMaxTotalListElementCount = HairData.DebugData.PPLLData.NodeDataBuffer->Desc.NumElements;
PassParameters->PPLLCounter = HairData.DebugData.PPLLData.NodeCounterTexture;
PassParameters->PPLLNodeIndex = HairData.DebugData.PPLLData.NodeIndexTexture;
PassParameters->PPLLNodeData = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(HairData.DebugData.PPLLData.NodeDataBuffer));
PassParameters->ViewUniformBuffer = View.ViewUniformBuffer;
PassParameters->SceneColorTextureUAV = GraphBuilder.CreateUAV(Params.SceneColorTexture);
ShaderPrint::SetParameters(GraphBuilder, View.ShaderPrintData, PassParameters->ShaderPrintParameters);
FHairVisibilityDebugPPLLCS::FPermutationDomain PermutationVector;
TShaderMapRef<FHairVisibilityDebugPPLLCS> ComputeShader(View.ShaderMap, PermutationVector);
FIntVector TextureSize = Params.SceneColorTexture->Desc.GetSize(); TextureSize.Z = 1;
FComputeShaderUtils::AddPass(GraphBuilder, RDG_EVENT_NAME("HairStrands::PPLLDebug"), ComputeShader, PassParameters, FIntVector::DivideAndRoundUp(TextureSize, FIntVector(8, 8, 1)));
}
if (ViewMode != EGroomViewMode::None)
{
AddDrawCanvasPass(GraphBuilder, {}, View, SceneColor, [&View, YStep, ViewMode](FCanvas& Canvas)
{
float X = 40;
float Y = View.ViewRect.Height() - YStep * 3.f;
FString Line;
if (ViewMode != EGroomViewMode::None)
{
Line = FString::Printf(TEXT("Hair Debug mode - %s"), GetGroomViewModeName(ViewMode));
}
Canvas.DrawShadowedString(X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 0));
});
}
}
void RenderHairStrandsDebugInfo(
FRDGBuilder& GraphBuilder,
FScene* Scene,
TArrayView<FViewInfo> Views,
FHairStrandsBookmarkParameters& Parameters)
{
bool bHasHairData = false;
for (FViewInfo& View : Views)
{
InternalRenderHairStrandsDebugInfo(GraphBuilder, Scene, View, Parameters);
}
}