ShowFlag.LightFunctions
ShowFlag.LightFunctions
#Overview
name: ShowFlag.LightFunctions
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 20
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of ShowFlag.LightFunctions is to control the visibility and rendering of light functions in Unreal Engine 5. Light functions are materials that can be applied to light sources to modify their output, allowing for complex lighting effects and patterns.
This setting variable is primarily used by the rendering system, specifically in the following Unreal Engine subsystems and modules:
- Deferred Shading Renderer
- Light Function Atlas
- Light Function Rendering
- Light Rendering
- Lumen Scene Direct Lighting
- Mobile Deferred Shading
- Path Tracing
- Ray Tracing Lighting
- Reflection Environment Capture
- Translucent Lighting
- Variable Rate Shading
- Volumetric Fog Light Function
The value of this variable is typically set through the engine show flags, which can be controlled via the UI or programmatically. It is often accessed through ViewFamily.EngineShowFlags.LightFunctions
.
Several other variables and systems interact with ShowFlag.LightFunctions:
- It is often used in conjunction with
GetLightFunctionMaterial()
to determine if a light function should be applied. - It interacts with the Light Function Atlas system.
- It affects various rendering passes, including forward shading, deferred shading, and ray tracing.
Developers should be aware of the following when using this variable:
- Enabling light functions can have performance implications, especially in complex scenes with many lights.
- Light functions are not supported in all rendering paths or on all platforms.
- The variable’s state can affect the appearance and behavior of lights in the scene.
Best practices for using this variable include:
- Only enable light functions when necessary, as they can impact performance.
- Use it in conjunction with proper light function materials for desired effects.
- Consider the target platform and rendering path when relying on light functions.
- Be aware of its interaction with other lighting and rendering systems.
The associated variable LightFunctions
is essentially the same as ShowFlag.LightFunctions
. It is used interchangeably in the code and serves the same purpose of controlling the visibility and rendering of light functions. The same considerations and best practices apply to both variables.
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:173
Scope: file
Source code excerpt:
SHOWFLAG_ALWAYS_ACCESSIBLE(TexturedLightProfiles, SFG_LightingFeatures, NSLOCTEXT("UnrealEd", "TexturedLightProfilesSF", "Textured Light Profiles (IES Texture)"))
/** LightFunctions (masking light sources with a material), for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(LightFunctions, SFG_LightingFeatures, NSLOCTEXT("UnrealEd", "LightFunctionsSF", "Light Functions"))
/** Draws instanced static meshes that are not foliage or grass, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(InstancedStaticMeshes, SFG_Advanced, NSLOCTEXT("UnrealEd", "InstancedStaticMeshesSF", "Instanced Static Meshes"))
/** Draws instanced foliage, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(InstancedFoliage, SFG_Advanced, NSLOCTEXT("UnrealEd", "InstancedFoliageSF", "Foliage"))
/** Allow to see the foliage bounds used in the occlusion test */
SHOWFLAG_FIXED_IN_SHIPPING(0, HISMCOcclusionBounds, SFG_Advanced, NSLOCTEXT("UnrealEd", "HISMOcclusionBoundsSF", "HISM/Foliage Occlusion Bounds"))
#Associated Variable and Callsites
This variable is associated with another variable named LightFunctions
. They share the same value. See the following C++ source code.
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:172
Scope: file
Source code excerpt:
/** LightProfiles, usually 1d textures to have a light (IES), for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(TexturedLightProfiles, SFG_LightingFeatures, NSLOCTEXT("UnrealEd", "TexturedLightProfilesSF", "Textured Light Profiles (IES Texture)"))
/** LightFunctions (masking light sources with a material), for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(LightFunctions, SFG_LightingFeatures, NSLOCTEXT("UnrealEd", "LightFunctionsSF", "Light Functions"))
/** Draws instanced static meshes that are not foliage or grass, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(InstancedStaticMeshes, SFG_Advanced, NSLOCTEXT("UnrealEd", "InstancedStaticMeshesSF", "Instanced Static Meshes"))
/** Draws instanced foliage, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(InstancedFoliage, SFG_Advanced, NSLOCTEXT("UnrealEd", "InstancedFoliageSF", "Foliage"))
/** Allow to see the foliage bounds used in the occlusion test */
SHOWFLAG_FIXED_IN_SHIPPING(0, HISMCOcclusionBounds, SFG_Advanced, NSLOCTEXT("UnrealEd", "HISMOcclusionBoundsSF", "HISM/Foliage Occlusion Bounds"))
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/DeferredShadingRenderer.cpp:1779
Scope (from outer to inner):
file
function void FDeferredShadingSceneRenderer::Render
Source code excerpt:
}
if (ViewFamily.EngineShowFlags.LightFunctions)
{
// gather all the light functions that may be used (and also count how many miss shaders we will need)
FRayTracingLightFunctionMap RayTracingLightFunctionMap;
if (ViewFamily.EngineShowFlags.PathTracing)
{
RayTracingLightFunctionMap = GatherLightFunctionLightsPathTracing(Scene, ViewFamily.EngineShowFlags, ReferenceView.GetFeatureLevel());
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightFunctionAtlas.cpp:260
Scope (from outer to inner):
file
namespace LightFunctionAtlas
function void FLightFunctionAtlas::BeginSceneFrame
Source code excerpt:
// Now lets check if we need to generate the atlas for this frame
bLightFunctionAtlasEnabled = CVarLightFunctionAtlas.GetValueOnRenderThread() > 0 && ViewFamily.EngineShowFlags.LightFunctions > 0;
// But only really enable the atlas generation if a system asks for it
bool bVolumetricFogRequestsLF = false;
bool bDeferredlightingRequestsLF = false;
bool bManyLightsRequestsLF = false;
bool bLumenRequestsLF = false;
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightFunctionRendering.cpp:260
Scope (from outer to inner):
file
function bool FDeferredShadingSceneRenderer::RenderLightFunction
Source code excerpt:
bool bUseHairStrands)
{
if (ViewFamily.EngineShowFlags.LightFunctions)
{
return RenderLightFunctionForMaterial(GraphBuilder, SceneTextures, LightSceneInfo, ScreenShadowMaskTexture, LightSceneInfo->Proxy->GetLightFunctionMaterial(), bLightAttenuationCleared, bProjectingForForwardShading, false, bUseHairStrands);
}
return false;
}
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightFunctionRendering.cpp:349
Scope: file
Source code excerpt:
PassParameters->RenderTargets[0] = FRenderTargetBinding(ScreenShadowMaskTexture, bLightAttenuationCleared ? ERenderTargetLoadAction::ELoad : ERenderTargetLoadAction::ENoAction);
PassParameters->RenderTargets.DepthStencil = FDepthStencilBinding(SceneTextures.Depth.Target, ERenderTargetLoadAction::ELoad, ERenderTargetLoadAction::ELoad, FExclusiveDepthStencil::DepthRead_StencilWrite);
PassParameters->RenderTargets.ShadingRateTexture = GVRSImageManager.GetVariableRateShadingImage(GraphBuilder, View, FVariableRateShadingImageManager::EVRSPassType::LightFunctions);
// If render shadow mask for hair strands, then swap depth to hair only depth
if (bUseHairStrands)
{
PassParameters->RenderTargets.DepthStencil = FDepthStencilBinding(View.HairStrandsViewData.VisibilityData.HairOnlyDepthTexture, ERenderTargetLoadAction::ELoad, ERenderTargetLoadAction::ELoad, FExclusiveDepthStencil::DepthRead_StencilWrite);
}
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightRendering.cpp:1196
Scope (from outer to inner):
file
function void FSceneRenderer::GatherAndSortLights
Source code excerpt:
SortedLightInfo->SortKey.Fields.LightType = LightSceneInfoCompact.LightType;
SortedLightInfo->SortKey.Fields.bShadowed = bDynamicShadows && CheckForProjectedShadows(LightSceneInfo);
SortedLightInfo->SortKey.Fields.bLightFunction = ViewFamily.EngineShowFlags.LightFunctions && CheckForLightFunction(LightSceneInfo);
SortedLightInfo->SortKey.Fields.bUsesLightingChannels = Views[ViewIndex].bUsesLightingChannels && LightSceneInfo->Proxy->GetLightingChannelMask() != GetDefaultLightingChannelMask();
// These are not simple lights.
SortedLightInfo->SortKey.Fields.bIsNotSimpleLight = 1;
// Lights handled by Many Lights
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Lumen/LumenSceneDirectLighting.cpp:133
Scope (from outer to inner):
file
class class FLumenGatheredLight
function FLumenGatheredLight
Source code excerpt:
LightFunctionMaterialProxy = Proxy->GetLightFunctionMaterial();
if (LightFunctionMaterialProxy && (!View.Family->EngineShowFlags.LightFunctions || !LightFunctionMaterialProxy->GetIncompleteMaterialWithFallback(Scene->GetFeatureLevel()).IsLightFunction()))
{
LightFunctionMaterialProxy = nullptr;
}
const bool bBatchableLightFunction = LightFunctionMaterialProxy == nullptr || (LightFunctionAtlas::IsEnabled(View, ELightFunctionAtlasSystem::Lumen) && LightSceneInfo->Proxy->HasValidLightFunctionAtlasSlot());
FSceneRenderer::GetLightNameForDrawEvent(Proxy, Name);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/MobileDeferredShadingPass.cpp:164
Scope (from outer to inner):
file
function void SetParameters
Source code excerpt:
FMaterialShader::SetParameters(BatchedParameters, Proxy, Material, View);
// LightFunctions can use primitive data, set identity so we do not crash on a missing binding
auto& PrimitivePS = GetUniformBufferParameter<FPrimitiveUniformShaderParameters>();
SetUniformBufferParameter(BatchedParameters, PrimitivePS, GIdentityPrimitiveUniformBuffer);
}
};
IMPLEMENT_MATERIAL_SHADER_TYPE(, FMobileDirectionalLightFunctionPS, TEXT("/Engine/Private/MobileDeferredShading.usf"), TEXT("MobileDirectionalLightPS"), SF_Pixel);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/MobileDeferredShadingPass.cpp:247
Scope (from outer to inner):
file
class class FMobileRadialLightFunctionPS : public FMaterialShader
function void SetParameters
Source code excerpt:
FMaterialShader::SetParameters(BatchedParameters, Proxy, Material, View);
// LightFunctions can use primitive data, set identity so we do not crash on a missing binding
auto& PrimitivePS = GetUniformBufferParameter<FPrimitiveUniformShaderParameters>();
SetUniformBufferParameter(BatchedParameters, PrimitivePS, GIdentityPrimitiveUniformBuffer);
}
};
IMPLEMENT_MATERIAL_SHADER_TYPE(,FMobileRadialLightFunctionPS, TEXT("/Engine/Private/MobileDeferredShading.usf"), TEXT("MobileRadialLightPS"), SF_Pixel);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/MobileDeferredShadingPass.cpp:488
Scope (from outer to inner):
file
function static void RenderDirectionalLight
Source code excerpt:
const FMaterialRenderProxy* LightFunctionMaterialProxy = nullptr;
if (View.Family->EngineShowFlags.LightFunctions)
{
LightFunctionMaterialProxy = DirectionalLight.Proxy->GetLightFunctionMaterial();
}
FMobileDirectionalLightFunctionPS::FParameters PassParameters;
PassParameters.MobileDirectionalLight = Scene.UniformBuffers.MobileDirectionalLightUniformBuffers[LightingChannel + 1];
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/MobileDeferredShadingPass.cpp:765
Scope (from outer to inner):
file
function static void RenderLocalLight
Source code excerpt:
const FMaterialRenderProxy* LightFunctionMaterialProxy = nullptr;
if (View.Family->EngineShowFlags.LightFunctions)
{
LightFunctionMaterialProxy = LightSceneInfo.Proxy->GetLightFunctionMaterial();
}
FMobileRadialLightFunctionPS::FParameters PassParameters;
const bool bShouldCastShadow = LightSceneInfo.SetupMobileMovableLocalLightShadowParameters(View, VisibleLightInfos, PassParameters.MobileMovableLocalLightShadow);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/PathTracing.cpp:1363
Scope (from outer to inner):
file
function FRayTracingLightFunctionMap GatherLightFunctionLightsPathTracing
Source code excerpt:
FRayTracingLightFunctionMap GatherLightFunctionLightsPathTracing(FScene* Scene, const FEngineShowFlags EngineShowFlags, ERHIFeatureLevel::Type InFeatureLevel)
{
checkf(EngineShowFlags.LightFunctions, TEXT("This function should not be called if light functions are disabled"));
FRayTracingLightFunctionMap RayTracingLightFunctionMap;
for (const FLightSceneInfoCompact& Light : Scene->Lights)
{
FLightSceneInfo* LightSceneInfo = Light.LightSceneInfo;
auto MaterialProxy = LightSceneInfo->Proxy->GetLightFunctionMaterial();
if (MaterialProxy)
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/PathTracing.cpp:2491
Scope: file
Source code excerpt:
Config.LightShowFlags |= View.Family->EngineShowFlags.PointLights ? 1 << 4 : 0;
Config.LightShowFlags |= View.Family->EngineShowFlags.TexturedLightProfiles ? 1 << 5 : 0;
Config.LightShowFlags |= View.Family->EngineShowFlags.LightFunctions ? 1 << 6 : 0;
Config.LightShowFlags |= CVarPathTracingLightFunctionColor.GetValueOnRenderThread() ? 1 << 7 : 0;
// the following flags all mess with diffuse/spec overrides and therefore change the image
Config.LightShowFlags |= View.Family->EngineShowFlags.Diffuse ? 1 << 8 : 0;
Config.LightShowFlags |= View.Family->EngineShowFlags.Specular ? 1 << 9 : 0;
Config.LightShowFlags |= View.Family->EngineShowFlags.OverrideDiffuseAndSpecular ? 1 << 10 : 0;
Config.LightShowFlags |= View.Family->EngineShowFlags.LightingOnlyOverride ? 1 << 11 : 0;
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/RayTracing/RayTracingLighting.cpp:518
Scope (from outer to inner):
file
function FRayTracingLightFunctionMap GatherLightFunctionLights
Source code excerpt:
FRayTracingLightFunctionMap GatherLightFunctionLights(FScene* Scene, const FEngineShowFlags EngineShowFlags, ERHIFeatureLevel::Type InFeatureLevel)
{
checkf(EngineShowFlags.LightFunctions, TEXT("This function should not be called if light functions are disabled"));
// gives control over lighting functions in raytraced effects, independently of the show flag (for performance testing / debug)
if (CVarRayTracingLightFunction.GetValueOnRenderThread() == 0)
{
return {};
}
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/ReflectionEnvironmentCapture.cpp:1294
Scope (from outer to inner):
file
function void CaptureSceneIntoScratchCubemap
Source code excerpt:
// Conditionally exclude particles and light functions as they are usually dynamic, and can't be captured well
ViewFamily.EngineShowFlags.Particles = 0;
ViewFamily.EngineShowFlags.LightFunctions = abs(GReflectionCaptureEnableLightFunctions) ? 1 : 0;
ViewFamily.EngineShowFlags.SetCompositeEditorPrimitives(false);
// These are highly dynamic and can't be captured effectively
ViewFamily.EngineShowFlags.LightShafts = 0;
// Don't apply sky lighting diffuse when capturing the sky light source, or we would have feedback
ViewFamily.EngineShowFlags.SkyLighting = !bCapturingForSkyLight;
// Skip lighting for emissive only
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/TranslucentLighting.cpp:1044
Scope (from outer to inner):
file
function void FTranslucentLightInjectionCollector::AddLightForInjection
Source code excerpt:
const ERHIFeatureLevel::Type FeatureLevel = View.FeatureLevel;
const bool bApplyLightFunction = (View.Family->EngineShowFlags.LightFunctions &&
LightSceneInfo.Proxy->GetLightFunctionMaterial() &&
LightSceneInfo.Proxy->GetLightFunctionMaterial()->GetIncompleteMaterialWithFallback(FeatureLevel).IsLightFunction());
const FMaterialRenderProxy* MaterialProxy = bApplyLightFunction ?
LightSceneInfo.Proxy->GetLightFunctionMaterial() :
UMaterial::GetDefaultMaterial(MD_LightFunction)->GetRenderProxy();
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/VariableRateShading/VariableRateShadingImageManager.cpp:774
Scope (from outer to inner):
file
class class FDebugVariableRateShadingCS : public FGlobalShader
Source code excerpt:
CVarByPassType[EVRSPassType::SSR] = &CVarVRS_SSR;
CVarByPassType[EVRSPassType::ReflectionEnvironmentAndSky] = &CVarVRSReflectionEnvironmentSky;
CVarByPassType[EVRSPassType::LightFunctions] = &CVarVRSLightFunctions;
CVarByPassType[EVRSPassType::Decals] = &CVarVRSDecals;
}
} StaticData;
uint32 ImageTypeAsInt = StaticData.CVarByPassType[PassType]->GetValueOnRenderThread();
if (ImageTypeAsInt >= 0 && ImageTypeAsInt <= EVRSImageType::Conservative)
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/VolumetricFogLightFunction.cpp:145
Scope: file
Source code excerpt:
bOutUseDirectionalLightShadowing = LightSceneInfo->Proxy->CastsVolumetricShadow();
if (CheckForLightFunction(LightSceneInfo) && ViewFamily.EngineShowFlags.LightFunctions)
{
OutDirectionalLightSceneInfo = LightSceneInfo;
break; // we only deal with the directional light function so we directly stop now
}
}
}
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Public/VariableRateShadingImageManager.h:32
Scope (from outer to inner):
file
class class FVariableRateShadingImageManager : public FRenderResource
Source code excerpt:
SSR,
ReflectionEnvironmentAndSky,
LightFunctions,
Decals,
Num
};
/**
* Image type to request from generator. Only the CAS generator currently distinguishes between Full and Conservative