bUseFinalGathering
bUseFinalGathering
#Overview
name: bUseFinalGathering
The value of this variable can be defined or overridden in .ini config files. 1
.ini config file referencing this setting variable.
It is referenced in 14
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of bUseFinalGathering is to control whether final gathering is used in the photon mapping process for global illumination in Unreal Engine 5’s lightmass system. Final gathering is a technique that improves the quality of indirect lighting by sampling the surrounding environment at the final stage of light calculation.
This setting variable is primarily used in the lighting and rendering subsystems of Unreal Engine, specifically within the Lightmass module, which handles global illumination calculations for static lighting.
The value of this variable is set in the Lightmass configuration file (GLightmassIni) under the “DevOptions.PhotonMapping” section. It is read and applied in the FLightmassExporter::WriteSceneSettings function.
bUseFinalGathering interacts with several other variables, including:
- bUsePhotonMapping
- NumIndirectLightingBounces
- bUseIrradiancePhotons
- bVisualizeCachedApproximateDirectLighting
Developers must be aware that:
- Enabling final gathering significantly improves the quality of indirect lighting but increases computation time.
- When final gathering is disabled, the system relies more heavily on irradiance photons for indirect lighting.
- The number of indirect lighting bounces affects how final gathering is applied.
Best practices when using this variable include:
- Enable final gathering for higher quality results, especially in scenes with complex indirect lighting.
- Balance the use of final gathering with performance requirements, as it can significantly increase lightmap baking times.
- Adjust related settings like NumIndirectLightingBounces and bUseIrradiancePhotons in conjunction with bUseFinalGathering for optimal results.
- Use visualization tools to compare results with and without final gathering to make informed decisions about its use in specific scenes.
#Setting Variables
#References In INI files
Location: <Workspace>/Engine/Config/BaseLightmass.ini:167, section: [DevOptions.PhotonMapping]
- INI Section:
DevOptions.PhotonMapping
- Raw value:
True
- 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:2347
Scope (from outer to inner):
file
function void FLightmassExporter::WriteSceneSettings
Source code excerpt:
VERIFYLIGHTMASSINI(GConfig->GetBool(TEXT("DevOptions.PhotonMapping"), TEXT("bUsePhotonMapping"), bConfigBool, GLightmassIni));
Scene.PhotonMappingSettings.bUsePhotonMapping = bConfigBool;
VERIFYLIGHTMASSINI(GConfig->GetBool(TEXT("DevOptions.PhotonMapping"), TEXT("bUseFinalGathering"), bConfigBool, GLightmassIni));
Scene.PhotonMappingSettings.bUseFinalGathering = bConfigBool;
VERIFYLIGHTMASSINI(GConfig->GetBool(TEXT("DevOptions.PhotonMapping"), TEXT("bUsePhotonDirectLightingInFinalGather"), bConfigBool, GLightmassIni));
Scene.PhotonMappingSettings.bUsePhotonDirectLightingInFinalGather = bConfigBool;
VERIFYLIGHTMASSINI(GConfig->GetBool(TEXT("DevOptions.PhotonMapping"), TEXT("bVisualizeCachedApproximateDirectLighting"), bConfigBool, GLightmassIni));
Scene.PhotonMappingSettings.bVisualizeCachedApproximateDirectLighting = bConfigBool;
VERIFYLIGHTMASSINI(GConfig->GetBool(TEXT("DevOptions.PhotonMapping"), TEXT("bUseIrradiancePhotons"), bConfigBool, GLightmassIni));
Scene.PhotonMappingSettings.bUseIrradiancePhotons = bConfigBool;
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/FinalGather.cpp:1463
Scope (from outer to inner):
file
namespace Lightmass
function FFinalGatherSample FStaticLightingSystem::CachePointIncomingRadiance
Source code excerpt:
if (PhotonMappingSettings.bUsePhotonMapping
&& GeneralSettings.NumIndirectLightingBounces > 0
&& !PhotonMappingSettings.bUseFinalGathering)
{
// Use irradiance photons for indirect lighting
if (PhotonMappingSettings.bUseIrradiancePhotons)
{
FLinearColor Irradiance = FLinearColor::Black;
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/FinalGather.cpp:1474
Scope (from outer to inner):
file
namespace Lightmass
function FFinalGatherSample FStaticLightingSystem::CachePointIncomingRadiance
Source code excerpt:
// Trace a ray into the texel to get a good representation of what the final gather will see,
// Instead of just calculating lightmap UV's from the current texel's position.
// Speed does not matter here since !bUseFinalGathering is only used for debugging.
const FLightRay TexelRay(
Vertex.WorldPosition + Vertex.WorldTangentZ * SampleRadius,
Vertex.WorldPosition - Vertex.WorldTangentZ * SampleRadius,
Mapping,
NULL
);
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/LightingSystem.cpp:918
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::ValidateSettings
Source code excerpt:
}
if (InScene.PhotonMappingSettings.bUsePhotonMapping && !InScene.PhotonMappingSettings.bUseFinalGathering)
{
// Irradiance caching currently only supported with final gathering
InScene.IrradianceCachingSettings.bAllowIrradianceCaching = false;
}
InScene.PhotonMappingSettings.ConeFilterConstant = FMath::Max(InScene.PhotonMappingSettings.ConeFilterConstant, 1.0f);
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/LightingSystem.cpp:1233
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::ValidateSettings
function void FStaticLightingSystem::DumpStats
Source code excerpt:
}
if (PhotonMappingSettings.bUseFinalGathering)
{
uint64 TotalNumRefiningSamples = 0;
for (int i = 0; i < ImportanceTracingSettings.NumAdaptiveRefinementLevels; i++)
{
TotalNumRefiningSamples += Stats.NumRefiningFinalGatherSamples[i];
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:347
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::EmitDirectPhotons
Source code excerpt:
if (GeneralSettings.ViewSingleBounceNumber < 0
|| PhotonMappingSettings.bVisualizeCachedApproximateDirectLighting && GeneralSettings.ViewSingleBounceNumber == 0
|| PhotonMappingSettings.bUseFinalGathering && GeneralSettings.ViewSingleBounceNumber == 1)
{
if (PhotonMappingSettings.bUseIrradiancePhotons)
{
int32 NumDirectIrradiancePhotons = 0;
for (int32 ArrayIndex = 0; ArrayIndex < IrradiancePhotons.Num(); ArrayIndex++)
{
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:1054
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::EmitIndirectPhotonsWorkRange
Source code excerpt:
// The final gather is the first bounce when enabled
bShouldCreateIrradiancePhoton =
(PhotonMappingSettings.bUseFinalGathering && GeneralSettings.NumIndirectLightingBounces > 1)
|| (!PhotonMappingSettings.bUseFinalGathering && GeneralSettings.NumIndirectLightingBounces > 0);
}
else
{
Output.SecondBouncePhotons.Add(NewPhoton);
Output.NumPhotonsEmittedSecondBounce = Output.NumPhotonsEmitted;
// Only allow creating an irradiance photon if two or more indirect bounces are required
// The final gather is the first bounce when enabled
bShouldCreateIrradiancePhoton =
(PhotonMappingSettings.bUseFinalGathering && GeneralSettings.NumIndirectLightingBounces > 2)
|| (!PhotonMappingSettings.bUseFinalGathering && GeneralSettings.NumIndirectLightingBounces > 1);
}
#if ALLOW_LIGHTMAP_SAMPLE_DEBUGGING
if (PhotonMappingSettings.bVisualizePhotonPaths
&& !PhotonMappingSettings.bUseIrradiancePhotons
&& (GeneralSettings.ViewSingleBounceNumber < 0
|| PhotonMappingSettings.bUseFinalGathering && GeneralSettings.ViewSingleBounceNumber > 1
|| !PhotonMappingSettings.bUseFinalGathering && GeneralSettings.ViewSingleBounceNumber > 0))
{
FScopeLock DebugOutputLock(&DebugOutputSync);
if (StartupDebugOutput.IndirectPhotons.Num() == 0)
{
StartupDebugOutput.IndirectPhotons.Empty(FMath::TruncToInt(NumIndirectPhotonsToEmit * IndirectPhotonEfficiency));
}
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:1330
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::MarkIrradiancePhotonsWorkRange
Source code excerpt:
// Only add direct contribution if we are final gathering and at least one bounce is required,
if ((PhotonMappingSettings.bUseFinalGathering && GeneralSettings.NumIndirectLightingBounces > 0)
// Or if photon mapping is being used for direct lighting.
|| PhotonMappingSettings.bVisualizeCachedApproximateDirectLighting)
{
// Find a nearby direct photon
const bool bHasDirectContribution = FindAnyNearbyPhoton(DirectPhotonMap, CurrentIrradiancePhoton.GetPosition(), PhotonMappingSettings.DirectPhotonSearchDistance, false);
if (bHasDirectContribution)
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:1513
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::CalculateIrradiancePhotonsWorkRange
Source code excerpt:
FLinearColor AccumulatedIrradiance(FLinearColor::Black);
// Only add direct contribution if we are final gathering and at least one bounce is required,
if (((PhotonMappingSettings.bUseFinalGathering && GeneralSettings.NumIndirectLightingBounces > 0)
// Or if photon mapping is being used for direct lighting.
|| PhotonMappingSettings.bVisualizeCachedApproximateDirectLighting)
&& PhotonMappingSettings.bUsePhotonDirectLightingInFinalGather)
{
const FLinearColor DirectPhotonIrradiance = CalculatePhotonIrradiance(
DirectPhotonMap,
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:1532
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::CalculateIrradiancePhotonsWorkRange
Source code excerpt:
// Only add direct contribution if it should be viewed given ViewSingleBounceNumber
if (GeneralSettings.ViewSingleBounceNumber < 0
|| (PhotonMappingSettings.bUseFinalGathering && GeneralSettings.ViewSingleBounceNumber == 1)
|| (!PhotonMappingSettings.bUseFinalGathering && GeneralSettings.ViewSingleBounceNumber == 0)
|| (PhotonMappingSettings.bVisualizeCachedApproximateDirectLighting && GeneralSettings.ViewSingleBounceNumber == 0))
{
AccumulatedIrradiance = DirectPhotonIrradiance;
}
}
// If we are final gathering, first bounce photons are actually the second lighting bounce since the final gather is the first bounce
if ((PhotonMappingSettings.bUseFinalGathering && GeneralSettings.NumIndirectLightingBounces > 1)
|| (!PhotonMappingSettings.bUseFinalGathering && GeneralSettings.NumIndirectLightingBounces > 0))
{
const FLinearColor FirstBouncePhotonIrradiance = CalculatePhotonIrradiance(
FirstBouncePhotonMap,
NumPhotonsEmittedFirstBounce,
PhotonMappingSettings.NumIrradianceCalculationPhotons,
PhotonMappingSettings.IndirectPhotonSearchDistance,
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:1558
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::CalculateIrradiancePhotonsWorkRange
Source code excerpt:
// Only add first bounce contribution if it should be viewed given ViewSingleBounceNumber
if (GeneralSettings.ViewSingleBounceNumber < 0
|| (PhotonMappingSettings.bUseFinalGathering && GeneralSettings.ViewSingleBounceNumber == 2)
|| (!PhotonMappingSettings.bUseFinalGathering && GeneralSettings.ViewSingleBounceNumber == 1))
{
AccumulatedIrradiance += FirstBouncePhotonIrradiance;
}
// If we are final gathering, second bounce photons are actually the third lighting bounce since the final gather is the first bounce
if ((PhotonMappingSettings.bUseFinalGathering && GeneralSettings.NumIndirectLightingBounces > 2)
|| (!PhotonMappingSettings.bUseFinalGathering && GeneralSettings.NumIndirectLightingBounces > 1))
{
const FLinearColor SecondBouncePhotonIrradiance = CalculatePhotonIrradiance(
SecondBouncePhotonMap,
NumPhotonsEmittedSecondBounce,
PhotonMappingSettings.NumIrradianceCalculationPhotons,
PhotonMappingSettings.IndirectPhotonSearchDistance,
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:1582
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::CalculateIrradiancePhotonsWorkRange
Source code excerpt:
// Only add second and up bounce contribution if it should be viewed given ViewSingleBounceNumber
if (GeneralSettings.ViewSingleBounceNumber < 0
|| (PhotonMappingSettings.bUseFinalGathering && GeneralSettings.ViewSingleBounceNumber == 3)
|| (!PhotonMappingSettings.bUseFinalGathering && GeneralSettings.ViewSingleBounceNumber == 2))
{
AccumulatedIrradiance += SecondBouncePhotonIrradiance;
}
}
}
CurrentIrradiancePhoton.SetIrradiance(AccumulatedIrradiance);
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/SampleVolume.cpp:548
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::ProcessVolumeSamplesTask
Source code excerpt:
if (GeneralSettings.NumIndirectLightingBounces > 0
// Calculating incident radiance for volume samples requires final gathering, since photons are only stored on surfaces.
&& (!PhotonMappingSettings.bUsePhotonMapping || PhotonMappingSettings.bUseFinalGathering))
{
const bool bDebugSamples = false;
float BackfacingHitsFraction = 0.0f;
float Unused = 0.0f;
// Sample radius stores the interpolation radius, but CalculateVolumeSampleIncidentRadiance will use this to push out final gather rays (ignore geometry inside the radius)
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Public/SceneExport.h:570
Scope (from outer to inner):
file
namespace Lightmass
class class FPhotonMappingSettings
Source code excerpt:
* Final gathering is slow but gets vastly better results than using first bounce photons.
*/
bool bUseFinalGathering;
/**
* Whether to use photons to represent direct lighting in final gathers.
* This is useful to visualize direct photons. When false, explicitly sampled direct lighting will be used instead, which has less leaking.
*/
bool bUsePhotonDirectLightingInFinalGather;