Files
UnrealEngine/Engine/Source/Programs/UnrealLightmass/Private/Lighting/Embree.h
2025-05-18 13:04:45 +08:00

319 lines
9.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Lighting.h"
#if USE_EMBREE
namespace Lightmass
{
class FStaticLightingMesh;
#if USE_EMBREE_MAJOR_VERSION >= 3
void EmbreeFilterFunc(const RTCFilterFunctionNArguments* args);
#else
void EmbreeFilterFunc(void* UserPtr, RTCRay& InRay);
void EmbreeFilterFunc4(const void* valid, void* UserPtr, RTCRay4& InRay);
#endif // USE_EMBREE_MAJOR_VERSION >= 3
// Accumulates transmission color, and store the distance.
// This is required since Embree test collision in any order,
// possibly accumulating transmission that are being collision
struct FEmbreeTransmissionAccumulator
{
TArray<FLinearColor, TInlineAllocator<64> > Colors;
FORCEINLINE void Push(const FLinearColor& Color, float tFar)
{
new (Colors) FLinearColor(Color.R, Color.G, Color.B, tFar);
}
void Resolve(FLinearColor& FinalColor, float tCollide);
void Resolve(FLinearColor& FinalColor);
};
#if USE_EMBREE_MAJOR_VERSION >= 3
#if USE_EMBREE_MAJOR_VERSION >= 4
struct FEmbreeContext : public RTCRayQueryContext
#else
struct FEmbreeContext : public RTCIntersectContext
#endif // USE_EMBREE_MAJOR_VERSION >= 4
{
FEmbreeContext(
const FStaticLightingMesh* InShadowMesh,
const FStaticLightingMesh* InMappingMesh,
uint32 InTraceFlags,
bool InFindClosestIntersection,
bool InCalculateTransmission,
bool InDirectShadowingRay
);
const FStaticLightingMesh* ShadowMesh; // Controls self shadow behavior, such as only self shadow and no self shadow.
const FStaticLightingMesh* MappingMesh; // Controls LOD behavior to control which mesh are allowed to cast shadows
uint32 TraceFlags;
bool bFindClosestIntersection;
bool bCalculateTransmission;
bool bDirectShadowingRay;
bool bStaticAndOpaqueOnly;
bool bTwoSidedCollision;
bool bFlipSidedness;
// Outputs
// Warning: EmbreeFilterFunc must only modify these!
int32 ElementIndex; // Material Index
FVector2f TextureCoordinates; // Material Coordinates
FVector2f LightmapCoordinates;
FEmbreeTransmissionAccumulator TransmissionAcc;
};
#else
struct FEmbreeRay : public RTCRay
{
FEmbreeRay(
const FStaticLightingMesh* InShadowMesh,
const FStaticLightingMesh* InMappingMesh,
uint32 InTraceFlags,
bool InFindClosestIntersection,
bool InCalculateTransmission,
bool InDirectShadowingRay
);
// Inputs required by filter functions
const FStaticLightingMesh* ShadowMesh; // Controls self shadow behavior, such as only self shadow and no self shadow.
const FStaticLightingMesh* MappingMesh; // Controls LOD behavior to control which mesh are allowed to cast shadows
uint32 TraceFlags;
bool bFindClosestIntersection;
bool bCalculateTransmission;
bool bDirectShadowingRay;
bool bStaticAndOpaqueOnly;
bool bTwoSidedCollision;
bool bFlipSidedness;
// Additional Outputs.
// Warning: EmbreeFilterFunc must only modify these! Nothing else is copied back to FEmbreeRay4.
int32 ElementIndex; // Material Index
FVector2f TextureCoordinates; // Material Coordinates
FVector2f LightmapCoordinates;
FEmbreeTransmissionAccumulator TransmissionAcc;
};
struct FEmbreeRay4 : public RTCRay4
{
FEmbreeRay4(
const FStaticLightingMesh* InShadowMesh,
const FStaticLightingMesh* InMappingMesh,
uint32 InTraceFlags,
bool InFindClosestIntersection,
bool InCalculateTransmission,
bool InDirectShadowingRay
);
inline FEmbreeRay BuildSingleRay(int32 RayIndex)
{
FEmbreeRay Ray(ShadowMesh, MappingMesh, TraceFlags, bFindClosestIntersection, bCalculateTransmission, bDirectShadowingRay);
int32 debug = sizeof(FEmbreeRay);
int32 debug2 = sizeof(FEmbreeRay4);
//static_assert(sizeof(FEmbreeRay) == );
//static_assert(sizeof(FEmbreeRay4) == );
// Outputs
Ray.ElementIndex = ElementIndex[RayIndex];
Ray.TextureCoordinates = TextureCoordinates[RayIndex];
Ray.LightmapCoordinates = LightmapCoordinates[RayIndex];
Ray.TransmissionAcc = TransmissionAcc[RayIndex];
// RTCRay members
Ray.org[0] = orgx[RayIndex];
Ray.dir[0] = dirx[RayIndex];
Ray.Ng[0] = Ngx[RayIndex];
Ray.org[1] = orgy[RayIndex];
Ray.dir[1] = diry[RayIndex];
Ray.Ng[1] = Ngy[RayIndex];
Ray.org[2] = orgz[RayIndex];
Ray.dir[2] = dirz[RayIndex];
Ray.Ng[2] = Ngz[RayIndex];
Ray.tnear = tnear[RayIndex];
Ray.tfar = tfar[RayIndex];
Ray.time = time[RayIndex];
Ray.mask = mask[RayIndex];
Ray.u = u[RayIndex];
Ray.v = v[RayIndex];
Ray.geomID = geomID[RayIndex];
Ray.primID = primID[RayIndex];
Ray.instID = instID[RayIndex];
return Ray;
}
inline void SetFromSingleRay(FEmbreeRay SingleRay, int32 RayIndex)
{
// Copy outputs only
ElementIndex[RayIndex] = SingleRay.ElementIndex;
TextureCoordinates[RayIndex] = SingleRay.TextureCoordinates;
LightmapCoordinates[RayIndex] = SingleRay.LightmapCoordinates;
TransmissionAcc[RayIndex] = SingleRay.TransmissionAcc;
geomID[RayIndex] = SingleRay.geomID;
}
// Inputs required by filter functions
const FStaticLightingMesh* ShadowMesh; // Controls self shadow behavior, such as only self shadow and no self shadow.
const FStaticLightingMesh* MappingMesh; // Controls LOD behavior to control which mesh are allowed to cast shadows
uint32 TraceFlags;
bool bFindClosestIntersection;
bool bCalculateTransmission;
bool bDirectShadowingRay;
bool bStaticAndOpaqueOnly;
bool bTwoSidedCollision;
bool bFlipSidedness;
// Additional Outputs.
int32 ElementIndex[4]; // Material Index
FVector2f TextureCoordinates[4]; // Material Coordinates
FVector2f LightmapCoordinates[4];
FEmbreeTransmissionAccumulator TransmissionAcc[4];
};
#endif // USE_EMBREE_MAJOR_VERSION >= 3
struct FEmbreeTriangleDesc
{
int16 ElementIndex;
uint16 CastShadow : 1;
uint16 StaticAndOpaqueMask : 1;
uint16 TwoSidedMask: 1;
uint16 Translucent : 1;
uint16 SurfaceDomain : 1;
uint16 IndirectlyShadowedOnly : 1;
uint16 Masked : 1;
uint16 CastShadowAsMasked : 1;
};
// Mapping between Embree Geometry Id and Lightmass Mesh/LOD Id
struct FEmbreeGeometry
{
FEmbreeGeometry(
RTCDevice EmbreeDevice,
RTCScene EmbreeScene,
const FBoxSphereBounds3f& ImportanceBounds,
const FStaticLightingMesh* InMesh,
const FStaticLightingMapping* InMapping,
bool bUseForInstancing
);
const FStaticLightingMesh* Mesh;
const FStaticLightingMapping* Mapping;
TArray<FEmbreeTriangleDesc> TriangleDescs; // The material ID of each triangle.
TArray<FVector2f> UVs;
TArray<FVector2f> LightmapUVs;
uint32 GeomID; // Embree ID for this mesh.
float SurfaceArea;
float SurfaceAreaWithinImportanceVolume;
bool bHasShadowCastingPrimitives;
class FEmbreeAggregateMesh* ParentAggregateMesh;
};
class FEmbreeAggregateMesh final : public FStaticLightingAggregateMesh
{
public:
/** Initialization constructor. */
FEmbreeAggregateMesh(const FScene& InScene);
virtual ~FEmbreeAggregateMesh();
virtual void AddMesh(const FStaticLightingMesh* Mesh, const FStaticLightingMapping* Mapping) override;
virtual void ReserveMemory( int32 NumMeshes, int32 NumVertices, int32 NumTriangles ) override {}
/** Prepares the mesh for raytracing. */
virtual void PrepareForRaytracing() override;
virtual void DumpStats() const override;
virtual bool IntersectLightRay(
const FLightRay& LightRay,
bool bFindClosestIntersection,
bool bCalculateTransmission,
bool bDirectShadowingRay,
class FCoherentRayCache& CoherentRayCache,
FLightRayIntersection& Intersection) const override;
TArray<const FStaticLightingMapping*> StaticMeshInstancesToMappings;
private:
/** Information about the meshes used in the kDOP tree. */
TArray<const FEmbreeGeometry*> MeshInfos;
struct FEmbreeStaticMeshGeometry
{
RTCScene MeshScene;
FEmbreeGeometry* Geo;
};
TMap<const FStaticMeshLOD*, FEmbreeStaticMeshGeometry> StaticMeshGeometries;
/** Embree scene */
RTCDevice EmbreeDevice;
RTCScene EmbreeScene;
/** Total number of triangles in the shadow mesh */
int32 TotalNumTriangles;
/** Total number of instanced triangles in the shadow mesh */
int32 TotalNumTrianglesInstanced;
};
class FEmbreeVerifyAggregateMesh final : public FStaticLightingAggregateMesh
{
typedef FStaticLightingAggregateMesh Super;
public:
FEmbreeVerifyAggregateMesh(const FScene& InScene);
virtual void AddMesh(const FStaticLightingMesh* Mesh, const FStaticLightingMapping* Mapping) override;
virtual void ReserveMemory( int32 NumMeshes, int32 NumVertices, int32 NumTriangles ) override;
virtual void PrepareForRaytracing() override;
virtual void DumpStats() const override;
virtual void DumpCheckStats() const override;
virtual bool IntersectLightRay(
const FLightRay& LightRay,
bool bFindClosestIntersection,
bool bCalculateTransmission,
bool bDirectShadowingRay,
class FCoherentRayCache& CoherentRayCache,
FLightRayIntersection& Intersection) const override;
private:
static bool VerifyTransmissions(const FLightRayIntersection& EmbreeIntersection, const FLightRayIntersection& ClosestIntersection);
static bool VerifyChecks(const FLightRayIntersection& EmbreeIntersection, const FLightRayIntersection& ClosestIntersection, bool bFindClosestIntersection);
FDefaultAggregateMesh DefaultAggregate;
FEmbreeAggregateMesh EmbreeAggregate;
mutable volatile int64 TransmissionMismatchCount;
mutable volatile int64 TransmissionEqualCount;
mutable volatile int64 CheckEqualCount;
mutable volatile int64 CheckMismatchCount;
};
} // namespace
#endif // USE_EMBREE