NumAdaptiveRefinementLevels
NumAdaptiveRefinementLevels
#Overview
name: NumAdaptiveRefinementLevels
The value of this variable can be defined or overridden in .ini config files. 4
.ini config files referencing this setting variable.
It is referenced in 16
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of NumAdaptiveRefinementLevels is to control the number of recursive levels allowed for adaptive refinement in importance tracing, which is a technique used in global illumination calculations. This setting has a significant impact on both the quality of the lighting results and the build time of the lightmaps.
NumAdaptiveRefinementLevels is primarily used in the Lightmass subsystem of Unreal Engine, which is responsible for precomputed lighting calculations. It is part of the FImportanceTracingSettings struct, which suggests it’s specifically used for importance tracing in the global illumination process.
The value of this variable is set in the Lightmass configuration file (GLightmassIni). It can be adjusted based on the quality settings of the lightmap build process, as seen in the WriteSceneSettings function in Lightmass.cpp.
This variable interacts with other importance tracing settings, such as AdaptiveBrightnessThreshold and AdaptiveFirstBouncePhotonConeAngle. It’s also influenced by the IndirectLightingQuality setting, which can increase the number of refinement levels for higher quality settings.
Developers should be aware that increasing NumAdaptiveRefinementLevels will significantly increase build times but can also improve the quality of indirect lighting. It’s important to balance this setting with performance considerations.
Best practices when using this variable include:
- Start with lower values and incrementally increase if needed, as higher values dramatically increase build times.
- Consider the project’s requirements for lighting quality versus build time when adjusting this value.
- Use in conjunction with other importance tracing settings for optimal results.
- Be aware that very high values (beyond 4 or 5) may yield diminishing returns in terms of visual quality improvement.
- Test the impact of changes in a controlled environment before applying to a full production build.
Remember that this setting is part of the advanced lightmass configuration and should be adjusted with care and understanding of its impact on the lighting build process.
#Setting Variables
#References In INI files
Location: <Workspace>/Engine/Config/BaseLightmass.ini:157, section: [DevOptions.ImportanceTracing]
- INI Section:
DevOptions.ImportanceTracing
- Raw value:
2
- Is Array:
False
Location: <Workspace>/Engine/Config/BaseLightmass.ini:239, section: [DevOptions.StaticLightingMediumQuality]
- INI Section:
DevOptions.StaticLightingMediumQuality
- Raw value:
3
- Is Array:
False
Location: <Workspace>/Engine/Config/BaseLightmass.ini:259, section: [DevOptions.StaticLightingHighQuality]
- INI Section:
DevOptions.StaticLightingHighQuality
- Raw value:
3
- Is Array:
False
Location: <Workspace>/Engine/Config/BaseLightmass.ini:282, section: [DevOptions.StaticLightingProductionQuality]
- INI Section:
DevOptions.StaticLightingProductionQuality
- Raw value:
3
- Is Array:
False
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Lightmass/Lightmass.cpp:2328
Scope (from outer to inner):
file
function void FLightmassExporter::WriteSceneSettings
Source code excerpt:
Scene.ImportanceTracingSettings.bUseStratifiedSampling = bConfigBool;
VERIFYLIGHTMASSINI(GConfig->GetInt(TEXT("DevOptions.ImportanceTracing"), TEXT("NumHemisphereSamples"), Scene.ImportanceTracingSettings.NumHemisphereSamples, GLightmassIni));
VERIFYLIGHTMASSINI(GConfig->GetInt(TEXT("DevOptions.ImportanceTracing"), TEXT("NumAdaptiveRefinementLevels"), Scene.ImportanceTracingSettings.NumAdaptiveRefinementLevels, GLightmassIni));
float MaxHemisphereAngleDegrees;
VERIFYLIGHTMASSINI(GConfig->GetFloat(TEXT("DevOptions.ImportanceTracing"), TEXT("MaxHemisphereRayAngle"), MaxHemisphereAngleDegrees, GLightmassIni));
Scene.ImportanceTracingSettings.MaxHemisphereRayAngle = MaxHemisphereAngleDegrees * (float)PI / 180.0f;
VERIFYLIGHTMASSINI(GConfig->GetFloat(TEXT("DevOptions.ImportanceTracing"), TEXT("AdaptiveBrightnessThreshold"), Scene.ImportanceTracingSettings.AdaptiveBrightnessThreshold, GLightmassIni));
VERIFYLIGHTMASSINI(GConfig->GetFloat(TEXT("DevOptions.ImportanceTracing"), TEXT("AdaptiveFirstBouncePhotonConeAngle"), Scene.ImportanceTracingSettings.AdaptiveFirstBouncePhotonConeAngle, GLightmassIni));
VERIFYLIGHTMASSINI(GConfig->GetFloat(TEXT("DevOptions.ImportanceTracing"), TEXT("AdaptiveSkyVarianceThreshold"), Scene.ImportanceTracingSettings.AdaptiveSkyVarianceThreshold, GLightmassIni));
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Lightmass/Lightmass.cpp:2482
Scope (from outer to inner):
file
function void FLightmassExporter::WriteSceneSettings
Source code excerpt:
Scene.IrradianceCachingSettings.AngleSmoothFactor *= IrradianceCacheSmoothFactor;
VERIFYLIGHTMASSINI(GConfig->GetInt(QualitySectionNames[QualityLevel], TEXT("NumAdaptiveRefinementLevels"), Scene.ImportanceTracingSettings.NumAdaptiveRefinementLevels, GLightmassIni));
float AdaptiveBrightnessThresholdScale;
VERIFYLIGHTMASSINI(GConfig->GetFloat(QualitySectionNames[QualityLevel], TEXT("AdaptiveBrightnessThresholdScale"), AdaptiveBrightnessThresholdScale, GLightmassIni));
Scene.ImportanceTracingSettings.AdaptiveBrightnessThreshold = Scene.ImportanceTracingSettings.AdaptiveBrightnessThreshold * AdaptiveBrightnessThresholdScale;
float AdaptiveFirstBouncePhotonConeAngleScale;
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/FinalGather.cpp:126
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::CalculateVolumeSampleIncidentRadiance
Source code excerpt:
MappingContext.Stats.VolumetricLightmapDirectLightingTime += EndUpperDirectLightingTime - EndGatherTime;
int32 NumSampleAdaptiveRefinementLevels = ImportanceTracingSettings.NumAdaptiveRefinementLevels;
float SampleAdaptiveRefinementBrightnessScale = 1.0f;
FLightingCacheGatherInfo UpperGatherInfo;
FFinalGatherSample3 UpperHemisphereSample = IncomingRadianceAdaptive<FFinalGatherSample3>(
NULL,
RepresentativeVertex,
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/FinalGather.cpp:621
Scope (from outer to inner):
file
namespace Lightmass
class class FUniformHemisphereRefinementGrid
function void RefineIncomingRadiance
Source code excerpt:
EHemisphereGatherClassification GatherClassification,
bool bGatheringForCachedDirectLighting,
int32 NumAdaptiveRefinementLevels,
float BrightnessThresholdScale,
const TArray<FVector4f, TInlineAllocator<30> >& TangentImportancePhotonDirections,
const TArray<FSphere3f>& PortalBoundingSpheres,
FStaticLightingMappingContext& MappingContext,
FGatherHitPoints* HitPointRecorder,
FLMRandomStream& RandomStream,
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/FinalGather.cpp:669
Scope (from outer to inner):
file
namespace Lightmass
class class FUniformHemisphereRefinementGrid
function void RefineIncomingRadiance
Source code excerpt:
// Operate on all cells at a refinement depth before going deeper
// This is necessary for the neighbor comparisons to work right
for (int32 RefinementDepth = 0; RefinementDepth < NumAdaptiveRefinementLevels; RefinementDepth++)
{
FLinearColor TotalLighting = FLinearColor::Black;
// Recalculate total lighting based on the refined results
for (int32 ThetaIndex = 0; ThetaIndex < NumThetaSteps; ThetaIndex++)
{
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/FinalGather.cpp:1135
Scope (from outer to inner):
file
namespace Lightmass
function SampleType FStaticLightingSystem::IncomingRadianceAdaptive
Source code excerpt:
EFinalGatherRayBiasMode RayBiasMode,
EHemisphereGatherClassification GatherClassification,
int32 NumAdaptiveRefinementLevels,
float BrightnessThresholdScale,
const TArray<FVector4f>& UniformHemisphereSamples,
const TArray<FVector2f>& UniformHemisphereSampleUniforms,
float MaxUnoccludedLength,
const TArray<FVector4f>& ImportancePhotonDirections,
FStaticLightingMappingContext& MappingContext,
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/FinalGather.cpp:1259
Scope (from outer to inner):
file
namespace Lightmass
function SampleType FStaticLightingSystem::IncomingRadianceAdaptive
Source code excerpt:
GatherClassification,
bGatheringForCachedDirectLighting,
NumAdaptiveRefinementLevels,
BrightnessThresholdScale,
TangentSpaceImportancePhotonDirections,
Scene.Portals,
MappingContext,
GatherInfo.HitPointRecorder,
RandomStream,
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/FinalGather.cpp:1596
Scope (from outer to inner):
file
namespace Lightmass
function FFinalGatherSample FStaticLightingSystem::CachePointIncomingRadiance
Source code excerpt:
RBM_ConstantNormalOffset,
GLM_FinalGather,
ImportanceTracingSettings.NumAdaptiveRefinementLevels,
1.0f,
CachedHemisphereSamples,
CachedHemisphereSampleUniforms,
CachedSamplesMaxUnoccludedLength,
ImportancePhotonDirections,
MappingContext,
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/LightingSystem.cpp:959
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::ValidateSettings
Source code excerpt:
if (InScene.GeneralSettings.IndirectLightingQuality > 50)
{
InScene.ImportanceTracingSettings.NumAdaptiveRefinementLevels += 2;
}
else if (InScene.GeneralSettings.IndirectLightingQuality > 10)
{
InScene.ImportanceTracingSettings.NumAdaptiveRefinementLevels += 1;
}
InScene.ShadowSettings.NumShadowRays = FMath::TruncToInt(InScene.ShadowSettings.NumShadowRays * FMath::Sqrt(InScene.GeneralSettings.IndirectLightingQuality));
InScene.ShadowSettings.NumPenumbraShadowRays = FMath::TruncToInt(InScene.ShadowSettings.NumPenumbraShadowRays * FMath::Sqrt(InScene.GeneralSettings.IndirectLightingQuality));
InScene.ImportanceTracingSettings.NumAdaptiveRefinementLevels = FMath::Min(InScene.ImportanceTracingSettings.NumAdaptiveRefinementLevels, MaxNumRefiningDepths);
}
/** Logs solver stats */
void FStaticLightingSystem::DumpStats(float TotalStaticLightingTime) const
{
FString SolverStats = TEXT("\n\n");
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/LightingSystem.cpp:1237
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::ValidateSettings
function void FStaticLightingSystem::DumpStats
Source code excerpt:
uint64 TotalNumRefiningSamples = 0;
for (int i = 0; i < ImportanceTracingSettings.NumAdaptiveRefinementLevels; i++)
{
TotalNumRefiningSamples += Stats.NumRefiningFinalGatherSamples[i];
}
SolverStats += FString::Printf( TEXT("Final Gather: %.1fs on %.3f million base samples, %.1fs on %.3f million refining samples for %u refinement levels. \n"), Stats.BaseFinalGatherSampleTime, Stats.NumBaseFinalGatherSamples / 1000000.0f, Stats.RefiningFinalGatherSampleTime, TotalNumRefiningSamples / 1000000.0f, ImportanceTracingSettings.NumAdaptiveRefinementLevels);
if (TotalNumRefiningSamples > 0)
{
SolverStats += FString::Printf( TEXT(" %.1f%% due to brightness differences, %.1f%% due to importance photons, %.1f%% other reasons, Samples at depth: "), 100.0f * Stats.NumRefiningSamplesDueToBrightness / TotalNumRefiningSamples, 100.0f * Stats.NumRefiningSamplesDueToImportancePhotons / TotalNumRefiningSamples, 100.0f * Stats.NumRefiningSamplesOther / TotalNumRefiningSamples);
for (int i = 0; i < ImportanceTracingSettings.NumAdaptiveRefinementLevels; i++)
{
SolverStats += FString::Printf(TEXT("%.1f%%, "), 100.0f * Stats.NumRefiningFinalGatherSamples[i] / TotalNumRefiningSamples);
}
SolverStats += FString::Printf(TEXT("\n"));
}
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/LightingSystem.h:2345
Scope (from outer to inner):
file
namespace Lightmass
class class FStaticLightingSystem
Source code excerpt:
EFinalGatherRayBiasMode RayBiasMode,
EHemisphereGatherClassification GatherClassification,
int32 NumAdaptiveRefinementLevels,
float BrightnessThresholdScale,
const TArray<FVector4f>& UniformHemisphereSamples,
const TArray<FVector2f>& UniformHemisphereSampleUniforms,
float MaxUnoccludedLength,
const TArray<FVector4f>& ImportancePhotonDirections,
FStaticLightingMappingContext& MappingContext,
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/Radiosity.cpp:305
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::RadiositySetupTextureMapping
Source code excerpt:
TArray<FVector4f> ImportancePhotonDirections;
FLightingCacheGatherInfo GatherInfo;
const int32 NumAdaptiveRefinementLevels = GeneralSettings.IndirectLightingQuality <= 10 ? 1 : 2;
if (bCacheFinalGatherHitPoints)
{
GatherHitPoints.GatherHitPointRanges.Add(FArrayRange(GatherHitPoints.GatherHitPointData.Num()));
GatherInfo.HitPointRecorder = &GatherHitPoints;
}
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/Radiosity.cpp:322
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::RadiositySetupTextureMapping
Source code excerpt:
RBM_ConstantNormalOffset,
GLM_GatherLightEmitted, /* Gather sky light and emissive only */
NumAdaptiveRefinementLevels,
1.0f,
CachedHemisphereSamplesForRadiosity[0],
CachedHemisphereSamplesForRadiosityUniforms[0],
1,
ImportancePhotonDirections,
MappingContext,
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/Radiosity.cpp:580
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::RadiosityIterationTextureMapping
Source code excerpt:
const int32 DestRadiosityBufferIndex = 1 - SourceRadiosityBufferIndex;
int32 NumAdaptiveRefinementLevels = PassIndex == 0 ? 1 : 0;
if (GeneralSettings.IndirectLightingQuality > 10)
{
NumAdaptiveRefinementLevels++;
}
const int32 RadiositySampleSet = FMath::Min<int32>(PassIndex, UE_ARRAY_COUNT(CachedHemisphereSamplesForRadiosity) - 1);
TLightingCache<FFinalGatherSample> RadiosityCache(TextureMapping->Mesh->BoundingBox, *this, 1);
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/Radiosity.cpp:634
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::RadiosityIterationTextureMapping
Source code excerpt:
RBM_ConstantNormalOffset,
GatherClassification,
NumAdaptiveRefinementLevels,
1.0f,
CachedHemisphereSamplesForRadiosity[RadiositySampleSet],
CachedHemisphereSamplesForRadiosityUniforms[RadiositySampleSet],
1,
ImportancePhotonDirections,
MappingContext,
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Public/SceneExport.h:520
Scope (from outer to inner):
file
namespace Lightmass
class class FImportanceTracingSettings
Source code excerpt:
/** Number of recursive levels allowed for adaptive refinement. This has a huge impact on build time but also quality. */
int32 NumAdaptiveRefinementLevels;
/**
* Largest angle from the sample normal that a hemisphere sample direction can be.
* Useful for preventing rays nearly perpendicular to the normal which may self intersect a flat surface due to imprecision in the normal.
*/
float MaxHemisphereRayAngle;