ShowFlag.LightShafts

ShowFlag.LightShafts

#Overview

name: ShowFlag.LightShafts

This variable is created as a Console Variable (cvar).

It is referenced in 17 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of ShowFlag.LightShafts is to control the rendering of light shafts in Unreal Engine 5’s rendering system. Light shafts, also known as god rays or crepuscular rays, are a visual effect that simulates the scattering of light in participating media, such as fog or dust.

This setting variable is primarily used in the Renderer module of Unreal Engine, particularly in the deferred shading renderer and light shaft rendering subsystems.

The value of this variable is typically set through the engine’s show flags system, which allows developers and users to toggle various rendering features on or off. It can be accessed and modified through the ViewFamily.EngineShowFlags structure.

Several other variables interact with ShowFlag.LightShafts:

  1. GLightShafts: A global variable that must be true for light shafts to be rendered.
  2. GLightShaftAllowTAA: Controls whether temporal anti-aliasing is applied to light shafts.
  3. GLightShaftBlurPasses: Determines the number of blur passes applied to light shafts.
  4. GLightShaftBlurNumSamples and GLightShaftFirstPassDistance: Control the quality and appearance of the light shaft blur.

Developers should be aware of the following when using this variable:

  1. Light shafts can be computationally expensive, so they should be used judiciously.
  2. The effect is disabled in certain debug view modes (e.g., VisualizeDOF, VisualizeBuffer, VisualizeHDR, VisualizeMotionBlur).
  3. Light shafts require the Lighting show flag to be enabled as well.

Best practices for using this variable include:

  1. Only enable light shafts for key light sources to maintain performance.
  2. Consider using the temporal anti-aliasing option (GLightShaftAllowTAA) to improve quality.
  3. Adjust blur settings (GLightShaftBlurPasses, GLightShaftBlurNumSamples, GLightShaftFirstPassDistance) to balance quality and performance.
  4. Be mindful of how light shafts interact with other post-processing effects.

The associated variable LightShafts is used interchangeably with ShowFlag.LightShafts in the engine code. It serves the same purpose and is typically accessed through the EngineShowFlags structure. The same considerations and best practices apply to this variable as well.

#References in C++ code

#Callsites

This variable is referenced in the following C++ source code:

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:293

Scope: file

Source code excerpt:

SHOWFLAG_FIXED_IN_SHIPPING(0, CollisionPawn, SFG_Hidden, NSLOCTEXT("UnrealEd", "CollisionPawn", "Pawn"))
/** Render LightShafts, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(LightShafts, SFG_LightingFeatures, NSLOCTEXT("UnrealEd", "LightShaftsSF", "Light Shafts"))
/** Render the PostProcess Material */
SHOWFLAG_FIXED_IN_SHIPPING(1, PostProcessMaterial, SFG_PostProcess, NSLOCTEXT("UnrealEd", "PostProcessMaterialSF", "Post Process Material"))
/** Render Sky and Atmospheric lighting, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(Atmosphere, SFG_Normal, NSLOCTEXT("UnrealEd", "AtmosphereSF", "Atmosphere"))
/** Render Cloud */
SHOWFLAG_FIXED_IN_SHIPPING(1, Cloud, SFG_Normal, NSLOCTEXT("UnrealEd", "CloudSF", "Cloud"))

#Associated Variable and Callsites

This variable is associated with another variable named LightShafts. They share the same value. See the following C++ source code.

#Loc: <Workspace>/Engine/Plugins/Compositing/Composure/Source/Composure/Private/ComposureUtils.cpp:12

Scope (from outer to inner):

file
function     void FComposureUtils::SetEngineShowFlagsForPostprocessingOnly

Source code excerpt:

	EngineShowFlags.ScreenSpaceReflections = false;
	EngineShowFlags.ScreenSpaceAO = false;
	EngineShowFlags.LightShafts = false;
	EngineShowFlags.Lighting = false;
	EngineShowFlags.DeferredLighting = false;
	EngineShowFlags.Decals = false;
	EngineShowFlags.Translucency = false;
	EngineShowFlags.AntiAliasing = false;
	EngineShowFlags.MotionBlur = false;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:292

Scope: file

Source code excerpt:

/** Collision blocking pawn against simple collision **/
SHOWFLAG_FIXED_IN_SHIPPING(0, CollisionPawn, SFG_Hidden, NSLOCTEXT("UnrealEd", "CollisionPawn", "Pawn"))
/** Render LightShafts, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(LightShafts, SFG_LightingFeatures, NSLOCTEXT("UnrealEd", "LightShaftsSF", "Light Shafts"))
/** Render the PostProcess Material */
SHOWFLAG_FIXED_IN_SHIPPING(1, PostProcessMaterial, SFG_PostProcess, NSLOCTEXT("UnrealEd", "PostProcessMaterialSF", "Post Process Material"))
/** Render Sky and Atmospheric lighting, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(Atmosphere, SFG_Normal, NSLOCTEXT("UnrealEd", "AtmosphereSF", "Atmosphere"))
/** Render Cloud */
SHOWFLAG_FIXED_IN_SHIPPING(1, Cloud, SFG_Normal, NSLOCTEXT("UnrealEd", "CloudSF", "Cloud"))

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/DeferredShadingRenderer.cpp:2902

Scope (from outer to inner):

file
function     void FDeferredShadingSceneRenderer::Render
lambda-function

Source code excerpt:

		{
			// Draw Lightshafts
			if (!bHasRayTracedOverlay && ViewFamily.EngineShowFlags.LightShafts)
			{
				SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_RenderLightShaftOcclusion);
				LightShaftOcclusionTexture = RenderLightShaftOcclusion(GraphBuilder, SceneTextures);
			}

			// Draw the sky atmosphere

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/DeferredShadingRenderer.cpp:3171

Scope (from outer to inner):

file
function     void FDeferredShadingSceneRenderer::Render

Source code excerpt:

		}

		if (!bHasRayTracedOverlay && ViewFamily.EngineShowFlags.LightShafts)
		{
			SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_RenderLightShaftBloom);
			GraphBuilder.SetCommandListStat(GET_STATID(STAT_CLM_LightShaftBloom));
			RenderLightShaftBloom(GraphBuilder, SceneTextures, /* inout */ TranslucencyResourceMap);
		}

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightShaftRendering.cpp:108

Scope (from outer to inner):

file
function     bool ShouldRenderLightShafts

Source code excerpt:

{
	return GLightShafts
		&& ViewFamily.EngineShowFlags.LightShafts
		&& ViewFamily.EngineShowFlags.Lighting
		&& !ViewFamily.UseDebugViewPS()
		&& !ViewFamily.EngineShowFlags.VisualizeDOF
		&& !ViewFamily.EngineShowFlags.VisualizeBuffer
		&& !ViewFamily.EngineShowFlags.VisualizeHDR
		&& !ViewFamily.EngineShowFlags.VisualizeMotionBlur;

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightShaftRendering.cpp:313

Scope (from outer to inner):

file
function     FScreenPassTexture AddDownsamplePass

Source code excerpt:


	auto* PassParameters = GraphBuilder.AllocParameters<FDownsampleLightShaftsPixelShader::FParameters>();
	PassParameters->LightShafts = LightShaftParameters;
	PassParameters->SceneTextures = SceneTextures;
	PassParameters->RenderTargets[0] = Output.GetRenderTargetBinding();

	FDownsampleLightShaftsPixelShader::FPermutationDomain PixelPermutationVector;
	PixelPermutationVector.Set<FDownsampleLightShaftsPixelShader::FOcclusionTerm>(LightShaftTechnique == ELightShaftTechnique::Occlusion);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightShaftRendering.cpp:334

Scope (from outer to inner):

file
function     FScreenPassTexture AddDownsamplePass
lambda-function

Source code excerpt:

	{
		FDownsampleLightShaftsVertexShader::FParameters VertexParameters;
		VertexParameters.View = PassParameters->LightShafts.View;
		SetShaderParameters(RHICmdList, VertexShader, VertexShader.GetVertexShader(), VertexParameters);
		SetShaderParameters(RHICmdList, PixelShader, PixelShader.GetPixelShader(), *PassParameters);
	});

	return FScreenPassTexture(Output);
}

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightShaftRendering.cpp:347

Scope (from outer to inner):

file
function     FScreenPassTexture AddTemporalAAPass

Source code excerpt:

	const TRDGUniformBufferRef<FSceneTextureUniformParameters> SceneTextures,
	FTemporalAAHistory* HistoryState,
	FScreenPassTexture LightShafts)
{
	if (IsTemporalAccumulationBasedMethod(View.AntiAliasingMethod) && HistoryState && GLightShaftAllowTAA)
	{
		const FSceneTextureParameters SceneTextureParameters = GetSceneTextureParameters(GraphBuilder, SceneTextures);

		FTAAPassParameters TAAParameters(View);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightShaftRendering.cpp:358

Scope (from outer to inner):

file
function     FScreenPassTexture AddTemporalAAPass

Source code excerpt:

		TAAParameters.SceneVelocityTexture = SceneTextureParameters.GBufferVelocityTexture;
		TAAParameters.SetupViewRect(View, GetLightShaftDownsampleFactor());
		TAAParameters.SceneColorInput = LightShafts.Texture;

		LightShafts.Texture = AddTemporalAAPass(GraphBuilder, View, TAAParameters, *HistoryState, HistoryState).SceneColor;
	}
	return LightShafts;
}

FScreenPassTexture AddRadialBlurPass(
	FRDGBuilder& GraphBuilder,
	const FViewInfo& View,
	const FLightShaftPixelShaderParameters& LightShaftParameters,
	FScreenPassTexture LightShafts)
{
	const uint32 NumPasses = FMath::Max(GLightShaftBlurPasses, 0);

	for (uint32 PassIndex = 0; PassIndex < NumPasses; PassIndex++)
	{
		const FScreenPassRenderTarget Output = CreateLightShaftTexture(GraphBuilder, FScreenPassTextureViewport(LightShafts), TEXT("LightShaftBlur"));

		auto* PassParameters = GraphBuilder.AllocParameters<FBlurLightShaftsPixelShader::FParameters>();
		PassParameters->LightShafts = LightShaftParameters;
		PassParameters->SourceTexture = LightShafts.Texture;
		PassParameters->RadialBlurParameters = FVector4f(GLightShaftBlurNumSamples, GLightShaftFirstPassDistance, PassIndex);
		PassParameters->RenderTargets[0] = Output.GetRenderTargetBinding();

		TShaderMapRef<FBlurLightShaftsPixelShader> PixelShader(View.ShaderMap);
		AddDrawScreenPass(GraphBuilder, RDG_EVENT_NAME("RadialBlur(%d)", PassIndex), View, FScreenPassTextureViewport(Output), FScreenPassTextureViewport(LightShafts), PixelShader, PassParameters);
		LightShafts = Output;
	}

	return LightShafts;
}

FScreenPassTexture AddLightShaftSetupPass(
	FRDGBuilder& GraphBuilder,
	const FViewInfo& View,
	const FLightShaftPixelShaderParameters& LightShaftParameters,

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightShaftRendering.cpp:402

Scope (from outer to inner):

file
function     FScreenPassTexture AddLightShaftSetupPass

Source code excerpt:

	ELightShaftTechnique LightShaftTechnique)
{
	FScreenPassTexture LightShafts;
	LightShafts = AddDownsamplePass(GraphBuilder, View, LightShaftParameters, SceneTextures, SceneViewport, LightShaftViewport, LightComponentType, LightShaftTechnique);
	LightShafts = AddTemporalAAPass(GraphBuilder, View, SceneTextures, LightShaftTemporalHistory, LightShafts);
	LightShafts = AddRadialBlurPass(GraphBuilder, View, LightShaftParameters, LightShafts);
	return LightShafts;
}

void AddOcclusionTermPass(
	FRDGBuilder& GraphBuilder,
	const FViewInfo& View,
	const FLightShaftPixelShaderParameters& LightShaftParameters,
	FScreenPassTexture LightShafts,
	FScreenPassRenderTarget Output)
{
	auto* PassParameters = GraphBuilder.AllocParameters<FFinishOcclusionPixelShader::FParameters>();
	PassParameters->LightShafts = LightShaftParameters;
	PassParameters->SourceTexture = LightShafts.Texture;
	PassParameters->RenderTargets[0] = Output.GetRenderTargetBinding();

	TShaderMapRef<FFinishOcclusionPixelShader> PixelShader(View.ShaderMap);
	AddDrawScreenPass(GraphBuilder, RDG_EVENT_NAME("FinishOcclusionTerm"), View, FScreenPassTextureViewport(Output), FScreenPassTextureViewport(LightShafts), PixelShader, PassParameters);
}

FRDGTextureRef FDeferredShadingSceneRenderer::RenderLightShaftOcclusion(
	FRDGBuilder& GraphBuilder,
	const FMinimalSceneTextures& SceneTextures)
{

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightShaftRendering.cpp:484

Scope (from outer to inner):

file
function     FRDGTextureRef FDeferredShadingSceneRenderer::RenderLightShaftOcclusion

Source code excerpt:

						}

						FScreenPassTexture LightShafts = AddLightShaftSetupPass(
							GraphBuilder,
							View,
							LightShaftParameters,
							SceneTextures.UniformBuffer,
							SceneViewport,
							OutputViewport,

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightShaftRendering.cpp:495

Scope (from outer to inner):

file
function     FRDGTextureRef FDeferredShadingSceneRenderer::RenderLightShaftOcclusion

Source code excerpt:

							ELightShaftTechnique::Occlusion);

						AddOcclusionTermPass(GraphBuilder, View, LightShaftParameters, LightShafts, Output);

						// Subsequent views are composited into the same output target.
						Output.LoadAction = ERenderTargetLoadAction::ELoad;
					}
				}
			}

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightShaftRendering.cpp:512

Scope (from outer to inner):

file
function     void AddLightShaftBloomPass

Source code excerpt:

	const FViewInfo& View,
	const FLightShaftPixelShaderParameters& LightShaftParameters,
	FScreenPassTexture LightShafts,
	FScreenPassTextureViewport OutputViewport,
	FRenderTargetBinding OutputBinding)
{
	auto* PassParameters = GraphBuilder.AllocParameters<FApplyLightShaftsPixelShader::FParameters>();
	PassParameters->LightShafts = LightShaftParameters;
	PassParameters->SourceTexture = LightShafts.Texture;
	PassParameters->RenderTargets[0] = OutputBinding;
	PassParameters->RenderTargets.ResolveRect = FResolveRect(OutputViewport.Rect);

	const FScreenPassTextureViewport InputViewport(LightShafts);

	TShaderMapRef<FScreenPassVS> VertexShader(View.ShaderMap);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightShaftRendering.cpp:623

Scope (from outer to inner):

file
function     void FDeferredShadingSceneRenderer::RenderLightShaftBloom

Source code excerpt:

							}

							FScreenPassTexture LightShafts = AddLightShaftSetupPass(
								GraphBuilder,
								View,
								LightShaftParameters,
								SceneTextures.UniformBuffer,
								SceneViewport,
								LightShaftViewport,

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightShaftRendering.cpp:634

Scope (from outer to inner):

file
function     void FDeferredShadingSceneRenderer::RenderLightShaftBloom

Source code excerpt:

								ELightShaftTechnique::Bloom);

							AddLightShaftBloomPass(GraphBuilder, View, LightShaftParameters, LightShafts, OutputViewport, OutputBinding);
							OutputLoadAction = ERenderTargetLoadAction::ELoad;

							FTranslucencyPassResources& TranslucencyPassResources = OutTranslucencyResourceMap.Get(ViewIndex, ETranslucencyPass::TPT_TranslucencyAfterDOF);
							if (bUpdateViewsSeparateTranslucency)
							{
								TranslucencyPassResources.ViewRect = OutputViewport.Rect;

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/ReflectionEnvironmentCapture.cpp:1297

Scope (from outer to inner):

file
function     void CaptureSceneIntoScratchCubemap

Source code excerpt:

		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
		ViewFamily.EngineShowFlags.Lighting = !bCaptureEmissiveOnly;
		// Never do screen percentage in reflection environment capture.
		ViewFamily.EngineShowFlags.ScreenPercentage = false;