ShowFlag.VolumeLightingSamples
ShowFlag.VolumeLightingSamples
#Overview
name: ShowFlag.VolumeLightingSamples
This variable is created as a Console Variable (cvar).
- type:
Var
- help:
Allows to override a specific showflag (works in editor and game, \
It is referenced in 17
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of ShowFlag.VolumeLightingSamples is to visualize volume lighting samples used for Global Illumination (GI) on dynamic objects in Unreal Engine 5. This setting variable is primarily related to the rendering system, specifically for debugging and visualizing lighting information.
The Unreal Engine subsystems and modules that rely on this setting variable include:
- The Renderer module
- The Lighting system
- The Static Lighting system
- The Lightmass system (for pre-computed lighting)
The value of this variable is typically set in the engine’s configuration files or through the editor’s UI. It can be toggled on or off to enable or disable the visualization of volume lighting samples.
This variable interacts with other lighting-related variables and systems, such as:
- The Indirect Lighting Cache
- Precomputed Light Volumes
- Dynamic object lighting settings
Developers should be aware of the following when using this variable:
- It is primarily intended for debugging and visualization purposes.
- Enabling this flag may impact performance, especially in complex scenes with many lighting samples.
- It is fixed in shipping builds, meaning it cannot be toggled in release versions of the game.
Best practices when using this variable include:
- Use it during development and lighting setup to ensure proper placement and distribution of volume lighting samples.
- Disable it in production builds to avoid performance overhead.
- Combine it with other visualization tools to get a comprehensive understanding of the scene’s lighting.
Regarding the associated variable VolumeLightingSamples:
The purpose of VolumeLightingSamples is to store and manage the actual volume lighting sample data used for Global Illumination on dynamic objects. This variable is used in various parts of the engine, including:
- The Lightmass processor for importing volume samples
- The Static Lighting system for generating and processing volume samples
- The Lightmass solver for exporting volume lighting samples
The value of this variable is set during the lightmass computation process and is used throughout the rendering pipeline.
Developers should be aware that:
- This variable contains important lighting data and should be handled carefully.
- It is used in both editor-time lightmass calculations and runtime rendering.
- The data stored in this variable can be significant in size, especially for large and complex scenes.
Best practices for working with VolumeLightingSamples include:
- Ensure proper memory management when working with large datasets.
- Optimize the number and distribution of volume lighting samples to balance quality and performance.
- Use the visualization tools (like ShowFlag.VolumeLightingSamples) to verify the correctness and efficiency of the volume lighting samples.
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:329
Scope: file
Source code excerpt:
SHOWFLAG_FIXED_IN_SHIPPING(0, VisualizeVolumetricLightmap, SFG_Visualize, NSLOCTEXT("UnrealEd", "VisualizeVolumetricLightmapSF", "Volumetric Lightmap"))
/** Visualize volume lighting samples used for GI on dynamic objects */
SHOWFLAG_FIXED_IN_SHIPPING(0, VolumeLightingSamples, SFG_Visualize, NSLOCTEXT("UnrealEd", "VolumeLightingSamplesSF", "Volume Lighting Samples"))
/** Render Paper2D sprites, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(Paper2DSprites, SFG_Advanced, NSLOCTEXT("UnrealEd", "Paper2DSpritesSF", "Paper 2D Sprites"))
/** Visualization of distance field AO */
SHOWFLAG_FIXED_IN_SHIPPING(0, VisualizeDistanceFieldAO, SFG_Visualize, NSLOCTEXT("UnrealEd", "VisualizeDistanceFieldAOSF", "Distance Field Ambient Occlusion"))
/** Mesh Distance fields */
SHOWFLAG_FIXED_IN_SHIPPING(0, VisualizeMeshDistanceFields, SFG_Visualize, NSLOCTEXT("UnrealEd", "MeshDistanceFieldsSF", "Mesh DistanceFields"))
#Associated Variable and Callsites
This variable is associated with another variable named VolumeLightingSamples
. They share the same value. See the following C++ source code.
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Lightmass/Lightmass.cpp:3468
Scope (from outer to inner):
file
function void FLightmassProcessor::ImportVolumeSamples
Source code excerpt:
if (Channel >= 0)
{
ReadArray(Channel, GDebugStaticLightingInfo.VolumeLightingSamples);
Swarm.CloseChannel(Channel);
}
}
const FString ChannelName = Lightmass::CreateChannelName(Lightmass::PrecomputedVolumeLightingGuid, Lightmass::LM_VOLUMESAMPLES_VERSION, Lightmass::LM_VOLUMESAMPLES_EXTENSION);
const int32 Channel = Swarm.OpenChannel( *ChannelName, LM_VOLUMESAMPLES_CHANNEL_FLAGS );
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/StaticLightingSystem/StaticLightingDebug.cpp:623
Scope (from outer to inner):
file
function void DrawStaticLightingDebugInfo
Source code excerpt:
}
for (int32 SampleIndex = 0; SampleIndex < GDebugStaticLightingInfo.VolumeLightingSamples.Num(); SampleIndex++)
{
const FDebugVolumeLightingSample& CurrentSample = GDebugStaticLightingInfo.VolumeLightingSamples[SampleIndex];
PDI->DrawPoint(FVector4(CurrentSample.Position), CurrentSample.AverageIncidentRadiance * GEngine->LightingOnlyBrightness, 12.0f, SDPG_World);
}
for (int32 RayIndex = 0; RayIndex < GDebugStaticLightingInfo.PrecomputedVisibilityRays.Num(); RayIndex++)
{
const FDebugStaticLightingRay& CurrentRay = GDebugStaticLightingInfo.PrecomputedVisibilityRays[RayIndex];
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/StaticLightingSystem/StaticLightingPrivate.h:525
Scope: file
Source code excerpt:
TArray<FDebugPhoton> GatheredImportancePhotons;
TArray<FDebugOctreeNode> GatheredPhotonNodes;
TArray<FDebugVolumeLightingSample> VolumeLightingSamples;
TArray<FDebugStaticLightingRay> PrecomputedVisibilityRays;
bool bDirectPhotonValid;
FDebugPhoton GatheredDirectPhoton;
FVector4f TexelCorners[NumTexelCorners];
bool bCornerValid[NumTexelCorners];
float SampleRadius;
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/ImportExport/Exporter.cpp:44
Scope (from outer to inner):
file
namespace Lightmass
function void FLightmassSolverExporter::ExportVolumeLightingSamples
Source code excerpt:
if( ErrorCode >= 0 )
{
WriteArray(DebugOutput.VolumeLightingSamples);
Swarm->CloseCurrentChannel();
}
else
{
UE_LOG(LogLightmass, Log, TEXT("Failed to open volume sample debug output channel!"));
}
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/LightingSystem.cpp:746
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::ExportNonMappingTasks
Source code excerpt:
VolumeBounds.Origin,
VolumeBounds.BoxExtent,
VolumeLightingSamples);
// Release volume lighting samples unless they are being used by the lighting threads for shading
if (!DynamicObjectSettings.bVisualizeVolumeLightInterpolation)
{
VolumeLightingSamples.Empty();
}
// Tell Swarm the task is complete (if we're not in debugging mode).
if ( !IsDebugMode() )
{
FLightmassSwarm* Swarm = GetExporter().GetSwarm();
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/LightingSystem.h:2594
Scope (from outer to inner):
file
namespace Lightmass
class class FStaticLightingSystem
Source code excerpt:
volatile int32 NumVolumeSampleTasksOutstanding;
volatile int32 bShouldExportVolumeSampleData;
/** Bounds that VolumeLightingSamples were generated in. */
FBoxSphereBounds3f VolumeBounds;
/** Octree used for interpolating the volume lighting samples if DynamicObjectSettings.bVisualizeVolumeLightInterpolation is true. */
FVolumeLightingInterpolationOctree VolumeLightingInterpolationOctree;
/** Map from Level Guid to array of volume lighting samples generated. */
TMap<FGuid,TArray<FVolumeLightingSample> > VolumeLightingSamples;
/** All precomputed visibility cells in the scene. Some of these may be processed on other agents. */
TArray<FPrecomputedVisibilityCell> AllPrecomputedVisibilityCells;
/** Threads must acquire this critical section before reading or writing to CompletedStaticShadowDepthMaps. */
FCriticalSection CompletedStaticShadowDepthMapsSync;
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/SampleVolume.cpp:216
Scope (from outer to inner):
file
namespace Lightmass
function void FVolumeSamplePlacementRasterPolicy::ProcessPixel
Source code excerpt:
if (NumBackfacingHits < .3f * UniformHemisphereSamples.Num() * 2)
{
TArray<FVolumeLightingSample>* VolumeLightingSamples = System.VolumeLightingSamples.Find(LevelGuid);
check(VolumeLightingSamples);
// Add a new sample for this layer
VolumeLightingSamples->Add(FVolumeLightingSample(FVector4f(SamplePosition, SampleRadius)));
// Add the sample to the proximity octree so we can avoid placing any more samples nearby
ProximityOctree.AddElement(FVolumeSampleProximityElement(VolumeLightingSamples->Num() - 1, *VolumeLightingSamples));
if (System.DynamicObjectSettings.bVisualizeVolumeLightInterpolation)
{
System.VolumeLightingInterpolationOctree.AddElement(FVolumeSampleInterpolationElement(VolumeLightingSamples->Num() - 1, *VolumeLightingSamples));
}
}
}
}
}
}
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/SampleVolume.cpp:280
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::BeginCalculateVolumeSamples
Source code excerpt:
//@todo - can this be presized more accurately?
VolumeLightingSamples.Empty(FMath::Max<int32>(5000, LandscapeEstimateNum));
FStaticLightingMappingContext MappingContext(nullptr, *this);
// Octree used to keep track of where existing samples have been placed
FVolumeLightingProximityOctree VolumeLightingOctree(VolumeBounds.Origin, VolumeBounds.BoxExtent.GetMax());
// Octree used for interpolating lighting for debugging
VolumeLightingInterpolationOctree = FVolumeLightingInterpolationOctree(VolumeBounds.Origin, VolumeBounds.BoxExtent.GetMax());
// Determine the resolution that the scene should be rasterized at based on SurfaceLightSampleSpacing and the scene's extent
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/SampleVolume.cpp:322
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::BeginCalculateVolumeSamples
Source code excerpt:
{
// Create a new LevelId array if necessary
if (!VolumeLightingSamples.Find(CurrentMesh->LevelGuid))
{
VolumeLightingSamples.Add(CurrentMesh->LevelGuid, TArray<FVolumeLightingSample>());
}
// Tell the rasterizer we are adding samples to this mesh's LevelId
Rasterizer.SetLevelGuid(CurrentMesh->LevelGuid);
// Rasterize all triangles in the mesh
for (int32 TriangleIndex = 0; TriangleIndex < CurrentMesh->NumTriangles; TriangleIndex++)
{
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/SampleVolume.cpp:422
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::BeginCalculateVolumeSamples
Source code excerpt:
// Place the sample in the intersected level, or the persistent level if there was no intersection
const FGuid LevelGuid = Intersection.bIntersects ? Intersection.Mesh->LevelGuid : FGuid(0,0,0,0);
TArray<FVolumeLightingSample>* VolumeLightingSampleArray = VolumeLightingSamples.Find(LevelGuid);
if (!VolumeLightingSampleArray)
{
VolumeLightingSampleArray = &VolumeLightingSamples.Add(LevelGuid, TArray<FVolumeLightingSample>());
}
// Add a sample and set its radius such that its influence touches a diagonal sample on the 3d grid.
VolumeLightingSampleArray->Add(FVolumeLightingSample(FVector4f(SamplePosition, DetailVolumeSpacing * FMath::Sqrt(3.0f))));
VolumeLightingOctree.AddElement(FVolumeSampleProximityElement(VolumeLightingSampleArray->Num() - 1, *VolumeLightingSampleArray));
if (DynamicObjectSettings.bVisualizeVolumeLightInterpolation)
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/SampleVolume.cpp:448
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::BeginCalculateVolumeSamples
Source code excerpt:
Stats.NumDynamicObjectSurfaceSamples = SurfaceSamples;
TArray<FVolumeLightingSample>* UniformVolumeSamples = VolumeLightingSamples.Find(FGuid(0,0,0,0));
if (!UniformVolumeSamples)
{
UniformVolumeSamples = &VolumeLightingSamples.Add(FGuid(0,0,0,0), TArray<FVolumeLightingSample>());
}
const float VolumeSpacingCubed = DynamicObjectSettings.VolumeLightSampleSpacing * DynamicObjectSettings.VolumeLightSampleSpacing * DynamicObjectSettings.VolumeLightSampleSpacing;
int32 RequestedVolumeSamples = FMath::TruncToInt(8.0f * VolumeBounds.BoxExtent.X * VolumeBounds.BoxExtent.Y * VolumeBounds.BoxExtent.Z / VolumeSpacingCubed);
RequestedVolumeSamples = RequestedVolumeSamples == appTruncErrorCode ? INT_MAX : RequestedVolumeSamples;
float EffectiveVolumeSpacing = DynamicObjectSettings.VolumeLightSampleSpacing;
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/SampleVolume.cpp:540
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::ProcessVolumeSamplesTask
Source code excerpt:
float MaxUnoccludedLength = (CombinedVector / UniformHemisphereSamples.Num()).Size3();
TArray<FVolumeLightingSample>& CurrentLevelSamples = VolumeLightingSamples.FindChecked(Task.LevelId);
for (int32 SampleIndex = Task.StartIndex; SampleIndex < Task.StartIndex + Task.NumSamples; SampleIndex++)
{
FVolumeLightingSample& CurrentSample = CurrentLevelSamples[SampleIndex];
if (GeneralSettings.NumIndirectLightingBounces > 0
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/SampleVolume.cpp:571
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingSystem::ProcessVolumeSamplesTask
Source code excerpt:
FSHVectorRGB3 IncidentRadiance;
CurrentSample.ToSHVector(IncidentRadiance);
VolumeLightingDebugOutput.VolumeLightingSamples.Add(FDebugVolumeLightingSample(CurrentSample.PositionAndRadius, IncidentRadiance.CalcIntegral() / FSHVector2::ConstantBasisIntegral));
}
#endif
}
MappingContext.Stats.TotalVolumeSampleLightingThreadTime += FPlatformTime::Seconds() - VolumeSampleStartTime;
}
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Public/ImportExport.h:484
Scope (from outer to inner):
file
namespace Lightmass
Source code excerpt:
struct FVolumeLightingDebugOutput
{
TArray<FDebugVolumeLightingSample> VolumeLightingSamples;
};
/** Guid used by Unreal to determine when the volume lighting debug channel with the same Guid can be opened. */
static const FGuid VolumeLightingDebugOutputGuid = FGuid(0x1e8119ff, 0xa46f48f8, 0x92b18d49, 0x172c5832);
/** Guid used by Unreal to determine when the volume lighting sample channel with the same Guid can be opened. */
static const FGuid PrecomputedVolumeLightingGuid = FGuid(0xce97c5c3, 0xab614fd3, 0xb2da55c0, 0xe6c33fb4);
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:329
Scope: file
Source code excerpt:
SHOWFLAG_FIXED_IN_SHIPPING(0, VisualizeVolumetricLightmap, SFG_Visualize, NSLOCTEXT("UnrealEd", "VisualizeVolumetricLightmapSF", "Volumetric Lightmap"))
/** Visualize volume lighting samples used for GI on dynamic objects */
SHOWFLAG_FIXED_IN_SHIPPING(0, VolumeLightingSamples, SFG_Visualize, NSLOCTEXT("UnrealEd", "VolumeLightingSamplesSF", "Volume Lighting Samples"))
/** Render Paper2D sprites, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(Paper2DSprites, SFG_Advanced, NSLOCTEXT("UnrealEd", "Paper2DSpritesSF", "Paper 2D Sprites"))
/** Visualization of distance field AO */
SHOWFLAG_FIXED_IN_SHIPPING(0, VisualizeDistanceFieldAO, SFG_Visualize, NSLOCTEXT("UnrealEd", "VisualizeDistanceFieldAOSF", "Distance Field Ambient Occlusion"))
/** Mesh Distance fields */
SHOWFLAG_FIXED_IN_SHIPPING(0, VisualizeMeshDistanceFields, SFG_Visualize, NSLOCTEXT("UnrealEd", "MeshDistanceFieldsSF", "Mesh DistanceFields"))
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/IndirectLightingCache.cpp:596
Scope (from outer to inner):
file
function void FIndirectLightingCache::FinalizeUpdateInternal_RenderThread
Source code excerpt:
}
if (GCacheDrawLightingSamples || Renderer.ViewFamily.EngineShowFlags.VolumeLightingSamples || GCacheDrawDirectionalShadowing)
{
FViewElementPDI DebugPDI(&Renderer.Views[0], nullptr, &Renderer.Views[0].DynamicPrimitiveCollector);
for (int32 VolumeIndex = 0; VolumeIndex < Scene->PrecomputedLightVolumes.Num(); VolumeIndex++)
{
const FPrecomputedLightVolume* PrecomputedLightVolume = Scene->PrecomputedLightVolumes[VolumeIndex];