VisibilityRayOffsetDistance

VisibilityRayOffsetDistance

#Overview

name: VisibilityRayOffsetDistance

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

#Summary

#Usage in the C++ source code

The purpose of VisibilityRayOffsetDistance is to prevent incorrect self-shadowing due to floating-point precision in Unreal Engine’s static lighting system.

This setting variable is primarily used in the Lightmass subsystem, which is responsible for generating static lighting in Unreal Engine. It is referenced in various parts of the lighting calculation process, including direct and indirect lighting, photon mapping, and shadow calculations.

The value of this variable is typically set in the Lightmass configuration file (GLightmassIni) under the “DevOptions.StaticLightingSceneConstants” section. It is read and applied in the FLightmassExporter::WriteSceneSettings function.

VisibilityRayOffsetDistance interacts closely with other visibility-related variables, such as VisibilityNormalOffsetDistance and VisibilityNormalOffsetSampleRadiusScale. These variables work together to fine-tune the ray tracing process for visibility calculations.

Developers must be aware that this variable directly affects the accuracy and quality of static lighting calculations. Adjusting this value can help resolve self-shadowing artifacts, but setting it too high might introduce other visual issues.

Best practices when using this variable include:

  1. Keep the value as low as possible while still preventing self-shadowing artifacts.
  2. Test thoroughly after making changes, as it can affect the overall lighting quality.
  3. Consider the scale of your scene when adjusting this value, as it is in world space units.
  4. Use in conjunction with other visibility-related settings for optimal results.
  5. Document any custom values used in your project for consistency across the development team.

#Setting Variables

#References In INI files

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

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

Scope (from outer to inner):

file
function     void FLightmassExporter::WriteSceneSettings

Source code excerpt:

		VERIFYLIGHTMASSINI(GConfig->GetFloat(TEXT("DevOptions.StaticLightingSceneConstants"), TEXT("StaticLightingLevelScale"), GlobalLevelScale, GLightmassIni));
		Scene.SceneConstants.StaticLightingLevelScale = GlobalLevelScale * LevelSettings.StaticLightingLevelScale;
		VERIFYLIGHTMASSINI(GConfig->GetFloat(TEXT("DevOptions.StaticLightingSceneConstants"), TEXT("VisibilityRayOffsetDistance"), Scene.SceneConstants.VisibilityRayOffsetDistance, GLightmassIni));
		VERIFYLIGHTMASSINI(GConfig->GetFloat(TEXT("DevOptions.StaticLightingSceneConstants"), TEXT("VisibilityNormalOffsetDistance"), Scene.SceneConstants.VisibilityNormalOffsetDistance, GLightmassIni));
		VERIFYLIGHTMASSINI(GConfig->GetFloat(TEXT("DevOptions.StaticLightingSceneConstants"), TEXT("VisibilityNormalOffsetSampleRadiusScale"), Scene.SceneConstants.VisibilityNormalOffsetSampleRadiusScale, GLightmassIni));
		VERIFYLIGHTMASSINI(GConfig->GetFloat(TEXT("DevOptions.StaticLightingSceneConstants"), TEXT("VisibilityTangentOffsetSampleRadiusScale"), Scene.SceneConstants.VisibilityTangentOffsetSampleRadiusScale, GLightmassIni));
		VERIFYLIGHTMASSINI(GConfig->GetFloat(TEXT("DevOptions.StaticLightingSceneConstants"), TEXT("SmallestTexelRadius"), Scene.SceneConstants.SmallestTexelRadius, GLightmassIni));
		VERIFYLIGHTMASSINI(GConfig->GetInt(TEXT("DevOptions.StaticLightingSceneConstants"), TEXT("LightGridSize"), Scene.SceneConstants.LightGridSize, GLightmassIni));
	}

#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/ImportExport/LightmassScene.cpp:511

Scope (from outer to inner):

file
namespace    Lightmass
function     void FScene::ApplyStaticLightingScale

Source code excerpt:

{
	// Scale world space distances directly
	SceneConstants.VisibilityRayOffsetDistance *= SceneConstants.StaticLightingLevelScale;
	SceneConstants.VisibilityNormalOffsetDistance *= SceneConstants.StaticLightingLevelScale;
	SceneConstants.SmallestTexelRadius *= SceneConstants.StaticLightingLevelScale;
	MeshAreaLightSettings.MeshAreaLightSimplifyCornerDistanceThreshold *= SceneConstants.StaticLightingLevelScale;
	MeshAreaLightSettings.MeshAreaLightGeneratedDynamicLightSurfaceOffset *= SceneConstants.StaticLightingLevelScale;
	DynamicObjectSettings.FirstSurfaceSampleLayerHeight *= SceneConstants.StaticLightingLevelScale;
	DynamicObjectSettings.SurfaceLightSampleSpacing *= SceneConstants.StaticLightingLevelScale;

#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/Collision.cpp:389

Scope (from outer to inner):

file
namespace    Lightmass
function     bool FDefaultAggregateMesh::IntersectLightRay

Source code excerpt:

			NumIterativeIntersections++;
			// Clip the ray so it is now from the intersection point (plus some amount to avoid intersecting the same triangle again) to the original end of the ray
			ClippedLightRay.ClipAgainstIntersectionFromEnd(ClosestIntersection.IntersectionVertex.WorldPosition + Scene.SceneConstants.VisibilityRayOffsetDistance * ClippedLightRay.Direction.GetUnsafeNormal3());
			
			if ((ClosestIntersection.Mesh == LightRay.Mesh && ((ClosestIntersection.Mesh->LightingFlags & GI_INSTANCE_SELFSHADOWDISABLE) || (LightRay.TraceFlags & LIGHTRAY_SELFSHADOWDISABLE)))
				|| (bDirectShadowingRay && ClosestIntersection.Mesh->IsIndirectlyShadowedOnly(ClosestIntersection.ElementIndex))
				|| (ClosestIntersection.Mesh != LightRay.Mesh && (ClosestIntersection.Mesh->LightingFlags & GI_INSTANCE_SELFSHADOWONLY))
				|| !ClosestIntersection.Mesh->IsSurfaceDomain(ClosestIntersection.ElementIndex))
			{

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

Scope (from outer to inner):

file
namespace    Lightmass
function     void FStaticLightingSystem::IntersectLightRays

Source code excerpt:

		// The offset along the normal is to push self-intersection patterns (like triangle shape) on highly curved surfaces onto the backfaces.
		FVector3f RayStart = Vertex.WorldPosition
			+ WorldPathDirection * SceneConstants.VisibilityRayOffsetDistance
			+ Vertex.WorldTangentZ * RayStartNormalBiasScale * SampleRadius
			+ SampleOffset;

		OutLightRays[RayIndex] = FLightRay(
			RayStart,
			Vertex.WorldPosition + WorldPathDirection * MaxRayDistance,

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

Scope (from outer to inner):

file
namespace    Lightmass
function     void FStaticLightingSystem::ValidateSettings
function     bool FStaticLightingSystem::CalculatePointShadowing

Source code excerpt:

			const FVector4f LightVector = LightPosition - WorldSurfacePoint * Light->Position.W;
			const FLightRay LightRay(
				WorldSurfacePoint + LightVector.GetSafeNormal() * SceneConstants.VisibilityRayOffsetDistance,
				WorldSurfacePoint + LightVector,
				Mapping,
				Light
				);

			// Check the line segment for intersection with the static lighting meshes.

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

Scope (from outer to inner):

file
namespace    Lightmass
function     void FStaticLightingSystem::ValidateSettings
function     FVector2f FStaticLightingSystem::CalculatePointAreaShadowing

Source code excerpt:

				// Offset the start of the ray by some fraction along the direction of the ray and some fraction along the vertex normal.
				Vertex.WorldPosition 
					+ LightVector.GetSafeNormal() * SceneConstants.VisibilityRayOffsetDistance 
					+ NormalForOffset * SampleRadius * SceneConstants.VisibilityNormalOffsetSampleRadiusScale 
					+ SampleOffset,
				Vertex.WorldPosition + LightVector,
				Mapping,
				Light
				);

#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/LightingSystem.inl:140

Scope (from outer to inner):

file
function     void FStaticLightingSystem::CalculateApproximateDirectLighting

Source code excerpt:

					FVector4f NormalForOffset = Vertex.WorldTangentZ;

					const FVector4f StartOffset = LightVector.GetSafeNormal() * SceneConstants.VisibilityRayOffsetDistance
						+ NormalForOffset * SampleRadius * SceneConstants.VisibilityNormalOffsetSampleRadiusScale;

					const FLightRay LightRay(
						// Offset the start of the ray by some fraction along the direction of the ray and some fraction along the vertex normal.
						Vertex.WorldPosition
						+ StartOffset,

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

Scope (from outer to inner):

file
namespace    Lightmass
function     void FStaticLightingSystem::EmitDirectPhotonsWorkRange

Source code excerpt:


				const FVector4f RayStart = IntersectionVertexWithTangents.WorldPosition 
					+ NewWorldPathDirection * SceneConstants.VisibilityRayOffsetDistance 
					+ IntersectionVertexWithTangents.WorldTangentZ * SceneConstants.VisibilityNormalOffsetDistance;
				const FVector4f RayEnd = IntersectionVertexWithTangents.WorldPosition + NewWorldPathDirection * MaxRayDistance;

				FLightRay IndirectSampleRay(
					RayStart,
					RayEnd,

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

Scope (from outer to inner):

file
namespace    Lightmass
function     void FStaticLightingSystem::EmitIndirectPhotonsWorkRange

Source code excerpt:


			const FVector4f RayStart = IntersectionVertexWithTangents.WorldPosition 
				+ NewWorldPathDirection * SceneConstants.VisibilityRayOffsetDistance 
				+ IntersectionVertexWithTangents.WorldTangentZ * SceneConstants.VisibilityNormalOffsetDistance;
			FVector4f RayEnd = IntersectionVertexWithTangents.WorldPosition + NewWorldPathDirection * MaxRayDistance;

			// Clip photon path end points to the importance volume, so we do not bother tracing rays outside the area that photons can be deposited.
			// If the photon path does not intersect the importance volume at all, it did not originate from inside the volume, so skip to the next photon.
			FVector4f ClippedStart, ClippedEnd;

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

Scope (from outer to inner):

file
namespace    Lightmass
function     FIrradiancePhoton* FStaticLightingSystem::FindNearestIrradiancePhoton

Source code excerpt:

			const FVector4f VertexToPhoton = CurrentPhoton->GetPosition() - Vertex.WorldPosition;
			const FLightRay VertexToPhotonRay(
				Vertex.WorldPosition + VertexToPhoton.GetSafeNormal() * SceneConstants.VisibilityRayOffsetDistance + Vertex.WorldTangentZ * SceneConstants.VisibilityNormalOffsetDistance,
				CurrentPhoton->GetPosition() + CurrentPhoton->GetSurfaceNormal() * SceneConstants.VisibilityNormalOffsetDistance,
				NULL,
				NULL
				);

			MappingContext.Stats.NumIrradiancePhotonSearchRays++;

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

Scope (from outer to inner):

file
namespace    Lightmass
function     void FStaticLightingSystem::CalculateDirectSignedDistanceFieldLightingTextureMappingTextureSpace

Source code excerpt:

						// Offset the start of the ray by some fraction along the direction of the ray and some fraction along the vertex normal.
						TexelToVertex.WorldPosition 
						+ LightVector * SceneConstants.VisibilityRayOffsetDistance 
						+ NormalForOffset * SceneConstants.VisibilityNormalOffsetDistance,
						LightPosition,
						TextureMapping,
						Light
						);

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

Scope: file

Source code excerpt:

									// Offset the start of the ray by some fraction along the direction of the ray and some fraction along the vertex normal.
									HighResSample.GetPosition() 
									+ LightVector * SceneConstants.VisibilityRayOffsetDistance 
									+ NormalForOffset * SceneConstants.VisibilityNormalOffsetDistance,
									LightPosition,
									TextureMapping, 
									Light
									);

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

Scope (from outer to inner):

file
namespace    Lightmass
class        class FStaticLightingSceneConstants

Source code excerpt:

	 * This is used to prevent incorrect self shadowing due to floating point precision.
	 */
	float VisibilityRayOffsetDistance;

	/** 
	 * World space distance to offset the origin of the ray along the direction of the normal.
	 * This is used to push triangle shaped self shadowing artifacts onto the backfaces of curved objects.
	 */
	float VisibilityNormalOffsetDistance;