Lightmass volumetric lightmaps
Key functions:
- CalculateVolumeSampleIncidentRadiance(): Main function
For volumetric irradience brick:
SetFromVolumeLightingSample(): Defines spherical harmonic encoding of what gets stored in the lightmap
C++
/*
 SH directional coefficients can be normalized by their ambient term, and then ranges can be derived from SH projection
 This allows packing into an 8 bit format
 [-1, 1] Normalization factors derived from SHBasisFunction
 Result.V0.x = 0.282095f;
 Result.V0.y = -0.488603f * InputVector.y;
 Result.V0.z = 0.488603f * InputVector.z;
 Result.V0.w = -0.488603f * InputVector.x;
 half3 VectorSquared = InputVector * InputVector;
 Result.V1.x = 1.092548f * InputVector.x * InputVector.y;
 Result.V1.y = -1.092548f * InputVector.y * InputVector.z;
 Result.V1.z = 0.315392f * (3.0f * VectorSquared.z - 1.0f);
 Result.V1.w = -1.092548f * InputVector.x * InputVector.z;
 Result.V2 = 0.546274f * (VectorSquared.x - VectorSquared.y);
 */
 // Note: encoding behavior has to match CPU decoding in InterpolateVolumetricLightmap and GPU decoding in GetVolumetricLightmapSH3
 FLinearColor CoefficientNormalizationScale0(
 0.282095f / 0.488603f,
 0.282095f / 0.488603f,
 0.282095f / 0.488603f,
 0.282095f / 1.092548f);
 FLinearColor CoefficientNormalizationScale1(
 0.282095f / 1.092548f,
 0.282095f / (4.0f * 0.315392f),
 0.282095f / 1.092548f,
 0.282095f / (2.0f * 0.546274f));
 for (int32 ChannelIndex = 0; ChannelIndex < 3; ChannelIndex++)
 {
 const float InvAmbient = 1.0f / FMath::Max(Sample.HighQualityCoefficients[0] [ChannelIndex], .0001f);
const FLinearColor Vector0Normalized =
 FLinearColor(Sample.HighQualityCoefficient [1] [ChannelIndex], Sample.HighQualityCoefficients [2] [ChannelIndex], Sample.HighQualityCoefficients[3] [ChannelIndex], Sample.HighQualityCoefficients [4] [ChannelIndex])
 \* CoefficientNormalizationScale0
 \*FLinearColor(InvAmbient, InvAmbient, InvAmbient, InvAmbient);
 SHCoefficients\[ChannelIndex \* 2 + 0]\[Index] = (Vector0Normalized \* FLinearColor(.5f, .5f, .5f, .5f) + FLinearColor(.5f, .5f, .5f, .5f)).QuantizeRound();
const FLinearColor Vector1Normalized =
FLinearColor(Sample.HighQualityCoefficients\[5]\[ChannelIndex], Sample.HighQualityCoefficients\[6]\[ChannelIndex], Sample.HighQualityCoefficients\[7]\[ChannelIndex], Sample.HighQualityCoefficients\[8]\[ChannelIndex])
\* CoefficientNormalizationScale1
\* FLinearColor(InvAmbient, InvAmbient, InvAmbient, InvAmbient);
SHCoefficients\[ChannelIndex \* 2 + 1]\[Index] = (Vector1Normalized \* FLinearColor(.5f, .5f, .5f, .5f) + FLinearColor(.5f, .5f, .5f, .5f)).QuantizeRound();
}
- 
GatherVolumeImportancePhotonDirections() 
- 
CalculateApproximateDirectLighting() 
- 
IncomingRadianceAdaptive() 
C++
  
    
  
  
    
  
  
  
                
              /**
* Precomputed lighting volumes in the scene, used for interpolating dynamic object lighting.
* These are typically one per streaming level and they store volume lighting samples computed by Lightmass.
*/
TArray<const FPrecomputedLightVolume*> PrecomputedLightVolumes;
/** Interpolates and caches indirect lighting for dynamic objects. */
FIndirectLightingCache IndirectLightingCache;
FVolumetricLightmapSceneData VolumetricLightmapSceneData;
/**
* Represents the Volumetric Lightmap for a specific ULevel.
*/
class FPrecomputedVolumetricLightmap
/**
* The light incident for a point on a surface, in the representation used when gathering lighting.
* This representation is additive, and allows for accumulating lighting contributions in-place.
*/
template <int32 SHOrder>
class TGatheredLightSample
/** Lighting for a point in space. */
class FVolumeLightingSampleData
{
public:
/** World space position and radius. */
FVector4 PositionAndRadius;
/** SH coefficients used with high quality lightmaps. */
float HighQualityCoefficients [LM_NUM_SH_COEFFICIENTS] [3];
/** SH coefficients used with low quality lightmaps. */
float LowQualityCoefficients [LM_NUM_SH_COEFFICIENTS] [3];
FVector SkyBentNormal;
/** Shadow factor for the stationary directional light. */
float DirectionalLightShadowing;
};