r.Mobile.Shadow.CSMShaderCullingMethod

r.Mobile.Shadow.CSMShaderCullingMethod

#Overview

name: r.Mobile.Shadow.CSMShaderCullingMethod

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

It is referenced in 7 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of r.Mobile.Shadow.CSMShaderCullingMethod is to determine the method for culling primitives that will receive Cascaded Shadow Map (CSM) shaders in mobile rendering. This variable is part of Unreal Engine’s mobile rendering system, specifically for shadow rendering optimization.

This setting variable is primarily used in the Renderer module of Unreal Engine, particularly in the mobile rendering pipeline. It’s referenced in files such as ShadowSetupMobile.cpp, RenderUtils.cpp, and LightSceneInfo.cpp.

The value of this variable is set through the console variable system. It’s defined as a TAutoConsoleVariable with a default value of 1 (CSMShaderCullingMethodDefault).

The variable interacts closely with its associated variable CVarsCsmShaderCullingMethod, which shares the same value. It’s also used in conjunction with other rendering-related variables and functions, such as those for mobile deferred shading and movable light CSM shader culling.

Developers should be aware that this variable affects performance and visual quality. Different culling methods have different trade-offs between performance and accuracy. The variable offers four main options:

0 - Disabled (all primitives receive CSM) 1 - Light frustum culling (default) 2 - Combined caster bounds culling 3 - Light frustum + caster bounds culling (slowest)

Best practices when using this variable include:

  1. Choose the appropriate culling method based on the specific needs of your game and target hardware.
  2. Test thoroughly with different settings to find the best balance between performance and visual quality.
  3. Consider using different settings for different quality levels or platforms.
  4. Be aware that changing this setting might require adjustments to other shadow-related settings for optimal results.

Regarding the associated variable CVarsCsmShaderCullingMethod:

The purpose of CVarsCsmShaderCullingMethod is the same as r.Mobile.Shadow.CSMShaderCullingMethod, as they share the same value and are used interchangeably in the code.

It’s used in the same Renderer module and files as r.Mobile.Shadow.CSMShaderCullingMethod.

The value is set when the TAutoConsoleVariable is initialized, and it can be changed at runtime through the console.

This variable interacts directly with r.Mobile.Shadow.CSMShaderCullingMethod and is used in various rendering functions related to mobile CSM.

Developers should be aware that changes to this variable will affect mobile shadow rendering performance and quality.

The best practices for using CVarsCsmShaderCullingMethod are the same as those for r.Mobile.Shadow.CSMShaderCullingMethod, as they are essentially the same variable.

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/ShadowSetupMobile.cpp:30

Scope: file

Source code excerpt:

const uint32 CSMShaderCullingMethodDefault = 1;
static TAutoConsoleVariable<int32> CVarsCsmShaderCullingMethod(
	TEXT("r.Mobile.Shadow.CSMShaderCullingMethod"),
	CSMShaderCullingMethodDefault,
	TEXT("Method to determine which primitives will receive CSM shaders:\n")
	TEXT("0 - disabled (all primitives will receive CSM)\n")
	TEXT("1 - Light frustum, all primitives whose bounding box is within CSM receiving distance. (default)\n")
	TEXT("2 - Combined caster bounds, all primitives whose bounds are within CSM receiving distance and the capsule of the combined bounds of all casters.\n")
	TEXT("3 - Light frustum + caster bounds, all primitives whose bounds are within CSM receiving distance and capsule of at least one caster. (slowest)\n")

#Loc: <Workspace>/Engine/Source/Runtime/RenderCore/Private/RenderUtils.cpp:601

Scope (from outer to inner):

file
function     bool MobileBasePassAlwaysUsesCSM

Source code excerpt:

RENDERCORE_API bool MobileBasePassAlwaysUsesCSM(const FStaticShaderPlatform Platform)
{
	static TConsoleVariableData<int32>* CVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.Mobile.Shadow.CSMShaderCullingMethod"));
	if (IsMobileDeferredShadingEnabled(Platform))
	{
		// deferred shading does not need CSM culling
		return true;
	}
	else

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/LightSceneInfo.cpp:336

Scope (from outer to inner):

file
function     bool FLightSceneInfo::ShouldRecordShadowSubjectsForMobile

Source code excerpt:

	const bool bMobileEnableMovableLightCSMShaderCulling = FReadOnlyCVARCache::MobileEnableMovableLightCSMShaderCulling();
		
	static auto* CVarMobileCSMShaderCullingMethod = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.Mobile.Shadow.CSMShaderCullingMethod"));
	const uint32 MobileCSMCullingMode = CVarMobileCSMShaderCullingMethod->GetValueOnAnyThread() & 0xF;

	const FLightSceneProxy* LightSceneProxy = Proxy;

	bool bRenderMovableDirectionalLightCSM = LightSceneProxy->IsMovable() && ShouldRenderViewIndependentWholeSceneShadows();

#Associated Variable and Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/ShadowSetupMobile.cpp:29

Scope: file

Source code excerpt:


const uint32 CSMShaderCullingMethodDefault = 1;
static TAutoConsoleVariable<int32> CVarsCsmShaderCullingMethod(
	TEXT("r.Mobile.Shadow.CSMShaderCullingMethod"),
	CSMShaderCullingMethodDefault,
	TEXT("Method to determine which primitives will receive CSM shaders:\n")
	TEXT("0 - disabled (all primitives will receive CSM)\n")
	TEXT("1 - Light frustum, all primitives whose bounding box is within CSM receiving distance. (default)\n")
	TEXT("2 - Combined caster bounds, all primitives whose bounds are within CSM receiving distance and the capsule of the combined bounds of all casters.\n")

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/ShadowSetupMobile.cpp:47

Scope (from outer to inner):

file
function     static void OnCsmShaderCullingMethodChanged

Source code excerpt:

#if !WITH_EDITOR
	static int32 PrevValue = CSMShaderCullingMethodDefault;
	const int32 CurValue = (CVarsCsmShaderCullingMethod.GetValueOnGameThread() & 0xF);
	
	if (CurValue != PrevValue && (CurValue == 5 || PrevValue == 5))
	{
		PrevValue = CurValue;

		if (CurValue == 5)

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/ShadowSetupMobile.cpp:235

Scope (from outer to inner):

file
function     static void VisualizeMobileDynamicCSMSubjectCapsules

Source code excerpt:

	FVector LightDir = LightSceneInfo->Proxy->GetDirection();
	const FVector::FReal ShadowCastLength = WORLD_MAX;
	const uint32 CullingMethod = CVarsCsmShaderCullingMethod.GetValueOnRenderThread() & 0xF;
	const bool bSphereTest = (CVarsCsmShaderCullingMethod.GetValueOnRenderThread() & 0x10) != 0;

	switch (CullingMethod)
	{
		case 2:
		{
			// Combined bounds

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/ShadowSetupMobile.cpp:406

Scope (from outer to inner):

file
function     void FMobileSceneRenderer::BuildCSMVisibilityState

Source code excerpt:

	SCOPE_CYCLE_COUNTER(STAT_BuildCSMVisibilityState);

	const uint32 CSMCullingMethod = CVarsCsmShaderCullingMethod.GetValueOnRenderThread() & 0xF;
	const bool bSphereTest = (CVarsCsmShaderCullingMethod.GetValueOnRenderThread() & 0x10) != 0;

	bool bMovableLightUsingCSM = LightSceneInfo->Proxy->IsMovable() && LightSceneInfo->ShouldRenderViewIndependentWholeSceneShadows();

	if (LightSceneInfo->Proxy->CastsDynamicShadow() && 
		(bMovableLightUsingCSM || (LightSceneInfo->Proxy->HasStaticShadowing() && LightSceneInfo->Proxy->UseCSMForDynamicObjects()))
		)