r.StaticMeshLODDistanceScale
r.StaticMeshLODDistanceScale
#Overview
name: r.StaticMeshLODDistanceScale
This variable is created as a Console Variable (cvar).
- type:
Var
- help:
Scale factor for the distance used in computing discrete LOD for static meshes. (defaults to 1)\n(higher values make LODs transition earlier, e.g., 2 is twice as fast / half the distance)
It is referenced in 12
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of r.StaticMeshLODDistanceScale is to control the distance at which Level of Detail (LOD) transitions occur for static meshes in Unreal Engine 5. It acts as a scale factor for the distance used in computing discrete LODs for static meshes.
This setting variable is primarily used by the rendering system, specifically in the following subsystems and modules:
- Renderer module
- Landscape system
- Instanced Actors plugin
- Ray Tracing system
The value of this variable is set through the console variable system, with a default value of 1.0f. It can be modified at runtime using console commands or through code.
The associated variable CVarStaticMeshLODDistanceScale interacts directly with r.StaticMeshLODDistanceScale, sharing the same value. This variable is used in various parts of the engine, particularly in the Landscape system and the main rendering pipeline.
Developers should be aware of the following when using this variable:
- Higher values will cause LOD transitions to occur earlier (at closer distances), while lower values will delay LOD transitions.
- This variable affects performance and visual quality, as it directly impacts when lower-detail models are used.
- It’s marked with ECVF_Scalability and ECVF_RenderThreadSafe flags, indicating it’s used for scalability settings and is safe to modify on the render thread.
Best practices for using this variable include:
- Use it as part of a comprehensive LOD strategy, considering both performance and visual quality.
- Test thoroughly with different values to find the optimal balance for your specific project.
- Consider exposing this setting to end-users as a graphics quality option.
- Be cautious when modifying this value dynamically, as it can cause sudden changes in visual quality.
Regarding the associated variable CVarStaticMeshLODDistanceScale:
The purpose of CVarStaticMeshLODDistanceScale is the same as r.StaticMeshLODDistanceScale, serving as an internal representation of the console variable.
This variable is used directly in the renderer and landscape systems to apply the LOD distance scaling. It’s particularly important in the Landscape system, where it’s used to calculate LOD transitions for landscape components.
The value of CVarStaticMeshLODDistanceScale is set automatically by the console variable system when r.StaticMeshLODDistanceScale is modified.
Developers should be aware that changes to this variable will affect both static meshes and landscape components. The Landscape system includes logic to “cancel out” the effect of this variable on landscape LODs, ensuring consistent behavior across different object types.
Best practices for CVarStaticMeshLODDistanceScale are similar to those for r.StaticMeshLODDistanceScale, with an additional note to be mindful of its impact on landscape rendering when modifying it.
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/SceneVisibility.cpp:128
Scope: file
Source code excerpt:
RENDERER_API TAutoConsoleVariable<float> CVarStaticMeshLODDistanceScale(
TEXT("r.StaticMeshLODDistanceScale"),
1.0f,
TEXT("Scale factor for the distance used in computing discrete LOD for static meshes. (defaults to 1)\n")
TEXT("(higher values make LODs transition earlier, e.g., 2 is twice as fast / half the distance)"),
ECVF_Scalability | ECVF_RenderThreadSafe);
static TAutoConsoleVariable<float> CVarMinAutomaticViewMipBias(
#Loc: <Workspace>/Engine/Plugins/Runtime/InstancedActors/Source/InstancedActors/Private/InstancedActorsStationaryLODBatchProcessor.cpp:189
Scope (from outer to inner):
file
function void UInstancedActorsStationaryLODBatchProcessor::Execute
Source code excerpt:
const double CurrentTime = LODSubsystem.GetWorld()->TimeSeconds;
static const auto ICVarStaticMeshLODDistanceScale = IConsoleManager::Get().FindConsoleVariable(TEXT("r.StaticMeshLODDistanceScale"));
const float StaticMeshLODDistanceScale = ICVarStaticMeshLODDistanceScale->GetFloat();
auto ExecutionFunction = [Viewers = MakeArrayView((const FViewerInfo*)&Viewers[0], Viewers.Num()), &EntityManager, &Context
, LODChangingEntityQuery = &LODChangingEntityQuery, StaticMeshLODDistanceScale, CurrentTime
, DelayPerBulkLOD = MakeArrayView((const double*)&DelayPerBulkLOD[0], (int)EInstancedActorsBulkLOD::MAX)]
(FInstancedActorsDataSharedFragment& ManagerSharedFragment) -> double
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/UnrealEngine.cpp:796
Scope (from outer to inner):
file
function void ScalabilityCVarsSinkCallback
Source code excerpt:
{
static const auto StaticMeshLODDistanceScale = IConsoleManager::Get().FindConsoleVariable(TEXT("r.StaticMeshLODDistanceScale"));
LocalScalabilityCVars.StaticMeshLODDistanceScale = StaticMeshLODDistanceScale->GetFloat();
}
{
static const auto SkeletalMeshOverlayDistanceScale = ConsoleMan.FindTConsoleVariableDataFloat(TEXT("r.ViewDistanceScale.SkeletalMeshOverlay"));
LocalScalabilityCVars.SkeletalMeshOverlayDistanceScale = FMath::Max(SkeletalMeshOverlayDistanceScale->GetValueOnGameThread(), 0.0f);
#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/Landscape.cpp:1775
Scope (from outer to inner):
file
function static TArray<float> GetLODScreenSizeArray
Source code excerpt:
}
static TConsoleVariableData<float>* CVarSMLODDistanceScale = IConsoleManager::Get().FindTConsoleVariableDataFloat(TEXT("r.StaticMeshLODDistanceScale"));
float CurrentScreenSize = LOD0ScreenSize / CVarSMLODDistanceScale->GetValueOnGameThread();
const float ScreenSizeMult = 1.f / FMath::Max(LOD0Distribution , 1.01f);
TArray<float> Result;
Result.Empty(InNumLODLevels);
#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeRender.cpp:1467
Scope (from outer to inner):
file
function FLandscapeComponentSceneProxy::FLandscapeComponentSceneProxy
Source code excerpt:
{
float ScreenSizeRatioDivider = FMath::Max(LOD0Distribution, 1.01f);
// Cancel out so that landscape is not affected by r.StaticMeshLODDistanceScale
float CurrentScreenSizeRatio = LOD0ScreenSize / CVarStaticMeshLODDistanceScale.GetValueOnAnyThread();
LODScreenRatioSquared.AddUninitialized(MaxLOD + 1);
// LOD 0 handling
LODScreenRatioSquared[0] = FMath::Square(CurrentScreenSizeRatio);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/RayTracing/RayTracing.cpp:411
Scope (from outer to inner):
file
namespace RayTracing
function void GatherRelevantPrimitives
Source code excerpt:
FPrimitiveSceneInfo::UpdateCachedRaytracingData(&Scene, Result.DirtyCachedRayTracingPrimitives);
static const auto ICVarStaticMeshLODDistanceScale = IConsoleManager::Get().FindConsoleVariable(TEXT("r.StaticMeshLODDistanceScale"));
const float LODScaleCVarValue = ICVarStaticMeshLODDistanceScale->GetFloat();
const int32 ForcedLODLevel = GetCVarForceLOD();
Result.StaticPrimitiveLODTask = FFunctionGraphTask::CreateAndDispatchWhenReady(
[&Result, &Scene, &View, LODScaleCVarValue, ForcedLODLevel, StaticPrimitiveIndices = MoveTemp(StaticPrimitives)]()
{
#Associated Variable and Callsites
This variable is associated with another variable named CVarStaticMeshLODDistanceScale
. They share the same value. See the following C++ source code.
#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/Landscape.cpp:2067
Scope (from outer to inner):
file
function static void OnStaticMeshLODDistanceScaleChanged
Source code excerpt:
static void OnStaticMeshLODDistanceScaleChanged()
{
extern RENDERER_API TAutoConsoleVariable<float> CVarStaticMeshLODDistanceScale;
static float LastValue = 1.0f;
if (LastValue != CVarStaticMeshLODDistanceScale.GetValueOnAnyThread())
{
LastValue = CVarStaticMeshLODDistanceScale.GetValueOnAnyThread();
for (auto* LandscapeComponent : TObjectRange<ULandscapeComponent>(RF_ClassDefaultObject | RF_ArchetypeObject, true, EInternalObjectFlags::Garbage))
{
LandscapeComponent->MarkRenderStateDirty();
}
}
#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeRender.cpp:202
Scope: file
Source code excerpt:
#endif
extern RENDERER_API TAutoConsoleVariable<float> CVarStaticMeshLODDistanceScale;
extern int32 GGrassMapUseRuntimeGeneration;
extern int32 GGrassMapAlwaysBuildRuntimeGenerationResources;
#if !UE_BUILD_SHIPPING
uint32 GVarDumpLandscapeLODsCurrentFrame = 0;
#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeRender.cpp:1468
Scope (from outer to inner):
file
function FLandscapeComponentSceneProxy::FLandscapeComponentSceneProxy
Source code excerpt:
float ScreenSizeRatioDivider = FMath::Max(LOD0Distribution, 1.01f);
// Cancel out so that landscape is not affected by r.StaticMeshLODDistanceScale
float CurrentScreenSizeRatio = LOD0ScreenSize / CVarStaticMeshLODDistanceScale.GetValueOnAnyThread();
LODScreenRatioSquared.AddUninitialized(MaxLOD + 1);
// LOD 0 handling
LODScreenRatioSquared[0] = FMath::Square(CurrentScreenSizeRatio);
LODSettings.LOD0ScreenSizeSquared = FMath::Square(CurrentScreenSizeRatio);
#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeRender.cpp:4422
Scope (from outer to inner):
file
function float FLandscapeComponentSceneProxy::ComputeLODForView
Source code excerpt:
const FMatrix& ViewProjectionMatrix = GetLODView(InView).ViewMatrices.GetProjectionMatrix();
float LODScale = ViewLODDistanceFactor * CVarStaticMeshLODDistanceScale.GetValueOnRenderThread();
FLandscapeRenderSystem* LandscapeRenderSystem = LandscapeRenderSystems.FindChecked(LandscapeKey);
// Prefer the RenderSystem's ForcedLODOverride if set over any per-component LOD override
int32 ForcedLODLevel = LandscapeRenderSystem->ForcedLODOverride >= 0 ? LandscapeRenderSystem->ForcedLODOverride : LODSettings.ForcedLOD;
ForcedLODLevel = ViewLODOverride >= 0 ? ViewLODOverride : ForcedLODLevel;
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/SceneVisibility.cpp:127
Scope: file
Source code excerpt:
);
RENDERER_API TAutoConsoleVariable<float> CVarStaticMeshLODDistanceScale(
TEXT("r.StaticMeshLODDistanceScale"),
1.0f,
TEXT("Scale factor for the distance used in computing discrete LOD for static meshes. (defaults to 1)\n")
TEXT("(higher values make LODs transition earlier, e.g., 2 is twice as fast / half the distance)"),
ECVF_Scalability | ECVF_RenderThreadSafe);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/SceneVisibility.cpp:1051
Scope (from outer to inner):
file
function FFilterStaticMeshesForViewData::FFilterStaticMeshesForViewData
Source code excerpt:
ForcedLODLevel = (View.Family->EngineShowFlags.LOD) ? GetCVarForceLOD() : 0;
LODScale = CVarStaticMeshLODDistanceScale.GetValueOnRenderThread() * View.LODDistanceFactor;
MinScreenRadiusForCSMDepthSquared = GMinScreenRadiusForCSMDepth * GMinScreenRadiusForCSMDepth;
MinScreenRadiusForDepthPrepassSquared = GMinScreenRadiusForDepthPrepass * GMinScreenRadiusForDepthPrepass;
bFullEarlyZPass = ShouldForceFullDepthPass(View.GetShaderPlatform());
}