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:

  1. bUsePhotonMapping
  2. NumIndirectLightingBounces
  3. bUseIrradiancePhotons
  4. bVisualizeCachedApproximateDirectLighting

Developers must be aware that:

  1. Enabling final gathering significantly improves the quality of indirect lighting but increases computation time.
  2. When final gathering is disabled, the system relies more heavily on irradiance photons for indirect lighting.
  3. The number of indirect lighting bounces affects how final gathering is applied.

Best practices when using this variable include:

  1. Enable final gathering for higher quality results, especially in scenes with complex indirect lighting.
  2. Balance the use of final gathering with performance requirements, as it can significantly increase lightmap baking times.
  3. Adjust related settings like NumIndirectLightingBounces and bUseIrradiancePhotons in conjunction with bUseFinalGathering for optimal results.
  4. 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]

#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;