374 lines
12 KiB
C++
374 lines
12 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
LightSceneInfo.h: Light scene info definitions.
|
|
=============================================================================*/
|
|
|
|
#pragma once
|
|
|
|
#include "CoreTypes.h"
|
|
#include "Math/Color.h"
|
|
#include "Math/GenericOctree.h"
|
|
#include "Math/GenericOctreePublic.h"
|
|
#include "Math/UnrealMath.h"
|
|
#include "PrimitiveSceneProxy.h"
|
|
#include "SceneTypes.h"
|
|
#include "SceneView.h"
|
|
|
|
class FLightPrimitiveInteraction;
|
|
class FLightSceneInfo;
|
|
class FMobileMovableLocalLightShadowParameters;
|
|
class FPrimitiveSceneInfoCompact;
|
|
class FPrimitiveSceneProxy;
|
|
class FScene;
|
|
class FViewInfo;
|
|
class FVisibleLightInfo;
|
|
|
|
namespace ECastRayTracedShadow
|
|
{
|
|
enum Type : int;
|
|
}
|
|
|
|
/**
|
|
* The information needed to cull a light-primitive interaction.
|
|
*/
|
|
class FLightSceneInfoCompact
|
|
{
|
|
public:
|
|
// XYZ: origin, W:sphere radius
|
|
VectorRegister BoundingSphereVector;
|
|
FLinearColor Color;
|
|
// must not be 0
|
|
FLightSceneInfo* LightSceneInfo;
|
|
// e.g. LightType_Directional, LightType_Point or LightType_Spot
|
|
uint32 LightType : LightType_NumBits;
|
|
uint32 bCastDynamicShadow : 1;
|
|
uint32 bCastStaticShadow : 1;
|
|
uint32 bStaticLighting : 1;
|
|
uint32 bAffectReflection : 1;
|
|
uint32 bAffectGlobalIllumination : 1;
|
|
uint32 bIsMovable : 1;
|
|
uint32 bAllowMegaLights : 1;
|
|
TEnumAsByte<EMegaLightsShadowMethod::Type> MegaLightsShadowMethod;
|
|
TEnumAsByte<ECastRayTracedShadow::Type> CastRaytracedShadow;
|
|
|
|
/** Initializes the compact scene info from the light's full scene info. */
|
|
void Init(FLightSceneInfo* InLightSceneInfo);
|
|
|
|
/** Default constructor. */
|
|
FLightSceneInfoCompact():
|
|
LightSceneInfo(NULL)
|
|
{}
|
|
|
|
/** Initialization constructor. */
|
|
FLightSceneInfoCompact(FLightSceneInfo* InLightSceneInfo)
|
|
{
|
|
Init(InLightSceneInfo);
|
|
}
|
|
|
|
/**
|
|
* Tests whether this light affects the given primitive. This checks both the primitive and light settings for light relevance
|
|
* and also calls AffectsBounds.
|
|
*
|
|
* @param CompactPrimitiveSceneInfo - The primitive to test.
|
|
* @return True if the light affects the primitive.
|
|
*/
|
|
bool AffectsPrimitive(const FBoxSphereBounds& PrimitiveBounds, const FPrimitiveSceneProxy* PrimitiveSceneProxy) const;
|
|
};
|
|
|
|
/** Information for sorting lights. */
|
|
struct FSortedLightSceneInfo
|
|
{
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
// Note: the order of these members controls the light sort order!
|
|
// Currently bHandledByMegaLights is the MSB and LightType is LSB
|
|
/** The type of light. */
|
|
uint32 LightType : LightType_NumBits;
|
|
/** Whether the light uses a light function. */
|
|
uint32 bLightFunction : 1;
|
|
/** Whether the light uses lighting channels. */
|
|
uint32 bUsesLightingChannels : 1;
|
|
/** Whether the light casts shadows. */
|
|
uint32 bShadowed : 1;
|
|
/** Whether the light is NOT a simple light - they always support tiled/clustered but may want to be selected separately. */
|
|
uint32 bIsNotSimpleLight : 1;
|
|
/**
|
|
* True if the light doesn't support clustered deferred, logic is inverted so that lights that DO support clustered deferred will sort first in list
|
|
* Super-set of lights supporting tiled, so the tiled lights will end up in the first part of this range.
|
|
*/
|
|
uint32 bClusteredDeferredNotSupported : 1;
|
|
/** Mega Lights must be sorted by GPU Scene Light Index - this field will only be set for MegaLights which don't rely on ordering of the other fields */
|
|
uint32 LightSceneId : LIGHT_ID_NUM_BITS;
|
|
/** Whether the light should be handled by Mega Lights, these will be sorted to the end so they can be skipped */
|
|
uint32 bHandledByMegaLights : 1;
|
|
} Fields;
|
|
/** Sort key bits packed into an integer. */
|
|
uint32 Packed;
|
|
static_assert(sizeof(Packed) >= sizeof(Fields), "SortKey Packed representation must include all bits in Fields");
|
|
} SortKey;
|
|
|
|
const FLightSceneInfo* LightSceneInfo;
|
|
int32 SimpleLightIndex;
|
|
bool bIsCompatibleWithLightFunctionAtlas;
|
|
|
|
/** Initialization constructor. */
|
|
explicit FSortedLightSceneInfo(const FLightSceneInfo* InLightSceneInfo)
|
|
: LightSceneInfo(InLightSceneInfo),
|
|
SimpleLightIndex(-1),
|
|
bIsCompatibleWithLightFunctionAtlas(false)
|
|
{
|
|
SortKey.Packed = 0;
|
|
SortKey.Fields.bIsNotSimpleLight = 1;
|
|
}
|
|
|
|
explicit FSortedLightSceneInfo(int32 InSimpleLightIndex)
|
|
: LightSceneInfo(nullptr),
|
|
SimpleLightIndex(InSimpleLightIndex),
|
|
bIsCompatibleWithLightFunctionAtlas(false)
|
|
{
|
|
SortKey.Packed = 0;
|
|
SortKey.Fields.bIsNotSimpleLight = 0;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Stores info about sorted lights and ranges.
|
|
* The sort-key in FSortedLightSceneInfo gives rise to the following order:
|
|
* [SimpleLights,Clustered,UnbatchedLights,LumenLights]
|
|
* Note that some shadowed lights can be included in the clustered pass when virtual shadow maps and one pass projection are used.
|
|
*/
|
|
struct FSortedLightSetSceneInfo
|
|
{
|
|
int32 SimpleLightsEnd;
|
|
int32 ClusteredSupportedEnd;
|
|
|
|
/** First light with shadow map or */
|
|
int32 UnbatchedLightStart;
|
|
|
|
// First light handled by Mega Lights
|
|
int32 MegaLightsLightStart;
|
|
|
|
bool bHasRectLights = false;
|
|
bool bHasLightFunctions = false;
|
|
bool bHasLightChannels = false;
|
|
bool bHasFirstPersonSelfShadowLights = false;
|
|
|
|
FSimpleLightArray SimpleLights;
|
|
TArray<FSortedLightSceneInfo, SceneRenderingAllocator> SortedLights;
|
|
};
|
|
|
|
template <>
|
|
struct TUseBitwiseSwap<FSortedLightSceneInfo>
|
|
{
|
|
enum { Value = false };
|
|
};
|
|
|
|
/** The type of the octree used by FScene to find lights. */
|
|
typedef TOctree2<FLightSceneInfoCompact,struct FLightOctreeSemantics> FSceneLightOctree;
|
|
|
|
struct FPersistentShadowStateKey
|
|
{
|
|
int32 AtlasIndex = -1;
|
|
int32 ProjectionId = -1;
|
|
int32 SubjectPrimitiveComponentIndex = -1;
|
|
};
|
|
|
|
inline uint32 GetTypeHash(const FPersistentShadowStateKey& Key)
|
|
{
|
|
return HashCombine(HashCombine((uint32)Key.AtlasIndex, (uint32)Key.ProjectionId), (uint32)Key.SubjectPrimitiveComponentIndex);
|
|
}
|
|
|
|
inline bool operator==(const FPersistentShadowStateKey& A, const FPersistentShadowStateKey& B)
|
|
{
|
|
return A.AtlasIndex == B.AtlasIndex && A.ProjectionId == B.ProjectionId && A.SubjectPrimitiveComponentIndex == B.SubjectPrimitiveComponentIndex;
|
|
}
|
|
|
|
class FPersistentShadowState
|
|
{
|
|
public:
|
|
FViewMatrices ViewMatrices;
|
|
|
|
FIntRect HZBTestViewRect;
|
|
TRefCountPtr<IPooledRenderTarget> HZB; // Direct HZB. nullptr for Atlas rendering.
|
|
};
|
|
|
|
/**
|
|
* The information used to render a light. This is the rendering thread's mirror of the game thread's ULightComponent.
|
|
* FLightSceneInfo is internal to the renderer module and contains internal scene state.
|
|
*/
|
|
class FLightSceneInfo
|
|
{
|
|
friend class FLightPrimitiveInteraction;
|
|
|
|
bool bRecordInteractionShadowPrimitives;
|
|
TArray<FLightPrimitiveInteraction*> InteractionShadowPrimitives;
|
|
|
|
/** The list of dynamic primitives affected by the light. */
|
|
FLightPrimitiveInteraction* DynamicInteractionOftenMovingPrimitiveList;
|
|
|
|
FLightPrimitiveInteraction* DynamicInteractionStaticPrimitiveList;
|
|
|
|
public:
|
|
using FPersistentId = int32;
|
|
|
|
/** The light's scene proxy. */
|
|
FLightSceneProxy* Proxy;
|
|
|
|
ELightComponentType Type;
|
|
|
|
/** If bVisible == true, this is the index of the primitive in Scene->Lights. */
|
|
FPersistentId Id;
|
|
FORCEINLINE FPersistentId GetPersistentIndex() const { return Id; }
|
|
|
|
/** The identifier for the primitive in Scene->PrimitiveOctree. */
|
|
FOctreeElementId2 OctreeId;
|
|
|
|
/** Persistent shadow state used for HZB occlusion culling. */
|
|
TMap<FPersistentShadowStateKey, FPersistentShadowState> PrevPersistentShadows;
|
|
TMap<FPersistentShadowStateKey, FPersistentShadowState> PersistentShadows;
|
|
|
|
protected:
|
|
|
|
/**
|
|
* ShadowMap channel assigned in the forward renderer when a movable shadow casting light is added to the scene.
|
|
* Used to pack shadow projections into channels of the light attenuation texture which is read in the base pass.
|
|
*/
|
|
int32 DynamicShadowMapChannel;
|
|
|
|
/** True if the light is built. */
|
|
uint32 bPrecomputedLightingIsValid : 1;
|
|
|
|
public:
|
|
|
|
/**
|
|
* True if the light is visible.
|
|
* False if the light is invisible but still needed for previewing, which can only happen in the editor.
|
|
*/
|
|
uint32 bVisible : 1;
|
|
|
|
/**
|
|
* Whether to render light shaft bloom from this light.
|
|
* For directional lights, the color around the light direction will be blurred radially and added back to the scene.
|
|
* for point lights, the color on pixels closer than the light's SourceRadius will be blurred radially and added back to the scene.
|
|
*/
|
|
uint32 bEnableLightShaftBloom : 1;
|
|
|
|
/** Scales the additive color. */
|
|
float BloomScale;
|
|
|
|
/** Scene color must be larger than this to create bloom in the light shafts. */
|
|
float BloomThreshold;
|
|
|
|
/** After exposure is applied, scene color brightness larger than BloomMaxBrightness will be rescaled down to BloomMaxBrightness. */
|
|
float BloomMaxBrightness;
|
|
|
|
/** Multiplies against scene color to create the bloom color. */
|
|
FColor BloomTint;
|
|
|
|
/** Number of dynamic interactions with statically lit primitives. */
|
|
int32 NumUnbuiltInteractions;
|
|
|
|
/** Cached value from the light proxy's virtual function, since it is checked many times during shadow setup. */
|
|
bool bCreatePerObjectShadowsForDynamicObjects;
|
|
|
|
/** The scene the light is in. */
|
|
FScene* Scene;
|
|
|
|
/** Initialization constructor. */
|
|
FLightSceneInfo(FLightSceneProxy* InProxy, bool InbVisible);
|
|
|
|
/** Adds the light to the scene. */
|
|
void AddToScene();
|
|
|
|
/**
|
|
* Returns true if the light affects the primitive
|
|
* @param LightSceneInfoCompact Compact representation of the light
|
|
* @param PrimitiveSceneInfoCompact Compact representation of the primitive
|
|
*/
|
|
bool ShouldCreateLightPrimitiveInteraction(const FLightSceneInfoCompact& LightSceneInfoCompact, const FPrimitiveSceneInfoCompact& PrimitiveSceneInfoCompact);
|
|
|
|
/**
|
|
* If the light affects the primitive, create an interaction, and process children
|
|
* @param LightSceneInfoCompact Compact representation of the light
|
|
* @param PrimitiveSceneInfoCompact Compact representation of the primitive
|
|
*/
|
|
void CreateLightPrimitiveInteraction(const FLightSceneInfoCompact& LightSceneInfoCompact, const FPrimitiveSceneInfoCompact& PrimitiveSceneInfoCompact);
|
|
|
|
/** Removes the light from the scene. */
|
|
void RemoveFromScene();
|
|
|
|
/** Detaches the light from the primitives it affects. */
|
|
void Detach();
|
|
|
|
/** Octree bounds setup. */
|
|
FBoxCenterAndExtent GetBoundingBox() const;
|
|
|
|
bool ShouldRenderLight(const FViewInfo& View, bool bOffscreen = false) const;
|
|
|
|
/** Encapsulates all View-Independent reasons to have this light render. */
|
|
bool ShouldRenderLightViewIndependent() const;
|
|
|
|
/** Encapsulates all View-Independent reasons to render ViewIndependentWholeSceneShadows for this light */
|
|
bool ShouldRenderViewIndependentWholeSceneShadows() const;
|
|
|
|
bool IsPrecomputedLightingValid() const;
|
|
|
|
void SetDynamicShadowMapChannel(int32 NewChannel);
|
|
|
|
int32 GetDynamicShadowMapChannel() const;
|
|
|
|
const TArray<FLightPrimitiveInteraction*>* GetInteractionShadowPrimitives() const;
|
|
|
|
FLightPrimitiveInteraction* GetDynamicInteractionOftenMovingPrimitiveList() const;
|
|
|
|
FLightPrimitiveInteraction* GetDynamicInteractionStaticPrimitiveList() const;
|
|
|
|
/** Hash function. */
|
|
friend uint32 GetTypeHash(const FLightSceneInfo* LightSceneInfo)
|
|
{
|
|
return (uint32)LightSceneInfo->Id;
|
|
}
|
|
|
|
bool SetupMobileMovableLocalLightShadowParameters(const FViewInfo& View, TConstArrayView<FVisibleLightInfo> VisibleLightInfos, FMobileMovableLocalLightShadowParameters& MobileMovableLocalLightShadowParameters) const;
|
|
|
|
bool ShouldRecordShadowSubjectsForMobile() const;
|
|
|
|
// Extra data such as shadow channel masks, light type and flags packed into a uint32.
|
|
// Unpacked in shader using helper functions defined in LightData.ush
|
|
uint32 PackExtraData(bool bAllowStaticLighting, bool bLightFunction, bool bMegaLight, bool bClusteredDeferredSupported) const;
|
|
};
|
|
|
|
/** Defines how the light is stored in the scene's light octree. */
|
|
struct FLightOctreeSemantics
|
|
{
|
|
enum { MaxElementsPerLeaf = 16 };
|
|
enum { MinInclusiveElementsPerNode = 7 };
|
|
enum { MaxNodeDepth = 12 };
|
|
|
|
typedef TInlineAllocator<MaxElementsPerLeaf, TAlignedHeapAllocator<alignof(FLightSceneInfoCompact)>> ElementAllocator;
|
|
|
|
FORCEINLINE static FBoxCenterAndExtent GetBoundingBox(const FLightSceneInfoCompact& Element)
|
|
{
|
|
return Element.LightSceneInfo->GetBoundingBox();
|
|
}
|
|
|
|
FORCEINLINE static bool AreElementsEqual(const FLightSceneInfoCompact& A,const FLightSceneInfoCompact& B)
|
|
{
|
|
return A.LightSceneInfo == B.LightSceneInfo;
|
|
}
|
|
|
|
FORCEINLINE static void SetElementId(const FLightSceneInfoCompact& Element,FOctreeElementId2 Id)
|
|
{
|
|
Element.LightSceneInfo->OctreeId = Id;
|
|
}
|
|
|
|
FORCEINLINE static void ApplyOffset(FLightSceneInfoCompact& Element, FVector Offset)
|
|
{
|
|
VectorRegister OffsetReg = VectorLoadFloat3_W0(&Offset);
|
|
Element.BoundingSphereVector = VectorAdd(Element.BoundingSphereVector, OffsetReg);
|
|
}
|
|
};
|