grass.GrassMap.UseRuntimeGeneration

grass.GrassMap.UseRuntimeGeneration

#Overview

name: grass.GrassMap.UseRuntimeGeneration

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 grass.GrassMap.UseRuntimeGeneration is to enable runtime grass map generation in Unreal Engine 5. This setting is primarily used for the landscape and grass rendering system.

The Unreal Engine subsystems that rely on this setting variable are primarily the Landscape module and the grass rendering system. This can be seen from the file locations where the variable is referenced, such as LandscapeGrassMapsBuilder.cpp, LandscapeEdit.cpp, and LandscapeGrassWeightExporter.cpp.

The value of this variable is set through a console variable, as seen in the FAutoConsoleVariableRef declaration. This allows the value to be changed at runtime or through configuration files.

The associated variable GGrassMapUseRuntimeGeneration interacts directly with grass.GrassMap.UseRuntimeGeneration. They share the same value and are used interchangeably in different parts of the code.

Developers must be aware that enabling this variable will cause grass density maps to be built on the fly at runtime instead of being serialized. This can save disk space and runtime memory but may have performance implications.

Best practices when using this variable include:

  1. Ensuring it’s enabled at cook time to reduce cooked data size.
  2. Considering the performance impact of runtime generation on target platforms.
  3. Being aware that it affects grass map generation beyond certain distances from the camera.

Regarding the associated variable GGrassMapUseRuntimeGeneration:

The purpose of GGrassMapUseRuntimeGeneration is the same as grass.GrassMap.UseRuntimeGeneration - to control runtime grass map generation.

It is used in various parts of the Landscape module, including grass map building, landscape proxy handling, and grass weight exporting.

The value is set through the console variable grass.GrassMap.UseRuntimeGeneration.

This variable interacts with other settings like GGrassMapAlwaysBuildRuntimeGenerationResources and is used in conjunction with platform-specific checks.

Developers should be aware that this variable affects grass data serialization, eviction of grass data from memory, and the distance at which grass maps are generated.

Best practices include considering this variable’s state when optimizing memory usage and performance, especially on different platforms and in editor vs. runtime contexts.

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeGrassMapsBuilder.cpp:38

Scope: file

Source code excerpt:

int32 GGrassMapUseRuntimeGeneration = 0;
FAutoConsoleVariableRef CVarGrassMapUseRuntimeGeneration(
	TEXT("grass.GrassMap.UseRuntimeGeneration"),
	GGrassMapUseRuntimeGeneration,
	TEXT("Enable runtime grass map generation to save disk space and runtime memory.  When enabled the grass density maps are not serialized and are built on the fly at runtime."));

int32 GGrassMapUseAsyncFetch = 0;
FAutoConsoleVariableRef CVarGrassMapUseAsyncFetch(
	TEXT("grass.GrassMap.UseAsyncFetch"),

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeEdit.cpp:7464

Scope (from outer to inner):

file
function     static void GetAllMobileRelevantLayerNames

Source code excerpt:

	{
		// if ANY mobile platform has runtime generation (because we don't calculate mobile weightmaps per platform, just mobile/non-mobile)
		static FShaderPlatformCachedIniValue<bool> UseRuntimeGenerationCVar(TEXT("grass.GrassMap.UseRuntimeGeneration"));
		FGenericDataDrivenShaderPlatformInfo::Initialize();
		for (int32 SPIndex = 0; SPIndex < SP_NumPlatforms; SPIndex++)
		{
			EShaderPlatform SP = static_cast<EShaderPlatform>(SPIndex);
			if (FGenericDataDrivenShaderPlatformInfo::IsValid(SP) && IsMobilePlatform(SP) && UseRuntimeGenerationCVar.Get(SP))
			{

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeGrassWeightExporter.cpp:53

Scope (from outer to inner):

file
function     static bool ShouldCacheLandscapeGrassShaders

Source code excerpt:


#if WITH_EDITOR
	static FShaderPlatformCachedIniValue<int32> GrassMapsUseRuntimeGenerationPerPlatform(TEXT("grass.GrassMap.UseRuntimeGeneration"));
	const bool bPlatformUsesRuntimeGen = (GrassMapsUseRuntimeGenerationPerPlatform.Get(Parameters.Platform) != 0);
#else
	const bool bPlatformUsesRuntimeGen = (GGrassMapUseRuntimeGeneration != 0);
#endif // WITH_EDITOR

	const bool bShouldBuildForPlatform = 

#Associated Variable and Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Classes/LandscapeProxy.h:65

Scope: file

Source code excerpt:

#if WITH_EDITOR
LANDSCAPE_API extern bool GLandscapeEditModeActive;
extern int32 GGrassMapUseRuntimeGeneration;

DECLARE_MULTICAST_DELEGATE_TwoParams(FOnLandscapeProxyComponentDataChanged, ALandscapeProxy*, const FLandscapeProxyComponentDataChangedParams&);
#endif // WITH_EDITOR


// ----------------------------------------------------------------------------------

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/Landscape.cpp:227

Scope: file

Source code excerpt:


extern int32 GGrassEnable;
extern int32 GGrassMapUseRuntimeGeneration;
extern FAutoConsoleVariableRef CVarGrassMapUseRuntimeGeneration;

struct FCompareULandscapeComponentClosest
{
	FCompareULandscapeComponentClosest(const FIntPoint& InCenter) : Center(InCenter) {}

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/Landscape.cpp:3639

Scope (from outer to inner):

file
function     void ALandscapeProxy::PreSave

Source code excerpt:

			}

			UE_LOG(LogGrass, Verbose, TEXT("PRESAVE: landscape %s has %d / %d valid grass components (UseRuntimeGeneration %d Disable %d)"), *GetName(), ValidGrassCount, LandscapeComponents.Num(), GGrassMapUseRuntimeGeneration, bDisableRuntimeGrassMapGeneration);
		}
	}

	if (ULandscapeInfo* LandscapeInfo = GetLandscapeInfo())
	{
		LandscapeInfo->UpdateNanite(ObjectSaveContext.GetTargetPlatform());

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/Landscape.cpp:4155

Scope (from outer to inner):

file
function     void ALandscapeProxy::PostLoad

Source code excerpt:

			*Comp->GetName(),
			*GetName(),
			GGrassMapUseRuntimeGeneration, bDisableRuntimeGrassMapGeneration, Comp->GrassData->NumElements);

#if !WITH_EDITOR
		// if using runtime grass gen, it should have been cleared out in PreSave
		if (GGrassMapUseRuntimeGeneration && !bDisableRuntimeGrassMapGeneration)
		{
			if (Comp->GrassData->HasData())
			{
				UE_LOG(LogGrass, Warning, TEXT("grass.GrassMap.UseRuntimeGeneration is enabled, but component %s on landscape %s has unnecessary grass data saved.  Ensure grass.GrassMap.UseRuntimeGeneration is enabled at cook time to reduce cooked data size."),
					*Comp->GetName(),
					*GetName());

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeGrassMapsBuilder.cpp:36

Scope: file

Source code excerpt:

extern float GGrassCullDistanceScale;

int32 GGrassMapUseRuntimeGeneration = 0;
FAutoConsoleVariableRef CVarGrassMapUseRuntimeGeneration(
	TEXT("grass.GrassMap.UseRuntimeGeneration"),
	GGrassMapUseRuntimeGeneration,
	TEXT("Enable runtime grass map generation to save disk space and runtime memory.  When enabled the grass density maps are not serialized and are built on the fly at runtime."));

int32 GGrassMapUseAsyncFetch = 0;
FAutoConsoleVariableRef CVarGrassMapUseAsyncFetch(
	TEXT("grass.GrassMap.UseAsyncFetch"),
	GGrassMapUseAsyncFetch,

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeGrassMapsBuilder.cpp:490

Scope (from outer to inner):

file
function     bool FLandscapeGrassMapsBuilder::UpdateTrackedComponents

Source code excerpt:


					// check if the component is too far from the camera and we can reclaim the grass data
					if (GGrassMapUseRuntimeGeneration &&
						State->IsBeyondEvictionRange(Cameras))
					{
						GRASS_DEBUG_LOG(TEXT("Evicting for being beyond eviction range"));
						break; // cancel and evict
					}

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeGrassMapsBuilder.cpp:643

Scope (from outer to inner):

file
function     void FLandscapeGrassMapsBuilder::StartPrioritizedGrassMapGeneration

Source code excerpt:


		// runtime generation doesn't generate past this distance
		if (GGrassMapUseRuntimeGeneration)
		{
			const double MaxSpawnDistance = Component->GrassTypeSummary.MaxInstanceDiscardDistance * MustHaveDistanceScale;
			if (Pending.PriorityKey > MaxSpawnDistance * MaxSpawnDistance)
			{
				// the closest component is not close enough to generate yet
				break;

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeGrassMapsBuilder.cpp:731

Scope (from outer to inner):

file
function     void FLandscapeGrassMapsBuilder::AmortizedUpdateGrassMaps

Source code excerpt:

{
#if !WITH_EDITOR
	if (!GGrassMapUseRuntimeGeneration) // in cooked builds, we don't run any updates at all unless runtime generation is enabled
	{
		return;
	}
#endif // WITH_EDITOR

	if (!CanEverRender())

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeGrassWeightExporter.cpp:30

Scope: file

Source code excerpt:


extern int32 GGrassMapAlwaysBuildRuntimeGenerationResources;
extern int32 GGrassMapUseRuntimeGeneration;

BEGIN_SHADER_PARAMETER_STRUCT(FLandscapeGrassPassParameters, )
	SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
	SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSceneUniformParameters, Scene)
	SHADER_PARAMETER_STRUCT_INCLUDE(FInstanceCullingDrawParams, InstanceCullingDrawParams)
	RENDER_TARGET_BINDING_SLOTS()

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeGrassWeightExporter.cpp:56

Scope (from outer to inner):

file
function     static bool ShouldCacheLandscapeGrassShaders

Source code excerpt:

	const bool bPlatformUsesRuntimeGen = (GrassMapsUseRuntimeGenerationPerPlatform.Get(Parameters.Platform) != 0);
#else
	const bool bPlatformUsesRuntimeGen = (GGrassMapUseRuntimeGeneration != 0);
#endif // WITH_EDITOR

	const bool bShouldBuildForPlatform = 
		bIsEditorPlatform ||
		GGrassMapAlwaysBuildRuntimeGenerationResources ||
		bPlatformUsesRuntimeGen;

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeRender.cpp:204

Scope: file

Source code excerpt:

extern RENDERER_API TAutoConsoleVariable<float> CVarStaticMeshLODDistanceScale;

extern int32 GGrassMapUseRuntimeGeneration;
extern int32 GGrassMapAlwaysBuildRuntimeGenerationResources;

#if !UE_BUILD_SHIPPING
uint32 GVarDumpLandscapeLODsCurrentFrame = 0;

static void OnDumpLandscapeLODs(const TArray< FString >& Args)

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeRender.cpp:294

Scope (from outer to inner):

file
namespace    UE::Landscape
function     bool ShouldBuildGrassMapRenderingResources

Source code excerpt:

			return true;
		#else
			return (GGrassMapUseRuntimeGeneration || GGrassMapAlwaysBuildRuntimeGenerationResources);
		#endif // WITH_EDITOR
	}
} // namespace UE::Landscape

//
// FLandscapeDebugOptions

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeSubsystem.cpp:62

Scope: file

Source code excerpt:

	TEXT("Update landscape proxy's rendering method (nanite enabled) when ticked. Always enabled in editor."));

extern int32 GGrassMapUseRuntimeGeneration;

DECLARE_CYCLE_STAT(TEXT("LandscapeSubsystem Tick"), STAT_LandscapeSubsystemTick, STATGROUP_Landscape);

#define LOCTEXT_NAMESPACE "LandscapeSubsystem"

namespace UE::Landscape

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeSubsystem.cpp:488

Scope (from outer to inner):

file
function     void ULandscapeSubsystem::Tick

Source code excerpt:

#endif // WITH_EDITOR

	bool bAllowStartGrassMapGeneration = bAllProxiesReadyForGrassMapGeneration && !bGrassMapGenerationDisabled && (!bIsGameWorld || GGrassMapUseRuntimeGeneration);

	GrassMapsBuilder->AmortizedUpdateGrassMaps(Cameras ? *Cameras : TArray<FVector>(), bIsGrassCreationPrioritized, bAllowStartGrassMapGeneration);

	int32 InOutNumComponentsCreated = 0;
#if WITH_EDITOR
	int32 NumProxiesUpdated = 0;