NumHemisphereSamples

NumHemisphereSamples

#Overview

name: NumHemisphereSamples

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

#Summary

#Usage in the C++ source code

The purpose of NumHemisphereSamples is to control the number of samples taken when performing importance tracing in Unreal Engine’s lighting system. This setting is primarily used for global illumination calculations and affects the quality and performance of indirect lighting computations.

NumHemisphereSamples is primarily used by the Lightmass system, which is Unreal Engine’s global illumination solution. It is part of the lighting and rendering subsystem, specifically the static lighting computation module.

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

This variable interacts with several other settings, including:

  1. GeneralSettings.IndirectLightingQuality
  2. PhotonMappingSettings.FinalGatherImportanceSampleFraction
  3. DynamicObjectSettings.NumHemisphereSamplesScale

Developers should be aware that:

  1. Increasing NumHemisphereSamples will improve lighting quality but also increase computation time.
  2. The actual number of samples used may be scaled based on other settings, such as IndirectLightingQuality.
  3. This setting affects both importance sampling and uniform sampling strategies.

Best practices when using this variable include:

  1. Balance quality and performance by adjusting this value in conjunction with other related settings.
  2. Consider the scene complexity and desired lighting quality when setting this value.
  3. Use higher values for final builds and lower values for iterative development to speed up lighting calculations.
  4. Test different values to find the optimal balance between quality and performance for your specific project.

#Setting Variables

#References In INI files

Location: <Workspace>/Engine/Config/BaseLightmass.ini:155, section: [DevOptions.ImportanceTracing]

#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:2327

Scope (from outer to inner):

file
function     void FLightmassExporter::WriteSceneSettings

Source code excerpt:

		VERIFYLIGHTMASSINI(GConfig->GetBool(TEXT("DevOptions.ImportanceTracing"), TEXT("bUseStratifiedSampling"), bConfigBool, GLightmassIni));
		Scene.ImportanceTracingSettings.bUseStratifiedSampling = bConfigBool;
		VERIFYLIGHTMASSINI(GConfig->GetInt(TEXT("DevOptions.ImportanceTracing"), TEXT("NumHemisphereSamples"), Scene.ImportanceTracingSettings.NumHemisphereSamples, GLightmassIni));
		VERIFYLIGHTMASSINI(GConfig->GetInt(TEXT("DevOptions.ImportanceTracing"), TEXT("NumAdaptiveRefinementLevels"), Scene.ImportanceTracingSettings.NumAdaptiveRefinementLevels, GLightmassIni));
		float MaxHemisphereAngleDegrees;
		VERIFYLIGHTMASSINI(GConfig->GetFloat(TEXT("DevOptions.ImportanceTracing"), TEXT("MaxHemisphereRayAngle"), MaxHemisphereAngleDegrees, GLightmassIni));
		Scene.ImportanceTracingSettings.MaxHemisphereRayAngle = MaxHemisphereAngleDegrees * (float)PI / 180.0f;
		VERIFYLIGHTMASSINI(GConfig->GetFloat(TEXT("DevOptions.ImportanceTracing"), TEXT("AdaptiveBrightnessThreshold"), Scene.ImportanceTracingSettings.AdaptiveBrightnessThreshold, GLightmassIni));
		VERIFYLIGHTMASSINI(GConfig->GetFloat(TEXT("DevOptions.ImportanceTracing"), TEXT("AdaptiveFirstBouncePhotonConeAngle"), Scene.ImportanceTracingSettings.AdaptiveFirstBouncePhotonConeAngle, GLightmassIni));

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Lightmass/Lightmass.cpp:2442

Scope (from outer to inner):

file
function     void FLightmassExporter::WriteSceneSettings

Source code excerpt:

		float NumHemisphereSamplesScale;
		VERIFYLIGHTMASSINI(GConfig->GetFloat(QualitySectionNames[QualityLevel], TEXT("NumHemisphereSamplesScale"), NumHemisphereSamplesScale, GLightmassIni));
		Scene.ImportanceTracingSettings.NumHemisphereSamples = FMath::TruncToInt(Scene.ImportanceTracingSettings.NumHemisphereSamples * NumHemisphereSamplesScale);

		float NumImportanceSearchPhotonsScale;
		VERIFYLIGHTMASSINI(GConfig->GetFloat(QualitySectionNames[QualityLevel], TEXT("NumImportanceSearchPhotonsScale"), NumImportanceSearchPhotonsScale, GLightmassIni));
		Scene.PhotonMappingSettings.NumImportanceSearchPhotons = FMath::TruncToInt(Scene.PhotonMappingSettings.NumImportanceSearchPhotons * NumImportanceSearchPhotonsScale);

		float NumDirectPhotonsScale;

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

Scope (from outer to inner):

file
namespace    Lightmass
function     int32 FStaticLightingSystem::GetNumPhotonImportanceHemisphereSamples

Source code excerpt:

{
	return PhotonMappingSettings.bUsePhotonMapping ? 
		FMath::TruncToInt(ImportanceTracingSettings.NumHemisphereSamples * PhotonMappingSettings.FinalGatherImportanceSampleFraction) : 0;
}

FBoxSphereBounds3f FStaticLightingSystem::GetImportanceBounds(bool bClampToScene) const
{
	FBoxSphereBounds3f ImportanceBounds = Scene.GetImportanceBounds();
	

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

Scope (from outer to inner):

file
namespace    Lightmass
function     void FStaticLightingSystem::ValidateSettings

Source code excerpt:

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

	if (InScene.PhotonMappingSettings.bUsePhotonMapping && !InScene.PhotonMappingSettings.bUseFinalGathering)

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

Scope (from outer to inner):

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

Source code excerpt:

	{
		const float NumSamplesFloat = 
			ImportanceTracingSettings.NumHemisphereSamples 
			* GeneralSettings.IndirectLightingQuality;

		NumUniformHemisphereSamples = FMath::TruncToInt(NumSamplesFloat);
	}
	else
	{
		NumUniformHemisphereSamples = ImportanceTracingSettings.NumHemisphereSamples;
	}

	CachedHemisphereSamples.Empty(NumUniformHemisphereSamples);
	CachedHemisphereSampleUniforms.Empty(NumUniformHemisphereSamples);

	if (ImportanceTracingSettings.bUseStratifiedSampling)

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

Scope (from outer to inner):

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

Source code excerpt:

	{
		float SampleSetScale = FMath::Lerp(.5f, .125f, SampleSet / ((float)UE_ARRAY_COUNT(CachedHemisphereSamplesForRadiosity) - 1));
		int32 TargetNumApproximateSkyLightingSamples = FMath::Max(FMath::TruncToInt(ImportanceTracingSettings.NumHemisphereSamples * SampleSetScale * GeneralSettings.IndirectLightingQuality), 12);
		CachedHemisphereSamplesForRadiosity[SampleSet].Empty(TargetNumApproximateSkyLightingSamples);
		CachedHemisphereSamplesForRadiosityUniforms[SampleSet].Empty(TargetNumApproximateSkyLightingSamples);

		const float NumThetaStepsFloat = FMath::Sqrt(TargetNumApproximateSkyLightingSamples / (float)PI);
		const int32 NumThetaSteps = FMath::TruncToInt(NumThetaStepsFloat);
		const int32 NumPhiSteps = FMath::TruncToInt(NumThetaStepsFloat * (float)PI);

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

Scope (from outer to inner):

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

Source code excerpt:


	{
		const int32 NumUpperVolumeSamples = ImportanceTracingSettings.NumHemisphereSamples * DynamicObjectSettings.NumHemisphereSamplesScale;
		const float NumThetaStepsFloat = FMath::Sqrt(NumUpperVolumeSamples / (float)PI);
		const int32 NumThetaSteps = FMath::TruncToInt(NumThetaStepsFloat);
		const int32 NumPhiSteps = FMath::TruncToInt(NumThetaStepsFloat * (float)PI);

		GenerateStratifiedUniformHemisphereSamples(NumThetaSteps, NumPhiSteps, RandomStream, CachedVolumetricLightmapUniformHemisphereSamples, CachedVolumetricLightmapUniformHemisphereSampleUniforms);

#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/SampleVolume.cpp:523

Scope (from outer to inner):

file
namespace    Lightmass
function     void FStaticLightingSystem::ProcessVolumeSamplesTask

Source code excerpt:

	TArray<FVector4f> UniformHemisphereSamples;
	TArray<FVector2f> UniformHemisphereSampleUniforms;
	const int32 NumUpperVolumeSamples = ImportanceTracingSettings.NumHemisphereSamples * DynamicObjectSettings.NumHemisphereSamplesScale;
	// Volume samples don't do any importance sampling so they need more samples for the same amount of variance as surface samples
	const float NumThetaStepsFloat = FMath::Sqrt(NumUpperVolumeSamples / (float)PI);
	const int32 NumThetaSteps = FMath::TruncToInt(NumThetaStepsFloat);
	const int32 NumPhiSteps = FMath::TruncToInt(NumThetaStepsFloat * (float)PI);

	GenerateStratifiedUniformHemisphereSamples(NumThetaSteps, NumPhiSteps, RandomStream, UniformHemisphereSamples, UniformHemisphereSampleUniforms);

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

Scope (from outer to inner):

file
namespace    Lightmass
class        class FImportanceTracingSettings

Source code excerpt:

	 * When photon mapping is enabled, these are called final gather rays.
	 */
	int32 NumHemisphereSamples;

	/** Number of recursive levels allowed for adaptive refinement.  This has a huge impact on build time but also quality. */
	int32 NumAdaptiveRefinementLevels;

	/** 
	 * Largest angle from the sample normal that a hemisphere sample direction can be. 

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

Scope (from outer to inner):

file
namespace    Lightmass
class        class FPhotonMappingSettings

Source code excerpt:


	/** 
	 * Fraction of NumHemisphereSamples to use for importance sampling instead of uniform sampling the final gather.
	 * If this fraction is close to 1, no uniform samples will be done and irradiance caching will be forced off as a result.
	 * If this is 0, only uniform samples will be taken.
	 */
	float FinalGatherImportanceSampleFraction;

	/** Cosine of the cone angle from an importance photon direction to generate ray directions for importance sampled final gathering. */
	float FinalGatherImportanceSampleCosConeAngle;

	/** World space radius of the disk around an indirect photon path in which indirect photons will be emitted from directional lights. */
	float IndirectPhotonEmitDiskRadius;