bCacheIrradiancePhotonsOnSurfaces

bCacheIrradiancePhotonsOnSurfaces

#Overview

name: bCacheIrradiancePhotonsOnSurfaces

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 12 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of bCacheIrradiancePhotonsOnSurfaces is to optimize the performance and accuracy of the photon mapping system in Unreal Engine’s lighting calculations. This setting is part of the global illumination and photon mapping subsystem within the Unreal Engine’s rendering pipeline.

This setting variable is primarily used in the Lightmass module, which is responsible for global illumination calculations in Unreal Engine. It’s specifically utilized in the photon mapping and final gathering processes.

The value of this variable is typically set in the Lightmass configuration file (GLightmassIni). It’s read from the configuration file in the FLightmassExporter::WriteSceneSettings function.

This variable interacts closely with other photon mapping settings, such as bUseIrradiancePhotons and various visualization options like bVisualizePhotonPaths.

Developers should be aware of the following when using this variable:

  1. When enabled, it caches irradiance photons on surfaces, which can significantly optimize final gathering.
  2. It affects the performance and memory usage of the lighting build process.
  3. It can impact the accuracy and quality of the final lighting results.

Best practices for using this variable include:

  1. Enable it for production builds to optimize lighting calculations.
  2. Consider disabling it during development or debugging if you need to analyze raw photon distribution.
  3. Use it in conjunction with other photon mapping settings to fine-tune the balance between performance and quality.
  4. Monitor the impact on build times and memory usage when enabled, especially for large scenes.

Remember that this setting is part of the advanced lighting system and should be adjusted with care, considering its impact on both performance and visual quality.

#Setting Variables

#References In INI files

Location: <Workspace>/Engine/Config/BaseLightmass.ini:171, 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:2355

Scope (from outer to inner):

file
function     void FLightmassExporter::WriteSceneSettings

Source code excerpt:

		VERIFYLIGHTMASSINI(GConfig->GetBool(TEXT("DevOptions.PhotonMapping"), TEXT("bUseIrradiancePhotons"), bConfigBool, GLightmassIni));
		Scene.PhotonMappingSettings.bUseIrradiancePhotons = bConfigBool;
		VERIFYLIGHTMASSINI(GConfig->GetBool(TEXT("DevOptions.PhotonMapping"), TEXT("bCacheIrradiancePhotonsOnSurfaces"), bConfigBool, GLightmassIni));
		Scene.PhotonMappingSettings.bCacheIrradiancePhotonsOnSurfaces = bConfigBool;
		VERIFYLIGHTMASSINI(GConfig->GetBool(TEXT("DevOptions.PhotonMapping"), TEXT("bVisualizePhotonPaths"), bConfigBool, GLightmassIni));
		Scene.PhotonMappingSettings.bVisualizePhotonPaths = bConfigBool;
		VERIFYLIGHTMASSINI(GConfig->GetBool(TEXT("DevOptions.PhotonMapping"), TEXT("bVisualizePhotonGathers"), bConfigBool, GLightmassIni));
		Scene.PhotonMappingSettings.bVisualizePhotonGathers = bConfigBool;
		VERIFYLIGHTMASSINI(GConfig->GetBool(TEXT("DevOptions.PhotonMapping"), TEXT("bVisualizePhotonImportanceSamples"), bConfigBool, GLightmassIni));
		Scene.PhotonMappingSettings.bVisualizePhotonImportanceSamples = bConfigBool;

#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/FinalGather.cpp:1470

Scope (from outer to inner):

file
namespace    Lightmass
function     FFinalGatherSample FStaticLightingSystem::CachePointIncomingRadiance

Source code excerpt:

				FLinearColor Irradiance = FLinearColor::Black;

				if (PhotonMappingSettings.bCacheIrradiancePhotonsOnSurfaces)
				{
					// 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,

#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/LightingSystem.cpp:909

Scope (from outer to inner):

file
namespace    Lightmass
function     void FStaticLightingSystem::ValidateSettings

Source code excerpt:

#endif
	{
		InScene.PhotonMappingSettings.bCacheIrradiancePhotonsOnSurfaces = false;
	}
	InScene.PhotonMappingSettings.FinalGatherImportanceSampleFraction = FMath::Clamp(InScene.PhotonMappingSettings.FinalGatherImportanceSampleFraction, 0.0f, 1.0f);
	if (InScene.ImportanceTracingSettings.NumHemisphereSamples * (1.0f - InScene.PhotonMappingSettings.FinalGatherImportanceSampleFraction) < 1)
	{
		// Irradiance caching needs some uniform samples
		InScene.IrradianceCachingSettings.bAllowIrradianceCaching = false;

#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/LightingSystem.cpp:991

Scope (from outer to inner):

file
namespace    Lightmass
function     void FStaticLightingSystem::ValidateSettings
function     void FStaticLightingSystem::DumpStats

Source code excerpt:

		{
			SolverStats += FString::Printf( TEXT("%4.1f%%%8.1fs    Mark %.3f million Irradiance Photons\n"), 100.0f * Stats.IrradiancePhotonMarkingTime / TotalStaticLightingTime, Stats.IrradiancePhotonMarkingTime, Stats.NumIrradiancePhotons / 1000000.0f);
			if (PhotonMappingSettings.bCacheIrradiancePhotonsOnSurfaces)
			{
				SolverStats += FString::Printf( TEXT("%4.1f%%%8.1fs    Cache %.3f million Irradiance Photon Samples on surfaces\n"), 100.0f * Stats.CacheIrradiancePhotonsTime / TotalStaticLightingTime, Stats.CacheIrradiancePhotonsTime, Stats.NumCachedIrradianceSamples / 1000000.0f);
			}
			SolverStats += FString::Printf( TEXT("%4.1f%%%8.1fs    Calculate %.3f million Irradiance Photons\n"), 100.0f * Stats.IrradiancePhotonCalculatingTime / TotalStaticLightingTime, Stats.IrradiancePhotonCalculatingTime, Stats.NumFoundIrradiancePhotons / 1000000.0f);
		}
	}

#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/LightingSystem.cpp:1039

Scope (from outer to inner):

file
namespace    Lightmass
function     void FStaticLightingSystem::ValidateSettings
function     void FStaticLightingSystem::DumpStats

Source code excerpt:

		if (PhotonMappingSettings.bUseIrradiancePhotons)
		{
			if (PhotonMappingSettings.bCacheIrradiancePhotonsOnSurfaces
				// Only log Irradiance photon caching stats if it was more than 2 percent of the total time
				&& Stats.CacheIrradiancePhotonsTime / TotalStaticLightingTime > .02)
			{
				SolverStats += FString::Printf( TEXT("\n") );
				SolverStats += FString::Printf( TEXT("Total Irradiance Photon Caching thread seconds: %.1f\n"), Stats.IrradiancePhotonCachingThreadTime);
				SolverStats += FString::Printf( TEXT("%4.1f%%%8.1fs    Octree traversal\n"), 100.0f * Stats.IrradiancePhotonOctreeTraversalTime / Stats.IrradiancePhotonCachingThreadTime, Stats.IrradiancePhotonOctreeTraversalTime);

#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:168

Scope (from outer to inner):

file
namespace    Lightmass
function     void FStaticLightingSystem::EmitPhotons

Source code excerpt:

		LogSolverMessage(FString::Printf(TEXT("Marking Irradiance Photons complete, %.3f million photons marked in %.1f seconds"), Stats.NumIrradiancePhotons / 1000000.0f, Stats.IrradiancePhotonMarkingTime));

		if (PhotonMappingSettings.bCacheIrradiancePhotonsOnSurfaces)
		{
			// Cache irradiance photons on surfaces, as an optimization for final gathering.
			// Final gather rays already know which surface they intersected, so we can do a constant time lookup to find
			// The nearest irradiance photon instead of doing a photon map gather at the end of each final gather ray.
			// As an additional benefit, only cached irradiance photons are actually used for rendering, so we only need to calculate irradiance for the used ones.
			CacheIrradiancePhotons();

#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:1353

Scope (from outer to inner):

file
namespace    Lightmass
function     void FStaticLightingSystem::CalculateIrradiancePhotons

Source code excerpt:

	//GSwarm->SendMessage( NSwarm::FTimingMessage( NSwarm::PROGSTATE_Preparing2, 0 ) );

	if (!PhotonMappingSettings.bCacheIrradiancePhotonsOnSurfaces)
	{
		// Without bCacheIrradiancePhotonsOnSurfaces, treat all irradiance photons as found since we'll have to calculate irradiance for all of them.
		Stats.NumFoundIrradiancePhotons = Stats.NumIrradiancePhotons;
	}

	if (PhotonMappingSettings.bVisualizeIrradiancePhotonCalculation && Scene.DebugMapping)
	{
		float ClosestIrradiancePhotonDistSq = FLT_MAX;

#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:1372

Scope (from outer to inner):

file
namespace    Lightmass
function     void FStaticLightingSystem::CalculateIrradiancePhotons

Source code excerpt:

				const FIrradiancePhoton& CurrentPhoton = IrradiancePhotons[ArrayIndex][PhotonIndex];
				const float CurrentDistSquared = (CurrentPhoton.GetPosition() - Scene.DebugInput.Position).SizeSquared3();
				if ((!PhotonMappingSettings.bCacheIrradiancePhotonsOnSurfaces || CurrentPhoton.IsUsed())
					&& CurrentDistSquared < ClosestIrradiancePhotonDistSq)
				{
					// Debug the closest irradiance photon to the selected position.
					// NOTE: This is not necessarily the photon that will get cached for the selected texel!
					// It's not easy to figure out which photon will get cached at this point in the lighting process, so we use the closest instead.
					//@todo - if bCacheIrradiancePhotonsOnSurfaces is enabled, we can figure out exactly which photon will be used by the selected texel or vertex.
					ClosestIrradiancePhotonDistSq = CurrentDistSquared;
					DebugIrradiancePhotonCalculationArrayIndex = ArrayIndex;
					DebugIrradiancePhotonCalculationPhotonIndex = PhotonIndex;
				}
			}
		}

#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:1502

Scope (from outer to inner):

file
namespace    Lightmass
function     void FStaticLightingSystem::CalculateIrradiancePhotonsWorkRange

Source code excerpt:

		FIrradiancePhoton& CurrentIrradiancePhoton = CurrentArray[PhotonIndex];
		// If we already cached irradiance photons on surfaces, only calculate irradiance for photons which actually got found.
		if (PhotonMappingSettings.bCacheIrradiancePhotonsOnSurfaces && !CurrentIrradiancePhoton.IsUsed())
		{
			continue;
		}

		const bool bDebugThisPhoton = PhotonMappingSettings.bVisualizeIrradiancePhotonCalculation
			&& DebugIrradiancePhotonCalculationArrayIndex == WorkRange.IrradiancePhotonArrayIndex 

#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:1596

Scope (from outer to inner):

file
namespace    Lightmass
function     void FStaticLightingSystem::CacheIrradiancePhotons

Source code excerpt:

void FStaticLightingSystem::CacheIrradiancePhotons()
{
	check(PhotonMappingSettings.bCacheIrradiancePhotonsOnSurfaces);
	for(int32 ThreadIndex = 1; ThreadIndex < NumStaticLightingThreads; ThreadIndex++)
	{
		FMappingProcessingThreadRunnable* ThreadRunnable = new FMappingProcessingThreadRunnable(this, ThreadIndex, StaticLightingTask_CacheIrradiancePhotons);
		IrradiancePhotonCachingThreads.Add(ThreadRunnable);
		const FString ThreadName = FString::Printf(TEXT("IrradiancePhotonCachingThread%u"), ThreadIndex);
		ThreadRunnable->Thread = FRunnableThread::Create(ThreadRunnable, *ThreadName);

#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/TextureMapping.cpp:2776

Scope (from outer to inner):

file
namespace    Lightmass
function     void FStaticLightingSystem::CalculateDirectLightingTextureMappingPhotonMap

Source code excerpt:


					const FIrradiancePhoton* NearestPhoton = NULL;
					if (PhotonMappingSettings.bCacheIrradiancePhotonsOnSurfaces)
					{
						// Trace a ray into the current texel to get a good representation of what the final gather will see.
						// Speed does not matter here since bVisualizeCachedApproximateDirectLighting is only used for debugging.
						const FLightRay TexelRay(
							CurrentVertex.WorldPosition + CurrentVertex.WorldTangentZ * TexelToVertex.TexelRadius,
							CurrentVertex.WorldPosition - CurrentVertex.WorldTangentZ * TexelToVertex.TexelRadius,

#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Public/SceneExport.h:593

Scope (from outer to inner):

file
namespace    Lightmass
class        class FPhotonMappingSettings

Source code excerpt:

	* Only visible photons are cached, which reduces light leaking.
	*/
	bool bCacheIrradiancePhotonsOnSurfaces;

	/** 
	 * Debugging - whether to draw lines in the editor representing photon paths.  
	 * They will only be drawn if a texel is selected and ViewSingleBounceNumber is >= 0.
	 */
	bool bVisualizePhotonPaths;