MeshAreaLightGridSize
MeshAreaLightGridSize
#Overview
name: MeshAreaLightGridSize
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 7
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of MeshAreaLightGridSize is to define the resolution of a grid used for optimizing mesh area light calculations in Unreal Engine’s lighting system. This variable is primarily used in the context of static lighting and global illumination computations.
MeshAreaLightGridSize is utilized by the Lightmass subsystem, which is responsible for precalculating global illumination and static lighting in Unreal Engine. It’s particularly relevant to the mesh area lights feature, which allows emissive materials to act as area light sources.
The value of this variable is typically set in the Lightmass configuration file (GLightmassIni). It’s read from the configuration during the light baking process, specifically in the FLightmassExporter::WriteSceneSettings function.
This variable interacts closely with other mesh area light settings, such as EmissiveIntensityThreshold, MeshAreaLightSimplifyNormalAngleThreshold, and MeshAreaLightSimplifyCornerDistanceThreshold. These settings collectively control how mesh area lights are processed and optimized.
Developers should be aware that increasing the MeshAreaLightGridSize value will result in more accurate light sampling but at the cost of increased precomputation time and memory usage. Conversely, decreasing this value will speed up calculations but may lead to less precise lighting results.
Best practices when using this variable include:
- Balancing performance and quality by adjusting the grid size based on the project’s needs.
- Testing different values to find the optimal balance between lighting quality and build times.
- Considering the complexity of the scene and the number of emissive materials when setting this value.
- Coordinating changes to this variable with other mesh area light settings for consistent results.
- Documenting the chosen value and the reasoning behind it for future reference and team communication.
#Setting Variables
#References In INI files
Location: <Workspace>/Engine/Config/BaseLightmass.ini:69, section: [DevOptions.MeshAreaLights]
- INI Section:
DevOptions.MeshAreaLights
- Raw value:
100
- 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:2232
Scope (from outer to inner):
file
function void FLightmassExporter::WriteSceneSettings
Source code excerpt:
Scene.MeshAreaLightSettings.bVisualizeMeshAreaLightPrimitives = bConfigBool;
VERIFYLIGHTMASSINI(GConfig->GetFloat(TEXT("DevOptions.MeshAreaLights"), TEXT("EmissiveIntensityThreshold"), Scene.MeshAreaLightSettings.EmissiveIntensityThreshold, GLightmassIni));
VERIFYLIGHTMASSINI(GConfig->GetInt(TEXT("DevOptions.MeshAreaLights"), TEXT("MeshAreaLightGridSize"), Scene.MeshAreaLightSettings.MeshAreaLightGridSize, GLightmassIni));
float MeshAreaLightSimplifyNormalAngleThreshold;
VERIFYLIGHTMASSINI(GConfig->GetFloat(TEXT("DevOptions.MeshAreaLights"), TEXT("MeshAreaLightSimplifyNormalAngleThreshold"), MeshAreaLightSimplifyNormalAngleThreshold, GLightmassIni));
Scene.MeshAreaLightSettings.MeshAreaLightSimplifyNormalCosAngleThreshold = FMath::Cos(FMath::Clamp(MeshAreaLightSimplifyNormalAngleThreshold, 0.0f, 90.0f) * (float)PI / 180.0f);
VERIFYLIGHTMASSINI(GConfig->GetFloat(TEXT("DevOptions.MeshAreaLights"), TEXT("MeshAreaLightSimplifyCornerDistanceThreshold"), Scene.MeshAreaLightSettings.MeshAreaLightSimplifyCornerDistanceThreshold, GLightmassIni));
VERIFYLIGHTMASSINI(GConfig->GetFloat(TEXT("DevOptions.MeshAreaLights"), TEXT("MeshAreaLightSimplifyMeshBoundingRadiusFractionThreshold"), Scene.MeshAreaLightSettings.MeshAreaLightSimplifyMeshBoundingRadiusFractionThreshold, GLightmassIni));
VERIFYLIGHTMASSINI(GConfig->GetFloat(TEXT("DevOptions.MeshAreaLights"), TEXT("MeshAreaLightGeneratedDynamicLightSurfaceOffset"), Scene.MeshAreaLightSettings.MeshAreaLightGeneratedDynamicLightSurfaceOffset, GLightmassIni));
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/ImportExport/LightmassScene.cpp:2218
Scope (from outer to inner):
file
namespace Lightmass
function void FMeshAreaLight::SetPrimitives
Source code excerpt:
check(InPrimitives.Num() > 0);
Primitives = InPrimitives;
MeshAreaLightGridSize = InMeshAreaLightGridSize;
LevelGuid = InLevelGuid;
TotalSurfaceArea = 0.0f;
TotalPower = FLinearColor::Black;
Position = FVector4f(0,0,0);
FBox3f Bounds(ForceInit);
CachedPrimitiveNormals.Empty(MeshAreaLightGridSize * MeshAreaLightGridSize);
CachedPrimitiveNormals.AddZeroed(MeshAreaLightGridSize * MeshAreaLightGridSize);
PrimitivePDFs.Empty(Primitives.Num());
for (int32 PrimitiveIndex = 0; PrimitiveIndex < Primitives.Num(); PrimitiveIndex++)
{
const FMeshLightPrimitive& CurrentPrimitive = Primitives[PrimitiveIndex];
TotalSurfaceArea += CurrentPrimitive.SurfaceArea;
TotalPower += CurrentPrimitive.Power;
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/ImportExport/LightmassScene.cpp:2240
Scope (from outer to inner):
file
namespace Lightmass
function void FMeshAreaLight::SetPrimitives
Source code excerpt:
const FVector2f SphericalCoordinates = FVector3f(CurrentPrimitive.SurfaceNormal).UnitCartesianToSpherical();
// Determine grid cell the primitive's normal falls into based on spherical coordinates
const int32 CacheX = FMath::Clamp(FMath::TruncToInt(SphericalCoordinates.X / (float)PI * MeshAreaLightGridSize), 0, MeshAreaLightGridSize - 1);
const int32 CacheY = FMath::Clamp(FMath::TruncToInt((SphericalCoordinates.Y + (float)PI) / (2 * (float)PI) * MeshAreaLightGridSize), 0, MeshAreaLightGridSize - 1);
CachedPrimitiveNormals[CacheY * MeshAreaLightGridSize + CacheX].Add(CurrentPrimitive.SurfaceNormal);
}
for (int32 PhiStep = 0; PhiStep < MeshAreaLightGridSize; PhiStep++)
{
for (int32 ThetaStep = 0; ThetaStep < MeshAreaLightGridSize; ThetaStep++)
{
const TArray<FVector4f>& CurrentCachedNormals = CachedPrimitiveNormals[PhiStep * MeshAreaLightGridSize + ThetaStep];
if (CurrentCachedNormals.Num() > 0)
{
OccupiedCachedPrimitiveNormalCells.Add(FIntPoint(ThetaStep, PhiStep));
}
}
}
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/ImportExport/LightmassScene.cpp:2431
Scope (from outer to inner):
file
namespace Lightmass
function void FMeshAreaLight::SampleDirection
Source code excerpt:
const int32 ThetaStep = OccupiedCachedPrimitiveNormalCells[OccupiedCellIndex].X;
const int32 PhiStep = OccupiedCachedPrimitiveNormalCells[OccupiedCellIndex].Y;
const TArray<FVector4f>& CurrentCachedNormals = CachedPrimitiveNormals[PhiStep * MeshAreaLightGridSize + ThetaStep];
if (CurrentCachedNormals.Num() > 0)
{
bool bAllCornersInSameHemisphere = true;
bool bAllCornersInOppositeHemisphere = true;
// Determine whether the cell is completely in the same hemisphere as the sample direction, completely on the other side or spanning the terminator
// This is done by checking each cell's corners
for (int32 CornerIndex = 0; CornerIndex < UE_ARRAY_COUNT(Corners); CornerIndex++)
{
const float Theta = (ThetaStep + Corners[CornerIndex].X) / (float)MeshAreaLightGridSize * (float)PI;
const float Phi = (PhiStep + Corners[CornerIndex].Y) / (float)MeshAreaLightGridSize * 2 * (float)PI - (float)PI;
// Calculate the cartesian unit direction corresponding to this corner
const FVector4f CurrentCornerDirection = FVector2f(Theta, Phi).SphericalToUnitCartesian();
bAllCornersInSameHemisphere = bAllCornersInSameHemisphere && Dot3(CurrentCornerDirection, SampleDir) > 0.0f;
bAllCornersInOppositeHemisphere = bAllCornersInOppositeHemisphere && Dot3(CurrentCornerDirection, SampleDir) < 0.0f;
}
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/ImportExport/LightmassScene.h:689
Scope (from outer to inner):
file
namespace Lightmass
class class FMeshAreaLight : public FLight
Source code excerpt:
/** Size of the data stored in CachedPrimitiveNormals in each dimension. */
int32 MeshAreaLightGridSize;
FGuid LevelGuid;
/** Grid of arrays of primitive normals, used to accelerate PDF calculation once a sample is generated. */
TArray<TArray<FVector4f> > CachedPrimitiveNormals;
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Private/Lighting/LightingMesh.cpp:487
Scope (from outer to inner):
file
namespace Lightmass
function void FStaticLightingMesh::CreateMeshAreaLights
Source code excerpt:
MaterialElements[MaterialIndex].EmissiveLightFalloffExponent,
MaterialElements[MaterialIndex].EmissiveLightExplicitInfluenceRadius,
Scene.MeshAreaLightSettings.MeshAreaLightGridSize,
LevelGuid);
MeshAreaLights.Add(NewLight);
}
}
}
}
#Loc: <Workspace>/Engine/Source/Programs/UnrealLightmass/Public/SceneExport.h:235
Scope (from outer to inner):
file
namespace Lightmass
Source code excerpt:
* Larger grids take longer to precompute, but result in accelerated light sampling.
*/
int32 MeshAreaLightGridSize;
/** Cosine of the maximum angle allowed between mesh area light primitives that get merged into the same simplified primitive. */
float MeshAreaLightSimplifyNormalCosAngleThreshold;
/** Maximum distance allowed between any mesh area light primitive corners that get merged into the same simplified primitive. */
float MeshAreaLightSimplifyCornerDistanceThreshold;