r.SkeletalMeshLODBias

r.SkeletalMeshLODBias

#Overview

name: r.SkeletalMeshLODBias

The value of this variable can be defined or overridden in .ini config files. 5 .ini config files referencing this setting variable.

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

It is referenced in 10 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of r.SkeletalMeshLODBias is to control the Level of Detail (LOD) bias for skeletal meshes in Unreal Engine 5. It affects the rendering system, specifically the LOD selection for skeletal meshes.

This setting variable is primarily used in the Engine’s rendering and skeletal mesh components. It’s referenced in the SkinnedMeshComponent.cpp file, which is part of the core Engine module. It’s also used in the MovieRenderPipeline plugin, specifically in the MovieRenderPipelineCore module.

The value of this variable is set through the console variable system. It’s defined as an FAutoConsoleVariableRef, which means it can be changed at runtime through console commands or configuration files.

The r.SkeletalMeshLODBias variable interacts closely with GSkeletalMeshLODBias. In fact, GSkeletalMeshLODBias is the actual integer variable that stores the value, while r.SkeletalMeshLODBias is the console variable name used to access and modify it.

Developers should be aware that this variable affects the visual quality and performance of skeletal meshes. A positive bias will force higher quality LODs to be used, potentially improving visual quality at the cost of performance. A negative bias will use lower quality LODs, potentially improving performance at the cost of visual quality.

Best practices when using this variable include:

  1. Use it for fine-tuning performance and visual quality in different scenarios.
  2. Be cautious when setting extreme values, as they can significantly impact performance or visual quality.
  3. Consider different values for different platforms or quality settings.
  4. Remember that it doesn’t affect animation editor viewports, so testing should be done in-game.

Regarding the associated variable GSkeletalMeshLODBias:

The purpose of GSkeletalMeshLODBias is to store the actual integer value of the LOD bias for skeletal meshes. It’s used internally by the Engine to apply the bias when calculating which LOD level to use for skeletal meshes.

This variable is used in the Engine module, specifically in the SkinnedMeshComponent class. It’s accessed in methods like GetLODBias(), GetDesiredSyncLOD(), and UpdateLODStatus_Internal().

The value of GSkeletalMeshLODBias is set through the r.SkeletalMeshLODBias console variable. They share the same value and are essentially two ways of accessing the same setting.

GSkeletalMeshLODBias interacts directly with the LOD selection logic in the SkinnedMeshComponent. It’s added to the calculated LOD level to determine the final LOD to use.

Developers should be aware that modifying GSkeletalMeshLODBias directly in code is not recommended. Instead, they should use the r.SkeletalMeshLODBias console variable to ensure consistency across the engine.

Best practices for GSkeletalMeshLODBias are essentially the same as for r.SkeletalMeshLODBias, as they represent the same setting.

#Setting Variables

#References In INI files

Location: <Workspace>/Engine/Config/BaseScalability.ini:106, section: [ViewDistanceQuality@0]

Location: <Workspace>/Engine/Config/BaseScalability.ini:110, section: [ViewDistanceQuality@1]

Location: <Workspace>/Engine/Config/BaseScalability.ini:114, section: [ViewDistanceQuality@2]

Location: <Workspace>/Engine/Config/BaseScalability.ini:118, section: [ViewDistanceQuality@3]

Location: <Workspace>/Engine/Config/BaseScalability.ini:122, section: [ViewDistanceQuality@Cine]

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/SkinnedMeshComponent.cpp:47

Scope: file

Source code excerpt:

int32 GSkeletalMeshLODBias = 0;
FAutoConsoleVariableRef CVarSkeletalMeshLODBias(
	TEXT("r.SkeletalMeshLODBias"),
	GSkeletalMeshLODBias,
	TEXT("LOD bias for skeletal meshes (does not affect animation editor viewports)."),
	ECVF_Scalability
	);

static TAutoConsoleVariable<int32> CVarEnableAnimRateOptimization(

#Loc: <Workspace>/Engine/Plugins/MovieScene/MovieRenderPipeline/Source/MovieRenderPipelineCore/Private/Graph/Nodes/MovieGraphGlobalGameOverrides.cpp:51

Scope (from outer to inner):

file
function     void UMovieGraphGlobalGameOverridesNode::BuildNewProcessCommandLineArgsImpl

Source code excerpt:

	{
		InOutDeviceProfileCvars.Add(TEXT("r.ForceLOD=0"));
		InOutDeviceProfileCvars.Add(TEXT("r.SkeletalMeshLODBias=-10"));
		InOutDeviceProfileCvars.Add(TEXT("r.ParticleLODBias=-10"));
		InOutDeviceProfileCvars.Add(TEXT("foliage.DitheredLOD=0"));
		InOutDeviceProfileCvars.Add(TEXT("foliage.ForceLOD=0"));
	}

	if (bDisableHLODs)

#Loc: <Workspace>/Engine/Plugins/MovieScene/MovieRenderPipeline/Source/MovieRenderPipelineCore/Private/Graph/Nodes/MovieGraphGlobalGameOverrides.cpp:117

Scope (from outer to inner):

file
function     void UMovieGraphGlobalGameOverridesNode::ApplySettings

Source code excerpt:

	{
		MOVIEPIPELINE_STORE_AND_OVERRIDE_CVAR_INT(PreviousForceLOD, TEXT("r.ForceLOD"), 0, bOverrideValues);
		MOVIEPIPELINE_STORE_AND_OVERRIDE_CVAR_INT(PreviousSkeletalMeshBias, TEXT("r.SkeletalMeshLODBias"), -10, bOverrideValues);
		MOVIEPIPELINE_STORE_AND_OVERRIDE_CVAR_INT(PreviousParticleLODBias, TEXT("r.ParticleLODBias"), -10, bOverrideValues);
		MOVIEPIPELINE_STORE_AND_OVERRIDE_CVAR_INT(PreviousFoliageDitheredLOD, TEXT("foliage.DitheredLOD"), 0, bOverrideValues);
		MOVIEPIPELINE_STORE_AND_OVERRIDE_CVAR_INT(PreviousFoliageForceLOD, TEXT("foliage.ForceLOD"), 0, bOverrideValues);
	}

	if (bDisableHLODs)

#Loc: <Workspace>/Engine/Plugins/MovieScene/MovieRenderPipeline/Source/MovieRenderPipelineCore/Private/MoviePipelineGameOverrideSetting.cpp:65

Scope (from outer to inner):

file
function     void UMoviePipelineGameOverrideSetting::ApplyCVarSettings

Source code excerpt:

	{
		MOVIEPIPELINE_STORE_AND_OVERRIDE_CVAR_INT(PreviousForceLOD, TEXT("r.ForceLOD"), 0, bOverrideValues);
		MOVIEPIPELINE_STORE_AND_OVERRIDE_CVAR_INT(PreviousSkeletalMeshBias, TEXT("r.SkeletalMeshLODBias"), -10, bOverrideValues);
		MOVIEPIPELINE_STORE_AND_OVERRIDE_CVAR_INT(PreviousParticleLODBias, TEXT("r.ParticleLODBias"), -10, bOverrideValues);
		MOVIEPIPELINE_STORE_AND_OVERRIDE_CVAR_INT(PreviousFoliageDitheredLOD, TEXT("foliage.DitheredLOD"), 0, bOverrideValues);
		MOVIEPIPELINE_STORE_AND_OVERRIDE_CVAR_INT(PreviousFoliageForceLOD, TEXT("foliage.ForceLOD"), 0, bOverrideValues);
	}

	if (bDisableHLODs)

#Loc: <Workspace>/Engine/Plugins/MovieScene/MovieRenderPipeline/Source/MovieRenderPipelineCore/Private/MoviePipelineGameOverrideSetting.cpp:191

Scope (from outer to inner):

file
function     void UMoviePipelineGameOverrideSetting::BuildNewProcessCommandLineArgsImpl

Source code excerpt:

	{
		InOutDeviceProfileCvars.Add(TEXT("r.ForceLOD=0"));
		InOutDeviceProfileCvars.Add(TEXT("r.SkeletalMeshLODBias=-10"));
		InOutDeviceProfileCvars.Add(TEXT("r.ParticleLODBias=-10"));
		InOutDeviceProfileCvars.Add(TEXT("foliage.DitheredLOD=0"));
		InOutDeviceProfileCvars.Add(TEXT("foliage.ForceLOD=0"));
	}

	if (bDisableHLODs)

#Loc: <Workspace>/Engine/Plugins/MovieScene/MovieRenderPipeline/Source/MovieRenderPipelineCore/Public/Graph/Nodes/MovieGraphGlobalGameOverrides.h:118

Scope (from outer to inner):

file
function     class MOVIERENDERPIPELINECORE_API UMovieGraphGlobalGameOverridesNode : public UMovieGraphSettingNode { GENERATED_BODY

Source code excerpt:

	 * Configures the following cvars:
	 * - r.ForceLOD
	 * - r.SkeletalMeshLODBias
	 * - r.ParticleLODBias
	 * - foliage.DitheredLOD
	 * - foliage.ForceLOD
	 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Rendering", meta = (EditCondition = "bOverride_bDisableLODs"))
	bool bDisableLODs;

	/**
	 * Determines if hierarchical LODs should be disabled and their real meshes used instead, regardless of distance.
	 * Note that this does not affect World Partition HLODs.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Rendering", meta = (EditCondition = "bOverride_bDisableHLODs"))
	bool bDisableHLODs;

	/**
	 * Flushing level streaming ensures that any pending changes to sub-levels or world partition are fully processed before we render

#Associated Variable and Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/SkinnedMeshComponent.cpp:45

Scope: file

Source code excerpt:

DEFINE_LOG_CATEGORY_STATIC(LogSkinnedMeshComp, Log, All);

int32 GSkeletalMeshLODBias = 0;
FAutoConsoleVariableRef CVarSkeletalMeshLODBias(
	TEXT("r.SkeletalMeshLODBias"),
	GSkeletalMeshLODBias,
	TEXT("LOD bias for skeletal meshes (does not affect animation editor viewports)."),
	ECVF_Scalability
	);

static TAutoConsoleVariable<int32> CVarEnableAnimRateOptimization(
	TEXT("a.URO.Enable"),

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/SkinnedMeshComponent.cpp:3869

Scope (from outer to inner):

file
function     int32 USkinnedMeshComponent::GetLODBias

Source code excerpt:

int32 USkinnedMeshComponent::GetLODBias() const
{
	return GSkeletalMeshLODBias;
}
#endif

void USkinnedMeshComponent::SetCastCapsuleDirectShadow(bool bNewValue)
{
	if (bNewValue != bCastCapsuleDirectShadow)

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/SkinnedMeshComponent.cpp:3908

Scope (from outer to inner):

file
function     int32 USkinnedMeshComponent::GetDesiredSyncLOD

Source code excerpt:

		const int32 LODBias = GetLODBias();
#else
		const int32 LODBias = GSkeletalMeshLODBias;
#endif
		return MeshObject->MinDesiredLODLevel + LODBias;
	}

	return INDEX_NONE;
}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/SkinnedMeshComponent.cpp:3997

Scope (from outer to inner):

file
function     bool USkinnedMeshComponent::UpdateLODStatus_Internal

Source code excerpt:

		const int32 LODBias = GetLODBias();
#else
		const int32 LODBias = GSkeletalMeshLODBias;
#endif

		const int32 MinLodIndex = ComputeMinLOD();
		const int32 MaxLODIndex = FMath::Max(GetNumLODs() - 1, MinLodIndex);

		if (MeshObject)