grass.GrassMap.UseRuntimeGeneration
grass.GrassMap.UseRuntimeGeneration
#Overview
name: grass.GrassMap.UseRuntimeGeneration
This variable is created as a Console Variable (cvar).
- type:
Var
- help:
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.
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:
- Ensuring it’s enabled at cook time to reduce cooked data size.
- Considering the performance impact of runtime generation on target platforms.
- 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;