ShowFlag.VisualizeLightCulling
ShowFlag.VisualizeLightCulling
#Overview
name: ShowFlag.VisualizeLightCulling
This variable is created as a Console Variable (cvar).
- type:
Var
- help:
Allows to override a specific showflag (works in editor and game, \
It is referenced in 24
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of ShowFlag.VisualizeLightCulling is to enable a visualization mode for light culling in the Unreal Engine 5 rendering system. This setting variable is used primarily for debugging and optimizing the lighting system, allowing developers to visually inspect how lights are being culled in the scene.
The Unreal Engine subsystems that rely on this setting variable are primarily within the rendering module. Based on the callsites, it’s used in various parts of the renderer, including deferred shading, mobile shading, and post-processing.
The value of this variable is typically set through the engine’s show flags system, which allows toggling various debug visualization modes. It’s not directly set in the code snippets provided, but it’s accessed through ViewFamily.EngineShowFlags.VisualizeLightCulling
.
This variable interacts with several other rendering systems and flags. For example, it’s often used in conjunction with other show flags and can affect the behavior of various rendering passes.
Developers should be aware that enabling this flag will change the visual output of the renderer, as it’s designed to show debug information rather than the final, intended visual result. It may also have performance implications, as it can disable certain optimizations or enable additional rendering passes.
Best practices for using this variable include:
- Use it primarily for debugging and optimizing light culling.
- Be aware that it may affect performance when enabled.
- Remember to disable it before final builds or when not actively debugging lighting issues.
The associated variable VisualizeLightCulling
appears to be used interchangeably with ShowFlag.VisualizeLightCulling
in some parts of the code. It serves the same purpose and is likely just an alternative way to access the same functionality. The same considerations and best practices apply to this associated variable.
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:317
Scope: file
Source code excerpt:
SHOWFLAG_ALWAYS_ACCESSIBLE(DistanceCulledPrimitives, SFG_Hidden, NSLOCTEXT("UnrealEd", "DistanceCulledPrimitivesSF", "Distance Culled Primitives"))
/** To visualize the culling in Tile Based Deferred Lighting, later for non tiled as well */
SHOWFLAG_FIXED_IN_SHIPPING(0, VisualizeLightCulling, SFG_Hidden, NSLOCTEXT("UnrealEd", "VisualizeLightCullingSF", "Light Culling"))
/** To disable precomputed visibility */
SHOWFLAG_FIXED_IN_SHIPPING(1, PrecomputedVisibility, SFG_Advanced, NSLOCTEXT("UnrealEd", "PrecomputedVisibilitySF", "Precomputed Visibility"))
/** Contribution from sky light, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(SkyLighting, SFG_LightTypes, NSLOCTEXT("UnrealEd", "SkyLightingSF", "Sky Lighting"))
/** Visualize preview shadow indicator */
SHOWFLAG_FIXED_IN_SHIPPING(0, PreviewShadowsIndicator, SFG_Visualize, NSLOCTEXT("UnrealEd", "PreviewShadowIndicatorSF", "Preview Shadows Indicator"))
#Associated Variable and Callsites
This variable is associated with another variable named VisualizeLightCulling
. They share the same value. See the following C++ source code.
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/ShowFlags.cpp:760
Scope: file
Source code excerpt:
return VMI_ShaderComplexity;
}
else if (EngineShowFlags.VisualizeLightCulling)
{
return VMI_LightComplexity;
}
else if (EngineShowFlags.LightMapDensity)
{
if (EngineShowFlags.Lighting)
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:317
Scope: file
Source code excerpt:
SHOWFLAG_ALWAYS_ACCESSIBLE(DistanceCulledPrimitives, SFG_Hidden, NSLOCTEXT("UnrealEd", "DistanceCulledPrimitivesSF", "Distance Culled Primitives"))
/** To visualize the culling in Tile Based Deferred Lighting, later for non tiled as well */
SHOWFLAG_FIXED_IN_SHIPPING(0, VisualizeLightCulling, SFG_Hidden, NSLOCTEXT("UnrealEd", "VisualizeLightCullingSF", "Light Culling"))
/** To disable precomputed visibility */
SHOWFLAG_FIXED_IN_SHIPPING(1, PrecomputedVisibility, SFG_Advanced, NSLOCTEXT("UnrealEd", "PrecomputedVisibilitySF", "Precomputed Visibility"))
/** Contribution from sky light, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(SkyLighting, SFG_LightTypes, NSLOCTEXT("UnrealEd", "SkyLightingSF", "Sky Lighting"))
/** Visualize preview shadow indicator */
SHOWFLAG_FIXED_IN_SHIPPING(0, PreviewShadowsIndicator, SFG_Visualize, NSLOCTEXT("UnrealEd", "PreviewShadowIndicatorSF", "Preview Shadows Indicator"))
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/ClusteredDeferredShadingPass.cpp:216
Scope (from outer to inner):
file
function static void InternalAddClusteredDeferredShadingPass
lambda-function
Source code excerpt:
FClusteredShadingPS::FPermutationDomain PermutationVector;
PermutationVector.Set<FClusteredShadingPS::FVisualizeLightCullingDim>(View.Family->EngineShowFlags.VisualizeLightCulling);
PermutationVector.Set<FClusteredShadingPS::FHairStrandsLighting>(bHairStrands);
PermutationVector.Set<FClusteredShadingPS::FSubstrateTileType>(bSubstrate ? TileType : 0);
PermutationVector.Set<FClusteredShadingPS::FRectLight>(bHasRectLights);
PermutationVector.Set<FClusteredShadingPS::FLightFunctionAtlasDim>(bLightFunctionAtlas);
TShaderMapRef<FClusteredShadingPS> PixelShader(View.ShaderMap, PermutationVector);
{
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/CompositionLighting/PostProcessDeferredDecals.cpp:56
Scope (from outer to inner):
file
function bool AreDecalsEnabled
Source code excerpt:
bool AreDecalsEnabled(const FSceneViewFamily& ViewFamily)
{
return ViewFamily.EngineShowFlags.Decals && !ViewFamily.EngineShowFlags.VisualizeLightCulling;
}
bool IsDBufferEnabled(const FSceneViewFamily& ViewFamily, EShaderPlatform ShaderPlatform)
{
return IsUsingDBuffers(ShaderPlatform)
&& AreDecalsEnabled(ViewFamily)
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/DeferredShadingRenderer.cpp:2484
Scope (from outer to inner):
file
function void FDeferredShadingSceneRenderer::Render
Source code excerpt:
}
if (ViewFamily.EngineShowFlags.VisualizeLightCulling)
{
FRDGTextureRef VisualizeLightCullingTexture = GraphBuilder.CreateTexture(SceneTextures.Color.Target->Desc, TEXT("SceneColorVisualizeLightCulling"));
AddClearRenderTargetPass(GraphBuilder, VisualizeLightCullingTexture, FLinearColor::Transparent);
SceneTextures.Color.Target = VisualizeLightCullingTexture;
// When not in MSAA, assign to both targets.
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/DistanceFieldAmbientOcclusion.cpp:693
Scope (from outer to inner):
file
function bool ShouldRenderDeferredDynamicSkyLight
Source code excerpt:
&& Scene->GetFeatureLevel() >= ERHIFeatureLevel::SM5
&& !IsForwardShadingEnabled(Scene->GetShaderPlatform())
&& !ViewFamily.EngineShowFlags.VisualizeLightCulling
&& !ShouldRenderRayTracingSkyLight(Scene->SkyLight, Scene->GetShaderPlatform()); // Disable diffuse sky contribution if evaluated by RT Sky;
}
bool ShouldDoReflectionEnvironment(const FScene* Scene, const FSceneViewFamily& ViewFamily)
{
const ERHIFeatureLevel::Type SceneFeatureLevel = Scene->GetFeatureLevel();
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/IndirectLightRendering.cpp:876
Scope (from outer to inner):
file
function void FDeferredShadingSceneRenderer::DispatchAsyncLumenIndirectLightingWork
Source code excerpt:
|| !bAsyncComputeDiffuseIndirect
|| GLumenVisualizeIndirectDiffuse
|| ViewFamily.EngineShowFlags.VisualizeLightCulling)
{
return;
}
// Decals may modify GBuffers so they need to be done first. Can decals read velocities and/or custom depth? If so, they need to be rendered earlier too.
CompositionLighting.ProcessAfterBasePass(GraphBuilder, InstanceCullingManager, FCompositionLighting::EProcessAfterBasePassMode::OnlyBeforeLightingDecals);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/IndirectLightRendering.cpp:952
Scope (from outer to inner):
file
function void FDeferredShadingSceneRenderer::RenderDiffuseIndirectAndAmbientOcclusion
Source code excerpt:
extern int32 GLumenVisualizeIndirectDiffuse;
if ((GLumenVisualizeIndirectDiffuse != 0) != bIsVisualizePass
|| ViewFamily.EngineShowFlags.VisualizeLightCulling)
{
return;
}
TRACE_CPUPROFILER_EVENT_SCOPE(FDeferredShadingSceneRenderer::RenderDiffuseIndirectAndAmbientOcclusion);
RDG_EVENT_SCOPE(GraphBuilder, "DiffuseIndirectAndAO");
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/IndirectLightRendering.cpp:1909
Scope (from outer to inner):
file
function void FDeferredShadingSceneRenderer::RenderDeferredReflectionsAndSkyLighting
Source code excerpt:
{
extern int32 GLumenVisualizeIndirectDiffuse;
if (ViewFamily.EngineShowFlags.VisualizeLightCulling
|| ViewFamily.EngineShowFlags.RayTracingDebug
|| ViewFamily.EngineShowFlags.PathTracing
|| !ViewFamily.EngineShowFlags.Lighting
|| GLumenVisualizeIndirectDiffuse != 0)
{
return;
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/IndirectLightRendering.cpp:2183
Scope (from outer to inner):
file
function void FDeferredShadingSceneRenderer::RenderDeferredReflectionsAndSkyLightingHair
Source code excerpt:
void FDeferredShadingSceneRenderer::RenderDeferredReflectionsAndSkyLightingHair(FRDGBuilder& GraphBuilder)
{
if (ViewFamily.EngineShowFlags.VisualizeLightCulling || !ViewFamily.EngineShowFlags.Lighting)
{
return;
}
for (FViewInfo& View : Views)
{
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightRendering.cpp:2648
Scope: file
Source code excerpt:
PermutationVector.Set< FDeferredLightPS::FHairLighting>(0);
PermutationVector.Set< FDeferredLightPS::FLightingChannelsDim >(View.bUsesLightingChannels);
PermutationVector.Set< FDeferredLightPS::FVisualizeCullingDim >(View.Family->EngineShowFlags.VisualizeLightCulling);
PermutationVector.Set< FDeferredLightPS::FVirtualShadowMapMask >(bUseVirtualShadowMapMask);
PermutationVector.Set< FDeferredLightPS::FSubstrateTileType >(0);
PermutationVector.Set< FDeferredLightPS::FHairComplexTransmittance >(bNeedComplexTransmittanceSupport);
PermutationVector.Set< FDeferredLightPS::FLightFunctionAtlasDim >(
LightFunctionAtlas::IsEnabled(View, ELightFunctionAtlasSystem::DeferredLighting) && LightSceneInfo->Proxy->HasValidLightFunctionAtlasSlot() &&
LightSceneInfo->Proxy->GetLightFunctionMaterial() != nullptr && !View.Family->EngineShowFlags.VisualizeLightCulling);
if (bIsRadial)
{
PermutationVector.Set< FDeferredLightPS::FSourceShapeDim >(LightProxy->IsRectLight() ? ELightSourceShape::Rect : ELightSourceShape::Capsule);
PermutationVector.Set< FDeferredLightPS::FSourceTextureDim >(LightProxy->IsRectLight() && LightProxy->HasSourceTexture());
PermutationVector.Set< FDeferredLightPS::FIESProfileDim >(bUseIESTexture);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightRendering.cpp:2743
Scope: file
Source code excerpt:
// Ensure the light is valid for this view
const bool bHairRenderingEnabled = HairStrands::HasViewHairStrandsData(View);
if (!bHairRenderingEnabled || !LightSceneInfo->ShouldRenderLight(View) || View.HairStrandsViewData.VisibilityData.SampleLightingTexture == nullptr || View.Family->EngineShowFlags.VisualizeLightCulling)
{
return;
}
// Sanity check
check(InTransmittanceMaskData.TransmittanceMask);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightRendering.cpp:2810
Scope: file
Source code excerpt:
PermutationVector.Set< FDeferredLightPS::FLightFunctionAtlasDim >(
LightFunctionAtlas::IsEnabled(View, ELightFunctionAtlasSystem::DeferredLighting) && LightSceneInfo->Proxy->HasValidLightFunctionAtlasSlot() &&
LightSceneInfo->Proxy->GetLightFunctionMaterial() != nullptr && !View.Family->EngineShowFlags.VisualizeLightCulling);
if (bIsDirectional)
{
PermutationVector.Set< FDeferredLightPS::FSourceShapeDim >(ELightSourceShape::Directional);
PermutationVector.Set< FDeferredLightPS::FSourceTextureDim >(false);
PermutationVector.Set< FDeferredLightPS::FIESProfileDim >(false);
PermutationVector.Set< FDeferredLightPS::FAtmosphereTransmittance >(IsLightAtmospherePerPixelTransmittanceEnabled(Scene, View, LightSceneInfo));
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightRendering.cpp:2996
Scope: file
Source code excerpt:
PermutationVector.Set< FDeferredLightPS::FIESProfileDim >(false);
PermutationVector.Set< FDeferredLightPS::FLightFunctionAtlasDim>(false);
PermutationVector.Set< FDeferredLightPS::FVisualizeCullingDim >(View.Family->EngineShowFlags.VisualizeLightCulling);
PermutationVector.Set< FDeferredLightPS::FLightingChannelsDim >(false);
PermutationVector.Set< FDeferredLightPS::FAnistropicMaterials >(false);
PermutationVector.Set< FDeferredLightPS::FTransmissionDim >(false);
PermutationVector.Set< FDeferredLightPS::FHairLighting>(0);
PermutationVector.Set< FDeferredLightPS::FHairComplexTransmittance>(bNeedComplexTransmittanceSupport);
PermutationVector.Set< FDeferredLightPS::FAtmosphereTransmittance >(false);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Lumen/Lumen.cpp:110
Scope (from outer to inner):
file
function bool Lumen::ShouldHandleSkyLight
Source code excerpt:
&& Scene->GetFeatureLevel() >= ERHIFeatureLevel::SM5
&& !IsForwardShadingEnabled(Scene->GetShaderPlatform())
&& !ViewFamily.EngineShowFlags.VisualizeLightCulling;
}
bool ShouldRenderLumenForViewFamily(const FScene* Scene, const FSceneViewFamily& ViewFamily, bool bSkipProjectCheck)
{
return Scene
&& Scene->GetLumenSceneData(*ViewFamily.Views[0])
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/MobileShadingRenderer.cpp:546
Scope (from outer to inner):
file
function void FMobileSceneRenderer::InitViews
Source code excerpt:
&& !ViewFamily.EngineShowFlags.HitProxies
&& ViewFamily.EngineShowFlags.Lighting
&& !ViewFamily.EngineShowFlags.VisualizeLightCulling
&& !ViewFamily.UseDebugViewPS()
&& bRendererOutputFinalSceneColor;
bRequiresAmbientOcclusionPass = IsUsingMobileAmbientOcclusion(ShaderPlatform)
&& Views[0].FinalPostProcessSettings.AmbientOcclusionIntensity > 0
&& (Views[0].FinalPostProcessSettings.AmbientOcclusionStaticFraction >= 1 / 100.0f || (Scene && Scene->SkyLight && Scene->SkyLight->ProcessedTexture && Views[0].Family->EngineShowFlags.SkyLighting))
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/MobileShadingRenderer.cpp:557
Scope (from outer to inner):
file
function void FMobileSceneRenderer::InitViews
Source code excerpt:
&& !Views[0].bIsPlanarReflection
&& !ViewFamily.EngineShowFlags.HitProxies
&& !ViewFamily.EngineShowFlags.VisualizeLightCulling
&& !ViewFamily.UseDebugViewPS()
&& bRendererOutputFinalSceneColor;
bShouldRenderVelocities = ShouldRenderVelocities();
bRequiresShadowProjections = MobileUsesShadowMaskTexture(ShaderPlatform)
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/MobileShadingRenderer.cpp:568
Scope (from outer to inner):
file
function void FMobileSceneRenderer::InitViews
Source code excerpt:
&& !Views[0].bIsPlanarReflection
&& !ViewFamily.EngineShowFlags.HitProxies
&& !ViewFamily.EngineShowFlags.VisualizeLightCulling
&& !ViewFamily.UseDebugViewPS()
&& bRendererOutputFinalSceneColor;
bShouldRenderHZB = ShouldRenderHZB() && bRendererOutputFinalSceneColor;
// Whether we need to store depth for post-processing
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/MobileShadingRenderer.cpp:933
Scope (from outer to inner):
file
function void FMobileSceneRenderer::Render
Source code excerpt:
&& !Views[0].bIsReflectionCapture
&& !Views[0].bIsPlanarReflection
&& !ViewFamily.EngineShowFlags.VisualizeLightCulling
&& !ViewFamily.UseDebugViewPS()
&& (CVarDistanceFieldShadowQuality != nullptr && CVarDistanceFieldShadowQuality->GetInt() > 0)
&& bRendererOutputFinalSceneColor)
{
PrepareDistanceFieldScene(GraphBuilder, ExternalAccessQueue);
}
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/PostProcess/PostProcessing.cpp:369
Scope (from outer to inner):
file
function void AddPostProcessingPasses
Source code excerpt:
VisualizeDepthOfField,
VisualizeStationaryLightOverlap,
VisualizeLightCulling,
VisualizePostProcessStack,
VisualizeSubstrate,
VisualizeLightGrid,
VisualizeSkyAtmosphere,
VisualizeSkyLightIlluminanceMeter,
VisualizeLightFunctionAtlas,
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/PostProcess/PostProcessing.cpp:458
Scope (from outer to inner):
file
function void AddPostProcessingPasses
Source code excerpt:
PassSequence.SetNames(PassNames, UE_ARRAY_COUNT(PassNames));
PassSequence.SetEnabled(EPass::VisualizeStationaryLightOverlap, EngineShowFlags.StationaryLightOverlap);
PassSequence.SetEnabled(EPass::VisualizeLightCulling, EngineShowFlags.VisualizeLightCulling);
#if DEBUG_POST_PROCESS_VOLUME_ENABLE
PassSequence.SetEnabled(EPass::VisualizePostProcessStack, EngineShowFlags.VisualizePostProcessStack);
#else
PassSequence.SetEnabled(EPass::VisualizePostProcessStack, false);
#endif
PassSequence.SetEnabled(EPass::VisualizeLumenScene, LumenVisualizeMode >= 0 && LumenVisualizeMode != VISUALIZE_MODE_OVERVIEW && LumenVisualizeMode != VISUALIZE_MODE_PERFORMANCE_OVERVIEW && bPostProcessingEnabled);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/PostProcess/PostProcessing.cpp:1398
Scope (from outer to inner):
file
function void AddPostProcessingPasses
Source code excerpt:
}
if (PassSequence.IsEnabled(EPass::VisualizeLightCulling))
{
ensureMsgf(View.PrimaryScreenPercentageMethod != EPrimaryScreenPercentageMethod::TemporalUpscale, TEXT("TAAU should be disabled when visualizing light culling."));
// 0.1f comes from the values used in LightAccumulator_GetResult
const float ComplexityScale = 1.0f / (float)(GEngine->LightComplexityColors.Num() - 1) / 0.1f;
FVisualizeComplexityInputs PassInputs;
PassSequence.AcceptOverrideIfLastPass(EPass::VisualizeLightCulling, PassInputs.OverrideOutput);
PassInputs.SceneColor = OriginalSceneColor;
PassInputs.Colors = GEngine->LightComplexityColors;
PassInputs.ColorSamplingMethod = FVisualizeComplexityInputs::EColorSamplingMethod::Linear;
PassInputs.ComplexityScale = ComplexityScale;
PassInputs.bDrawLegend = true;
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/TranslucentRendering.cpp:685
Scope (from outer to inner):
file
function bool FSceneRenderer::ShouldRenderTranslucency
Source code excerpt:
{
return ViewFamily.EngineShowFlags.Translucency
&& !ViewFamily.EngineShowFlags.VisualizeLightCulling
&& !ViewFamily.UseDebugViewPS();
}
bool FSceneRenderer::ShouldRenderTranslucency(ETranslucencyPass::Type TranslucencyPass) const
{
extern int32 GLightShaftRenderAfterDOF;