533 lines
16 KiB
C++
533 lines
16 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
//#include "CoreMinimal.h"
|
|
//#include "HAL/UnrealMemory.h"
|
|
//#include "Math/UnrealMathUtility.h"
|
|
//#include "Containers/UnrealString.h"
|
|
//#include "Misc/Guid.h"
|
|
//#include "Math/Color.h"
|
|
//#include "Math/Vector.h"
|
|
//#include "Math/Vector4.h"
|
|
//#include "Math/Matrix.h"
|
|
//#include "Math/Float16.h"
|
|
|
|
#include "CoreTypes.h"
|
|
#include "HAL/UnrealMemory.h"
|
|
#include "Containers/Array.h"
|
|
#include "Math/UnrealMathUtility.h"
|
|
#include "Containers/UnrealString.h"
|
|
#include "Math/Color.h"
|
|
#include "Math/Vector.h"
|
|
#include "Math/Vector4.h"
|
|
#include "Math/Matrix.h"
|
|
#include "Math/Float16.h"
|
|
#include "Misc/Guid.h"
|
|
#include "SceneExport.h"
|
|
|
|
struct FDebugLightingCacheRecord;
|
|
struct FDebugLightingOutput;
|
|
struct FDebugOctreeNode;
|
|
struct FDebugPhoton;
|
|
struct FDebugStaticLightingRay;
|
|
struct FDebugStaticLightingVertex;
|
|
struct FDebugVolumeLightingSample;
|
|
|
|
namespace Lightmass
|
|
{
|
|
/** Whether or not to request compression on heavyweight input file types */
|
|
#define LM_COMPRESS_INPUT_DATA 1
|
|
|
|
#define LM_NUM_SH_COEFFICIENTS 9
|
|
|
|
/** The number of coefficients that are stored for each light sample. */
|
|
static const int32 LM_NUM_STORED_LIGHTMAP_COEF = 4;
|
|
/** The number of high quality coefficients which the lightmap stores for each light sample. */
|
|
static const int32 LM_NUM_HQ_LIGHTMAP_COEF = 2;
|
|
/** The index at which low quality coefficients are stored in any array containing all LM_NUM_STORED_LIGHTMAP_COEF coefficients. */
|
|
static const int32 LM_LQ_LIGHTMAP_COEF_INDEX = 2;
|
|
|
|
/** Output channel types (extensions) */
|
|
static const TCHAR LM_TEXTUREMAPPING_EXTENSION[] = TEXT("tmap");
|
|
static const TCHAR LM_VOLUMESAMPLES_EXTENSION[] = TEXT("vols");
|
|
static const TCHAR LM_VOLUMEDEBUGOUTPUT_EXTENSION[] = TEXT("vold");
|
|
static const TCHAR LM_VOLUMETRICLIGHTMAP_EXTENSION[] = TEXT("irvol");
|
|
static const TCHAR LM_PRECOMPUTEDVISIBILITY_EXTENSION[] = TEXT("vis");
|
|
static const TCHAR LM_DOMINANTSHADOW_EXTENSION[] = TEXT("doms");
|
|
static const TCHAR LM_MESHAREALIGHTDATA_EXTENSION[] = TEXT("arealights");
|
|
static const TCHAR LM_DEBUGOUTPUT_EXTENSION[] = TEXT("dbgo");
|
|
|
|
/** Input channel types (extensions) */
|
|
#if LM_COMPRESS_INPUT_DATA
|
|
static const TCHAR LM_SCENE_EXTENSION[] = TEXT("scenegz");
|
|
static const TCHAR LM_STATICMESH_EXTENSION[] = TEXT("meshgz");
|
|
static const TCHAR LM_MATERIAL_EXTENSION[] = TEXT("mtrlgz");
|
|
#else
|
|
static const TCHAR LM_SCENE_EXTENSION[] = TEXT("scene");
|
|
static const TCHAR LM_STATICMESH_EXTENSION[] = TEXT("mesh");
|
|
static const TCHAR LM_MATERIAL_EXTENSION[] = TEXT("mtrl");
|
|
#endif
|
|
|
|
/**
|
|
* Channel versions
|
|
* Adding a new guid for any of these forces re-exporting of that data type.
|
|
* This must be done whenever modifying code that changes how each data type is exported!
|
|
*/
|
|
|
|
static const int32 LM_TEXTUREMAPPING_VERSION = 2;
|
|
static const int32 LM_VOLUMESAMPLES_VERSION = 2;
|
|
static const int32 LM_VOLUMETRICLIGHTMAP_VERSION = 4;
|
|
static const int32 LM_PRECOMPUTEDVISIBILITY_VERSION = 2;
|
|
static const int32 LM_VOLUMEDEBUGOUTPUT_VERSION = 2;
|
|
static const int32 LM_DOMINANTSHADOW_VERSION = 2;
|
|
static const int32 LM_MESHAREALIGHTDATA_VERSION = 2;
|
|
static const int32 LM_DEBUGOUTPUT_VERSION = 2;
|
|
static const int32 LM_SCENE_VERSION = 2;
|
|
static const int32 LM_STATICMESH_VERSION = 2;
|
|
static const int32 LM_MATERIAL_VERSION = 2;
|
|
|
|
|
|
/** Alert source object type identifiers... */
|
|
enum ESourceObjectType
|
|
{
|
|
SOURCEOBJECTTYPE_Unknown = 0,
|
|
SOURCEOBJECTTYPE_Scene,
|
|
SOURCEOBJECTTYPE_Material,
|
|
SOURCEOBJECTTYPE_BSP,
|
|
SOURCEOBJECTTYPE_StaticMesh,
|
|
SOURCEOBJECTTYPE_Fluid,
|
|
SOURCEOBJECTTYPE_SpeedTree,
|
|
SOURCEOBJECTTYPE_TextureMapping,
|
|
SOURCEOBJECTTYPE_VertexMapping,
|
|
SOURCEOBJECTTYPE_Mapping
|
|
};
|
|
|
|
#if !PLATFORM_MAC && !PLATFORM_LINUX
|
|
#pragma pack(push, 1)
|
|
#endif
|
|
|
|
/**
|
|
* Incident lighting for a single sample, as produced by a lighting build.
|
|
* FGatheredLightSample is used for gathering lighting instead of this format as FLightSampleData is not additive.
|
|
*/
|
|
struct FLightSampleData
|
|
{
|
|
FLightSampleData()
|
|
{
|
|
bIsMapped = false;
|
|
FMemory::Memzero(Coefficients,sizeof(Coefficients));
|
|
SkyOcclusion[0] = 0;
|
|
SkyOcclusion[1] = 0;
|
|
SkyOcclusion[2] = 0;
|
|
AOMaterialMask = 0;
|
|
}
|
|
|
|
/**
|
|
* Coefficients[0] stores the normalized average color,
|
|
* Coefficients[1] stores the maximum color component in each lightmap basis direction,
|
|
* and Coefficients[2] stores the simple lightmap which is colored incident lighting along the vertex normal.
|
|
*/
|
|
float Coefficients[LM_NUM_STORED_LIGHTMAP_COEF][3];
|
|
|
|
float SkyOcclusion[3];
|
|
|
|
float AOMaterialMask;
|
|
|
|
/** True if this sample maps to a valid point on a triangle. This is only meaningful for texture lightmaps. */
|
|
bool bIsMapped;
|
|
|
|
/**
|
|
* Export helper
|
|
* @param Component Which directional lightmap component to retrieve
|
|
* @return An FColor for this component, clamped to White
|
|
*/
|
|
FColor GetColor(int32 Component) const
|
|
{
|
|
return FColor(
|
|
(uint8)FMath::Clamp<int32>(Coefficients[Component][0] * 255, 0, 255),
|
|
(uint8)FMath::Clamp<int32>(Coefficients[Component][1] * 255, 0, 255),
|
|
(uint8)FMath::Clamp<int32>(Coefficients[Component][2] * 255, 0, 255),
|
|
0);
|
|
}
|
|
};
|
|
|
|
/** The light incident for a point on a surface. */
|
|
class FLightSample : public FLightSampleData
|
|
{
|
|
public:
|
|
/** Initialization constructor. */
|
|
FLightSample() : FLightSampleData() {}
|
|
FLightSample(EForceInit) : FLightSampleData() {}
|
|
};
|
|
|
|
/**
|
|
* The quantized coefficients for a single light-map texel.
|
|
*/
|
|
struct FQuantizedLightSampleData
|
|
{
|
|
uint8 Coverage;
|
|
uint8 Coefficients[LM_NUM_STORED_LIGHTMAP_COEF][4];
|
|
uint8 SkyOcclusion[4];
|
|
uint8 AOMaterialMask;
|
|
};
|
|
|
|
struct FLightMapDataBase
|
|
{
|
|
/** Size of compressed lightmap data */
|
|
uint32 CompressedDataSize;
|
|
|
|
/** Size of uncompressed lightmap data */
|
|
uint32 UncompressedDataSize;
|
|
|
|
/** Scale applied to the quantized light samples */
|
|
float Multiply[LM_NUM_STORED_LIGHTMAP_COEF][4];
|
|
|
|
/** Bias applied to the quantized light samples */
|
|
float Add[LM_NUM_STORED_LIGHTMAP_COEF][4];
|
|
};
|
|
|
|
/** LightMap data 2D */
|
|
struct FLightMapData2DData : public FLightMapDataBase
|
|
{
|
|
FLightMapData2DData(uint32 InSizeX,uint32 InSizeY):
|
|
SizeX(InSizeX),
|
|
SizeY(InSizeY),
|
|
bHasSkyShadowing(false)
|
|
{
|
|
}
|
|
|
|
/** The width of the light-map. */
|
|
uint32 SizeX;
|
|
/** The height of the light-map. */
|
|
uint32 SizeY;
|
|
bool bHasSkyShadowing;
|
|
};
|
|
|
|
struct FShadowMapDataBase
|
|
{
|
|
/** Size of compressed shadowmap data */
|
|
uint32 CompressedDataSize;
|
|
|
|
/** Size of uncompressed shadowmap data */
|
|
uint32 UncompressedDataSize;
|
|
};
|
|
|
|
/** A sample of the visibility factor between a light and a single point. */
|
|
struct FShadowSampleData
|
|
{
|
|
/** The fraction of light that reaches this point from the light, between 0 and 1. */
|
|
float Visibility;
|
|
/** True if this sample maps to a valid point on a surface. */
|
|
bool bIsMapped;
|
|
|
|
/**
|
|
* Export helper
|
|
* @param Component Which directional lightmap component to retrieve
|
|
* @return An FColor for this component, clamped to White
|
|
*/
|
|
FColor GetColor(int32 Component) const
|
|
{
|
|
uint8 Gray = (uint8)FMath::Clamp<int32>(Visibility * 255, 0, 255);
|
|
return FColor(Gray, Gray, Gray, 0);
|
|
}
|
|
|
|
};
|
|
|
|
/** The quantized value for a single shadowmap texel */
|
|
struct FQuantizedShadowSampleData
|
|
{
|
|
uint8 Visibility;
|
|
uint8 Coverage;
|
|
};
|
|
|
|
/** ShadowMap data 2D */
|
|
struct FShadowMapData2DData : public FShadowMapDataBase
|
|
{
|
|
FShadowMapData2DData(uint32 InSizeX,uint32 InSizeY):
|
|
SizeX(InSizeX),
|
|
SizeY(InSizeY)
|
|
{
|
|
}
|
|
|
|
/** The width of the shadow-map. */
|
|
uint32 SizeX;
|
|
/** The height of the shadow-map. */
|
|
uint32 SizeY;
|
|
};
|
|
|
|
struct FSignedDistanceFieldShadowSampleData
|
|
{
|
|
/** Normalized and encoded distance to the nearest shadow transition, in the range [0,1], where .5 is the transition. */
|
|
float Distance;
|
|
/** Normalized penumbra size, in [0,1] */
|
|
float PenumbraSize;
|
|
/** True if this sample maps to a valid point on a surface. */
|
|
bool bIsMapped;
|
|
};
|
|
|
|
/** The quantized value for a single signed-distance field texel */
|
|
struct FQuantizedSignedDistanceFieldShadowSampleData
|
|
{
|
|
uint8 Distance;
|
|
uint8 PenumbraSize;
|
|
uint8 Coverage;
|
|
};
|
|
|
|
/** 2D distance field data. */
|
|
struct FSignedDistanceFieldShadowMapData2DData : public FShadowMapData2DData
|
|
{
|
|
FSignedDistanceFieldShadowMapData2DData(uint32 InSizeX,uint32 InSizeY):
|
|
FShadowMapData2DData(InSizeX, InSizeY)
|
|
{
|
|
}
|
|
};
|
|
|
|
/** Lighting for a point in space. */
|
|
class FVolumeLightingSampleData
|
|
{
|
|
public:
|
|
/** World space position and radius. */
|
|
FVector4f 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];
|
|
|
|
FVector3f SkyBentNormal;
|
|
|
|
/** Shadow factor for the stationary directional light. */
|
|
float DirectionalLightShadowing;
|
|
};
|
|
|
|
/** Data used by the editor import process and not uploaded into textures. */
|
|
struct FIrradianceVoxelImportProcessingData
|
|
{
|
|
bool bInsideGeometry;
|
|
bool bBorderVoxel;
|
|
float ClosestGeometryDistance;
|
|
};
|
|
|
|
/** */
|
|
class FStaticShadowDepthMapSampleData
|
|
{
|
|
public:
|
|
FFloat16 Distance;
|
|
};
|
|
|
|
class FStaticShadowDepthMapData
|
|
{
|
|
public:
|
|
/** Transform from world space to the coordinate space that FStaticShadowDepthMapSampleData's are stored in. */
|
|
FMatrix44f WorldToLight;
|
|
/** Dimensions of the generated shadow map. */
|
|
int32 ShadowMapSizeX;
|
|
int32 ShadowMapSizeY;
|
|
};
|
|
|
|
static const FGuid MeshAreaLightDataGuid = FGuid(0xe11f4760, 0xfa454d2b, 0xa090c388, 0x33326646);
|
|
|
|
static const FGuid VolumeDistanceFieldGuid = FGuid(0x4abf306e, 0x4c2f4a6e, 0x9feb5fa4, 0x5b910a8f);
|
|
|
|
class FMeshAreaLightData
|
|
{
|
|
public:
|
|
FGuid LevelGuid;
|
|
FVector4f Position;
|
|
FVector4f Direction;
|
|
float Radius;
|
|
float ConeAngle;
|
|
FColor Color;
|
|
float Brightness;
|
|
float FalloffExponent;
|
|
};
|
|
|
|
/**
|
|
* Types used for transfering debug information back to Unreal.
|
|
* NOTE: These must stay binary compatible with the corresponding versions in Unreal.
|
|
*/
|
|
|
|
struct FDebugStaticLightingRay
|
|
{
|
|
FVector4f Start;
|
|
FVector4f End;
|
|
bool bHit;
|
|
bool bPositive;
|
|
|
|
FDebugStaticLightingRay() {}
|
|
FDebugStaticLightingRay(const FVector4f& InStart, const FVector4f& InEnd, bool bInHit, bool bInPositive = false) :
|
|
Start(InStart),
|
|
End(InEnd),
|
|
bHit(bInHit),
|
|
bPositive(bInPositive)
|
|
{}
|
|
};
|
|
|
|
struct FDebugStaticLightingVertex
|
|
{
|
|
FVector4f VertexNormal;
|
|
FVector4f VertexPosition;
|
|
};
|
|
|
|
struct FDebugLightingCacheRecord
|
|
{
|
|
bool bNearSelectedTexel;
|
|
bool bAffectsSelectedTexel;
|
|
int32 RecordId;
|
|
FDebugStaticLightingVertex Vertex;
|
|
float Radius;
|
|
|
|
FDebugLightingCacheRecord() :
|
|
bNearSelectedTexel(false),
|
|
bAffectsSelectedTexel(false)
|
|
{}
|
|
};
|
|
|
|
struct FDebugPhoton
|
|
{
|
|
int32 Id;
|
|
FVector4f Position;
|
|
FVector4f Direction;
|
|
FVector4f Normal;
|
|
|
|
FDebugPhoton() :
|
|
Id(-1)
|
|
{}
|
|
|
|
FDebugPhoton(int32 InId, const FVector4f& InPosition, const FVector4f& InDirection, const FVector4f& InNormal) :
|
|
Id(InId),
|
|
Position(InPosition),
|
|
Direction(InDirection),
|
|
Normal(InNormal)
|
|
{}
|
|
};
|
|
|
|
struct FDebugOctreeNode
|
|
{
|
|
FVector4f Center;
|
|
FVector4f Extent;
|
|
|
|
FDebugOctreeNode(const FVector4f& InCenter, const FVector4f& InExtent) :
|
|
Center(InCenter),
|
|
Extent(InExtent)
|
|
{}
|
|
};
|
|
|
|
/** Guid used by Unreal to determine when the debug channel with the same Guid can be opened. */
|
|
static const FGuid DebugOutputGuid = FGuid(0x23219c9e, 0xb5934266, 0xb2144a7d, 0x3448abac);
|
|
|
|
/**
|
|
* Debug output from the static lighting build.
|
|
*/
|
|
struct FDebugLightingOutput
|
|
{
|
|
/** Whether the debug output is valid. */
|
|
bool bValid;
|
|
/** Final gather, hemisphere sample and path rays */
|
|
TArray<FDebugStaticLightingRay> PathRays;
|
|
/** Area shadow rays */
|
|
TArray<FDebugStaticLightingRay> ShadowRays;
|
|
/** Photon paths used for guiding indirect photon emission */
|
|
TArray<FDebugStaticLightingRay> IndirectPhotonPaths;
|
|
/** Indices into Vertices of the selected sample's vertices */
|
|
TArray<int32> SelectedVertexIndices;
|
|
/** Vertices near the selected sample */
|
|
TArray<FDebugStaticLightingVertex> Vertices;
|
|
/** Lighting cache records */
|
|
TArray<FDebugLightingCacheRecord> CacheRecords;
|
|
/** Photons in the direct photon map */
|
|
TArray<FDebugPhoton> DirectPhotons;
|
|
/** Photons in the indirect photon map */
|
|
TArray<FDebugPhoton> IndirectPhotons;
|
|
/** Photons in the irradiance photon map */
|
|
TArray<FDebugPhoton> IrradiancePhotons;
|
|
/** Normal and irradiance photons that were gathered for the selected sample */
|
|
TArray<FDebugPhoton> GatheredPhotons;
|
|
/** Importance photons that were gathered for the selected sample */
|
|
TArray<FDebugPhoton> GatheredImportancePhotons;
|
|
/** Photon map octree nodes gathered during a photon map search. */
|
|
TArray<FDebugOctreeNode> GatheredPhotonNodes;
|
|
/** Whether GatheredDirectPhoton is valid */
|
|
bool bDirectPhotonValid;
|
|
/** Direct photon that was found during direct lighting. */
|
|
FDebugPhoton GatheredDirectPhoton;
|
|
/** Positions of the selected texel's corners */
|
|
FVector4f TexelCorners[NumTexelCorners];
|
|
/** Whether each of the selected texel's corners were valid */
|
|
bool bCornerValid[NumTexelCorners];
|
|
/** World space radius of the selected sample */
|
|
float SampleRadius;
|
|
|
|
FDebugLightingOutput() :
|
|
bValid(false),
|
|
bDirectPhotonValid(false)
|
|
{
|
|
for (int32 CornerIndex = 0; CornerIndex < NumTexelCorners; CornerIndex++)
|
|
{
|
|
bCornerValid[CornerIndex] = false;
|
|
}
|
|
}
|
|
};
|
|
|
|
struct FDebugVolumeLightingSample
|
|
{
|
|
FVector4f PositionAndRadius;
|
|
FLinearColor AverageIncidentRadiance;
|
|
|
|
FDebugVolumeLightingSample(const FVector4f& InPositionAndRadius, const FLinearColor& InAverageIncidentRadiance) :
|
|
PositionAndRadius(InPositionAndRadius),
|
|
AverageIncidentRadiance(InAverageIncidentRadiance)
|
|
{}
|
|
};
|
|
|
|
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);
|
|
|
|
#if !PLATFORM_MAC && !PLATFORM_LINUX
|
|
#pragma pack(pop)
|
|
#endif
|
|
|
|
/**
|
|
* Creates a standardized channel name based on Guid, version and type
|
|
*
|
|
* @param Guid Unique ID of the channel
|
|
* @param Version Version of the data inside
|
|
* @param LMExecutableHash Hash of UnrealLightmass executable, to avoid stale cache content from a different build
|
|
* @param Extension Type of the data
|
|
*
|
|
* @return Standard channel name
|
|
*/
|
|
FORCEINLINE FString CreateChannelNameWithLMExecutableHash(const FGuid& Guid, const int32 Version, const FSHAHash& LMExecutableHash, const FString& Extension)
|
|
{
|
|
return FString::Printf(TEXT("v%d.%08X%08X%08X%08X.%s.%s"), Version, Guid.A, Guid.B, Guid.C, Guid.D, *LMExecutableHash.ToString(), *Extension);
|
|
}
|
|
FORCEINLINE FString CreateChannelName(const FGuid& Guid, const int32 Version, const FString& Extension)
|
|
{
|
|
return FString::Printf(TEXT("v%d.%08X%08X%08X%08X.%s"), Version, Guid.A, Guid.B, Guid.C, Guid.D, *Extension);
|
|
}
|
|
|
|
/**
|
|
* Creates a standardized channel name based a FSA Hash, version and type. Used for exporting materials
|
|
*
|
|
* @param Hash Unique ID of the channel
|
|
* @param Version Version of the data inside
|
|
* @param LMExecutableHash Hash of UnrealLightmass executable, to avoid stale cache content from a different build
|
|
* @param Extension Type of the data
|
|
*
|
|
* @return Standard channel name
|
|
*/
|
|
FORCEINLINE FString CreateChannelNameWithLMExecutableHash(const FSHAHash& Hash, const int32 Version, const FSHAHash& LMExecutableHash, const FString& Extension)
|
|
{
|
|
return FString::Printf(TEXT("v%d.%s.%s.%s"), Version, *Hash.ToString(), *LMExecutableHash.ToString(), *Extension);
|
|
}
|
|
} // namespace Lightmass
|