r.Nanite.MaxPixelsPerEdge
r.Nanite.MaxPixelsPerEdge
#Overview
name: r.Nanite.MaxPixelsPerEdge
This variable is created as a Console Variable (cvar).
- type:
Var
- help:
The triangle edge length that the Nanite runtime targets, measured in pixels.
It is referenced in 11
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of r.Nanite.MaxPixelsPerEdge is to control the triangle edge length that the Nanite runtime targets, measured in pixels. This setting variable is primarily used in the rendering system, specifically for the Nanite geometry virtualization system in Unreal Engine 5.
The Nanite subsystem within the Renderer module relies on this setting variable. It is used in various parts of the Nanite rendering pipeline, including culling, rasterization, and virtual shadow map generation.
The value of this variable is set through a console variable (CVarNaniteMaxPixelsPerEdge) with a default value of 1.0f. It can be modified at runtime through console commands or programmatically.
This variable interacts with several other variables and systems:
- It’s used in conjunction with r.Nanite.DicingRate to calculate the inverse dicing rate for tessellation.
- It’s used in dynamic render scaling calculations for both primary and shadow rasters.
- It’s used in the creation of packed views for Nanite rendering.
- It’s used in virtual shadow map generation.
Developers should be aware that:
- This variable directly affects the level of detail and performance of Nanite-rendered geometry.
- Changing this value will impact both visual quality and rendering performance.
- It’s used in conjunction with other Nanite-related variables, so changing it in isolation may not have the desired effect.
Best practices when using this variable include:
- Use it in conjunction with profiling tools to find the right balance between visual quality and performance.
- Consider the target hardware when setting this value, as higher values may impact performance on less powerful systems.
- Test thoroughly across different types of geometry and scenes to ensure consistent results.
The associated variable CVarNaniteMaxPixelsPerEdge is the actual console variable that stores and provides access to the r.Nanite.MaxPixelsPerEdge value. It’s used throughout the code to retrieve the current value of the setting. The same considerations and best practices apply to this variable as they do to r.Nanite.MaxPixelsPerEdge.
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/NaniteCullRaster.cpp:139
Scope: file
Source code excerpt:
TAutoConsoleVariable<float> CVarNaniteMaxPixelsPerEdge(
TEXT("r.Nanite.MaxPixelsPerEdge"),
1.0f,
TEXT("The triangle edge length that the Nanite runtime targets, measured in pixels."),
ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<int32> CVarNaniteImposterMaxPixels(
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/NaniteCullRaster.cpp:250
Scope: file
Source code excerpt:
);
// i.e. if r.Nanite.MaxPixelsPerEdge is 1.0 and r.Nanite.PrimaryRaster.PixelsPerEdgeScaling is 20%, when heavily over budget r.Nanite.MaxPixelsPerEdge will be scaled to to 5.0
static TAutoConsoleVariable<float> CVarNanitePrimaryPixelsPerEdgeScalingPercentage(
TEXT("r.Nanite.PrimaryRaster.PixelsPerEdgeScaling"),
30.0f, // 100% - no scaling - set to < 100% to scale pixel error when over budget
TEXT("Lower limit percentage to scale the Nanite primary raster MaxPixelsPerEdge value when over budget."),
ECVF_RenderThreadSafe | ECVF_Default);
// i.e. if r.Nanite.MaxPixelsPerEdge is 1.0 and r.Nanite.ShadowRaster.PixelsPerEdgeScaling is 20%, when heavily over budget r.Nanite.MaxPixelsPerEdge will be scaled to to 5.0
static TAutoConsoleVariable<float> CVarNaniteShadowPixelsPerEdgeScalingPercentage(
TEXT("r.Nanite.ShadowRaster.PixelsPerEdgeScaling"),
100.0f, // 100% - no scaling - set to < 100% to scale pixel error when over budget
TEXT("Lower limit percentage to scale the Nanite shadow raster MaxPixelsPerEdge value when over budget."),
ECVF_RenderThreadSafe | ECVF_Default);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/NaniteCullRaster.cpp:288
Scope (from outer to inner):
file
function static DynamicRenderScaling::FHeuristicSettings GetDynamicNaniteScalingPrimarySettings
Source code excerpt:
DynamicRenderScaling::FHeuristicSettings BucketSetting;
BucketSetting.Model = DynamicRenderScaling::EHeuristicModel::Linear;
BucketSetting.bModelScalesWithPrimaryScreenPercentage = false; // r.Nanite.MaxPixelsPerEdge is not scaled by dynamic resolution of the primary view
BucketSetting.MinResolutionFraction = DynamicRenderScaling::PercentageToFraction(PixelsPerEdgeScalingPercentage);
BucketSetting.MaxResolutionFraction = DynamicRenderScaling::PercentageToFraction(100.0f);
BucketSetting.BudgetMs = CVarNanitePrimaryTimeBudgetMs.GetValueOnAnyThread();
BucketSetting.ChangeThreshold = DynamicRenderScaling::PercentageToFraction(1.0f);
BucketSetting.TargetedHeadRoom = DynamicRenderScaling::PercentageToFraction(5.0f); // 5% headroom
BucketSetting.UpperBoundQuantization = DynamicRenderScaling::FHeuristicSettings::kDefaultUpperBoundQuantization;
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/NaniteCullRaster.cpp:304
Scope (from outer to inner):
file
function static DynamicRenderScaling::FHeuristicSettings GetDynamicNaniteScalingShadowSettings
Source code excerpt:
DynamicRenderScaling::FHeuristicSettings BucketSetting;
BucketSetting.Model = DynamicRenderScaling::EHeuristicModel::Linear;
BucketSetting.bModelScalesWithPrimaryScreenPercentage = false; // r.Nanite.MaxPixelsPerEdge is not scaled by dynamic resolution of the primary view
BucketSetting.MinResolutionFraction = DynamicRenderScaling::PercentageToFraction(PixelsPerEdgeScalingPercentage);
BucketSetting.MaxResolutionFraction = DynamicRenderScaling::PercentageToFraction(100.0f);
BucketSetting.BudgetMs = CVarNaniteShadowTimeBudgetMs.GetValueOnAnyThread();
BucketSetting.ChangeThreshold = DynamicRenderScaling::PercentageToFraction(1.0f);
BucketSetting.TargetedHeadRoom = DynamicRenderScaling::PercentageToFraction(5.0f); // 5% headroom
BucketSetting.UpperBoundQuantization = DynamicRenderScaling::FHeuristicSettings::kDefaultUpperBoundQuantization;
#Associated Variable and Callsites
This variable is associated with another variable named CVarNaniteMaxPixelsPerEdge
. They share the same value. See the following C++ source code.
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/NaniteCullRaster.cpp:138
Scope: file
Source code excerpt:
);
TAutoConsoleVariable<float> CVarNaniteMaxPixelsPerEdge(
TEXT("r.Nanite.MaxPixelsPerEdge"),
1.0f,
TEXT("The triangle edge length that the Nanite runtime targets, measured in pixels."),
ECVF_RenderThreadSafe
);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/NaniteCullRaster.cpp:4382
Scope (from outer to inner):
file
namespace Nanite
function FBinningData FRenderer::AddPass_Rasterize
lambda-function
Source code excerpt:
RasterPassParameters->TessellationTable_Offsets = GTessellationTable.Offsets.SRV;
RasterPassParameters->TessellationTable_VertsAndIndexes = GTessellationTable.VertsAndIndexes.SRV;
RasterPassParameters->InvDiceRate = CVarNaniteMaxPixelsPerEdge.GetValueOnRenderThread() / CVarNaniteDicingRate.GetValueOnRenderThread();
RasterPassParameters->MaxPatchesPerGroup = GetMaxPatchesPerGroup();
RasterPassParameters->MeshPass = Configuration.bIsLumenCapture ? ENaniteMeshPass::LumenCardCapture : ENaniteMeshPass::BasePass;
RasterPassParameters->VirtualShadowMap = VirtualTargetParameters;
RasterPassParameters->OutStatsBuffer = GraphBuilder.CreateUAV(StatsBuffer, ERDGUnorderedAccessViewFlags::SkipBarrier);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/NaniteCullRaster.cpp:4616
Scope (from outer to inner):
file
namespace Nanite
Source code excerpt:
PassParameters->TessellationTable_Offsets = GTessellationTable.Offsets.SRV;
PassParameters->TessellationTable_VertsAndIndexes = GTessellationTable.VertsAndIndexes.SRV;
PassParameters->InvDiceRate = CVarNaniteMaxPixelsPerEdge.GetValueOnRenderThread() / CVarNaniteDicingRate.GetValueOnRenderThread();
PassParameters->RWVisiblePatches = GraphBuilder.CreateUAV( VisiblePatches );
PassParameters->RWVisiblePatchesArgs = GraphBuilder.CreateUAV( VisiblePatchesArgs );
PassParameters->VisiblePatchesSize = VisiblePatches->GetSize() / 16;
PassParameters->OutStatsBuffer = GNaniteShowStats != 0u ? GraphBuilder.CreateUAV(StatsBuffer) : nullptr;
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/NaniteShared.cpp:17
Scope: file
Source code excerpt:
IMPLEMENT_STATIC_AND_SHADER_UNIFORM_BUFFER_STRUCT(FNaniteRayTracingUniformParameters, "NaniteRayTracing", NaniteRayTracing);
extern TAutoConsoleVariable<float> CVarNaniteMaxPixelsPerEdge;
extern TAutoConsoleVariable<float> CVarNaniteMinPixelsPerEdgeHW;
// Optimized compute dual depth export pass on supported platforms.
int32 GNaniteExportDepth = 1;
static FAutoConsoleVariableRef CVarNaniteExportDepth(
TEXT("r.Nanite.ExportDepth"),
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/NaniteShared.cpp:117
Scope (from outer to inner):
file
namespace Nanite
function FPackedView CreatePackedView
Source code excerpt:
const FVector4f ViewSizeAndInvSize(ViewRect.Width(), ViewRect.Height(), 1.0f / float(ViewRect.Width()), 1.0f / float(ViewRect.Height()));
const float NaniteMaxPixelsPerEdge = CVarNaniteMaxPixelsPerEdge.GetValueOnRenderThread() * Params.MaxPixelsPerEdgeMultipler;
const float NaniteMinPixelsPerEdgeHW = CVarNaniteMinPixelsPerEdgeHW.GetValueOnRenderThread();
const FVector CullingViewOrigin = Params.bUseCullingViewOverrides ? Params.CullingViewOrigin : Params.ViewMatrices.GetViewOrigin();
// We bake the view lod scales into ScreenMultiple since the two things are always used together.
const float ViewDistanceLODScale = GetCachedScalabilityCVars().StaticMeshLODDistanceScale * Params.ViewLODDistanceFactor;
const float ScreenMultiple = FMath::Max(Params.ViewMatrices.GetProjectionMatrix().M[0][0], Params.ViewMatrices.GetProjectionMatrix().M[1][1]) / ViewDistanceLODScale;
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/VirtualShadowMaps/VirtualShadowMapArray.cpp:38
Scope: file
Source code excerpt:
extern int32 GForceInvalidateDirectionalVSM;
extern int32 GVSMMaxPageAgeSinceLastRequest;
extern TAutoConsoleVariable<float> CVarNaniteMaxPixelsPerEdge;
extern TAutoConsoleVariable<float> CVarNaniteMinPixelsPerEdgeHW;
int32 GVSMShowLightDrawEvents = 0;
FAutoConsoleVariableRef CVarVSMShowLightDrawEvents(
TEXT("r.Shadow.Virtual.ShowLightDrawEvents"),
GVSMShowLightDrawEvents,
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/VirtualShadowMaps/VirtualShadowMapArray.cpp:1985
Scope (from outer to inner):
file
function void FVirtualShadowMapArray::CreateMipViews
Source code excerpt:
const int32 NumPrimaryViews = Views.Num();
const float NaniteMaxPixelsPerEdge = CVarNaniteMaxPixelsPerEdge.GetValueOnRenderThread();
const float NaniteMinPixelsPerEdgeHW = CVarNaniteMinPixelsPerEdgeHW.GetValueOnRenderThread();
// 1. create derivative views for each of the Mip levels,
Views.AddDefaulted( NumPrimaryViews * ( FVirtualShadowMap::MaxMipLevels - 1) );
int32 MaxMips = 0;