bUseIrradiancePhotons
bUseIrradiancePhotons
#Overview
name: bUseIrradiancePhotons
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 21
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of bUseIrradiancePhotons is to enable the use of irradiance photons in the photon mapping process for global illumination calculations in Unreal Engine’s Lightmass system.
This setting variable is primarily used in the Lightmass module, which is responsible for the offline global illumination calculations in Unreal Engine. It’s part of the photon mapping subsystem within Lightmass.
The value of this variable is set in the Lightmass configuration file (GLightmassIni). It’s read from the configuration file in the FLightmassExporter::WriteSceneSettings function.
Several other variables interact with bUseIrradiancePhotons:
- bCacheIrradiancePhotonsOnSurfaces: This setting determines whether to cache irradiance photon calculations on surfaces.
- bUsePhotonDirectLightingInFinalGather: This affects how irradiance photons are used in the final gathering step.
- DirectIrradiancePhotonFraction and IndirectIrradiancePhotonFraction: These control the proportion of direct and indirect photons that become irradiance photons.
Developers should be aware that:
- Enabling this feature can significantly impact performance and memory usage, as it involves storing and processing additional photon data.
- It affects the accuracy and quality of indirect lighting calculations, particularly for multi-bounce lighting.
- Its effectiveness can vary depending on the scene complexity and lighting conditions.
Best practices when using this variable include:
- Use it in conjunction with bCacheIrradiancePhotonsOnSurfaces for optimal performance.
- Adjust the DirectIrradiancePhotonFraction and IndirectIrradiancePhotonFraction to balance quality and performance.
- Consider disabling it for simpler scenes where the additional accuracy may not be noticeable.
- Test thoroughly with and without this feature enabled to determine the best setting for your specific project.
#Setting Variables
#References In INI files
Location: <Workspace>/Engine/Config/BaseLightmass.ini:170, 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:2353
Scope (from outer to inner):
file
function void FLightmassExporter::WriteSceneSettings
Source code excerpt:
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;
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;
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/FinalGather.cpp:1466
Scope (from outer to inner):
file
namespace Lightmass
function FFinalGatherSample FStaticLightingSystem::CachePointIncomingRadiance
Source code excerpt:
{
// Use irradiance photons for indirect lighting
if (PhotonMappingSettings.bUseIrradiancePhotons)
{
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,
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/LightingSystem.cpp:906
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::ValidateSettings
Source code excerpt:
}
#if LIGHTMASS_DO_PROCESSING
if (!InScene.PhotonMappingSettings.bUseIrradiancePhotons)
#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)
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/LightingSystem.cpp:988
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 Cache Indirect Photon Paths\n"), 100.0f * Stats.CachingIndirectPhotonPathsTime / TotalStaticLightingTime, Stats.CachingIndirectPhotonPathsTime);
SolverStats += FString::Printf( TEXT("%4.1f%%%8.1fs Emit Indirect Photons\n"), 100.0f * Stats.EmitIndirectPhotonsTime / TotalStaticLightingTime, Stats.EmitIndirectPhotonsTime);
if (PhotonMappingSettings.bUseIrradiancePhotons)
{
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);
}
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/LightingSystem.cpp:1037
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") );
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/LightingSystem.cpp:1208
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::ValidateSettings
function void FStaticLightingSystem::DumpStats
Source code excerpt:
SolverStats += FString::Printf( TEXT("%.3f million Photon Gathers, %.3f million Irradiance Photon Gathers\n"), Stats.NumPhotonGathers / 1000000.0f, Stats.NumIrradiancePhotonMapSearches / 1000000.0f);
SolverStats += FString::Printf( TEXT("%.3f million Importance Photons found, %.3f million Importance Photon PDF calculations\n"), Stats.TotalFoundImportancePhotons / 1000000.0f, Stats.NumImportancePDFCalculations / 1000000.0f);
if (PhotonMappingSettings.bUseIrradiancePhotons && Stats.IrradiancePhotonCalculatingTime / TotalStaticLightingTime > .02)
{
SolverStats += FString::Printf( TEXT("%.3f million Irradiance Photons, %.1f%% Direct, %.1f%% Indirect, %.3f million actually found\n"), Stats.NumIrradiancePhotons / 1000000.0f, 100.0f * Stats.NumDirectIrradiancePhotons / Stats.NumIrradiancePhotons, 100.0f * (Stats.NumIrradiancePhotons - Stats.NumDirectIrradiancePhotons) / Stats.NumIrradiancePhotons, Stats.NumFoundIrradiancePhotons / 1000000.0f);
const float IterationsPerSearch = Stats.CalculateIrradiancePhotonStats.NumSearchIterations / (float)Stats.CalculateIrradiancePhotonStats.NumIterativePhotonMapSearches;
if (Stats.CalculateIrradiancePhotonStats.NumIterativePhotonMapSearches > 0)
{
SolverStats += FString::Printf( TEXT("%.1f Irradiance calculating search iterations per search (%.3f million searches, %.3f million iterations)\n"), IterationsPerSearch, Stats.CalculateIrradiancePhotonStats.NumIterativePhotonMapSearches / 1000000.0f, Stats.CalculateIrradiancePhotonStats.NumSearchIterations / 1000000.0f);
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:158
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::EmitPhotons
Source code excerpt:
LogSolverMessage(FString::Printf(TEXT("EmitIndirectPhotons complete, %.3f million photons emitted in %.1f seconds"), Stats.NumSecondPassPhotonsEmitted / 1000000.0f, Stats.EmitIndirectPhotonsTime));
if (PhotonMappingSettings.bUseIrradiancePhotons)
{
// Process all irradiance photons and mark ones that have direct photons nearby,
// So that we can search for those with a smaller radius when using them for rendering.
// This allows more accurate direct shadow transitions with irradiance photons.
MarkIrradiancePhotons(ImportanceVolumeBounds, mIrradiancePhotons);
const double EndMarkIrradiancePhotonsTime = FPlatformTime::Seconds();
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:304
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::EmitDirectPhotons
Source code excerpt:
}
if (PhotonMappingSettings.bUseIrradiancePhotons && PhotonMappingSettings.bUsePhotonDirectLightingInFinalGather)
{
for (int32 PhotonIndex = 0; PhotonIndex < CurrentOutput.IrradiancePhotons->Num(); PhotonIndex++)
{
// Add the irradiance photons to an octree
IrradiancePhotonMap.AddElement(FIrradiancePhotonElement(PhotonIndex, *CurrentOutput.IrradiancePhotons));
}
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:349
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::EmitDirectPhotons
Source code excerpt:
|| PhotonMappingSettings.bUseFinalGathering && GeneralSettings.ViewSingleBounceNumber == 1)
{
if (PhotonMappingSettings.bUseIrradiancePhotons)
{
int32 NumDirectIrradiancePhotons = 0;
for (int32 ArrayIndex = 0; ArrayIndex < IrradiancePhotons.Num(); ArrayIndex++)
{
NumDirectIrradiancePhotons += IrradiancePhotons[ArrayIndex].Num();
}
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:480
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::EmitDirectPhotonsWorkRange
Source code excerpt:
Output.IndirectPathRays[LightIndex].Empty(WorkRange.TargetNumIndirectPhotonPaths);
}
if (PhotonMappingSettings.bUseIrradiancePhotons)
{
// Attempt to preallocate irradiance photons based on the percentage of photons that go into the irradiance photon map.
// The actual number of irradiance photons is based on probability.
Output.IrradiancePhotons->Empty(FMath::TruncToInt(DirectIrradiancePhotonFraction * DirectPhotonEfficiency * WorkRange.NumDirectPhotonsToEmit));
}
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:586
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::EmitDirectPhotonsWorkRange
Source code excerpt:
Output.DirectPhotons.Add(NewPhoton);
Output.NumPhotonsEmittedDirect = Output.NumPhotonsEmitted;
if (PhotonMappingSettings.bUseIrradiancePhotons
// Create an irradiance photon for a fraction of the direct photons
&& RandomStream.GetFraction() < DirectIrradiancePhotonFraction)
{
const FIrradiancePhoton NewIrradiancePhoton(PathIntersection.IntersectionVertex.WorldPosition, PathIntersection.IntersectionVertex.WorldTangentZ, true);
Output.IrradiancePhotons->Add(NewIrradiancePhoton);
}
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:781
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::EmitIndirectPhotons
Source code excerpt:
}
if (PhotonMappingSettings.bUseIrradiancePhotons)
{
for (int32 PhotonIndex = 0; PhotonIndex < CurrentOutput.IrradiancePhotons->Num(); PhotonIndex++)
{
// Add the irradiance photons to an octree
IrradiancePhotonMap.AddElement(FIrradiancePhotonElement(PhotonIndex, *CurrentOutput.IrradiancePhotons));
}
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:831
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::EmitIndirectPhotons
Source code excerpt:
#if ALLOW_LIGHTMAP_SAMPLE_DEBUGGING
if (PhotonMappingSettings.bVisualizePhotonPaths
&& PhotonMappingSettings.bUseIrradiancePhotons
&& GeneralSettings.ViewSingleBounceNumber != 0)
{
int32 NumIndirectIrradiancePhotons = 0;
for (int32 RangeIndex = NumPhotonWorkRanges; RangeIndex < IrradiancePhotons.Num(); RangeIndex++)
{
NumIndirectIrradiancePhotons += IrradiancePhotons[RangeIndex].Num();
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:930
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::EmitIndirectPhotonsWorkRange
Source code excerpt:
Output.FirstBounceEscapedPhotons.Empty(FMath::TruncToInt(WorkRange.NumIndirectPhotonsToEmit * .6f * IndirectPhotonEfficiency * PhotonMappingSettings.GeneratePhotonSegmentChance));
Output.SecondBouncePhotons.Empty(FMath::TruncToInt(WorkRange.NumIndirectPhotonsToEmit * .4f * IndirectPhotonEfficiency));
if (PhotonMappingSettings.bUseIrradiancePhotons)
{
// Attempt to preallocate irradiance photons based on the percentage of photons that go into the irradiance photon map.
// The actual number of irradiance photons is based on probability.
Output.IrradiancePhotons->Empty(FMath::TruncToInt(IndirectIrradiancePhotonFraction * IndirectPhotonEfficiency * WorkRange.NumIndirectPhotonsToEmit));
}
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:1070
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::EmitIndirectPhotonsWorkRange
Source code excerpt:
#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)
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:1084
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::EmitIndirectPhotonsWorkRange
Source code excerpt:
#endif
// Create an irradiance photon for a fraction of the deposited photons
if (PhotonMappingSettings.bUseIrradiancePhotons
&& bShouldCreateIrradiancePhoton
&& RandomStream.GetFraction() < IndirectIrradiancePhotonFraction)
{
const FIrradiancePhoton NewIrradiancePhoton(NewPhoton.GetPosition(), PathIntersection.IntersectionVertex.WorldTangentZ, false);
Output.IrradiancePhotons->Add(NewIrradiancePhoton);
}
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:1218
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::MarkIrradiancePhotons
Source code excerpt:
void FStaticLightingSystem::MarkIrradiancePhotons(const FBoxSphereBounds3f& ImportanceBounds, TArray<TArray<FIrradiancePhoton>>& IrradiancePhotons)
{
check(PhotonMappingSettings.bUseIrradiancePhotons);
GSwarm->SendMessage( NSwarm::FTimingMessage( NSwarm::PROGSTATE_Preparing2, 0 ) );
// Setup work ranges for processing the irradiance photons
IrradianceMarkWorkRanges.Empty(IrradiancePhotons.Num());
for (int32 WorkRange = 0; WorkRange < IrradiancePhotons.Num(); WorkRange++)
{
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/PhotonMapping.cpp:1349
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::CalculateIrradiancePhotons
Source code excerpt:
void FStaticLightingSystem::CalculateIrradiancePhotons(const FBoxSphereBounds3f& ImportanceBounds, TArray<TArray<FIrradiancePhoton>>& IrradiancePhotons)
{
check(PhotonMappingSettings.bUseIrradiancePhotons);
//@todo - add a preparing stage for the swarm visualizer
//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.
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/TextureMapping.cpp:651
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::FinalizeSurfaceCacheTextureMapping
Source code excerpt:
if ((GeneralSettings.ViewSingleBounceNumber < 0 || GeneralSettings.ViewSingleBounceNumber >= 2)
&& !ImportanceTracingSettings.bUseRadiositySolverForLightMultibounce
&& PhotonMappingSettings.bUseIrradiancePhotons)
{
const FIrradiancePhoton* NearestPhoton = TextureMapping->CachedIrradiancePhotons[SurfaceCacheIndex];
if (NearestPhoton)
{
// The irradiance photon contains 2nd and up bounce lighting for point / spot / directional lights (since they emit photons)
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/TextureMapping.cpp:2771
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::CalculateDirectLightingTextureMappingPhotonMap
Source code excerpt:
FStaticLightingVertex CurrentVertex = TexelToVertex.GetVertex();
if (PhotonMappingSettings.bUseIrradiancePhotons)
{
FLinearColor DirectLighting;
const FIrradiancePhoton* NearestPhoton = NULL;
if (PhotonMappingSettings.bCacheIrradiancePhotonsOnSurfaces)
{
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Public/SceneExport.h:586
Scope (from outer to inner):
file
namespace Lightmass
class class FPhotonMappingSettings
Source code excerpt:
/** Debugging - whether to use the optimization of caching irradiance calculations in deposited photons (called Irradiance photons). */
bool bUseIrradiancePhotons;
/**
* Debugging - whether to cache the result of the search for the nearest irradiance photon on surfaces.
* This results in a constant time lookup at the end of each final gather ray instead of a photon map search.
* Only visible photons are cached, which reduces light leaking.
*/