foliage.RandomLODRange

foliage.RandomLODRange

#Overview

name: foliage.RandomLODRange

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

It is referenced in 6 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of foliage.RandomLODRange is to add a random distance to each instance when computing the Level of Detail (LOD) for foliage and instanced static meshes. This variable is primarily used in the rendering system, specifically for managing LOD transitions in instanced and hierarchical instanced static meshes.

This setting variable is mainly utilized by the Engine module, particularly in the handling of instanced and hierarchical instanced static meshes. It’s referenced in files such as HierarchicalInstancedStaticMesh.cpp and InstancedStaticMesh.cpp.

The value of this variable is set as a console variable (CV) with a default value of 0.0f. It can be modified at runtime through the console or configuration files.

The associated variable CVarRandomLODRange interacts directly with foliage.RandomLODRange, as they share the same value. This variable is used to retrieve the current value of the setting in the render thread.

Developers should be aware that:

  1. This variable affects the LOD computation for instanced meshes, which can impact both performance and visual quality.
  2. A non-zero value will introduce some randomness in LOD transitions, which can help reduce popping artifacts but may also cause inconsistencies in LOD appearance across instances.

Best practices when using this variable include:

  1. Use small values (e.g., 0.1 to 1.0) to introduce subtle variation without causing drastic changes in LOD behavior.
  2. Test thoroughly with different values to find the right balance between visual quality and performance for your specific use case.
  3. Consider the interaction with other LOD-related settings, such as LODDistanceScale and MinimumScreenSize.

Regarding the associated variable CVarRandomLODRange:

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/HierarchicalInstancedStaticMesh.cpp:102

Scope: file

Source code excerpt:


TAutoConsoleVariable<float> CVarRandomLODRange(
	TEXT("foliage.RandomLODRange"),
	0.0f,
	TEXT("Random distance added to each instance distance to compute LOD."));

static TAutoConsoleVariable<int32> CVarMinVertsToSplitNode(
	TEXT("foliage.MinVertsToSplitNode"),
	8192,

#Associated Variable and Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/Engine/InstancedStaticMesh.h:36

Scope: file

Source code excerpt:


extern TAutoConsoleVariable<float> CVarFoliageMinimumScreenSize;
extern TAutoConsoleVariable<float> CVarRandomLODRange;
extern TAutoConsoleVariable<int32> CVarMinLOD;

BEGIN_GLOBAL_SHADER_PARAMETER_STRUCT(FInstancedStaticMeshVertexFactoryUniformShaderParameters, ENGINE_API)
	SHADER_PARAMETER_SRV(Buffer<float4>, VertexFetch_InstanceOriginBuffer)
	SHADER_PARAMETER_SRV(Buffer<float4>, VertexFetch_InstanceTransformBuffer)
	SHADER_PARAMETER_SRV(Buffer<float4>, VertexFetch_InstanceLightmapBuffer)

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/HierarchicalInstancedStaticMesh.cpp:101

Scope: file

Source code excerpt:

	);

TAutoConsoleVariable<float> CVarRandomLODRange(
	TEXT("foliage.RandomLODRange"),
	0.0f,
	TEXT("Random distance added to each instance distance to compute LOD."));

static TAutoConsoleVariable<int32> CVarMinVertsToSplitNode(
	TEXT("foliage.MinVertsToSplitNode"),

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/HierarchicalInstancedStaticMesh.cpp:1630

Scope (from outer to inner):

file
function     void FHierarchicalStaticMeshSceneProxy::GetDynamicMeshElements

Source code excerpt:

				float LODScale = UserData_AllInstances.LODDistanceScale;
				int MaxEndCullDistance = CVarFoliageMaxEndCullDistance.GetValueOnRenderThread();
				float LODRandom = CVarRandomLODRange.GetValueOnRenderThread();
				float MaxDrawDistanceScale = GetCachedScalabilityCVars().ViewDistanceScale;
								
				FVector AverageScale(InstanceParams.Tree[0].MinInstanceScale + (InstanceParams.Tree[0].MaxInstanceScale - InstanceParams.Tree[0].MinInstanceScale) / 2.0f);
				FBoxSphereBounds ScaledBounds = RenderData->Bounds.TransformBy(FTransform(FRotator::ZeroRotator, FVector::ZeroVector, AverageScale));
				float SphereRadius = ScaledBounds.SphereRadius + InstanceParams.MaxWPODisplacement;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/HierarchicalInstancedStaticMesh.cpp:1844

Scope (from outer to inner):

file
function     void FHierarchicalStaticMeshSceneProxy::GetDynamicMeshElements

Source code excerpt:

						const float LODScale = UserData_AllInstances.LODDistanceScale;
						int MaxEndCullDistance = CVarFoliageMaxEndCullDistance.GetValueOnRenderThread();
						const float LODRandom = CVarRandomLODRange.GetValueOnRenderThread();
						const float MaxDrawDistanceScale = GetCachedScalabilityCVars().ViewDistanceScale;
						const float SphereRadius = RenderData->Bounds.SphereRadius + GetMaxWorldPositionOffsetExtent();

						checkSlow(NumLODs > 0);

						float FinalCull = MAX_flt;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/InstancedStaticMesh.cpp:1162

Scope (from outer to inner):

file
function     FInstancedStaticMeshVFLooseUniformShaderParametersRef FInstancedStaticMeshSceneProxy::CreateLooseUniformBuffer

Source code excerpt:

			float MinSize = View->ViewMatrices.IsPerspectiveProjection() ? CVarFoliageMinimumScreenSize.GetValueOnRenderThread() : 0.0f;
			float LODScale = InstancingUserData->LODDistanceScale;
			float LODRandom = CVarRandomLODRange.GetValueOnRenderThread();
			float MaxDrawDistanceScale = GetCachedScalabilityCVars().ViewDistanceScale;

			if (InstancedLODIndex)
			{
				InstancingViewZConstant.X = -1.0f;
			}