1655 lines
66 KiB
C++
1655 lines
66 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "LumenVisualize.h"
|
|
#include "Materials/Material.h"
|
|
#include "RendererPrivate.h"
|
|
#include "ScenePrivate.h"
|
|
#include "SceneUtils.h"
|
|
#include "PipelineStateCache.h"
|
|
#include "ShaderParameterStruct.h"
|
|
#include "ReflectionEnvironment.h"
|
|
#include "LumenMeshCards.h"
|
|
#include "LumenRadianceCache.h"
|
|
#include "DynamicMeshBuilder.h"
|
|
#include "LumenScreenProbeGather.h"
|
|
#include "DistanceFieldAtlas.h"
|
|
#include "LumenSurfaceCacheFeedback.h"
|
|
#include "LumenVisualizationData.h"
|
|
#include "MeshCardBuild.h"
|
|
#include "LumenReflections.h"
|
|
#include "InstanceDataSceneProxy.h"
|
|
#include "LumenHardwareRayTracingCommon.h"
|
|
|
|
// Must be in sync with VISUALIZE_MODE_* in LumenVisualize.h
|
|
int32 GLumenVisualize = 0;
|
|
FAutoConsoleVariableRef CVarLumenVisualize(
|
|
TEXT("r.Lumen.Visualize"),
|
|
GLumenVisualize,
|
|
TEXT("Lumen scene visualization mode.\n")
|
|
TEXT("0 - Disable\n")
|
|
TEXT("1 - Overview\n")
|
|
TEXT("2 - Performance Overview\n")
|
|
TEXT("3 - Lumen Scene\n")
|
|
TEXT("4 - Reflection View\n")
|
|
TEXT("5 - Surface Cache Coverage\n")
|
|
TEXT("6 - Geometry normals\n")
|
|
TEXT("7 - Dedicated Reflection Rays\n")
|
|
TEXT("8 - Albedo\n")
|
|
TEXT("9 - Normals\n")
|
|
TEXT("10 - Emissive\n")
|
|
TEXT("11 - Opacity (disable alpha masking)\n")
|
|
TEXT("12 - Card weights\n")
|
|
TEXT("13 - Direct lighting\n")
|
|
TEXT("14 - Indirect lighting\n")
|
|
TEXT("15 - Local Position (hardware ray-tracing only)\n")
|
|
TEXT("16 - Velocity (hardware ray-tracing only)\n")
|
|
TEXT("17 - Direct lighting updates\n")
|
|
TEXT("18 - Indirect lighting updates\n")
|
|
TEXT("19 - Last used pages\n")
|
|
TEXT("20 - Last used high res pages\n")
|
|
TEXT("21 - Card tile shadow downsample factor\n")
|
|
TEXT("22 - Card sharing ID\n")
|
|
TEXT("23 - ScreenProbeGather fast update mode amount\n")
|
|
TEXT("24 - ScreenProbeGather number of frames accumulated"),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
static TAutoConsoleVariable<int> CVarLumenVisualizeCullingMode(
|
|
TEXT("r.Lumen.Visualize.CullingMode"),
|
|
0,
|
|
TEXT("Visualize culling mode:\n")
|
|
TEXT("0 - none\n")
|
|
TEXT("1 - cull back facing triangles\n")
|
|
TEXT("2 - cull front facing triangles"),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
static TAutoConsoleVariable<bool> CVarLumenVisualizeToneMap(
|
|
TEXT("r.Lumen.Visualize.ToneMap"),
|
|
true,
|
|
TEXT("Whether to apply tone mapping to Lumen visualization."),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GVisualizeLumenSceneGridPixelSize = 32;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneGridPixelSize(
|
|
TEXT("r.Lumen.Visualize.GridPixelSize"),
|
|
GVisualizeLumenSceneGridPixelSize,
|
|
TEXT(""),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GLumenVisualizeIndirectDiffuse = 0;
|
|
FAutoConsoleVariableRef CVarLumenVisualizeIndirectDiffuse(
|
|
TEXT("r.Lumen.Visualize.IndirectDiffuse"),
|
|
GLumenVisualizeIndirectDiffuse,
|
|
TEXT("Visualize Lumen Indirect Diffuse."),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GVisualizeLumenSceneTraceMeshSDFs = 1;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneTraceMeshSDFs(
|
|
TEXT("r.Lumen.Visualize.TraceMeshSDFs"),
|
|
GVisualizeLumenSceneTraceMeshSDFs,
|
|
TEXT("Whether to use Mesh SDF tracing for lumen scene visualization."),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
float GVisualizeLumenSceneMaxMeshSDFTraceDistance = -1.0f;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneCardMaxTraceDistance(
|
|
TEXT("r.Lumen.Visualize.MaxMeshSDFTraceDistance"),
|
|
GVisualizeLumenSceneMaxMeshSDFTraceDistance,
|
|
TEXT("Max trace distance for Lumen scene visualization rays. Values below 0 will automatically derrive this from cone angle."),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GVisualizeLumenSceneHiResSurface = 1;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneHiResSurface(
|
|
TEXT("r.Lumen.Visualize.HiResSurface"),
|
|
GVisualizeLumenSceneHiResSurface,
|
|
TEXT("Whether visualization should sample highest available surface data or use lowest res always resident pages."),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
static TAutoConsoleVariable<int32> CVarVisualizeLumenSceneSurfaceCacheFeedback(
|
|
TEXT("r.Lumen.Visualize.SurfaceCacheFeedback"),
|
|
0,
|
|
TEXT("Whether visualization should write surface cache feedback requests into the feedback buffer."),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GVisualizeLumenSceneTraceRadianceCache = 0;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneTraceRadianceCache(
|
|
TEXT("r.Lumen.Visualize.TraceRadianceCache"),
|
|
GVisualizeLumenSceneTraceRadianceCache,
|
|
TEXT("Whether to use radiance cache for Lumen scene visualization."),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
float GVisualizeLumenSceneConeAngle = 0.0f;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneConeAngle(
|
|
TEXT("r.Lumen.Visualize.ConeAngle"),
|
|
GVisualizeLumenSceneConeAngle,
|
|
TEXT("Visualize cone angle, in degrees."),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
float GVisualizeLumenSceneConeStepFactor = 2.0f;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneConeStepFactor(
|
|
TEXT("r.Lumen.Visualize.ConeStepFactor"),
|
|
GVisualizeLumenSceneConeStepFactor,
|
|
TEXT("Cone step scale on sphere radius step size."),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
float GVisualizeLumenSceneMinTraceDistance = 0;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneMinTraceDistance(
|
|
TEXT("r.Lumen.Visualize.MinTraceDistance"),
|
|
GVisualizeLumenSceneMinTraceDistance,
|
|
TEXT(""),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
float GVisualizeLumenSceneMaxTraceDistance = 100000;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneMaxTraceDistance(
|
|
TEXT("r.Lumen.Visualize.MaxTraceDistance"),
|
|
GVisualizeLumenSceneMaxTraceDistance,
|
|
TEXT(""),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GVisualizeLumenCardGenerationSurfels = 0;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneCardGenerationSurfels(
|
|
TEXT("r.Lumen.Visualize.CardGenerationSurfels"),
|
|
GVisualizeLumenCardGenerationSurfels,
|
|
TEXT(""),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
float GVisualizeLumenCardGenerationSurfelScale = 1.0f;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneCardGenerationSurfelScale(
|
|
TEXT("r.Lumen.Visualize.CardGenerationSurfelScale"),
|
|
GVisualizeLumenCardGenerationSurfelScale,
|
|
TEXT(""),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
float GVisualizeLumenCardGenerationClusterScale = 1.0f;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneCardGenerationClusterScale(
|
|
TEXT("r.Lumen.Visualize.CardGenerationClusterScale"),
|
|
GVisualizeLumenCardGenerationClusterScale,
|
|
TEXT(""),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GVisualizeLumenCardGenerationCluster = 0;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneCardGenerationCluster(
|
|
TEXT("r.Lumen.Visualize.CardGenerationCluster"),
|
|
GVisualizeLumenCardGenerationCluster,
|
|
TEXT(""),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GVisualizeLumenCardGenerationMaxSurfel = -1;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneCardGenerationMaxSurfel(
|
|
TEXT("r.Lumen.Visualize.CardGenerationMaxSurfel"),
|
|
GVisualizeLumenCardGenerationMaxSurfel,
|
|
TEXT(""),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GVisualizeLumenCardPlacement = 0;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneCardPlacement(
|
|
TEXT("r.Lumen.Visualize.CardPlacement"),
|
|
GVisualizeLumenCardPlacement,
|
|
TEXT(""),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
float GVisualizeLumenCardPlacementDistance = 5000.0f;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneCardPlacementDistance(
|
|
TEXT("r.Lumen.Visualize.CardPlacementDistance"),
|
|
GVisualizeLumenCardPlacementDistance,
|
|
TEXT(""),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GVisualizeLumenCardPlacementLOD = 0;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneCardPlacementLOD(
|
|
TEXT("r.Lumen.Visualize.CardPlacementLOD"),
|
|
GVisualizeLumenCardPlacementLOD,
|
|
TEXT("0 - all\n")
|
|
TEXT("1 - only primitives\n")
|
|
TEXT("2 - only merged instances\n")
|
|
TEXT("3 - only merged components\n")
|
|
TEXT("4 - only far field\n"),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GVisualizeLumenCardPlacementPrimitives = 0;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneCardPlacementPrimitives(
|
|
TEXT("r.Lumen.Visualize.CardPlacementPrimitives"),
|
|
GVisualizeLumenCardPlacementPrimitives,
|
|
TEXT("Whether to visualize primitive bounding boxes.\n"),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GVisualizeLumenRayTracingGroups = 0;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenRayTracingGroups(
|
|
TEXT("r.Lumen.Visualize.RayTracingGroups"),
|
|
GVisualizeLumenRayTracingGroups,
|
|
TEXT("Visualize bounds for ray tracing groups. Control visualization distance using r.Lumen.Visualize.CardPlacementDistance.\n")
|
|
TEXT("0 - disable\n")
|
|
TEXT("1 - all groups\n")
|
|
TEXT("2 - groups with a single instance"),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GVisualizeLumenCardPlacementIndex = -1;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneCardPlacementIndex(
|
|
TEXT("r.Lumen.Visualize.CardPlacementIndex"),
|
|
GVisualizeLumenCardPlacementIndex,
|
|
TEXT("Visualize only a single card per mesh."),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GVisualizeLumenCardPlacementDirection = -1;
|
|
FAutoConsoleVariableRef CVarVisualizeLumenSceneCardPlacementDirection(
|
|
TEXT("r.Lumen.Visualize.CardPlacementDirection"),
|
|
GVisualizeLumenCardPlacementDirection,
|
|
TEXT("Visualize only a single card direction."),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GLumenSceneDumpStats = 0;
|
|
FAutoConsoleVariableRef CVarLumenSceneDumpStats(
|
|
TEXT("r.LumenScene.DumpStats"),
|
|
GLumenSceneDumpStats,
|
|
TEXT("Whether to log Lumen scene stats on the next frame. 2 - dump mesh DF. 3 - dump LumenScene objects."),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
float GVisualizeLumenSceneCardInterpolateInfluenceRadius = 10.0f;
|
|
FAutoConsoleVariableRef CVarCardInterpolateInfluenceRadius(
|
|
TEXT("r.Lumen.Visualize.CardInterpolateInfluenceRadius"),
|
|
GVisualizeLumenSceneCardInterpolateInfluenceRadius,
|
|
TEXT(""),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
static TAutoConsoleVariable<int> CVarVisualizeUseShaderPrintForTraces(
|
|
TEXT("r.Lumen.Visualize.UseShaderPrintForTraces"),
|
|
1,
|
|
TEXT("Whether to use ShaderPrint or custom line renderer for trace visualization."),
|
|
ECVF_Scalability | ECVF_RenderThreadSafe
|
|
);
|
|
|
|
bool Lumen::ShouldVisualizeScene(const FEngineShowFlags& ShowFlags)
|
|
{
|
|
return ShowFlags.VisualizeLumen || GLumenVisualize > 0;
|
|
}
|
|
|
|
bool LumenVisualize::UseSurfaceCacheFeedback(const FEngineShowFlags& ShowFlags)
|
|
{
|
|
return CVarVisualizeLumenSceneSurfaceCacheFeedback.GetValueOnRenderThread() != 0
|
|
&& Lumen::ShouldVisualizeScene(ShowFlags);
|
|
}
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FLumenVisualizeSceneSoftwareRayTracingParameters, )
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(LumenVisualize::FSceneParameters, CommonParameters)
|
|
SHADER_PARAMETER(float, VisualizeStepFactor)
|
|
SHADER_PARAMETER(float, MinTraceDistance)
|
|
SHADER_PARAMETER(float, MaxTraceDistance)
|
|
SHADER_PARAMETER(float, MaxMeshSDFTraceDistanceForVoxelTracing)
|
|
SHADER_PARAMETER(float, MaxMeshSDFTraceDistance)
|
|
SHADER_PARAMETER(float, CardInterpolateInfluenceRadius)
|
|
SHADER_PARAMETER(int, HeightfieldMaxTracingSteps)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
class FVisualizeLumenSceneCS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FVisualizeLumenSceneCS)
|
|
SHADER_USE_PARAMETER_STRUCT(FVisualizeLumenSceneCS, FGlobalShader)
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FSceneTextureParameters, SceneTextureParameters)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FSceneTextureShaderParameters, SceneTextures)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FLumenCardTracingParameters, TracingParameters)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FLumenMeshSDFGridParameters, MeshSDFGridParameters)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FLumenVisualizeSceneSoftwareRayTracingParameters, VisualizeParameters)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(LumenRadianceCache::FRadianceCacheInterpolationParameters, RadianceCacheParameters)
|
|
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSubstrateGlobalUniformParameters, Substrate)
|
|
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWSceneColor)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
class FTraceMeshSDF : SHADER_PERMUTATION_BOOL("TRACE_MESH_SDF");
|
|
class FTraceGlobalSDF : SHADER_PERMUTATION_BOOL("TRACE_GLOBAL_SDF");
|
|
class FSimpleCoverageBasedExpand : SHADER_PERMUTATION_BOOL("GLOBALSDF_SIMPLE_COVERAGE_BASED_EXPAND");
|
|
class FRadianceCache : SHADER_PERMUTATION_BOOL("RADIANCE_CACHE");
|
|
class FTraceHeightfields : SHADER_PERMUTATION_BOOL("SCENE_TRACE_HEIGHTFIELDS");
|
|
|
|
using FPermutationDomain = TShaderPermutationDomain<FTraceMeshSDF, FTraceGlobalSDF, FSimpleCoverageBasedExpand, FRadianceCache, FTraceHeightfields>;
|
|
|
|
public:
|
|
static FPermutationDomain RemapPermutation(FPermutationDomain PermutationVector)
|
|
{
|
|
if (!PermutationVector.Get<FTraceGlobalSDF>())
|
|
{
|
|
PermutationVector.Set<FSimpleCoverageBasedExpand>(false);
|
|
}
|
|
|
|
return PermutationVector;
|
|
}
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
FPermutationDomain PermutationVector(Parameters.PermutationId);
|
|
|
|
if (RemapPermutation(PermutationVector) != PermutationVector)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return DoesPlatformSupportLumenGI(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("THREADGROUP_SIZE"), GetGroupSize());
|
|
OutEnvironment.SetDefine(TEXT("ENABLE_VISUALIZE_MODE"), 1);
|
|
OutEnvironment.SetDefine(TEXT("SURFACE_CACHE_FEEDBACK"), 1);
|
|
OutEnvironment.SetDefine(TEXT("SURFACE_CACHE_HIGH_RES_PAGES"), 1);
|
|
OutEnvironment.SetDefine(TEXT("VF_SUPPORTS_PRIMITIVE_SCENE_DATA"), 1);
|
|
|
|
// Workaround for an internal PC FXC compiler crash when compiling with disabled optimizations
|
|
if (Parameters.Platform == SP_PCD3D_SM5)
|
|
{
|
|
OutEnvironment.CompilerFlags.Add(CFLAG_ForceOptimization);
|
|
}
|
|
}
|
|
|
|
static int32 GetGroupSize()
|
|
{
|
|
return 8;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FVisualizeLumenSceneCS, "/Engine/Private/Lumen/LumenVisualize.usf", "VisualizeQuadsCS", SF_Compute);
|
|
|
|
|
|
class FVisualizeLumenSceneCursorDataCS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FVisualizeLumenSceneCursorDataCS)
|
|
SHADER_USE_PARAMETER_STRUCT(FVisualizeLumenSceneCursorDataCS, FGlobalShader)
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FSceneTextureShaderParameters, SceneTextures)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FLumenCardTracingParameters, TracingParameters)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FLumenVisualizeSceneSoftwareRayTracingParameters, VisualizeParameters)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, DebugData)
|
|
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWSceneColor)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
using FPermutationDomain = TShaderPermutationDomain<>;
|
|
|
|
public:
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return DoesPlatformSupportLumenGI(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("THREADGROUP_SIZE"), GetGroupSize());
|
|
OutEnvironment.SetDefine(TEXT("ENABLE_VISUALIZE_MODE"), 1);
|
|
OutEnvironment.SetDefine(TEXT("SURFACE_CACHE_FEEDBACK"), 1);
|
|
OutEnvironment.SetDefine(TEXT("SURFACE_CACHE_HIGH_RES_PAGES"), 1);
|
|
|
|
// Workaround for an internal PC FXC compiler crash when compiling with disabled optimizations
|
|
if (Parameters.Platform == SP_PCD3D_SM5)
|
|
{
|
|
OutEnvironment.CompilerFlags.Add(CFLAG_ForceOptimization);
|
|
}
|
|
}
|
|
|
|
static int32 GetGroupSize()
|
|
{
|
|
return 8;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FVisualizeLumenSceneCursorDataCS, "/Engine/Private/Lumen/LumenVisualize.usf", "VisualizeCursorDataCS", SF_Compute);
|
|
|
|
class FVisualizeBitFieldFloatTexturePS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FVisualizeBitFieldFloatTexturePS)
|
|
SHADER_USE_PARAMETER_STRUCT(FVisualizeBitFieldFloatTexturePS, FGlobalShader)
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SceneColorTexture)
|
|
SHADER_PARAMETER_RDG_TEXTURE_SRV(Texture2D, InputTexture)
|
|
SHADER_PARAMETER(FVector2f, ToIntMulAdd)
|
|
SHADER_PARAMETER(FVector2f, PreOutputMulAdd)
|
|
SHADER_PARAMETER(FUintVector2, BitMaskShift)
|
|
RENDER_TARGET_BINDING_SLOTS()
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return DoesPlatformSupportLumenGI(Parameters.Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FVisualizeBitFieldFloatTexturePS, "/Engine/Private/Lumen/LumenVisualize.usf", "VisualizeBitFieldFloatTexturePS", SF_Pixel);
|
|
|
|
class FVisualizeTracesVS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FVisualizeTracesVS)
|
|
SHADER_USE_PARAMETER_STRUCT(FVisualizeTracesVS, FGlobalShader)
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<float3>, VisualizeTracesData)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return DoesPlatformSupportLumenGI(Parameters.Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FVisualizeTracesVS, "/Engine/Private/Lumen/LumenVisualize.usf", "VisualizeTracesVS", SF_Vertex);
|
|
|
|
|
|
class FVisualizeTracesPS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FVisualizeTracesPS)
|
|
SHADER_USE_PARAMETER_STRUCT(FVisualizeTracesPS, FGlobalShader)
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return DoesPlatformSupportLumenGI(Parameters.Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FVisualizeTracesPS, "/Engine/Private/Lumen/LumenVisualize.usf", "VisualizeTracesPS", SF_Pixel);
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FVisualizeTraces, )
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FVisualizeTracesVS::FParameters, VS)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FVisualizeTracesPS::FParameters, PS)
|
|
RENDER_TARGET_BINDING_SLOTS()
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
class FVisualizeTracesCS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FVisualizeTracesCS)
|
|
SHADER_USE_PARAMETER_STRUCT(FVisualizeTracesCS, FGlobalShader)
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(ShaderPrint::FShaderParameters, ShaderPrintUniformBuffer)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(LumenVisualize::FTonemappingParameters, TonemappingParameters)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<float3>, VisualizeTracesData)
|
|
SHADER_PARAMETER(uint32, NumTracesToVisualize)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
static int32 GetGroupSize()
|
|
{
|
|
return 8;
|
|
}
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return DoesPlatformSupportLumenGI(Parameters.Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FVisualizeTracesCS, "/Engine/Private/Lumen/LumenVisualize.usf", "VisualizeTracesCS", SF_Compute);
|
|
|
|
class FVisualizeTracesVertexDeclaration : public FRenderResource
|
|
{
|
|
public:
|
|
FVertexDeclarationRHIRef VertexDeclarationRHI;
|
|
|
|
/** Destructor. */
|
|
virtual ~FVisualizeTracesVertexDeclaration() {}
|
|
|
|
virtual void InitRHI(FRHICommandListBase& RHICmdList)
|
|
{
|
|
FVertexDeclarationElementList Elements;
|
|
VertexDeclarationRHI = RHICreateVertexDeclaration(Elements);
|
|
}
|
|
|
|
virtual void ReleaseRHI()
|
|
{
|
|
VertexDeclarationRHI.SafeRelease();
|
|
}
|
|
};
|
|
|
|
TGlobalResource<FVisualizeTracesVertexDeclaration> GVisualizeTracesVertexDeclaration;
|
|
|
|
namespace LumenVisualize
|
|
{
|
|
FTonemappingParameters GetTonemappingParameters(
|
|
FRDGBuilder& GraphBuilder,
|
|
const FEngineShowFlags& ShowFlags,
|
|
FRDGTextureRef ColorGradingTexture,
|
|
FRDGBufferRef EyeAdaptationBuffer)
|
|
{
|
|
FTonemappingParameters TonemappingParameters;
|
|
|
|
TonemappingParameters.Tonemap = 0;
|
|
if (EyeAdaptationBuffer != nullptr
|
|
&& ColorGradingTexture != nullptr
|
|
&& ShowFlags.Tonemapper != 0
|
|
&& CVarLumenVisualizeToneMap.GetValueOnRenderThread())
|
|
{
|
|
TonemappingParameters.Tonemap = 1;
|
|
}
|
|
|
|
TonemappingParameters.ColorGradingLUT = ColorGradingTexture;
|
|
TonemappingParameters.ColorGradingLUTSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
|
|
TonemappingParameters.EyeAdaptationBuffer = GraphBuilder.CreateSRV(EyeAdaptationBuffer);
|
|
|
|
if (!TonemappingParameters.ColorGradingLUT)
|
|
{
|
|
TonemappingParameters.ColorGradingLUT = FRDGSystemTextures::Get(GraphBuilder).VolumetricBlack;
|
|
}
|
|
|
|
return TonemappingParameters;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Render gathered traces using ShaderPrint line rendering.
|
|
*/
|
|
void RenderVisualizeTraces(
|
|
FRDGBuilder& GraphBuilder,
|
|
const FViewInfo& View,
|
|
FRDGTextureRef ColorGradingTexture,
|
|
FRDGBufferRef EyeAdaptationBuffer)
|
|
{
|
|
if (CVarVisualizeUseShaderPrintForTraces.GetValueOnRenderThread() == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
extern void GetReflectionsVisualizeTracesBuffer(TRefCountPtr<FRDGPooledBuffer>&VisualizeTracesData);
|
|
extern void GetScreenProbeVisualizeTracesBuffer(TRefCountPtr<FRDGPooledBuffer>&VisualizeTracesData);
|
|
|
|
TRefCountPtr<FRDGPooledBuffer> PooledVisualizeTracesData;
|
|
GetReflectionsVisualizeTracesBuffer(PooledVisualizeTracesData);
|
|
GetScreenProbeVisualizeTracesBuffer(PooledVisualizeTracesData);
|
|
|
|
if (PooledVisualizeTracesData.IsValid())
|
|
{
|
|
FRDGBufferRef VisualizeTracesData = GraphBuilder.RegisterExternalBuffer(PooledVisualizeTracesData);
|
|
const int32 NumTraces = LumenScreenProbeGather::GetTracingOctahedronResolution(View) * LumenScreenProbeGather::GetTracingOctahedronResolution(View);
|
|
|
|
ShaderPrint::SetEnabled(true);
|
|
ShaderPrint::RequestSpaceForLines(FMath::Max(NumTraces, 1024));
|
|
|
|
FVisualizeTracesCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FVisualizeTracesCS::FParameters>();
|
|
PassParameters->View = View.ViewUniformBuffer;
|
|
PassParameters->TonemappingParameters = LumenVisualize::GetTonemappingParameters(GraphBuilder, View.Family->EngineShowFlags, ColorGradingTexture, EyeAdaptationBuffer);
|
|
PassParameters->VisualizeTracesData = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(VisualizeTracesData, PF_A32B32G32R32F));
|
|
PassParameters->NumTracesToVisualize = NumTraces;
|
|
ShaderPrint::SetParameters(GraphBuilder, View.ShaderPrintData, PassParameters->ShaderPrintUniformBuffer);
|
|
|
|
auto ComputeShader = View.ShaderMap->GetShader<FVisualizeTracesCS>();
|
|
|
|
const FIntVector GroupCount = FComputeShaderUtils::GetGroupCount(NumTraces, FVisualizeTracesCS::GetGroupSize());
|
|
|
|
FComputeShaderUtils::AddPass(
|
|
GraphBuilder,
|
|
RDG_EVENT_NAME("VisualizeTraces %d", NumTraces),
|
|
ComputeShader,
|
|
PassParameters,
|
|
GroupCount);
|
|
}
|
|
}
|
|
|
|
void RenderVisualizeTraces(
|
|
FRDGBuilder& GraphBuilder,
|
|
const FViewInfo& View,
|
|
const FMinimalSceneTextures& SceneTextures)
|
|
{
|
|
if (CVarVisualizeUseShaderPrintForTraces.GetValueOnRenderThread() != 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
extern void GetReflectionsVisualizeTracesBuffer(TRefCountPtr<FRDGPooledBuffer>& VisualizeTracesData);
|
|
extern void GetScreenProbeVisualizeTracesBuffer(TRefCountPtr<FRDGPooledBuffer>& VisualizeTracesData);
|
|
|
|
TRefCountPtr<FRDGPooledBuffer> PooledVisualizeTracesData;
|
|
GetReflectionsVisualizeTracesBuffer(PooledVisualizeTracesData);
|
|
GetScreenProbeVisualizeTracesBuffer(PooledVisualizeTracesData);
|
|
|
|
if (PooledVisualizeTracesData.IsValid())
|
|
{
|
|
FRDGBufferRef VisualizeTracesData = GraphBuilder.RegisterExternalBuffer(PooledVisualizeTracesData);
|
|
|
|
FVisualizeTraces* PassParameters = GraphBuilder.AllocParameters<FVisualizeTraces>();
|
|
PassParameters->RenderTargets[0] = FRenderTargetBinding(SceneTextures.Color.Target, ERenderTargetLoadAction::ELoad);
|
|
PassParameters->RenderTargets.DepthStencil = FDepthStencilBinding(SceneTextures.Depth.Target, ERenderTargetLoadAction::ELoad, FExclusiveDepthStencil::DepthRead_StencilNop);
|
|
PassParameters->VS.View = View.ViewUniformBuffer;
|
|
PassParameters->VS.VisualizeTracesData = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(VisualizeTracesData, PF_A32B32G32R32F));
|
|
|
|
auto VertexShader = View.ShaderMap->GetShader<FVisualizeTracesVS>();
|
|
auto PixelShader = View.ShaderMap->GetShader<FVisualizeTracesPS>();
|
|
|
|
const int32 NumPrimitives = LumenScreenProbeGather::GetTracingOctahedronResolution(View) * LumenScreenProbeGather::GetTracingOctahedronResolution(View);
|
|
|
|
GraphBuilder.AddPass(
|
|
RDG_EVENT_NAME("VisualizeTraces"),
|
|
PassParameters,
|
|
ERDGPassFlags::Raster,
|
|
[PassParameters, VertexShader, PixelShader, &View, NumPrimitives](FRDGAsyncTask, FRHICommandList& RHICmdList)
|
|
{
|
|
FGraphicsPipelineStateInitializer GraphicsPSOInit;
|
|
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
|
|
|
|
RHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0.0f, View.ViewRect.Max.X, View.ViewRect.Max.Y, 1.0f);
|
|
|
|
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<FM_Solid, CM_None>::GetRHI();
|
|
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_DepthNearOrEqual>::GetRHI();
|
|
GraphicsPSOInit.BlendState = TStaticBlendState<CW_RGB>::GetRHI();
|
|
|
|
GraphicsPSOInit.PrimitiveType = PT_LineList;
|
|
|
|
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GVisualizeTracesVertexDeclaration.VertexDeclarationRHI;
|
|
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();
|
|
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader();
|
|
|
|
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0);
|
|
|
|
SetShaderParameters(RHICmdList, VertexShader, VertexShader.GetVertexShader(), PassParameters->VS);
|
|
SetShaderParameters(RHICmdList, PixelShader, PixelShader.GetPixelShader(), PassParameters->PS);
|
|
|
|
RHICmdList.SetStreamSource(0, nullptr, 0);
|
|
RHICmdList.DrawPrimitive(0, NumPrimitives, 1);
|
|
});
|
|
}
|
|
}
|
|
|
|
void GetVisualizeTileOutputView(const FIntRect& ViewRect, int32 TileIndex, FIntPoint& OutputViewOffset, FIntPoint& OutputViewSize)
|
|
{
|
|
if (TileIndex >= 0)
|
|
{
|
|
const FIntPoint TileSize = FMath::DivideAndRoundDown<FIntPoint>(ViewRect.Size() - LumenVisualize::OverviewTileMargin * (LumenVisualize::NumOverviewTilesPerRow + 1), LumenVisualize::NumOverviewTilesPerRow);
|
|
|
|
OutputViewSize = TileSize;
|
|
OutputViewOffset.X = ViewRect.Min.X + TileSize.X * TileIndex + LumenVisualize::OverviewTileMargin * (TileIndex + 1);
|
|
OutputViewOffset.Y = ViewRect.Min.Y + LumenVisualize::OverviewTileMargin;
|
|
}
|
|
else
|
|
{
|
|
OutputViewOffset = ViewRect.Min;
|
|
OutputViewSize = ViewRect.Size();
|
|
}
|
|
}
|
|
|
|
void SetupVisualizeParameters(
|
|
FRDGBuilder& GraphBuilder,
|
|
const FViewInfo& View,
|
|
const FIntRect& ViewRect,
|
|
FRDGTextureRef ColorGradingTexture,
|
|
FRDGBufferRef EyeAdaptationBuffer,
|
|
int32 VisualizeMode,
|
|
int32 VisualizeTileIndex,
|
|
FLumenVisualizeSceneSoftwareRayTracingParameters& VisualizeParameters)
|
|
{
|
|
float MaxMeshSDFTraceDistance = GVisualizeLumenSceneMaxMeshSDFTraceDistance >= 0.0f ? GVisualizeLumenSceneMaxMeshSDFTraceDistance : FLT_MAX;
|
|
if (!View.IsPerspectiveProjection())
|
|
{
|
|
const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.Lumen.Ortho.OverrideMeshDFTraceDistances"));
|
|
if (CVar && CVar->GetValueOnRenderThread() > 0)
|
|
{
|
|
MaxMeshSDFTraceDistance = View.ViewMatrices.GetOrthoDimensions().GetMax();
|
|
}
|
|
}
|
|
|
|
float MaxTraceDistance = GVisualizeLumenSceneMaxTraceDistance;
|
|
uint32 MaxReflectionBounces = 1;
|
|
uint32 MaxRefractionBounces = LumenReflections::UseTranslucentRayTracing(View) ? 1 : 0;
|
|
|
|
// Reflection scene view uses reflection setup
|
|
if (VisualizeMode == VISUALIZE_MODE_REFLECTION_VIEW)
|
|
{
|
|
extern FLumenGatherCvarState GLumenGatherCvars;
|
|
MaxMeshSDFTraceDistance = GLumenGatherCvars.MeshSDFTraceDistance;
|
|
MaxTraceDistance = Lumen::GetMaxTraceDistance(View);
|
|
MaxReflectionBounces = LumenReflections::GetMaxReflectionBounces(View);
|
|
MaxRefractionBounces = LumenReflections::GetMaxRefractionBounces(View);
|
|
}
|
|
|
|
FRDGBufferRef MeshCardsIndexToCardSharingIdBuffer = GSystemTextures.GetDefaultBuffer<uint32>(GraphBuilder);
|
|
if (VisualizeMode == VISUALIZE_MODE_CARD_SHARING_ID)
|
|
{
|
|
const FScene* Scene = (const FScene*)View.Family->Scene;
|
|
const FLumenSceneData& LumenSceneData = *Scene->GetLumenSceneData(*View.Family->Views[0]);
|
|
const uint32 NumMeshCards = LumenSceneData.MeshCards.Num();
|
|
|
|
if (NumMeshCards > 0u)
|
|
{
|
|
FRDGUploadData<uint32> UploadData(GraphBuilder, NumMeshCards);
|
|
|
|
for (uint32 Index = 0; Index < NumMeshCards; ++Index)
|
|
{
|
|
uint32 CardSharingId = UINT32_MAX;
|
|
if (LumenSceneData.MeshCards.IsAllocated(Index))
|
|
{
|
|
const int32 PrimitiveGroupIndex = LumenSceneData.MeshCards[Index].PrimitiveGroupIndex;
|
|
const FLumenPrimitiveGroup& PrimitiveGroup = LumenSceneData.PrimitiveGroups[PrimitiveGroupIndex];
|
|
CardSharingId = PrimitiveGroup.CustomId;
|
|
}
|
|
|
|
UploadData[Index] = CardSharingId;
|
|
}
|
|
|
|
const uint32 NumBufferElements = FMath::RoundUpToPowerOfTwo(NumMeshCards);
|
|
|
|
MeshCardsIndexToCardSharingIdBuffer = CreateUploadBuffer(
|
|
GraphBuilder,
|
|
TEXT("Lumen.Visualize.MeshCardsIndexToCardSharingIdBuffer"),
|
|
sizeof(uint32),
|
|
NumBufferElements,
|
|
UploadData);
|
|
}
|
|
}
|
|
|
|
// FLumenVisualizeSceneParameters
|
|
{
|
|
LumenVisualize::FSceneParameters& CommonParameters = VisualizeParameters.CommonParameters;
|
|
|
|
ShaderPrint::SetEnabled(true);
|
|
ShaderPrint::SetParameters(GraphBuilder, View.ShaderPrintData, CommonParameters.ShaderPrintUniformBuffer);
|
|
|
|
CommonParameters.TonemappingParameters = LumenVisualize::GetTonemappingParameters(GraphBuilder, View.Family->EngineShowFlags, ColorGradingTexture, EyeAdaptationBuffer);
|
|
CommonParameters.VisualizeHiResSurface = GVisualizeLumenSceneHiResSurface ? 1 : 0;
|
|
CommonParameters.VisualizeMode = VisualizeMode;
|
|
CommonParameters.VisualizeCullingMode = CVarLumenVisualizeCullingMode.GetValueOnRenderThread();
|
|
CommonParameters.MaxReflectionBounces = MaxReflectionBounces;
|
|
CommonParameters.MaxRefractionBounces = MaxRefractionBounces;
|
|
CommonParameters.MeshCardsIndexToCardSharingIdBuffer = GraphBuilder.CreateSRV(MeshCardsIndexToCardSharingIdBuffer, PF_R32_UINT);
|
|
|
|
LumenReflections::SetupCompositeParameters(View, CommonParameters.ReflectionsCompositeParameters);
|
|
CommonParameters.PreIntegratedGF = GSystemTextures.PreintegratedGF->GetRHI();
|
|
CommonParameters.PreIntegratedGFSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
|
|
|
|
CommonParameters.InputViewOffset = ViewRect.Min;
|
|
CommonParameters.OutputViewOffset = ViewRect.Min;
|
|
CommonParameters.InputViewSize = ViewRect.Size();
|
|
CommonParameters.OutputViewSize = ViewRect.Size();
|
|
|
|
GetVisualizeTileOutputView(ViewRect, VisualizeTileIndex, CommonParameters.OutputViewOffset, CommonParameters.OutputViewSize);
|
|
}
|
|
|
|
// FLumenVisualizeSceneSoftwareRayTracingParameters
|
|
{
|
|
bool bTraceMeshSDF = GVisualizeLumenSceneTraceMeshSDFs != 0 && View.Family->EngineShowFlags.LumenDetailTraces;
|
|
if (!bTraceMeshSDF)
|
|
{
|
|
MaxMeshSDFTraceDistance = 0.0f;
|
|
}
|
|
|
|
VisualizeParameters.VisualizeStepFactor = FMath::Clamp(GVisualizeLumenSceneConeStepFactor, .1f, 10.0f);
|
|
VisualizeParameters.MinTraceDistance = FMath::Clamp(GVisualizeLumenSceneMinTraceDistance, .01f, 1000.0f);
|
|
VisualizeParameters.MaxTraceDistance = FMath::Clamp(MaxTraceDistance, .01f, Lumen::MaxTraceDistance);
|
|
VisualizeParameters.CardInterpolateInfluenceRadius = GVisualizeLumenSceneCardInterpolateInfluenceRadius;
|
|
VisualizeParameters.MaxMeshSDFTraceDistanceForVoxelTracing = FMath::Clamp(MaxMeshSDFTraceDistance, VisualizeParameters.MinTraceDistance, VisualizeParameters.MaxTraceDistance);
|
|
VisualizeParameters.MaxMeshSDFTraceDistance = FMath::Clamp(MaxMeshSDFTraceDistance, VisualizeParameters.MinTraceDistance, VisualizeParameters.MaxTraceDistance);
|
|
VisualizeParameters.HeightfieldMaxTracingSteps = Lumen::GetHeightfieldMaxTracingSteps();
|
|
}
|
|
}
|
|
|
|
void FDeferredShadingSceneRenderer::RenderLumenMiscVisualizations(FRDGBuilder& GraphBuilder, const FMinimalSceneTextures& SceneTextures, const FLumenSceneFrameTemporaries& FrameTemporaries)
|
|
{
|
|
const FViewInfo& View = Views[0];
|
|
const FPerViewPipelineState& ViewPipelineState = GetViewPipelineState(View);
|
|
const bool bAnyLumenActive = ViewPipelineState.DiffuseIndirectMethod == EDiffuseIndirectMethod::Lumen || ViewPipelineState.ReflectionsMethod == EReflectionsMethod::Lumen;
|
|
|
|
if (Lumen::IsLumenFeatureAllowedForView(Scene, View) && bAnyLumenActive)
|
|
{
|
|
RDG_EVENT_SCOPE(GraphBuilder, "MiscLumenVisualization");
|
|
|
|
RenderVisualizeTraces(GraphBuilder, View, SceneTextures);
|
|
}
|
|
|
|
RenderLumenRadianceCacheVisualization(GraphBuilder, SceneTextures);
|
|
RenderLumenRadiosityProbeVisualization(GraphBuilder, SceneTextures, FrameTemporaries);
|
|
|
|
if (GLumenSceneDumpStats)
|
|
{
|
|
FLumenSceneData& LumenSceneData = *Scene->GetLumenSceneData(Views[0]);
|
|
const FDistanceFieldSceneData& DistanceFieldSceneData = Scene->DistanceFieldSceneData;
|
|
|
|
LumenSceneData.DumpStats(
|
|
DistanceFieldSceneData,
|
|
/*bDumpMeshDistanceFields*/ GLumenSceneDumpStats == 2,
|
|
/*bDumpPrimitiveGroups*/ GLumenSceneDumpStats == 3);
|
|
|
|
GLumenSceneDumpStats = 0;
|
|
}
|
|
}
|
|
|
|
LumenRadianceCache::FRadianceCacheInputs GetFinalGatherRadianceCacheInputsForVisualize(const FViewInfo& View)
|
|
{
|
|
if (GLumenIrradianceFieldGather)
|
|
{
|
|
return LumenIrradianceFieldGather::SetupRadianceCacheInputs();
|
|
}
|
|
else
|
|
{
|
|
return LumenScreenProbeGatherRadianceCache::SetupRadianceCacheInputs(View);
|
|
}
|
|
}
|
|
|
|
void VisualizeLumenScene(
|
|
const FScene* Scene,
|
|
FRDGBuilder& GraphBuilder,
|
|
const FEngineShowFlags& ShowFlags,
|
|
const FViewInfo& View,
|
|
const FLumenSceneFrameTemporaries& FrameTemporaries,
|
|
FScreenPassTexture Output,
|
|
FRDGTextureRef ColorGradingTexture,
|
|
FRDGBufferRef EyeAdaptationBuffer,
|
|
FSceneTextureShaderParameters SceneTextures,
|
|
int32 VisualizeMode,
|
|
int32 VisualizeTileIndex,
|
|
EDiffuseIndirectMethod DiffuseIndirectMethod)
|
|
{
|
|
FRDGTextureUAVRef SceneColorUAV = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(Output.Texture));
|
|
|
|
FLumenVisualizeSceneSoftwareRayTracingParameters VisualizeParameters;
|
|
SetupVisualizeParameters(GraphBuilder, View, Output.ViewRect, ColorGradingTexture, EyeAdaptationBuffer, VisualizeMode, VisualizeTileIndex, VisualizeParameters);
|
|
|
|
FLumenCardTracingParameters TracingParameters;
|
|
GetLumenCardTracingParameters(GraphBuilder, View, *Scene->GetLumenSceneData(View), FrameTemporaries, LumenVisualize::UseSurfaceCacheFeedback(ShowFlags), TracingParameters);
|
|
|
|
const FRadianceCacheState& RadianceCacheState = View.ViewState->Lumen.RadianceCacheState;
|
|
const LumenRadianceCache::FRadianceCacheInputs RadianceCacheInputs = GetFinalGatherRadianceCacheInputsForVisualize(View);
|
|
|
|
if (Lumen::ShouldVisualizeHardwareRayTracing(*View.Family))
|
|
{
|
|
FLumenIndirectTracingParameters IndirectTracingParameters;
|
|
IndirectTracingParameters.CardInterpolateInfluenceRadius = VisualizeParameters.CardInterpolateInfluenceRadius;
|
|
IndirectTracingParameters.MinTraceDistance = VisualizeParameters.MinTraceDistance;
|
|
IndirectTracingParameters.MaxTraceDistance = VisualizeParameters.MaxTraceDistance;
|
|
IndirectTracingParameters.MaxMeshSDFTraceDistance = VisualizeParameters.MaxMeshSDFTraceDistance;
|
|
|
|
const bool bVisualizeModeWithHitLighting = (VisualizeMode == VISUALIZE_MODE_LUMEN_SCENE || VisualizeMode == VISUALIZE_MODE_REFLECTION_VIEW);
|
|
|
|
LumenVisualize::VisualizeHardwareRayTracing(
|
|
GraphBuilder,
|
|
Scene,
|
|
GetSceneTextureParameters(GraphBuilder, View),
|
|
View,
|
|
FrameTemporaries,
|
|
TracingParameters,
|
|
IndirectTracingParameters,
|
|
VisualizeParameters.CommonParameters,
|
|
Output.Texture,
|
|
bVisualizeModeWithHitLighting,
|
|
DiffuseIndirectMethod);
|
|
}
|
|
else
|
|
{
|
|
const uint32 CullGridPixelSize = FMath::Clamp(GVisualizeLumenSceneGridPixelSize, 8, 1024);
|
|
const FIntPoint CullGridSizeXY = FIntPoint::DivideAndRoundUp(View.ViewRect.Size(), CullGridPixelSize);
|
|
const FIntVector CullGridSize = FIntVector(CullGridSizeXY.X, CullGridSizeXY.Y, 1);
|
|
|
|
FLumenMeshSDFGridParameters MeshSDFGridParameters;
|
|
MeshSDFGridParameters.CardGridPixelSizeShift = FMath::FloorLog2(CullGridPixelSize);
|
|
MeshSDFGridParameters.CullGridSize = CullGridSize;
|
|
|
|
{
|
|
const float CardTraceEndDistanceFromCamera = VisualizeParameters.MaxMeshSDFTraceDistance;
|
|
|
|
CullMeshObjectsToViewGrid(
|
|
View,
|
|
Scene,
|
|
FrameTemporaries,
|
|
0,
|
|
CardTraceEndDistanceFromCamera,
|
|
CullGridPixelSize,
|
|
1,
|
|
FVector::ZeroVector,
|
|
GraphBuilder,
|
|
MeshSDFGridParameters);
|
|
}
|
|
|
|
const bool bTraceGlobalSDF = Lumen::UseGlobalSDFTracing(View.Family->EngineShowFlags);
|
|
const bool bTraceMeshSDF = Lumen::UseMeshSDFTracing(View.Family->EngineShowFlags)
|
|
&& MeshSDFGridParameters.TracingParameters.DistanceFieldObjectBuffers.NumSceneObjects > 0
|
|
&& VisualizeParameters.MaxMeshSDFTraceDistance > VisualizeParameters.MinTraceDistance;
|
|
|
|
{
|
|
FVisualizeLumenSceneCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FVisualizeLumenSceneCS::FParameters>();
|
|
PassParameters->RWSceneColor = SceneColorUAV;
|
|
PassParameters->SceneTextures = SceneTextures;
|
|
PassParameters->SceneTextureParameters = GetSceneTextureParameters(GraphBuilder, View);
|
|
PassParameters->MeshSDFGridParameters = MeshSDFGridParameters;
|
|
PassParameters->VisualizeParameters = VisualizeParameters;
|
|
LumenRadianceCache::GetInterpolationParameters(View, GraphBuilder, RadianceCacheState, RadianceCacheInputs, PassParameters->RadianceCacheParameters);
|
|
PassParameters->Substrate = Substrate::BindSubstrateGlobalUniformParameters(View);
|
|
PassParameters->TracingParameters = TracingParameters;
|
|
|
|
FVisualizeLumenSceneCS::FPermutationDomain PermutationVector;
|
|
PermutationVector.Set<FVisualizeLumenSceneCS::FTraceMeshSDF>(bTraceMeshSDF);
|
|
PermutationVector.Set<FVisualizeLumenSceneCS::FTraceGlobalSDF>(bTraceGlobalSDF);
|
|
PermutationVector.Set<FVisualizeLumenSceneCS::FSimpleCoverageBasedExpand>(bTraceGlobalSDF && Lumen::UseGlobalSDFSimpleCoverageBasedExpand());
|
|
PermutationVector.Set<FVisualizeLumenSceneCS::FRadianceCache>(GVisualizeLumenSceneTraceRadianceCache != 0 && LumenScreenProbeGather::UseRadianceCache());
|
|
PermutationVector.Set<FVisualizeLumenSceneCS::FTraceHeightfields>(Lumen::UseHeightfieldTracing(*View.Family, *Scene->GetLumenSceneData(View)));
|
|
PermutationVector = FVisualizeLumenSceneCS::RemapPermutation(PermutationVector);
|
|
|
|
auto ComputeShader = View.ShaderMap->GetShader<FVisualizeLumenSceneCS>(PermutationVector);
|
|
FIntPoint GroupSize(FIntPoint::DivideAndRoundUp(VisualizeParameters.CommonParameters.OutputViewSize, FVisualizeLumenSceneCS::GetGroupSize()));
|
|
|
|
FComputeShaderUtils::AddPass(
|
|
GraphBuilder,
|
|
RDG_EVENT_NAME("LumenSceneVisualization"),
|
|
ComputeShader,
|
|
PassParameters,
|
|
FIntVector(GroupSize.X, GroupSize.Y, 1));
|
|
}
|
|
|
|
}
|
|
|
|
if (FrameTemporaries.DebugData != nullptr)
|
|
{
|
|
FVisualizeLumenSceneCursorDataCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FVisualizeLumenSceneCursorDataCS::FParameters>();
|
|
PassParameters->DebugData = FrameTemporaries.DebugData;
|
|
PassParameters->RWSceneColor = SceneColorUAV;
|
|
PassParameters->SceneTextures = SceneTextures;
|
|
PassParameters->VisualizeParameters = VisualizeParameters;
|
|
PassParameters->TracingParameters = TracingParameters;
|
|
|
|
FVisualizeLumenSceneCursorDataCS::FPermutationDomain PermutationVector;
|
|
auto ComputeShader = View.ShaderMap->GetShader<FVisualizeLumenSceneCursorDataCS>(PermutationVector);
|
|
FIntPoint GroupSize(FIntPoint::DivideAndRoundUp(VisualizeParameters.CommonParameters.OutputViewSize, FVisualizeLumenSceneCursorDataCS::GetGroupSize()));
|
|
|
|
FComputeShaderUtils::AddPass(
|
|
GraphBuilder,
|
|
RDG_EVENT_NAME("LumenSceneLightingCursorVisualization"),
|
|
ComputeShader,
|
|
PassParameters,
|
|
FIntVector(GroupSize.X, GroupSize.Y, 1));
|
|
}
|
|
}
|
|
|
|
int32 GetLumenVisualizeMode(const FViewInfo& View)
|
|
{
|
|
const FLumenVisualizationData& VisualizationData = GetLumenVisualizationData();
|
|
const int32 VisualizeMode = GLumenVisualize > 0 ? GLumenVisualize : VisualizationData.GetModeID(View.CurrentLumenVisualizationMode);
|
|
return VisualizeMode;
|
|
}
|
|
|
|
FScreenPassTexture AddVisualizeLumenScenePass(FRDGBuilder& GraphBuilder, const FViewInfo& View, bool bAnyLumenActive, EDiffuseIndirectMethod DiffuseIndirectMethod, const FVisualizeLumenSceneInputs& Inputs, FLumenSceneFrameTemporaries& FrameTemporaries)
|
|
{
|
|
check(Inputs.SceneColor.IsValid());
|
|
|
|
FScreenPassTexture Output = Inputs.SceneColor;
|
|
|
|
const FScene* Scene = (const FScene*)View.Family->Scene;
|
|
const FSceneViewFamily& ViewFamily = *View.Family;
|
|
|
|
if (Lumen::IsLumenFeatureAllowedForView(Scene, View) && bAnyLumenActive)
|
|
{
|
|
RenderVisualizeTraces(GraphBuilder, View, Inputs.ColorGradingTexture, Inputs.EyeAdaptationBuffer);
|
|
|
|
const bool bVisualizeScene = Lumen::ShouldVisualizeScene(ViewFamily.EngineShowFlags);
|
|
|
|
if (bVisualizeScene && (Lumen::ShouldVisualizeHardwareRayTracing(ViewFamily) || Lumen::IsSoftwareRayTracingSupported()))
|
|
{
|
|
RDG_EVENT_SCOPE(GraphBuilder, "VisualizeLumenScene");
|
|
|
|
// Create a new output just to make sure the right flags are set
|
|
FRDGTextureDesc VisualizeOutputDesc = Inputs.SceneColor.Texture->Desc;
|
|
VisualizeOutputDesc.Flags |= TexCreate_UAV | TexCreate_RenderTargetable;
|
|
Output = FScreenPassTexture(GraphBuilder.CreateTexture(VisualizeOutputDesc, TEXT("VisualizeLumenScene")), Inputs.SceneColor.ViewRect);
|
|
|
|
const int32 VisualizeMode = GetLumenVisualizeMode(View);
|
|
|
|
// In the overview mode we don't fully overwrite, copy the old Scene Color
|
|
if (VisualizeMode == VISUALIZE_MODE_OVERVIEW || VisualizeMode == VISUALIZE_MODE_PERFORMANCE_OVERVIEW)
|
|
{
|
|
FRHICopyTextureInfo CopyInfo;
|
|
|
|
AddCopyTexturePass(
|
|
GraphBuilder,
|
|
Inputs.SceneColor.Texture,
|
|
Output.Texture,
|
|
CopyInfo);
|
|
}
|
|
|
|
if (VisualizeMode == VISUALIZE_MODE_OVERVIEW)
|
|
{
|
|
struct FVisualizeTile
|
|
{
|
|
int32 Mode;
|
|
const TCHAR* Name;
|
|
};
|
|
|
|
FVisualizeTile VisualizeTiles[LumenVisualize::NumOverviewTilesPerRow];
|
|
VisualizeTiles[0].Mode = VISUALIZE_MODE_GEOMETRY_NORMALS;
|
|
VisualizeTiles[0].Name = TEXT("Geometry Normals");
|
|
VisualizeTiles[1].Mode = VISUALIZE_MODE_REFLECTION_VIEW;
|
|
if (Lumen::UseHardwareRayTracing(ViewFamily))
|
|
{
|
|
LumenHardwareRayTracing::EHitLightingMode HitLightingMode = LumenHardwareRayTracing::GetHitLightingMode(View, DiffuseIndirectMethod);
|
|
switch (HitLightingMode)
|
|
{
|
|
case LumenHardwareRayTracing::EHitLightingMode::HitLighting:
|
|
VisualizeTiles[1].Name = TEXT("Reflection View, HWRT, Hit Lighting");
|
|
break;
|
|
|
|
case LumenHardwareRayTracing::EHitLightingMode::HitLightingForReflections:
|
|
VisualizeTiles[1].Name = TEXT("Reflection View, HWRT, Hit Lighting for Reflections");
|
|
break;
|
|
|
|
default:
|
|
VisualizeTiles[1].Name = TEXT("Reflection View, HWRT");
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
VisualizeTiles[1].Name = Lumen::UseMeshSDFTracing(ViewFamily.EngineShowFlags) ? TEXT("Reflection View, SWRT with detail tracing") : TEXT("Reflection View, SWRT");
|
|
}
|
|
VisualizeTiles[2].Mode = VISUALIZE_MODE_SURFACE_CACHE;
|
|
VisualizeTiles[2].Name = TEXT("Lumen Scene, Pink - missing Surface Cache coverage, Yellow - culled Surface Cache");
|
|
|
|
for (int32 TileIndex = 0; TileIndex < LumenVisualize::NumOverviewTilesPerRow; ++TileIndex)
|
|
{
|
|
VisualizeLumenScene(Scene, GraphBuilder, ViewFamily.EngineShowFlags, View, FrameTemporaries, Output, Inputs.ColorGradingTexture, Inputs.EyeAdaptationBuffer, Inputs.SceneTextures, VisualizeTiles[TileIndex].Mode, TileIndex, DiffuseIndirectMethod);
|
|
}
|
|
|
|
AddDrawCanvasPass(GraphBuilder, RDG_EVENT_NAME("LumenVisualizeLabels"), View, FScreenPassRenderTarget(Output, ERenderTargetLoadAction::ELoad),
|
|
[&ViewRect = Inputs.SceneColor.ViewRect, &VisualizeTiles](FCanvas& Canvas)
|
|
{
|
|
const float DPIScale = Canvas.GetDPIScale();
|
|
Canvas.SetBaseTransform(FMatrix(FScaleMatrix(DPIScale)* Canvas.CalcBaseTransform2D(Canvas.GetViewRect().Width(), Canvas.GetViewRect().Height())));
|
|
|
|
const FLinearColor LabelColor(1, 1, 0);
|
|
|
|
for (int32 TileIndex = 0; TileIndex < LumenVisualize::NumOverviewTilesPerRow; ++TileIndex)
|
|
{
|
|
FIntPoint OutputViewSize;
|
|
FIntPoint OutputViewOffset;
|
|
GetVisualizeTileOutputView(ViewRect, TileIndex, OutputViewOffset, OutputViewSize);
|
|
|
|
FIntPoint LabelLocation(OutputViewOffset.X + 2 * LumenVisualize::OverviewTileMargin, OutputViewOffset.Y + OutputViewSize.Y - 20);
|
|
Canvas.DrawShadowedString(LabelLocation.X / DPIScale, LabelLocation.Y / DPIScale, VisualizeTiles[TileIndex].Name, GetStatsFont(), LabelColor);
|
|
}
|
|
});
|
|
}
|
|
else if (VisualizeMode == VISUALIZE_MODE_PERFORMANCE_OVERVIEW)
|
|
{
|
|
struct FVisualizeTile
|
|
{
|
|
int32 Mode;
|
|
FString Name;
|
|
};
|
|
|
|
LumenReflections::FCompositeParameters ReflectionCompositeParameters;
|
|
LumenReflections::SetupCompositeParameters(View, ReflectionCompositeParameters);
|
|
|
|
FVisualizeTile VisualizeTiles[1];
|
|
VisualizeTiles[0].Mode = VISUALIZE_MODE_DEDICATED_REFLECTION_RAYS;
|
|
VisualizeTiles[0].Name = FString::Printf(
|
|
TEXT("Pixels tracing dedicated reflection rays.")
|
|
TEXT("\nGreen - foliage(Subsurface or Two Sided Foliage shading model). Red - other.")
|
|
TEXT("\nMaxRoughness: %.2f MaxFoliageRoughness: %.2f"),
|
|
ReflectionCompositeParameters.MaxRoughnessToTrace,
|
|
ReflectionCompositeParameters.MaxRoughnessToTraceForFoliage);
|
|
|
|
for (int32 TileIndex = 0; TileIndex < UE_ARRAY_COUNT(VisualizeTiles); ++TileIndex)
|
|
{
|
|
VisualizeLumenScene(Scene, GraphBuilder, ViewFamily.EngineShowFlags, View, FrameTemporaries, Output, Inputs.ColorGradingTexture, Inputs.EyeAdaptationBuffer, Inputs.SceneTextures, VisualizeTiles[TileIndex].Mode, TileIndex, DiffuseIndirectMethod);
|
|
}
|
|
|
|
AddDrawCanvasPass(GraphBuilder, RDG_EVENT_NAME("LumenVisualizeLabels"), View, FScreenPassRenderTarget(Output, ERenderTargetLoadAction::ELoad),
|
|
[&ViewRect = Inputs.SceneColor.ViewRect, &VisualizeTiles](FCanvas& Canvas)
|
|
{
|
|
const float DPIScale = Canvas.GetDPIScale();
|
|
Canvas.SetBaseTransform(FMatrix(FScaleMatrix(DPIScale) * Canvas.CalcBaseTransform2D(Canvas.GetViewRect().Width(), Canvas.GetViewRect().Height())));
|
|
|
|
const FLinearColor LabelColor(1, 1, 0);
|
|
|
|
for (int32 TileIndex = 0; TileIndex < UE_ARRAY_COUNT(VisualizeTiles); ++TileIndex)
|
|
{
|
|
FIntPoint OutputViewSize;
|
|
FIntPoint OutputViewOffset;
|
|
GetVisualizeTileOutputView(ViewRect, TileIndex, OutputViewOffset, OutputViewSize);
|
|
|
|
FIntPoint LabelLocation(OutputViewOffset.X + 2 * LumenVisualize::OverviewTileMargin, OutputViewOffset.Y + OutputViewSize.Y - 46);
|
|
Canvas.DrawShadowedString(LabelLocation.X / DPIScale, LabelLocation.Y / DPIScale, *VisualizeTiles[TileIndex].Name, GetStatsFont(), LabelColor);
|
|
}
|
|
});
|
|
}
|
|
else if (VisualizeMode == VISUALIZE_MODE_SCREENPROBEGATHER_FAST_UPDATE_MODE_AMOUNT || VisualizeMode == VISUALIZE_MODE_SCREENPROBEGATHER_NUM_FRAMES_ACCUMULATED)
|
|
{
|
|
FRDGTextureRef InputTexture = FrameTemporaries.NewHistoryFastUpdateMode_NumFramesAccumulated.GetRenderTarget();
|
|
FIntRect InputViewRect = View.ViewRect;
|
|
if (!InputTexture)
|
|
{
|
|
InputTexture = GSystemTextures.GetBlackArrayDummy(GraphBuilder);
|
|
InputViewRect = FIntRect(0, 0, 1, 1);
|
|
}
|
|
FScreenPassTexture Input(InputTexture, InputViewRect);
|
|
|
|
FVisualizeBitFieldFloatTexturePS::FParameters* PassParameters = GraphBuilder.AllocParameters<FVisualizeBitFieldFloatTexturePS::FParameters>();
|
|
PassParameters->View = View.ViewUniformBuffer;
|
|
PassParameters->SceneColorTexture = Inputs.SceneColor.Texture;
|
|
PassParameters->InputTexture = GraphBuilder.CreateSRV(FRDGTextureSRVDesc::CreateForSlice(InputTexture, 0));
|
|
PassParameters->ToIntMulAdd = FVector2f(255.0f, 0.0f);
|
|
PassParameters->PreOutputMulAdd = FVector2f(1.0f / 15.0f, 0.0f);
|
|
PassParameters->BitMaskShift = VisualizeMode == VISUALIZE_MODE_SCREENPROBEGATHER_FAST_UPDATE_MODE_AMOUNT ? FUintVector2(0xf0, 4) : FUintVector2(0x0f, 0);
|
|
PassParameters->RenderTargets[0] = FRenderTargetBinding(Output.Texture, ERenderTargetLoadAction::ENoAction);
|
|
|
|
auto PixelShader = View.ShaderMap->GetShader<FVisualizeBitFieldFloatTexturePS>();
|
|
|
|
AddDrawScreenPass(
|
|
GraphBuilder,
|
|
RDG_EVENT_NAME("LumenVisualizeScreenProbeGather%s"),
|
|
FScreenPassViewInfo(),
|
|
FScreenPassTextureViewport(Output),
|
|
FScreenPassTextureViewport(Input),
|
|
PixelShader,
|
|
PassParameters);
|
|
}
|
|
else
|
|
{
|
|
VisualizeLumenScene(Scene, GraphBuilder, ViewFamily.EngineShowFlags, View, FrameTemporaries, Output, Inputs.ColorGradingTexture, Inputs.EyeAdaptationBuffer, Inputs.SceneTextures, VisualizeMode, /*VisualizeTileIndex*/ -1, DiffuseIndirectMethod);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (FrameTemporaries.DebugData != nullptr)
|
|
{
|
|
// Create a new output just to make sure the right flags are set
|
|
FRDGTextureDesc VisualizeOutputDesc = Inputs.SceneColor.Texture->Desc;
|
|
VisualizeOutputDesc.Flags |= TexCreate_UAV | TexCreate_RenderTargetable;
|
|
Output = FScreenPassTexture(GraphBuilder.CreateTexture(VisualizeOutputDesc, TEXT("VisualizeLumenScene")), Inputs.SceneColor.ViewRect);
|
|
|
|
// In the overview mode we don't fully overwrite, copy the old Scene Color
|
|
{
|
|
FRHICopyTextureInfo CopyInfo;
|
|
|
|
AddCopyTexturePass(
|
|
GraphBuilder,
|
|
Inputs.SceneColor.Texture,
|
|
Output.Texture,
|
|
CopyInfo);
|
|
}
|
|
|
|
ShaderPrint::SetEnabled(true);
|
|
|
|
FRDGTextureUAVRef SceneColorUAV = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(Output.Texture));
|
|
|
|
FLumenVisualizeSceneSoftwareRayTracingParameters VisualizeParameters;
|
|
SetupVisualizeParameters(GraphBuilder, View, Output.ViewRect, Inputs.ColorGradingTexture, Inputs.EyeAdaptationBuffer, 0, 0, VisualizeParameters);
|
|
|
|
FLumenCardTracingParameters TracingParameters;
|
|
GetLumenCardTracingParameters(GraphBuilder, View, *Scene->GetLumenSceneData(View), FrameTemporaries, LumenVisualize::UseSurfaceCacheFeedback(ViewFamily.EngineShowFlags), TracingParameters);
|
|
|
|
FVisualizeLumenSceneCursorDataCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FVisualizeLumenSceneCursorDataCS::FParameters>();
|
|
PassParameters->DebugData = FrameTemporaries.DebugData;
|
|
PassParameters->RWSceneColor = SceneColorUAV;
|
|
PassParameters->SceneTextures = Inputs.SceneTextures;
|
|
PassParameters->VisualizeParameters = VisualizeParameters;
|
|
PassParameters->TracingParameters = TracingParameters;
|
|
|
|
FVisualizeLumenSceneCursorDataCS::FPermutationDomain PermutationVector;
|
|
auto ComputeShader = View.ShaderMap->GetShader<FVisualizeLumenSceneCursorDataCS>(PermutationVector);
|
|
FIntPoint GroupSize(FIntPoint::DivideAndRoundUp(VisualizeParameters.CommonParameters.OutputViewSize, FVisualizeLumenSceneCursorDataCS::GetGroupSize()));
|
|
|
|
FComputeShaderUtils::AddPass(
|
|
GraphBuilder,
|
|
RDG_EVENT_NAME("LumenSceneLightingCursorVisualization"),
|
|
ComputeShader,
|
|
PassParameters,
|
|
FIntVector(GroupSize.X, GroupSize.Y, 1));
|
|
}
|
|
|
|
if (Inputs.OverrideOutput.IsValid())
|
|
{
|
|
AddDrawTexturePass(GraphBuilder, View, Output, Inputs.OverrideOutput);
|
|
return Inputs.OverrideOutput;
|
|
}
|
|
|
|
return MoveTemp(Output);
|
|
}
|
|
|
|
void AddBoxFaceTriangles(FDynamicMeshBuilder& MeshBuilder, int32 FaceIndex)
|
|
{
|
|
const int32 BoxIndices[6][4] =
|
|
{
|
|
{ 0, 2, 3, 1 }, // back, -z
|
|
{ 4, 5, 7, 6 }, // front, +z
|
|
{ 0, 4, 6, 2 }, // left, -x
|
|
{ 1, 3, 7, 5 }, // right, +x,
|
|
{ 0, 4, 5, 1 }, // bottom, -y
|
|
{ 2, 3, 7, 6 } // top, +y
|
|
};
|
|
|
|
MeshBuilder.AddTriangle(BoxIndices[FaceIndex][0], BoxIndices[FaceIndex][2], BoxIndices[FaceIndex][1]);
|
|
MeshBuilder.AddTriangle(BoxIndices[FaceIndex][0], BoxIndices[FaceIndex][3], BoxIndices[FaceIndex][2]);
|
|
}
|
|
|
|
void DrawPrimitiveBounds(const FLumenPrimitiveGroup& PrimitiveGroup, FLinearColor BoundsColor, FViewElementPDI& ViewPDI)
|
|
{
|
|
const uint8 DepthPriority = SDPG_World;
|
|
|
|
for (const FPrimitiveSceneInfo* PrimitiveSceneInfo : PrimitiveGroup.Primitives)
|
|
{
|
|
const FMatrix& PrimitiveToWorld = PrimitiveSceneInfo->Proxy->GetLocalToWorld();
|
|
if (const FInstanceSceneDataBuffers *InstanceData = PrimitiveSceneInfo->GetInstanceSceneDataBuffers())
|
|
{
|
|
for (int32 InstanceIndex = 0; InstanceIndex < InstanceData->GetNumInstances(); ++InstanceIndex)
|
|
{
|
|
const FBox LocalBoundingBox = InstanceData->GetInstanceLocalBounds(InstanceIndex).ToBox();
|
|
FMatrix LocalToWorld = InstanceData->GetInstanceToWorld(InstanceIndex);
|
|
DrawWireBox(&ViewPDI, LocalToWorld, LocalBoundingBox, BoundsColor, DepthPriority);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const FBox LocalBoundingBox = PrimitiveSceneInfo->Proxy->GetLocalBounds().GetBox();
|
|
DrawWireBox(&ViewPDI, PrimitiveToWorld, LocalBoundingBox, BoundsColor, DepthPriority);
|
|
}
|
|
}
|
|
}
|
|
|
|
void DrawSurfels(FSceneRenderingBulkObjectAllocator& Allocator, const TArray<FLumenCardBuildDebugData::FSurfel>& Surfels, const FMatrix& PrimitiveToWorld, FLumenCardBuildDebugData::ESurfelType SurfelType, FLinearColor SurfelColor, FViewElementPDI& ViewPDI, float SurfelRadius = 2.0f)
|
|
{
|
|
FColoredMaterialRenderProxy* MaterialRenderProxy = Allocator.Create<FColoredMaterialRenderProxy>(GEngine->LevelColorationUnlitMaterial->GetRenderProxy(), SurfelColor);
|
|
|
|
FDynamicMeshBuilder MeshBuilder(ViewPDI.View->GetFeatureLevel());
|
|
|
|
int32 NumSurfels = 0;
|
|
FVector3f NormalSum(0.0f, 0.0f, 0.0f);
|
|
FBox LocalBounds;
|
|
LocalBounds.Init();
|
|
|
|
const FMatrix WorldToPrimitiveT = PrimitiveToWorld.Inverse().GetTransposed();
|
|
|
|
int32 BaseVertex = 0;
|
|
for (int32 SurfelIndex = 0; SurfelIndex < Surfels.Num(); ++SurfelIndex)
|
|
{
|
|
if (GVisualizeLumenCardGenerationMaxSurfel >= 0 && NumSurfels >= GVisualizeLumenCardGenerationMaxSurfel)
|
|
{
|
|
break;
|
|
}
|
|
|
|
const FLumenCardBuildDebugData::FSurfel& Surfel = Surfels[SurfelIndex];
|
|
if (Surfel.Type == SurfelType)
|
|
{
|
|
FVector3f DiskPosition = (FVector4f)PrimitiveToWorld.TransformPosition((FVector)Surfel.Position);
|
|
FVector3f DiskNormal = (FVector4f)WorldToPrimitiveT.TransformVector((FVector)Surfel.Normal).GetSafeNormal();
|
|
|
|
// Surface bias
|
|
DiskPosition += DiskNormal * 0.5f;
|
|
|
|
FVector3f AxisX;
|
|
FVector3f AxisY;
|
|
DiskNormal.FindBestAxisVectors(AxisX, AxisY);
|
|
|
|
const int32 NumSides = 6;
|
|
const float AngleDelta = 2.0f * PI / NumSides;
|
|
for (int32 SideIndex = 0; SideIndex < NumSides; ++SideIndex)
|
|
{
|
|
const FVector3f VertexPosition = DiskPosition + (AxisX * FMath::Cos(AngleDelta * (SideIndex)) + AxisY * FMath::Sin(AngleDelta * (SideIndex))) * SurfelRadius * GVisualizeLumenCardGenerationSurfelScale;
|
|
|
|
MeshBuilder.AddVertex(VertexPosition, FVector2f(0, 0), FVector3f(1, 0, 0), FVector3f(0, 1, 0), FVector3f(0, 0, 1), FColor::White);
|
|
}
|
|
|
|
for (int32 SideIndex = 0; SideIndex < NumSides - 1; ++SideIndex)
|
|
{
|
|
int32 V0 = BaseVertex + 0;
|
|
int32 V1 = BaseVertex + SideIndex;
|
|
int32 V2 = BaseVertex + (SideIndex + 1);
|
|
|
|
MeshBuilder.AddTriangle(V0, V1, V2);
|
|
}
|
|
BaseVertex += NumSides;
|
|
NormalSum += DiskNormal;
|
|
++NumSurfels;
|
|
|
|
LocalBounds += (FVector)Surfel.Position;
|
|
}
|
|
}
|
|
|
|
const uint8 DepthPriority = SDPG_World;
|
|
MeshBuilder.Draw(&ViewPDI, FMatrix::Identity, MaterialRenderProxy, DepthPriority, false);
|
|
|
|
if (SurfelType == FLumenCardBuildDebugData::ESurfelType::Cluster
|
|
&& GVisualizeLumenCardGenerationMaxSurfel >= 0)
|
|
{
|
|
LocalBounds = LocalBounds.ExpandBy(1.0f);
|
|
|
|
DrawWireBox(&ViewPDI, PrimitiveToWorld, LocalBounds, SurfelColor, DepthPriority, GVisualizeLumenCardGenerationClusterScale);
|
|
|
|
const FVector Start = PrimitiveToWorld.TransformPosition(LocalBounds.GetCenter());
|
|
const FVector End = PrimitiveToWorld.TransformPosition(LocalBounds.GetCenter() + (FVector)NormalSum.GetSafeNormal() * 100.0f);
|
|
ViewPDI.DrawLine(Start, End, FLinearColor::Red, 0, 0.2f, 0.0f, false);
|
|
}
|
|
}
|
|
|
|
void VisualizeRayTracingGroups(const FViewInfo& View, const FLumenSceneData& LumenSceneData, FViewElementPDI& ViewPDI)
|
|
{
|
|
if (GVisualizeLumenRayTracingGroups == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
FConvexVolume ViewFrustum;
|
|
GetViewFrustumBounds(ViewFrustum, View.ViewMatrices.GetViewProjectionMatrix(), true);
|
|
|
|
for (const FLumenPrimitiveGroup& PrimitiveGroup : LumenSceneData.PrimitiveGroups)
|
|
{
|
|
if ((GVisualizeLumenRayTracingGroups != 2 || !PrimitiveGroup.HasMergedInstances()) && PrimitiveGroup.HasMergedPrimitives())
|
|
{
|
|
const FRenderBounds& WorldSpaceBoundingBox = LumenSceneData.GetPrimitiveGroupCullingInfo(PrimitiveGroup).WorldSpaceBoundingBox;
|
|
|
|
if (WorldSpaceBoundingBox.ComputeSquaredDistanceToPoint((FVector3f)View.ViewMatrices.GetViewOrigin()) < GVisualizeLumenCardPlacementDistance * GVisualizeLumenCardPlacementDistance
|
|
&& ViewFrustum.IntersectBox((FVector)WorldSpaceBoundingBox.GetCenter(), (FVector)WorldSpaceBoundingBox.GetExtent()))
|
|
{
|
|
const uint32 GroupIdHash = GetTypeHash(PrimitiveGroup.RayTracingGroupMapElementId.GetIndex());
|
|
const uint8 DepthPriority = SDPG_World;
|
|
const uint8 Hue = GroupIdHash & 0xFF;
|
|
const uint8 Saturation = 0xFF;
|
|
const uint8 Value = 0xFF;
|
|
|
|
FLinearColor GroupColor = FLinearColor::MakeFromHSV8(Hue, Saturation, Value);
|
|
GroupColor.A = 1.0f;
|
|
|
|
DrawPrimitiveBounds(PrimitiveGroup, GroupColor, ViewPDI);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void VisualizeCardPlacement(FSceneRenderingBulkObjectAllocator& Allocator, const FViewInfo& View, const FLumenSceneData& LumenSceneData, FViewElementPDI& ViewPDI)
|
|
{
|
|
if (GVisualizeLumenCardPlacement == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
FConvexVolume ViewFrustum;
|
|
GetViewFrustumBounds(ViewFrustum, View.ViewMatrices.GetViewProjectionMatrix(), true);
|
|
|
|
for (const FLumenPrimitiveGroup& PrimitiveGroup : LumenSceneData.PrimitiveGroups)
|
|
{
|
|
bool bVisible = PrimitiveGroup.MeshCardsIndex >= 0;
|
|
|
|
switch (GVisualizeLumenCardPlacementLOD)
|
|
{
|
|
case 1:
|
|
bVisible = bVisible && !PrimitiveGroup.HasMergedInstances();
|
|
break;
|
|
|
|
case 2:
|
|
bVisible = bVisible && PrimitiveGroup.HasMergedInstances() && !PrimitiveGroup.HasMergedPrimitives();
|
|
break;
|
|
|
|
case 3:
|
|
bVisible = bVisible && PrimitiveGroup.HasMergedInstances() && PrimitiveGroup.HasMergedPrimitives();
|
|
break;
|
|
|
|
case 4:
|
|
bVisible = bVisible && PrimitiveGroup.bFarField;
|
|
break;
|
|
}
|
|
|
|
if (!bVisible)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
const FRenderBounds& WorldSpaceBoundingBox = LumenSceneData.GetPrimitiveGroupCullingInfo(PrimitiveGroup).WorldSpaceBoundingBox;
|
|
|
|
if (WorldSpaceBoundingBox.ComputeSquaredDistanceToPoint((FVector3f)View.ViewMatrices.GetViewOrigin()) < GVisualizeLumenCardPlacementDistance * GVisualizeLumenCardPlacementDistance
|
|
&& ViewFrustum.IntersectBox((FVector)WorldSpaceBoundingBox.GetCenter(), (FVector)WorldSpaceBoundingBox.GetExtent()))
|
|
{
|
|
const FLumenMeshCards& MeshCardsEntry = LumenSceneData.MeshCards[PrimitiveGroup.MeshCardsIndex];
|
|
|
|
for (uint32 CardIndex = MeshCardsEntry.FirstCardIndex; CardIndex < MeshCardsEntry.FirstCardIndex + MeshCardsEntry.NumCards; ++CardIndex)
|
|
{
|
|
const FLumenCard& Card = LumenSceneData.Cards[CardIndex];
|
|
|
|
bVisible = Card.bVisible;
|
|
|
|
if (GVisualizeLumenCardPlacementIndex >= 0 && Card.IndexInMeshCards != GVisualizeLumenCardPlacementIndex)
|
|
{
|
|
bVisible = false;
|
|
}
|
|
|
|
if (bVisible)
|
|
{
|
|
uint32 CardHash = HashCombine(GetTypeHash(Card.LocalOBB.Origin), GetTypeHash(Card.LocalOBB.Extent));
|
|
CardHash = HashCombine(CardHash, GetTypeHash(Card.LocalOBB.AxisZ));
|
|
CardHash = HashCombine(CardHash, GetTypeHash(CardIndex));
|
|
|
|
const uint8 DepthPriority = SDPG_World;
|
|
const uint8 CardHue = CardHash & 0xFF;
|
|
const uint8 CardSaturation = 0xFF;
|
|
const uint8 CardValue = 0xFF;
|
|
|
|
FLinearColor CardColor = FLinearColor::MakeFromHSV8(CardHue, CardSaturation, CardValue);
|
|
CardColor.A = 1.0f;
|
|
|
|
const FMatrix CardToWorld(Card.WorldOBB.GetCardToLocal());
|
|
const FBox LocalBounds(-Card.WorldOBB.Extent, Card.WorldOBB.Extent);
|
|
|
|
DrawWireBox(&ViewPDI, CardToWorld, LocalBounds, CardColor, DepthPriority);
|
|
|
|
// Visualize bounds of primitives which make current card
|
|
if (GVisualizeLumenCardPlacementPrimitives != 0 && PrimitiveGroup.HasMergedInstances())
|
|
{
|
|
DrawPrimitiveBounds(PrimitiveGroup, CardColor, ViewPDI);
|
|
}
|
|
|
|
// Draw card "projection face"
|
|
{
|
|
CardColor.A = 0.25f;
|
|
|
|
FColoredMaterialRenderProxy* MaterialRenderProxy = Allocator.Create<FColoredMaterialRenderProxy>(GEngine->EmissiveMeshMaterial->GetRenderProxy(), CardColor, NAME_Color);
|
|
|
|
FDynamicMeshBuilder MeshBuilder(ViewPDI.View->GetFeatureLevel());
|
|
|
|
for (int32 VertIndex = 0; VertIndex < 8; ++VertIndex)
|
|
{
|
|
FVector BoxVertex;
|
|
BoxVertex.X = VertIndex & 0x1 ? LocalBounds.Max.X : LocalBounds.Min.X;
|
|
BoxVertex.Y = VertIndex & 0x2 ? LocalBounds.Max.Y : LocalBounds.Min.Y;
|
|
BoxVertex.Z = VertIndex & 0x4 ? LocalBounds.Max.Z : LocalBounds.Min.Z;
|
|
MeshBuilder.AddVertex((FVector3f)BoxVertex, FVector2f(0, 0), FVector3f(1, 0, 0), FVector3f(0, 1, 0), FVector3f(0, 0, 1), FColor::White);
|
|
}
|
|
|
|
AddBoxFaceTriangles(MeshBuilder, 1);
|
|
|
|
MeshBuilder.Draw(&ViewPDI, CardToWorld, MaterialRenderProxy, DepthPriority, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void VisualizeCardGeneration(FSceneRenderingBulkObjectAllocator& Allocator, const FViewInfo& View, const FLumenSceneData& LumenSceneData, FViewElementPDI& ViewPDI)
|
|
{
|
|
if (GVisualizeLumenCardGenerationSurfels == 0
|
|
&& GVisualizeLumenCardGenerationCluster == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// VisualizeCardGeneration runs before LumenSceneUpdate and LumenScene may contain deleted proxies
|
|
if (LumenSceneData.PendingRemoveOperations.Num() > 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
FConvexVolume ViewFrustum;
|
|
GetViewFrustumBounds(ViewFrustum, View.ViewMatrices.GetViewProjectionMatrix(), true);
|
|
|
|
for (const FLumenPrimitiveGroup& PrimitiveGroup : LumenSceneData.PrimitiveGroups)
|
|
{
|
|
const FRenderBounds& WorldSpaceBoundingBox = LumenSceneData.GetPrimitiveGroupCullingInfo(PrimitiveGroup).WorldSpaceBoundingBox;
|
|
|
|
if (WorldSpaceBoundingBox.ComputeSquaredDistanceToPoint((FVector3f)View.ViewMatrices.GetViewOrigin()) < GVisualizeLumenCardPlacementDistance * GVisualizeLumenCardPlacementDistance
|
|
&& ViewFrustum.IntersectBox((FVector)WorldSpaceBoundingBox.GetCenter(), (FVector)WorldSpaceBoundingBox.GetExtent()))
|
|
{
|
|
for (const FPrimitiveSceneInfo* PrimitiveSceneInfo : PrimitiveGroup.Primitives)
|
|
{
|
|
if (PrimitiveSceneInfo && PrimitiveSceneInfo->Proxy)
|
|
{
|
|
const FCardRepresentationData* CardRepresentationData = PrimitiveSceneInfo->Proxy->GetMeshCardRepresentation();
|
|
if (CardRepresentationData)
|
|
{
|
|
const uint8 DepthPriority = SDPG_World;
|
|
const FMatrix PrimitiveToWorld = PrimitiveSceneInfo->Proxy->GetLocalToWorld();
|
|
const FLumenCardBuildDebugData& DebugData = CardRepresentationData->MeshCardsBuildData.DebugData;
|
|
|
|
if (GVisualizeLumenCardGenerationSurfels)
|
|
{
|
|
DrawSurfels(Allocator, DebugData.Surfels, PrimitiveToWorld, FLumenCardBuildDebugData::ESurfelType::Valid, FLinearColor::Green, ViewPDI);
|
|
DrawSurfels(Allocator, DebugData.Surfels, PrimitiveToWorld, FLumenCardBuildDebugData::ESurfelType::Invalid, FLinearColor::Red, ViewPDI);
|
|
|
|
for (const FLumenCardBuildDebugData::FRay& Ray : DebugData.SurfelRays)
|
|
{
|
|
const FVector Start = PrimitiveToWorld.TransformPosition((FVector)Ray.RayStart);
|
|
const FVector End = PrimitiveToWorld.TransformPosition((FVector)Ray.RayEnd);
|
|
ViewPDI.DrawLine(Start, End, Ray.bHit ? FLinearColor::Red : FLinearColor::White, 0, 0.2f, 0.0f, false);
|
|
}
|
|
}
|
|
|
|
if (GVisualizeLumenCardGenerationSurfels == 0
|
|
&& GVisualizeLumenCardGenerationCluster != 0
|
|
&& PrimitiveGroup.MeshCardsIndex >= 0)
|
|
{
|
|
const FLumenMeshCards& MeshCardsEntry = LumenSceneData.MeshCards[PrimitiveGroup.MeshCardsIndex];
|
|
for (uint32 CardIndex = MeshCardsEntry.FirstCardIndex; CardIndex < MeshCardsEntry.FirstCardIndex + MeshCardsEntry.NumCards; ++CardIndex)
|
|
{
|
|
const FLumenCard& Card = LumenSceneData.Cards[CardIndex];
|
|
|
|
if (Card.bVisible
|
|
&& (Card.IndexInMeshCards == GVisualizeLumenCardPlacementIndex || GVisualizeLumenCardPlacementIndex < 0)
|
|
&& (Card.AxisAlignedDirectionIndex == GVisualizeLumenCardPlacementDirection || GVisualizeLumenCardPlacementDirection < 0)
|
|
&& Card.IndexInBuildData < DebugData.Clusters.Num())
|
|
{
|
|
const FLumenCardBuildDebugData::FSurfelCluster& Cluster = DebugData.Clusters[Card.IndexInBuildData];
|
|
|
|
uint32 CardHash = HashCombine(GetTypeHash(Card.LocalOBB.Origin), GetTypeHash(Card.LocalOBB.Extent));
|
|
CardHash = HashCombine(CardHash, GetTypeHash(Card.IndexInBuildData));
|
|
|
|
const uint8 CardHue = CardHash & 0xFF;
|
|
const uint8 CardSaturation = 0xFF;
|
|
const uint8 CardValue = 0xFF;
|
|
|
|
FLinearColor CardColor = FLinearColor::MakeFromHSV8(CardHue, CardSaturation, CardValue);
|
|
CardColor.A = 1.0f;
|
|
|
|
DrawSurfels(Allocator, Cluster.Surfels, PrimitiveToWorld, FLumenCardBuildDebugData::ESurfelType::Cluster, CardColor, ViewPDI);
|
|
DrawSurfels(Allocator, Cluster.Surfels, PrimitiveToWorld, FLumenCardBuildDebugData::ESurfelType::Used, FLinearColor::Gray, ViewPDI);
|
|
DrawSurfels(Allocator, Cluster.Surfels, PrimitiveToWorld, FLumenCardBuildDebugData::ESurfelType::Idle, FLinearColor::Blue, ViewPDI);
|
|
|
|
for (const FLumenCardBuildDebugData::FRay& Ray : Cluster.Rays)
|
|
{
|
|
const FVector Start = PrimitiveToWorld.TransformPosition((FVector)Ray.RayStart);
|
|
const FVector End = PrimitiveToWorld.TransformPosition((FVector)Ray.RayEnd);
|
|
ViewPDI.DrawLine(Start, End, Ray.bHit ? FLinearColor::Red : FLinearColor::White, 0, 0.2f, 0.0f, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void FDeferredShadingSceneRenderer::LumenScenePDIVisualization()
|
|
{
|
|
FLumenSceneData& LumenSceneData = *Scene->GetLumenSceneData(Views[0]);
|
|
|
|
const bool bAnyLumenEnabled = ShouldRenderLumenDiffuseGI(Scene, Views[0])
|
|
|| ShouldRenderLumenReflections(Views[0]);
|
|
|
|
if (bAnyLumenEnabled)
|
|
{
|
|
if (GVisualizeLumenCardPlacement != 0
|
|
|| GVisualizeLumenRayTracingGroups != 0
|
|
|| GVisualizeLumenCardGenerationCluster != 0
|
|
|| GVisualizeLumenCardGenerationSurfels != 0)
|
|
{
|
|
FViewElementPDI ViewPDI(&Views[0], nullptr, &Views[0].DynamicPrimitiveCollector);
|
|
VisualizeRayTracingGroups(Views[0], LumenSceneData, ViewPDI);
|
|
VisualizeCardPlacement(Allocator, Views[0], LumenSceneData, ViewPDI);
|
|
VisualizeCardGeneration(Allocator, Views[0], LumenSceneData, ViewPDI);
|
|
}
|
|
}
|
|
|
|
static bool bVisualizeLumenSceneViewOrigin = false;
|
|
|
|
if (bVisualizeLumenSceneViewOrigin)
|
|
{
|
|
const int32 NumClipmaps = Lumen::GetNumGlobalDFClipmaps(Views[0]);
|
|
|
|
for (int32 ClipmapIndex = 0; ClipmapIndex < NumClipmaps; ClipmapIndex++)
|
|
{
|
|
FViewElementPDI ViewPDI(&Views[0], nullptr, &Views[0].DynamicPrimitiveCollector);
|
|
const uint8 MarkerHue = (ClipmapIndex * 100) & 0xFF;
|
|
const uint8 MarkerSaturation = 0xFF;
|
|
const uint8 MarkerValue = 0xFF;
|
|
|
|
FLinearColor MarkerColor = FLinearColor::MakeFromHSV8(MarkerHue, MarkerSaturation, MarkerValue);
|
|
MarkerColor.A = 0.5f;
|
|
const FVector LumenSceneCameraOrigin = Lumen::GetLumenSceneViewOrigin(Views[0], ClipmapIndex);
|
|
DrawWireSphere(&ViewPDI, LumenSceneCameraOrigin, MarkerColor, 10 * (1 << ClipmapIndex), 32, SDPG_World);
|
|
}
|
|
}
|
|
} |