You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
1841 lines
65 KiB
C++
1841 lines
65 KiB
C++
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
ScenePrivate.h: Private scene manager definitions.
|
|
=============================================================================*/
|
|
|
|
#ifndef __SCENEPRIVATE_H__
|
|
#define __SCENEPRIVATE_H__
|
|
|
|
class SceneRenderingAllocator;
|
|
class USceneCaptureComponent;
|
|
class UTextureRenderTarget;
|
|
|
|
class SceneRenderingBitArrayAllocator
|
|
: public TInlineAllocator<4,SceneRenderingAllocator>
|
|
{
|
|
};
|
|
|
|
class SceneRenderingSparseArrayAllocator
|
|
: public TSparseArrayAllocator<SceneRenderingAllocator,SceneRenderingBitArrayAllocator>
|
|
{
|
|
};
|
|
|
|
class SceneRenderingSetAllocator
|
|
: public TSetAllocator<SceneRenderingSparseArrayAllocator,TInlineAllocator<1,SceneRenderingAllocator> >
|
|
{
|
|
};
|
|
|
|
typedef TBitArray<SceneRenderingBitArrayAllocator> FSceneBitArray;
|
|
typedef TConstSetBitIterator<SceneRenderingBitArrayAllocator> FSceneSetBitIterator;
|
|
typedef TConstDualSetBitIterator<SceneRenderingBitArrayAllocator,SceneRenderingBitArrayAllocator> FSceneDualSetBitIterator;
|
|
|
|
// Forward declarations.
|
|
class FScene;
|
|
class FLightPropagationVolume;
|
|
|
|
/** True if HDR is enabled for the mobile renderer. */
|
|
bool IsMobileHDR();
|
|
|
|
/** True if the mobile renderer is emulating HDR in a 32bpp render target. */
|
|
bool IsMobileHDR32bpp();
|
|
|
|
// Dependencies.
|
|
#include "StaticBoundShaderState.h"
|
|
#include "BatchedElements.h"
|
|
#include "PostProcess/SceneRenderTargets.h"
|
|
#include "GenericOctree.h"
|
|
#include "SceneCore.h"
|
|
#include "PrimitiveSceneInfo.h"
|
|
#include "LightSceneInfo.h"
|
|
#include "ShaderBaseClasses.h"
|
|
#include "DrawingPolicy.h"
|
|
#include "DepthRendering.h"
|
|
#include "SceneHitProxyRendering.h"
|
|
#include "ShaderComplexityRendering.h"
|
|
#include "ShadowRendering.h"
|
|
#include "SceneRendering.h"
|
|
#include "StaticMeshDrawList.h"
|
|
#include "DeferredShadingRenderer.h"
|
|
#include "FogRendering.h"
|
|
#include "BasePassRendering.h"
|
|
#include "ForwardBasePassRendering.h"
|
|
#include "DynamicPrimitiveDrawing.h"
|
|
#include "TranslucentRendering.h"
|
|
#include "VelocityRendering.h"
|
|
#include "LightMapDensityRendering.h"
|
|
#include "TextureLayout.h"
|
|
#include "TextureLayout3d.h"
|
|
#include "ScopedPointer.h"
|
|
#include "ClearQuad.h"
|
|
#include "AtmosphereRendering.h"
|
|
|
|
#if WITH_SLI || PLATFORM_SHOULD_BUFFER_QUERIES
|
|
#define BUFFERED_OCCLUSION_QUERIES 1
|
|
#endif
|
|
|
|
/** Factor by which to grow occlusion tests **/
|
|
#define OCCLUSION_SLOP (1.0f)
|
|
|
|
class FOcclusionQueryHelpers
|
|
{
|
|
public:
|
|
|
|
// get the system-wide number of frames of buffered occlusion queries.
|
|
static int32 GetNumBufferedFrames()
|
|
{
|
|
int32 NumBufferedFrames = 1;
|
|
|
|
#if BUFFERED_OCCLUSION_QUERIES
|
|
# if WITH_SLI
|
|
// If we're running with SLI, assume throughput is more important than latency, and buffer an extra frame
|
|
NumBufferedFrames = GNumActiveGPUsForRendering == 1 ? 1 : GNumActiveGPUsForRendering;
|
|
# else
|
|
static const auto NumBufferedQueriesVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.NumBufferedOcclusionQueries"));
|
|
NumBufferedFrames = NumBufferedQueriesVar->GetValueOnAnyThread();
|
|
# endif
|
|
#endif
|
|
return NumBufferedFrames;
|
|
}
|
|
|
|
// get the index of the oldest query based on the current frame and number of buffered frames.
|
|
static uint32 GetQueryLookupIndex(int32 CurrentFrame, int32 NumBufferedFrames)
|
|
{
|
|
// queries are currently always requested earlier in the frame than they are issued.
|
|
// thus we can always overwrite the oldest query with the current one as we never need them
|
|
// to coexist. This saves us a buffer entry.
|
|
const uint32 QueryIndex = CurrentFrame % NumBufferedFrames;
|
|
return QueryIndex;
|
|
}
|
|
|
|
// get the index of the query to overwrite for new queries.
|
|
static uint32 GetQueryIssueIndex(int32 CurrentFrame, int32 NumBufferedFrames)
|
|
{
|
|
// queries are currently always requested earlier in the frame than they are issued.
|
|
// thus we can always overwrite the oldest query with the current one as we never need them
|
|
// to coexist. This saves us a buffer entry.
|
|
const uint32 QueryIndex = CurrentFrame % NumBufferedFrames;
|
|
return QueryIndex;
|
|
}
|
|
};
|
|
|
|
/** Holds information about a single primitive's occlusion. */
|
|
class FPrimitiveOcclusionHistory
|
|
{
|
|
public:
|
|
/** The primitive the occlusion information is about. */
|
|
FPrimitiveComponentId PrimitiveId;
|
|
|
|
#if BUFFERED_OCCLUSION_QUERIES
|
|
/** The occlusion query which contains the primitive's pending occlusion results. */
|
|
TArray<FRenderQueryRHIRef, TInlineAllocator<1> > PendingOcclusionQuery;
|
|
#else
|
|
/** The occlusion query which contains the primitive's pending occlusion results. */
|
|
FRenderQueryRHIRef PendingOcclusionQuery;
|
|
#endif
|
|
|
|
uint32 HZBTestIndex;
|
|
uint32 HZBTestFrameNumber;
|
|
|
|
/** The last time the primitive was visible. */
|
|
float LastVisibleTime;
|
|
|
|
/** The last time the primitive was in the view frustum. */
|
|
float LastConsideredTime;
|
|
|
|
/**
|
|
* The pixels that were rendered the last time the primitive was drawn.
|
|
* It is the ratio of pixels unoccluded to the resolution of the scene.
|
|
*/
|
|
float LastPixelsPercentage;
|
|
|
|
/** whether or not this primitive was grouped the last time it was queried */
|
|
bool bGroupedQuery;
|
|
|
|
/**
|
|
* Number of frames to buffer the occlusion queries.
|
|
* Larger numbers allow better SLI scaling but introduce latency in the results.
|
|
*/
|
|
int32 NumBufferedFrames;
|
|
|
|
/**
|
|
* For things that have subqueries (folaige), this is the non-zero
|
|
*/
|
|
int32 CustomIndex;
|
|
|
|
/** Initialization constructor. */
|
|
FORCEINLINE FPrimitiveOcclusionHistory(FPrimitiveComponentId InPrimitiveId, int32 SubQuery)
|
|
: PrimitiveId(InPrimitiveId)
|
|
, HZBTestIndex(0)
|
|
, HZBTestFrameNumber(~0u)
|
|
, LastVisibleTime(0.0f)
|
|
, LastConsideredTime(0.0f)
|
|
, LastPixelsPercentage(0.0f)
|
|
, bGroupedQuery(false)
|
|
, CustomIndex(SubQuery)
|
|
{
|
|
#if BUFFERED_OCCLUSION_QUERIES
|
|
NumBufferedFrames = FOcclusionQueryHelpers::GetNumBufferedFrames();
|
|
PendingOcclusionQuery.Empty(NumBufferedFrames);
|
|
PendingOcclusionQuery.AddZeroed(NumBufferedFrames);
|
|
#endif
|
|
}
|
|
|
|
/** Destructor. Note that the query should have been released already. */
|
|
~FPrimitiveOcclusionHistory()
|
|
{
|
|
// check( !IsValidRef(PendingOcclusionQuery) );
|
|
}
|
|
|
|
template<class TOcclusionQueryPool> // here we use a template just to allow this to be inlined without sorting out the header order
|
|
FORCEINLINE void ReleaseQueries(FRHICommandListImmediate& RHICmdList, TOcclusionQueryPool& Pool)
|
|
{
|
|
#if BUFFERED_OCCLUSION_QUERIES
|
|
for (int32 QueryIndex = 0; QueryIndex < NumBufferedFrames; QueryIndex++)
|
|
{
|
|
Pool.ReleaseQuery(RHICmdList, PendingOcclusionQuery[QueryIndex]);
|
|
}
|
|
#else
|
|
Pool.ReleaseQuery(RHICmdList, PendingOcclusionQuery);
|
|
#endif
|
|
}
|
|
|
|
FORCEINLINE FRenderQueryRHIRef& GetPastQuery(uint32 FrameNumber)
|
|
{
|
|
#if BUFFERED_OCCLUSION_QUERIES
|
|
// Get the oldest occlusion query
|
|
const uint32 QueryIndex = FOcclusionQueryHelpers::GetQueryLookupIndex(FrameNumber, NumBufferedFrames);
|
|
return PendingOcclusionQuery[QueryIndex];
|
|
#else
|
|
return PendingOcclusionQuery;
|
|
#endif
|
|
}
|
|
|
|
FORCEINLINE void SetCurrentQuery(uint32 FrameNumber, FRenderQueryRHIParamRef NewQuery)
|
|
{
|
|
#if BUFFERED_OCCLUSION_QUERIES
|
|
// Get the current occlusion query
|
|
const uint32 QueryIndex = FOcclusionQueryHelpers::GetQueryIssueIndex(FrameNumber, NumBufferedFrames);
|
|
PendingOcclusionQuery[QueryIndex] = NewQuery;
|
|
#else
|
|
PendingOcclusionQuery = NewQuery;
|
|
#endif
|
|
}
|
|
};
|
|
|
|
struct FPrimitiveOcclusionHistoryKey
|
|
{
|
|
FPrimitiveComponentId PrimitiveId;
|
|
int32 CustomIndex;
|
|
|
|
FPrimitiveOcclusionHistoryKey(const FPrimitiveOcclusionHistory& Element)
|
|
: PrimitiveId(Element.PrimitiveId)
|
|
, CustomIndex(Element.CustomIndex)
|
|
{
|
|
}
|
|
FPrimitiveOcclusionHistoryKey(FPrimitiveComponentId InPrimitiveId, int32 InCustomIndex)
|
|
: PrimitiveId(InPrimitiveId)
|
|
, CustomIndex(InCustomIndex)
|
|
{
|
|
}
|
|
};
|
|
|
|
/** Defines how the hash set indexes the FPrimitiveOcclusionHistory objects. */
|
|
struct FPrimitiveOcclusionHistoryKeyFuncs : BaseKeyFuncs<FPrimitiveOcclusionHistory,FPrimitiveOcclusionHistoryKey>
|
|
{
|
|
typedef FPrimitiveOcclusionHistoryKey KeyInitType;
|
|
|
|
static KeyInitType GetSetKey(const FPrimitiveOcclusionHistory& Element)
|
|
{
|
|
return FPrimitiveOcclusionHistoryKey(Element);
|
|
}
|
|
|
|
static bool Matches(KeyInitType A,KeyInitType B)
|
|
{
|
|
return A.PrimitiveId == B.PrimitiveId && A.CustomIndex == B.CustomIndex;
|
|
}
|
|
|
|
static uint32 GetKeyHash(KeyInitType Key)
|
|
{
|
|
return GetTypeHash(Key.PrimitiveId.PrimIDValue) ^ (GetTypeHash(Key.CustomIndex) >> 20);
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* A pool of render (e.g. occlusion/timer) queries which are allocated individually, and returned to the pool as a group.
|
|
*/
|
|
class FRenderQueryPool
|
|
{
|
|
public:
|
|
FRenderQueryPool(ERenderQueryType InQueryType) :QueryType(InQueryType) { }
|
|
virtual ~FRenderQueryPool();
|
|
|
|
/** Releases all the render queries in the pool. */
|
|
void Release();
|
|
|
|
/** Allocates an render query from the pool. */
|
|
FRenderQueryRHIRef AllocateQuery();
|
|
|
|
/** De-reference an render query, returning it to the pool instead of deleting it when the refcount reaches 0. */
|
|
void ReleaseQuery(FRHICommandListImmediate& RHICmdList, FRenderQueryRHIRef &Query);
|
|
|
|
private:
|
|
/** Container for available render queries. */
|
|
TArray<FRenderQueryRHIRef> Queries;
|
|
|
|
ERenderQueryType QueryType;
|
|
};
|
|
|
|
/**
|
|
* Distance cull fading uniform buffer containing faded in
|
|
*/
|
|
class FGlobalDistanceCullFadeUniformBuffer : public TUniformBuffer< FDistanceCullFadeUniformShaderParameters >
|
|
{
|
|
public:
|
|
/** Default constructor. */
|
|
FGlobalDistanceCullFadeUniformBuffer()
|
|
{
|
|
FDistanceCullFadeUniformShaderParameters Uniforms;
|
|
Uniforms.FadeTimeScaleBias.X = 0.0f;
|
|
Uniforms.FadeTimeScaleBias.Y = 1.0f;
|
|
SetContents( Uniforms );
|
|
}
|
|
};
|
|
|
|
/** Global primitive uniform buffer resource containing faded in */
|
|
extern TGlobalResource< FGlobalDistanceCullFadeUniformBuffer > GDistanceCullFadedInUniformBuffer;
|
|
|
|
/**
|
|
* Stores fading state for a single primitive in a single view
|
|
*/
|
|
class FPrimitiveFadingState
|
|
{
|
|
public:
|
|
FPrimitiveFadingState()
|
|
: FadeTimeScaleBias(ForceInitToZero)
|
|
, FrameNumber(0)
|
|
, EndTime(0.0f)
|
|
, bIsVisible(false)
|
|
, bValid(false)
|
|
{
|
|
}
|
|
|
|
/** Scale and bias to use on time to calculate fade opacity */
|
|
FVector2D FadeTimeScaleBias;
|
|
|
|
/** The uniform buffer for the fade parameters */
|
|
FDistanceCullFadeUniformBufferRef UniformBuffer;
|
|
|
|
/** Frame number when last updated */
|
|
uint32 FrameNumber;
|
|
|
|
/** Time when fade will be finished. */
|
|
float EndTime;
|
|
|
|
/** Currently visible? */
|
|
bool bIsVisible;
|
|
|
|
/** Valid? */
|
|
bool bValid;
|
|
};
|
|
|
|
/** Maps a single primitive to it's per-view fading state data */
|
|
typedef TMap<FPrimitiveComponentId, FPrimitiveFadingState> FPrimitiveFadingStateMap;
|
|
|
|
class FOcclusionRandomStream
|
|
{
|
|
enum {NumSamples = 3571};
|
|
public:
|
|
|
|
/** Default constructor - should set seed prior to use. */
|
|
FOcclusionRandomStream()
|
|
: CurrentSample(0)
|
|
{
|
|
FRandomStream RandomStream(0x83246);
|
|
for (int32 Index = 0; Index < NumSamples; Index++)
|
|
{
|
|
Samples[Index] = RandomStream.GetFraction();
|
|
}
|
|
Samples[0] = 0.0f; // we want to make sure we have at least a few zeros
|
|
Samples[NumSamples/3] = 0.0f; // we want to make sure we have at least a few zeros
|
|
Samples[(NumSamples*2)/3] = 0.0f; // we want to make sure we have at least a few zeros
|
|
}
|
|
|
|
/** @return A random number between 0 and 1. */
|
|
FORCEINLINE float GetFraction()
|
|
{
|
|
if (CurrentSample >= NumSamples)
|
|
{
|
|
CurrentSample = 0;
|
|
}
|
|
return Samples[CurrentSample++];
|
|
}
|
|
private:
|
|
|
|
/** Index of the last sample we produced **/
|
|
uint32 CurrentSample;
|
|
/** A list of float random samples **/
|
|
float Samples[NumSamples];
|
|
};
|
|
|
|
/** Random table for occlusion **/
|
|
extern FOcclusionRandomStream GOcclusionRandomStream;
|
|
|
|
/**
|
|
* The scene manager's private implementation of persistent view state.
|
|
* This class is associated with a particular camera across multiple frames by the game thread.
|
|
* The game thread calls FRendererModule::AllocateViewState to create an instance of this private implementation.
|
|
*/
|
|
class FSceneViewState : public FSceneViewStateInterface, public FDeferredCleanupInterface, public FRenderResource
|
|
{
|
|
public:
|
|
|
|
class FProjectedShadowKey
|
|
{
|
|
public:
|
|
|
|
FORCEINLINE bool operator == (const FProjectedShadowKey &Other) const
|
|
{
|
|
return (PrimitiveId == Other.PrimitiveId && Light == Other.Light && ShadowSplitIndex == Other.ShadowSplitIndex && bTranslucentShadow == Other.bTranslucentShadow);
|
|
}
|
|
|
|
FProjectedShadowKey(const FProjectedShadowInfo& ProjectedShadowInfo)
|
|
: PrimitiveId(ProjectedShadowInfo.GetParentSceneInfo() ? ProjectedShadowInfo.GetParentSceneInfo()->PrimitiveComponentId : FPrimitiveComponentId())
|
|
, Light(ProjectedShadowInfo.GetLightSceneInfo().Proxy->GetLightComponent())
|
|
, ShadowSplitIndex(ProjectedShadowInfo.CascadeSettings.ShadowSplitIndex)
|
|
, bTranslucentShadow(ProjectedShadowInfo.bTranslucentShadow)
|
|
{
|
|
}
|
|
|
|
FProjectedShadowKey(FPrimitiveComponentId InPrimitiveId, const ULightComponent* InLight, int32 InSplitIndex, bool bInTranslucentShadow)
|
|
: PrimitiveId(InPrimitiveId)
|
|
, Light(InLight)
|
|
, ShadowSplitIndex(InSplitIndex)
|
|
, bTranslucentShadow(bInTranslucentShadow)
|
|
{
|
|
}
|
|
|
|
friend FORCEINLINE uint32 GetTypeHash(const FSceneViewState::FProjectedShadowKey& Key)
|
|
{
|
|
return PointerHash(Key.Light,GetTypeHash(Key.PrimitiveId));
|
|
}
|
|
|
|
private:
|
|
FPrimitiveComponentId PrimitiveId;
|
|
const ULightComponent* Light;
|
|
int32 ShadowSplitIndex;
|
|
bool bTranslucentShadow;
|
|
};
|
|
|
|
int32 NumBufferedFrames;
|
|
uint32 UniqueID;
|
|
typedef TMap<FSceneViewState::FProjectedShadowKey, FRenderQueryRHIRef> ShadowKeyOcclusionQueryMap;
|
|
#if BUFFERED_OCCLUSION_QUERIES
|
|
TArray<ShadowKeyOcclusionQueryMap> ShadowOcclusionQueryMaps;
|
|
#else
|
|
ShadowKeyOcclusionQueryMap ShadowOcclusionQueryMap;
|
|
#endif
|
|
|
|
/** The view's occlusion query pool. */
|
|
FRenderQueryPool OcclusionQueryPool;
|
|
|
|
FHZBOcclusionTester HZBOcclusionTests;
|
|
|
|
/** Storage to which compressed visibility chunks are uncompressed at runtime. */
|
|
TArray<uint8> DecompressedVisibilityChunk;
|
|
|
|
/** Cached visibility data from the last call to GetPrecomputedVisibilityData. */
|
|
const TArray<uint8>* CachedVisibilityChunk;
|
|
int32 CachedVisibilityHandlerId;
|
|
int32 CachedVisibilityBucketIndex;
|
|
int32 CachedVisibilityChunkIndex;
|
|
|
|
/** Parameter to keep track of previous frame. Managed by the rendering thread. */
|
|
FViewMatrices PrevViewMatrices;
|
|
FViewMatrices PendingPrevViewMatrices;
|
|
|
|
uint32 PendingPrevFrameNumber;
|
|
uint32 PrevFrameNumber;
|
|
float LastRenderTime;
|
|
float LastRenderTimeDelta;
|
|
float MotionBlurTimeScale;
|
|
FMatrix PrevViewMatrixForOcclusionQuery;
|
|
FVector PrevViewOriginForOcclusionQuery;
|
|
|
|
// A counter incremented once each time this view is rendered.
|
|
uint32 OcclusionFrameCounter;
|
|
|
|
/** Used by states that have IsViewParent() == true to store primitives for child states. */
|
|
TSet<FPrimitiveComponentId> ParentPrimitives;
|
|
|
|
/** For this view, the set of primitives that are currently fading, either in or out. */
|
|
FPrimitiveFadingStateMap PrimitiveFadingStates;
|
|
|
|
FIndirectLightingCacheAllocation* TranslucencyLightingCacheAllocations[TVC_MAX];
|
|
|
|
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
/** Are we currently in the state of freezing rendering? (1 frame where we gather what was rendered) */
|
|
bool bIsFreezing;
|
|
|
|
/** Is rendering currently frozen? */
|
|
bool bIsFrozen;
|
|
|
|
/** The set of primitives that were rendered the frame that we froze rendering */
|
|
TSet<FPrimitiveComponentId> FrozenPrimitives;
|
|
#endif
|
|
|
|
private:
|
|
// to implement eye adaptation changes over time
|
|
TRefCountPtr<IPooledRenderTarget> EyeAdaptationRT;
|
|
|
|
// used by the Postprocess Material Blending system to avoid recreation and garbage collection of MIDs
|
|
TArray<UMaterialInstanceDynamic*> MIDPool;
|
|
uint32 MIDUsedCount;
|
|
|
|
// if TemporalAA is on this cycles through 0..TemporalAASampleCount-1
|
|
uint8 TemporalAASampleIndex;
|
|
// >= 1, 1 means there is no TemporalAA
|
|
uint8 TemporalAASampleCount;
|
|
|
|
// can be 0
|
|
FLightPropagationVolume* LightPropagationVolume;
|
|
|
|
public:
|
|
|
|
FHeightfieldLightingAtlas* HeightfieldLightingAtlas;
|
|
|
|
// If Translucency should be rendered into a separate RT and composited without DepthOfField, can be disabled in the materials (affects sorting)
|
|
TRefCountPtr<IPooledRenderTarget> SeparateTranslucencyRT;
|
|
// Temporal AA result of last frame
|
|
TRefCountPtr<IPooledRenderTarget> TemporalAAHistoryRT;
|
|
// Temporal AA result for DOF of last frame
|
|
TRefCountPtr<IPooledRenderTarget> DOFHistoryRT;
|
|
TRefCountPtr<IPooledRenderTarget> DOFHistoryRT2;
|
|
// Temporal AA result for SSR
|
|
TRefCountPtr<IPooledRenderTarget> SSRHistoryRT;
|
|
// Temporal AA result for light shafts of last frame
|
|
TRefCountPtr<IPooledRenderTarget> LightShaftOcclusionHistoryRT;
|
|
// Temporal AA result for light shafts of last frame
|
|
TMap<const ULightComponent*, TRefCountPtr<IPooledRenderTarget> > LightShaftBloomHistoryRTs;
|
|
TRefCountPtr<IPooledRenderTarget> DistanceFieldAOHistoryRT;
|
|
TRefCountPtr<IPooledRenderTarget> DistanceFieldIrradianceHistoryRT;
|
|
// Mobile temporal AA surfaces.
|
|
TRefCountPtr<IPooledRenderTarget> MobileAaBloomSunVignette0;
|
|
TRefCountPtr<IPooledRenderTarget> MobileAaBloomSunVignette1;
|
|
TRefCountPtr<IPooledRenderTarget> MobileAaColor0;
|
|
TRefCountPtr<IPooledRenderTarget> MobileAaColor1;
|
|
|
|
// cache for selection outline to a avoid reallocations of the SRV, Key is to detect if the object has changed
|
|
FTextureRHIRef SelectionOutlineCacheKey;
|
|
TRefCountPtr<FRHIShaderResourceView> SelectionOutlineCacheValue;
|
|
|
|
/** Distance field AO tile intersection GPU resources. Last frame's state is not used, but they must be sized exactly to the view so stored here. */
|
|
class FTileIntersectionResources* AOTileIntersectionResources;
|
|
|
|
// Is DOFHistoryRT set from Bokeh DOF?
|
|
bool bBokehDOFHistory;
|
|
bool bBokehDOFHistory2;
|
|
|
|
FTemporalLODState TemporalLODState;
|
|
|
|
// call after SetupTemporalAA()
|
|
uint32 GetCurrentTemporalAASampleIndex() const
|
|
{
|
|
return TemporalAASampleIndex;
|
|
}
|
|
|
|
// call after SetupTemporalAA()
|
|
uint32 GetCurrentTemporalAASampleCount() const
|
|
{
|
|
return TemporalAASampleCount;
|
|
}
|
|
|
|
// @param SampleCount 0 or 1 for no TemporalAA
|
|
void SetupTemporalAA(uint32 SampleCount, const FSceneViewFamily& Family)
|
|
{
|
|
if(!SampleCount)
|
|
{
|
|
SampleCount = 1;
|
|
}
|
|
|
|
TemporalAASampleCount = FMath::Min(SampleCount, (uint32)255);
|
|
|
|
if (!Family.bWorldIsPaused)
|
|
{
|
|
TemporalAASampleIndex++;
|
|
}
|
|
|
|
if(TemporalAASampleIndex >= TemporalAASampleCount)
|
|
{
|
|
TemporalAASampleIndex = 0;
|
|
}
|
|
}
|
|
|
|
void FreeSeparateTranslucency()
|
|
{
|
|
SeparateTranslucencyRT.SafeRelease();
|
|
|
|
check(!SeparateTranslucencyRT);
|
|
}
|
|
|
|
// call only if not yet created
|
|
void CreateLightPropagationVolumeIfNeeded(ERHIFeatureLevel::Type InFeatureLevel);
|
|
|
|
// @return can return 0 (if globally disabled)
|
|
FLightPropagationVolume* GetLightPropagationVolume() const { return LightPropagationVolume; }
|
|
|
|
/** Default constructor. */
|
|
FSceneViewState();
|
|
|
|
void DestroyLightPropagationVolume();
|
|
|
|
virtual ~FSceneViewState();
|
|
|
|
// called every frame after the view state was updated
|
|
void UpdateLastRenderTime(const FSceneViewFamily& Family)
|
|
{
|
|
// The editor can trigger multiple update calls within a frame
|
|
if(Family.CurrentRealTime != LastRenderTime)
|
|
{
|
|
LastRenderTimeDelta = Family.CurrentRealTime - LastRenderTime;
|
|
LastRenderTime = Family.CurrentRealTime;
|
|
}
|
|
}
|
|
|
|
void TrimHistoryRenderTargets(const FScene* Scene);
|
|
|
|
/**
|
|
* Called every frame after UpdateLastRenderTime, sets up the information for the lagged temporal LOD transition
|
|
*/
|
|
void UpdateTemporalLODTransition(const FViewInfo& View)
|
|
{
|
|
TemporalLODState.UpdateTemporalLODTransition(View, LastRenderTime);
|
|
}
|
|
|
|
/**
|
|
* Returns an array of visibility data for the given view, or NULL if none exists.
|
|
* The data bits are indexed by VisibilityId of each primitive in the scene.
|
|
* This method decompresses data if necessary and caches it based on the bucket and chunk index in the view state.
|
|
*/
|
|
const uint8* GetPrecomputedVisibilityData(FViewInfo& View, const FScene* Scene);
|
|
|
|
/**
|
|
* Cleans out old entries from the primitive occlusion history, and resets unused pending occlusion queries.
|
|
* @param MinHistoryTime - The occlusion history for any primitives which have been visible and unoccluded since
|
|
* this time will be kept. The occlusion history for any primitives which haven't been
|
|
* visible and unoccluded since this time will be discarded.
|
|
* @param MinQueryTime - The pending occlusion queries older than this will be discarded.
|
|
*/
|
|
void TrimOcclusionHistory(FRHICommandListImmediate& RHICmdList, float MinHistoryTime, float MinQueryTime, int32 FrameNumber);
|
|
|
|
/**
|
|
* Checks whether a shadow is occluded this frame.
|
|
* @param Primitive - The shadow subject.
|
|
* @param Light - The shadow source.
|
|
*/
|
|
bool IsShadowOccluded(FRHICommandListImmediate& RHICmdList, FPrimitiveComponentId PrimitiveId, const ULightComponent* Light, int32 SplitIndex, bool bTranslucentShadow) const;
|
|
|
|
TRefCountPtr<IPooledRenderTarget>& GetEyeAdaptation()
|
|
{
|
|
// Create the texture needed for EyeAdaptation
|
|
FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::Create2DDesc(FIntPoint(1, 1), PF_R32_FLOAT, TexCreate_None, TexCreate_RenderTargetable, false));
|
|
GRenderTargetPool.FindFreeElement(Desc, EyeAdaptationRT, TEXT("EyeAdaptation"));
|
|
|
|
return EyeAdaptationRT;
|
|
}
|
|
|
|
TRefCountPtr<IPooledRenderTarget>& GetSeparateTranslucency(const FViewInfo& View)
|
|
{
|
|
// Create the SeparateTranslucency render target (alpha is needed to lerping)
|
|
FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::Create2DDesc(GSceneRenderTargets.GetBufferSizeXY(), PF_FloatRGBA, TexCreate_None, TexCreate_RenderTargetable, false));
|
|
GRenderTargetPool.FindFreeElement(Desc, SeparateTranslucencyRT, TEXT("SeparateTranslucency"));
|
|
|
|
return SeparateTranslucencyRT;
|
|
}
|
|
|
|
// FRenderResource interface.
|
|
virtual void InitDynamicRHI() override
|
|
{
|
|
HZBOcclusionTests.InitDynamicRHI();
|
|
}
|
|
|
|
virtual void ReleaseDynamicRHI() override
|
|
{
|
|
#if BUFFERED_OCCLUSION_QUERIES
|
|
for (int i = 0; i < ShadowOcclusionQueryMaps.Num(); ++i)
|
|
{
|
|
ShadowOcclusionQueryMaps[i].Reset();
|
|
}
|
|
#else
|
|
ShadowOcclusionQueryMap.Reset();
|
|
#endif
|
|
PrimitiveOcclusionHistorySet.Empty();
|
|
PrimitiveFadingStates.Empty();
|
|
OcclusionQueryPool.Release();
|
|
HZBOcclusionTests.ReleaseDynamicRHI();
|
|
EyeAdaptationRT.SafeRelease();
|
|
SeparateTranslucencyRT.SafeRelease();
|
|
TemporalAAHistoryRT.SafeRelease();
|
|
DOFHistoryRT.SafeRelease();
|
|
DOFHistoryRT2.SafeRelease();
|
|
SSRHistoryRT.SafeRelease();
|
|
LightShaftOcclusionHistoryRT.SafeRelease();
|
|
LightShaftBloomHistoryRTs.Empty();
|
|
DistanceFieldAOHistoryRT.SafeRelease();
|
|
DistanceFieldIrradianceHistoryRT.SafeRelease();
|
|
MobileAaBloomSunVignette0.SafeRelease();
|
|
MobileAaBloomSunVignette1.SafeRelease();
|
|
MobileAaColor0.SafeRelease();
|
|
MobileAaColor1.SafeRelease();
|
|
SelectionOutlineCacheKey.SafeRelease();
|
|
SelectionOutlineCacheValue.SafeRelease();
|
|
}
|
|
|
|
// FSceneViewStateInterface
|
|
RENDERER_API virtual void Destroy() override;
|
|
|
|
virtual void AddReferencedObjects(FReferenceCollector& Collector) override
|
|
{
|
|
uint32 Count = MIDPool.Num();
|
|
|
|
for(uint32 i = 0; i < Count; ++i)
|
|
{
|
|
UMaterialInstanceDynamic* MID = MIDPool[i];
|
|
|
|
Collector.AddReferencedObject(MID);
|
|
}
|
|
}
|
|
|
|
/** called in InitViews() */
|
|
virtual void OnStartFrame(FSceneView& CurrentView) override
|
|
{
|
|
check(IsInRenderingThread());
|
|
|
|
if(!(CurrentView.FinalPostProcessSettings.IndirectLightingColor * CurrentView.FinalPostProcessSettings.IndirectLightingIntensity).IsAlmostBlack())
|
|
{
|
|
CreateLightPropagationVolumeIfNeeded(CurrentView.GetFeatureLevel());
|
|
}
|
|
}
|
|
|
|
// needed for GetReusableMID()
|
|
virtual void OnStartPostProcessing(FSceneView& CurrentView) override
|
|
{
|
|
check(IsInGameThread());
|
|
|
|
if(CurrentView.Family->Views[0] == &CurrentView)
|
|
{
|
|
// Needs to be done once for all views, otherwise garbage collection goes wrong
|
|
MIDUsedCount = 0;
|
|
}
|
|
}
|
|
|
|
// Note: OnStartPostProcessing() needs to be called each frame for each view
|
|
virtual UMaterialInstanceDynamic* GetReusableMID(class UMaterialInterface* InParentMaterial) override
|
|
{
|
|
check(IsInGameThread());
|
|
check(InParentMaterial);
|
|
|
|
auto ParentAsMaterialInstance = Cast<UMaterialInstanceDynamic>(InParentMaterial);
|
|
|
|
// fixup MID parents as this is not allowed, take the next MIC or Material.
|
|
UMaterialInterface* ParentMaterial = ParentAsMaterialInstance ? ParentAsMaterialInstance->Parent : InParentMaterial;
|
|
|
|
// this is not allowed and would cause an error later in the code
|
|
check(!ParentMaterial->IsA(UMaterialInstanceDynamic::StaticClass()));
|
|
|
|
if(MIDUsedCount < (uint32)MIDPool.Num())
|
|
{
|
|
UMaterialInstanceDynamic* MID = MIDPool[MIDUsedCount];
|
|
|
|
if(MID->Parent != ParentMaterial)
|
|
{
|
|
// create a new one
|
|
// garbage collector will remove the old one
|
|
// this should not happen too often
|
|
MID = UMaterialInstanceDynamic::Create(ParentMaterial, 0);
|
|
MIDPool[MIDUsedCount] = MID;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UMaterialInstanceDynamic* MID = UMaterialInstanceDynamic::Create(ParentMaterial, 0);
|
|
check(MID);
|
|
|
|
MIDPool.Add(MID);
|
|
}
|
|
|
|
UMaterialInstanceDynamic* Ret = MIDPool[MIDUsedCount++];
|
|
|
|
check(Ret->GetRenderProxy(false));
|
|
|
|
return Ret;
|
|
}
|
|
|
|
virtual FTemporalLODState& GetTemporalLODState() override
|
|
{
|
|
return TemporalLODState;
|
|
}
|
|
virtual const FTemporalLODState& GetTemporalLODState() const override
|
|
{
|
|
return TemporalLODState;
|
|
}
|
|
float GetTemporalLODTransition() const override
|
|
{
|
|
return TemporalLODState.GetTemporalLODTransition(LastRenderTime);
|
|
}
|
|
uint32 GetViewKey() const override
|
|
{
|
|
return UniqueID;
|
|
}
|
|
|
|
|
|
|
|
// FDeferredCleanupInterface
|
|
virtual void FinishCleanup() override
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
virtual SIZE_T GetSizeBytes() const override;
|
|
|
|
|
|
/** Information about visibility/occlusion states in past frames for individual primitives. */
|
|
TSet<FPrimitiveOcclusionHistory,FPrimitiveOcclusionHistoryKeyFuncs> PrimitiveOcclusionHistorySet;
|
|
};
|
|
|
|
/** Rendering resource class that manages a cubemap array for reflections. */
|
|
class FReflectionEnvironmentCubemapArray : public FRenderResource
|
|
{
|
|
public:
|
|
|
|
FReflectionEnvironmentCubemapArray(ERHIFeatureLevel::Type InFeatureLevel) :
|
|
FRenderResource(InFeatureLevel)
|
|
, MaxCubemaps(0)
|
|
{}
|
|
|
|
virtual void InitDynamicRHI() override;
|
|
virtual void ReleaseDynamicRHI() override;
|
|
|
|
/**
|
|
* Updates the maximum number of cubemaps that this array is allocated for.
|
|
* This reallocates the resource but does not copy over the old contents.
|
|
*/
|
|
void UpdateMaxCubemaps(uint32 InMaxCubemaps);
|
|
int32 GetMaxCubemaps() const { return MaxCubemaps; }
|
|
bool IsValid() const { return IsValidRef(ReflectionEnvs); }
|
|
FSceneRenderTargetItem& GetRenderTarget() const { return ReflectionEnvs->GetRenderTargetItem(); }
|
|
|
|
protected:
|
|
uint32 MaxCubemaps;
|
|
TRefCountPtr<IPooledRenderTarget> ReflectionEnvs;
|
|
|
|
void ReleaseCubeArray();
|
|
};
|
|
|
|
/** Per-component reflection capture state that needs to persist through a re-register. */
|
|
class FCaptureComponentSceneState
|
|
{
|
|
public:
|
|
/** Index of the cubemap in the array for this capture component. */
|
|
int32 CaptureIndex;
|
|
|
|
FCaptureComponentSceneState(int32 InCaptureIndex) :
|
|
CaptureIndex(InCaptureIndex)
|
|
{}
|
|
|
|
bool operator==(const FCaptureComponentSceneState& Other) const
|
|
{
|
|
return CaptureIndex == Other.CaptureIndex;
|
|
}
|
|
};
|
|
|
|
/** Scene state used to manage the reflection environment feature. */
|
|
class FReflectionEnvironmentSceneData
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Set to true for one frame whenever RegisteredReflectionCaptures or the transforms of any registered reflection proxy has changed,
|
|
* Which allows one frame to update cached proxy associations.
|
|
*/
|
|
bool bRegisteredReflectionCapturesHasChanged;
|
|
|
|
/** The rendering thread's list of visible reflection captures in the scene. */
|
|
TArray<FReflectionCaptureProxy*> RegisteredReflectionCaptures;
|
|
TArray<FVector> RegisteredReflectionCapturePositions;
|
|
|
|
/**
|
|
* Cubemap array resource which contains the captured scene for each reflection capture.
|
|
* This is indexed by the value of AllocatedReflectionCaptureState.CaptureIndex.
|
|
*/
|
|
FReflectionEnvironmentCubemapArray CubemapArray;
|
|
|
|
/** Rendering thread map from component to scene state. This allows storage of RT state that needs to persist through a component re-register. */
|
|
TMap<const UReflectionCaptureComponent*, FCaptureComponentSceneState> AllocatedReflectionCaptureState;
|
|
|
|
/**
|
|
* Game thread list of reflection components that have been allocated in the cubemap array.
|
|
* These are not necessarily all visible or being rendered, but their scene state is stored in the cubemap array.
|
|
*/
|
|
TSparseArray<UReflectionCaptureComponent*> AllocatedReflectionCapturesGameThread;
|
|
|
|
/** Game thread tracking of what size this scene has allocated for the cubemap array. */
|
|
int32 MaxAllocatedReflectionCubemapsGameThread;
|
|
|
|
FReflectionEnvironmentSceneData(ERHIFeatureLevel::Type InFeatureLevel) :
|
|
bRegisteredReflectionCapturesHasChanged(true),
|
|
CubemapArray(InFeatureLevel),
|
|
MaxAllocatedReflectionCubemapsGameThread(0)
|
|
{}
|
|
};
|
|
|
|
class FPrimitiveAndInstance
|
|
{
|
|
public:
|
|
|
|
FPrimitiveAndInstance(FPrimitiveSceneInfo* InPrimitive, int32 InInstanceIndex) :
|
|
Primitive(InPrimitive),
|
|
InstanceIndex(InInstanceIndex)
|
|
{}
|
|
|
|
FPrimitiveSceneInfo* Primitive;
|
|
int32 InstanceIndex;
|
|
};
|
|
|
|
class FPrimitiveSurfelFreeEntry
|
|
{
|
|
public:
|
|
FPrimitiveSurfelFreeEntry(int32 InOffset, int32 InNumSurfels) :
|
|
Offset(InOffset),
|
|
NumSurfels(InNumSurfels)
|
|
{}
|
|
|
|
FPrimitiveSurfelFreeEntry() :
|
|
Offset(0),
|
|
NumSurfels(0)
|
|
{}
|
|
|
|
int32 Offset;
|
|
int32 NumSurfels;
|
|
};
|
|
|
|
class FPrimitiveSurfelAllocation
|
|
{
|
|
public:
|
|
FPrimitiveSurfelAllocation(int32 InOffset, int32 InNumLOD0, int32 InNumSurfels, int32 InNumInstances) :
|
|
Offset(InOffset),
|
|
NumLOD0(InNumLOD0),
|
|
NumSurfels(InNumSurfels),
|
|
NumInstances(InNumInstances)
|
|
{}
|
|
|
|
FPrimitiveSurfelAllocation() :
|
|
Offset(0),
|
|
NumLOD0(0),
|
|
NumSurfels(0),
|
|
NumInstances(1)
|
|
{}
|
|
|
|
int32 GetTotalNumSurfels() const
|
|
{
|
|
return NumSurfels * NumInstances;
|
|
}
|
|
|
|
int32 Offset;
|
|
int32 NumLOD0;
|
|
int32 NumSurfels;
|
|
int32 NumInstances;
|
|
};
|
|
|
|
class FPrimitiveRemoveInfo
|
|
{
|
|
public:
|
|
FPrimitiveRemoveInfo(const FPrimitiveSceneInfo* InPrimitive) :
|
|
Primitive(InPrimitive),
|
|
DistanceFieldInstanceIndices(Primitive->DistanceFieldInstanceIndices)
|
|
{}
|
|
|
|
/**
|
|
* Must not be dereferenced after creation, the primitive was removed from the scene and deleted
|
|
* Value of the pointer is still useful for map lookups
|
|
*/
|
|
const FPrimitiveSceneInfo* Primitive;
|
|
|
|
TArray<int32, TInlineAllocator<1>> DistanceFieldInstanceIndices;
|
|
};
|
|
|
|
class FSurfelBufferAllocator
|
|
{
|
|
public:
|
|
|
|
FSurfelBufferAllocator() : NumSurfelsInBuffer(0) {}
|
|
|
|
int32 GetNumSurfelsInBuffer() const { return NumSurfelsInBuffer; }
|
|
void AddPrimitive(const FPrimitiveSceneInfo* PrimitiveSceneInfo, int32 PrimitiveLOD0Surfels, int32 PrimitiveNumSurfels, int32 NumInstances);
|
|
void RemovePrimitive(const FPrimitiveSceneInfo* Primitive);
|
|
|
|
const FPrimitiveSurfelAllocation* FindAllocation(const FPrimitiveSceneInfo* Primitive)
|
|
{
|
|
return Allocations.Find(Primitive);
|
|
}
|
|
|
|
private:
|
|
|
|
int32 NumSurfelsInBuffer;
|
|
TMap<const FPrimitiveSceneInfo*, FPrimitiveSurfelAllocation> Allocations;
|
|
TArray<FPrimitiveSurfelFreeEntry> FreeList;
|
|
};
|
|
|
|
/** Scene data used to manage distance field object buffers on the GPU. */
|
|
class FDistanceFieldSceneData
|
|
{
|
|
public:
|
|
|
|
FDistanceFieldSceneData(EShaderPlatform ShaderPlatform);
|
|
~FDistanceFieldSceneData();
|
|
|
|
void AddPrimitive(FPrimitiveSceneInfo* InPrimitive);
|
|
void UpdatePrimitive(FPrimitiveSceneInfo* InPrimitive);
|
|
void RemovePrimitive(FPrimitiveSceneInfo* InPrimitive);
|
|
void Release();
|
|
void VerifyIntegrity();
|
|
|
|
bool HasPendingOperations() const
|
|
{
|
|
return PendingAddOperations.Num() > 0 || PendingUpdateOperations.Num() > 0 || PendingRemoveOperations.Num() > 0;
|
|
}
|
|
|
|
bool HasPendingRemovePrimitive(const FPrimitiveSceneInfo* Primitive) const
|
|
{
|
|
for (int32 RemoveIndex = 0; RemoveIndex < PendingRemoveOperations.Num(); RemoveIndex++)
|
|
{
|
|
if (PendingRemoveOperations[RemoveIndex].Primitive == Primitive)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
int32 NumObjectsInBuffer;
|
|
class FDistanceFieldObjectBuffers* ObjectBuffers;
|
|
|
|
/** Stores the primitive and instance index of every entry in the object buffer. */
|
|
TArray<FPrimitiveAndInstance> PrimitiveInstanceMapping;
|
|
TArray<const FPrimitiveSceneInfo*> HeightfieldPrimitives;
|
|
|
|
class FSurfelBuffers* SurfelBuffers;
|
|
FSurfelBufferAllocator SurfelAllocations;
|
|
|
|
class FInstancedSurfelBuffers* InstancedSurfelBuffers;
|
|
FSurfelBufferAllocator InstancedSurfelAllocations;
|
|
|
|
/** Pending operations on the object buffers to be processed next frame. */
|
|
TArray<FPrimitiveSceneInfo*> PendingAddOperations;
|
|
TSet<FPrimitiveSceneInfo*> PendingUpdateOperations;
|
|
TArray<FPrimitiveRemoveInfo> PendingRemoveOperations;
|
|
|
|
/** Used to detect atlas reallocations, since objects store UVs into the atlas and need to be updated when it changes. */
|
|
int32 AtlasGeneration;
|
|
|
|
bool bTrackPrimitives;
|
|
};
|
|
|
|
/** Stores data for an allocation in the FIndirectLightingCache. */
|
|
class FIndirectLightingCacheBlock
|
|
{
|
|
public:
|
|
|
|
FIndirectLightingCacheBlock() :
|
|
MinTexel(FIntVector(0, 0, 0)),
|
|
TexelSize(0),
|
|
Min(FVector(0, 0, 0)),
|
|
Size(FVector(0, 0, 0)),
|
|
bHasEverBeenUpdated(false)
|
|
{}
|
|
|
|
FIntVector MinTexel;
|
|
int32 TexelSize;
|
|
FVector Min;
|
|
FVector Size;
|
|
bool bHasEverBeenUpdated;
|
|
};
|
|
|
|
/** Stores information about an indirect lighting cache block to be updated. */
|
|
class FBlockUpdateInfo
|
|
{
|
|
public:
|
|
|
|
FBlockUpdateInfo(const FIndirectLightingCacheBlock& InBlock, FIndirectLightingCacheAllocation* InAllocation) :
|
|
Block(InBlock),
|
|
Allocation(InAllocation)
|
|
{}
|
|
|
|
FIndirectLightingCacheBlock Block;
|
|
FIndirectLightingCacheAllocation* Allocation;
|
|
};
|
|
|
|
/**
|
|
* Implements a volume texture atlas for caching indirect lighting on a per-object basis.
|
|
* The indirect lighting is interpolated from Lightmass SH volume lighting samples.
|
|
*/
|
|
class FIndirectLightingCache : public FRenderResource
|
|
{
|
|
public:
|
|
|
|
/** true for the editor case where we want a better preview for object that have no valid lightmaps */
|
|
FIndirectLightingCache(ERHIFeatureLevel::Type InFeatureLevel);
|
|
|
|
// FRenderResource interface
|
|
virtual void InitDynamicRHI();
|
|
virtual void ReleaseDynamicRHI();
|
|
|
|
/** Allocates a block in the volume texture atlas for a primitive. */
|
|
FIndirectLightingCacheAllocation* AllocatePrimitive(const FPrimitiveSceneInfo* PrimitiveSceneInfo, bool bUnbuiltPreview);
|
|
|
|
/** Releases the indirect lighting allocation for the given primitive. */
|
|
void ReleasePrimitive(FPrimitiveComponentId PrimitiveId);
|
|
|
|
FIndirectLightingCacheAllocation* FindPrimitiveAllocation(FPrimitiveComponentId PrimitiveId);
|
|
|
|
/** Updates indirect lighting in the cache based on visibility. */
|
|
void UpdateCache(FScene* Scene, FSceneRenderer& Renderer, bool bAllowUnbuiltPreview);
|
|
|
|
/** Force all primitive allocations to be re-interpolated. */
|
|
void SetLightingCacheDirty();
|
|
|
|
// Accessors
|
|
FSceneRenderTargetItem& GetTexture0() { return Texture0->GetRenderTargetItem(); }
|
|
FSceneRenderTargetItem& GetTexture1() { return Texture1->GetRenderTargetItem(); }
|
|
FSceneRenderTargetItem& GetTexture2() { return Texture2->GetRenderTargetItem(); }
|
|
|
|
private:
|
|
|
|
/** Internal helper which adds an entry to the update lists for this allocation, if needed (due to movement, etc). */
|
|
void UpdateCacheAllocation(
|
|
const FBoxSphereBounds& Bounds,
|
|
int32 BlockSize,
|
|
bool bPointSample,
|
|
FIndirectLightingCacheAllocation*& Allocation,
|
|
TMap<FIntVector, FBlockUpdateInfo>& BlocksToUpdate,
|
|
TArray<FIndirectLightingCacheAllocation*>& TransitionsOverTimeToUpdate);
|
|
|
|
/**
|
|
* Creates a new allocation if needed, caches the result in PrimitiveSceneInfo->IndirectLightingCacheAllocation,
|
|
* And adds an entry to the update lists when an update is needed.
|
|
*/
|
|
void UpdateCachePrimitive(
|
|
FScene* Scene,
|
|
FPrimitiveSceneInfo* PrimitiveSceneInfo,
|
|
bool bAllowUnbuiltPreview,
|
|
bool bOpaqueRelevance,
|
|
TMap<FIntVector, FBlockUpdateInfo>& BlocksToUpdate,
|
|
TArray<FIndirectLightingCacheAllocation*>& TransitionsOverTimeToUpdate);
|
|
|
|
/** Updates the contents of the volume texture blocks in BlocksToUpdate. */
|
|
void UpdateBlocks(FScene* Scene, FViewInfo* DebugDrawingView, TMap<FIntVector, FBlockUpdateInfo>& BlocksToUpdate);
|
|
|
|
/** Updates any outstanding transitions with a new delta time. */
|
|
void UpdateTransitionsOverTime(const TArray<FIndirectLightingCacheAllocation*>& TransitionsOverTimeToUpdate, float DeltaWorldTime) const;
|
|
|
|
/** Creates an allocation to be used outside the indirect lighting cache and a block to be used internally. */
|
|
FIndirectLightingCacheAllocation* CreateAllocation(int32 BlockSize, const FBoxSphereBounds& Bounds, bool bPointSample);
|
|
|
|
/** Block accessors. */
|
|
FIndirectLightingCacheBlock& FindBlock(FIntVector TexelMin);
|
|
const FIndirectLightingCacheBlock& FindBlock(FIntVector TexelMin) const;
|
|
|
|
/** Block operations. */
|
|
void DeallocateBlock(FIntVector Min, int32 Size);
|
|
bool AllocateBlock(int32 Size, FIntVector& OutMin);
|
|
|
|
/**
|
|
* Updates an allocation block in the cache, by re-interpolating values and uploading to the cache volume texture.
|
|
* @param DebugDrawingView can be 0
|
|
*/
|
|
void UpdateBlock(FScene* Scene, FViewInfo* DebugDrawingView, FBlockUpdateInfo& Block);
|
|
|
|
/** Interpolates a single SH sample from all levels. */
|
|
void InterpolatePoint(
|
|
FScene* Scene,
|
|
const FIndirectLightingCacheBlock& Block,
|
|
float& OutDirectionalShadowing,
|
|
FSHVectorRGB2& OutIncidentRadiance,
|
|
FVector& OutSkyBentNormal);
|
|
|
|
/** Interpolates SH samples for a block from all levels. */
|
|
void InterpolateBlock(
|
|
FScene* Scene,
|
|
const FIndirectLightingCacheBlock& Block,
|
|
TArray<float>& AccumulatedWeight,
|
|
TArray<FSHVectorRGB2>& AccumulatedIncidentRadiance,
|
|
TArray<FVector>& AccumulatedSkyBentNormal);
|
|
|
|
/**
|
|
* Normalizes, adjusts for SH ringing, and encodes SH samples into a texture format.
|
|
* @param DebugDrawingView can be 0
|
|
*/
|
|
void EncodeBlock(
|
|
FViewInfo* DebugDrawingView,
|
|
const FIndirectLightingCacheBlock& Block,
|
|
const TArray<float>& AccumulatedWeight,
|
|
const TArray<FSHVectorRGB2>& AccumulatedIncidentRadiance,
|
|
const TArray<FVector>& AccumulatedSkyBentNormal,
|
|
TArray<FFloat16Color>& Texture0Data,
|
|
TArray<FFloat16Color>& Texture1Data,
|
|
TArray<FFloat16Color>& Texture2Data,
|
|
FSHVectorRGB2& SingleSample,
|
|
FVector& SkyBentNormal);
|
|
|
|
/** Helper that calculates an effective world position min and size given a bounds. */
|
|
void CalculateBlockPositionAndSize(const FBoxSphereBounds& Bounds, int32 TexelSize, FVector& OutMin, FVector& OutSize) const;
|
|
|
|
/** Helper that calculates a scale and add to convert world space position into volume texture UVs for a given block. */
|
|
void CalculateBlockScaleAndAdd(FIntVector InTexelMin, int32 AllocationTexelSize, FVector InMin, FVector InSize, FVector& OutScale, FVector& OutAdd, FVector& OutMinUV, FVector& OutMaxUV) const;
|
|
|
|
/** true: next rendering we update all entries no matter if they are visible to avoid further hitches */
|
|
bool bUpdateAllCacheEntries;
|
|
|
|
/** Size of the volume texture cache. */
|
|
int32 CacheSize;
|
|
|
|
/** Volume textures that store SH indirect lighting, interpolated from Lightmass volume samples. */
|
|
TRefCountPtr<IPooledRenderTarget> Texture0;
|
|
TRefCountPtr<IPooledRenderTarget> Texture1;
|
|
TRefCountPtr<IPooledRenderTarget> Texture2;
|
|
|
|
/** Tracks the allocation state of the atlas. */
|
|
TMap<FIntVector, FIndirectLightingCacheBlock> VolumeBlocks;
|
|
|
|
/** Tracks used sections of the volume texture atlas. */
|
|
FTextureLayout3d BlockAllocator;
|
|
|
|
/** Tracks primitive allocations by component, so that they persist across re-registers. */
|
|
TMap<FPrimitiveComponentId, FIndirectLightingCacheAllocation*> PrimitiveAllocations;
|
|
};
|
|
|
|
/**
|
|
* Bounding information used to cull primitives in the scene.
|
|
*/
|
|
struct FPrimitiveBounds
|
|
{
|
|
/** Origin of the primitive. */
|
|
FVector Origin;
|
|
/** Radius of the bounding sphere. */
|
|
float SphereRadius;
|
|
/** Extents of the axis-aligned bounding box. */
|
|
FVector BoxExtent;
|
|
/** Square of the minimum draw distance for the primitive. */
|
|
float MinDrawDistanceSq;
|
|
/** Maximum draw distance for the primitive. */
|
|
float MaxDrawDistance;
|
|
};
|
|
|
|
/**
|
|
* Precomputed primitive visibility ID.
|
|
*/
|
|
struct FPrimitiveVisibilityId
|
|
{
|
|
/** Index in to the byte where precomputed occlusion data is stored. */
|
|
int32 ByteIndex;
|
|
/** Mast of the bit where precomputed occlusion data is stored. */
|
|
uint8 BitMask;
|
|
};
|
|
|
|
/**
|
|
* Flags that affect how primitives are occlusion culled.
|
|
*/
|
|
namespace EOcclusionFlags
|
|
{
|
|
enum Type
|
|
{
|
|
/** No flags. */
|
|
None = 0x0,
|
|
/** Indicates the primitive can be occluded. */
|
|
CanBeOccluded = 0x1,
|
|
/** Allow the primitive to be batched with others to determine occlusion. */
|
|
AllowApproximateOcclusion = 0x4,
|
|
/** Indicates the primitive has a valid ID for precomputed visibility. */
|
|
HasPrecomputedVisibility = 0x8,
|
|
/** Indicates the primitive has a valid ID for precomputed visibility. */
|
|
HasSubprimitiveQueries = 0x10,
|
|
};
|
|
};
|
|
|
|
/** Information about the primitives that are attached together. */
|
|
class FAttachmentGroupSceneInfo
|
|
{
|
|
public:
|
|
|
|
/** The parent primitive, which is the root of the attachment tree. */
|
|
FPrimitiveSceneInfo* ParentSceneInfo;
|
|
|
|
/** The primitives in the attachment group. */
|
|
TArray<FPrimitiveSceneInfo*> Primitives;
|
|
|
|
FAttachmentGroupSceneInfo() :
|
|
ParentSceneInfo(nullptr)
|
|
{}
|
|
};
|
|
|
|
class FLODSceneTree
|
|
{
|
|
public:
|
|
FLODSceneTree(FScene* InScene)
|
|
: Scene(InScene)
|
|
, UpdateCount(0)
|
|
{}
|
|
|
|
/** Information about the primitives that are attached together. */
|
|
struct FLODSceneNode
|
|
{
|
|
/** The primitive. */
|
|
FPrimitiveSceneInfo* SceneInfo;
|
|
|
|
/** Children scene infos. */
|
|
TArray<FPrimitiveSceneInfo*> ChildrenSceneInfos;
|
|
|
|
/** Last updated FrameCount */
|
|
int32 LatestUpdateCount;
|
|
|
|
FLODSceneNode() :
|
|
SceneInfo(nullptr),
|
|
LatestUpdateCount(INDEX_NONE)
|
|
{}
|
|
|
|
void AddChild(FPrimitiveSceneInfo * NewChild)
|
|
{
|
|
if(NewChild && !ChildrenSceneInfos.Contains(NewChild))
|
|
{
|
|
ChildrenSceneInfos.Add(NewChild);
|
|
}
|
|
}
|
|
|
|
void RemoveChild(FPrimitiveSceneInfo * ChildToDelete)
|
|
{
|
|
if(ChildToDelete && ChildrenSceneInfos.Contains(ChildToDelete))
|
|
{
|
|
ChildrenSceneInfos.Remove(ChildToDelete);
|
|
}
|
|
}
|
|
};
|
|
|
|
void AddChildNode(FPrimitiveComponentId NodeId, FPrimitiveSceneInfo* ChildSceneInfo);
|
|
void RemoveChildNode(FPrimitiveComponentId NodeId, FPrimitiveSceneInfo* ChildSceneInfo);
|
|
|
|
void UpdateNodeSceneInfo(FPrimitiveComponentId NodeId, FPrimitiveSceneInfo* SceneInfo);
|
|
void PopulateHiddenFlags(FViewInfo& View, FSceneBitArray& HiddenFlags);
|
|
|
|
bool IsActive() { return SceneNodes.Num() > 0; }
|
|
|
|
private:
|
|
/** Scene this Tree belong to */
|
|
FScene* Scene;
|
|
|
|
/** The LOd groups in the scene. The map key is the current primitive who has children. */
|
|
TMap<FPrimitiveComponentId, FLODSceneNode> SceneNodes;
|
|
|
|
/** Update Count. This is used to skip Child node that has been updated */
|
|
int32 UpdateCount;
|
|
|
|
/** Populate Hidden Flags to the children **/
|
|
void PopulateHiddenFlagsToChildren(FSceneBitArray& HiddenFlags, FLODSceneNode& Node);
|
|
};
|
|
|
|
typedef TMap<FMaterial*, FMaterialShaderMap*> FMaterialsToUpdateMap;
|
|
|
|
/**
|
|
* Renderer scene which is private to the renderer module.
|
|
* Ordinarily this is the renderer version of a UWorld, but an FScene can be created for previewing in editors which don't have a UWorld as well.
|
|
* The scene stores renderer state that is independent of any view or frame, with the primary actions being adding and removing of primitives and lights.
|
|
*/
|
|
class FScene : public FSceneInterface
|
|
{
|
|
public:
|
|
|
|
/** An optional world associated with the scene. */
|
|
UWorld* World;
|
|
|
|
/** An optional FX system associated with the scene. */
|
|
class FFXSystemInterface* FXSystem;
|
|
|
|
enum EBasePassDrawListType
|
|
{
|
|
EBasePass_Default=0,
|
|
EBasePass_Masked,
|
|
EBasePass_MAX
|
|
};
|
|
|
|
// various static draw lists for this DPG
|
|
|
|
/** position-only opaque depth draw list */
|
|
TStaticMeshDrawList<FPositionOnlyDepthDrawingPolicy> PositionOnlyDepthDrawList;
|
|
/** opaque depth draw list */
|
|
TStaticMeshDrawList<FDepthDrawingPolicy> DepthDrawList;
|
|
/** masked depth draw list */
|
|
TStaticMeshDrawList<FDepthDrawingPolicy> MaskedDepthDrawList;
|
|
/** Base pass draw list - no light map */
|
|
TStaticMeshDrawList<TBasePassDrawingPolicy<FNoLightMapPolicy> > BasePassNoLightMapDrawList[EBasePass_MAX];
|
|
TStaticMeshDrawList<TBasePassDrawingPolicy<FCachedVolumeIndirectLightingPolicy> > BasePassCachedVolumeIndirectLightingDrawList[EBasePass_MAX];
|
|
TStaticMeshDrawList<TBasePassDrawingPolicy<FCachedPointIndirectLightingPolicy> > BasePassCachedPointIndirectLightingDrawList[EBasePass_MAX];
|
|
/** Base pass draw list - no light map */
|
|
TStaticMeshDrawList<TBasePassDrawingPolicy<FSimpleDynamicLightingPolicy> > BasePassSimpleDynamicLightingDrawList[EBasePass_MAX];
|
|
/** Base pass draw list - HQ light maps */
|
|
TStaticMeshDrawList<TBasePassDrawingPolicy< TLightMapPolicy<HQ_LIGHTMAP> > > BasePassHighQualityLightMapDrawList[EBasePass_MAX];
|
|
/** Base pass draw list - HQ light maps */
|
|
TStaticMeshDrawList<TBasePassDrawingPolicy< TDistanceFieldShadowsAndLightMapPolicy<HQ_LIGHTMAP> > > BasePassDistanceFieldShadowMapLightMapDrawList[EBasePass_MAX];
|
|
/** Base pass draw list - LQ light maps */
|
|
TStaticMeshDrawList<TBasePassDrawingPolicy< TLightMapPolicy<LQ_LIGHTMAP> > > BasePassLowQualityLightMapDrawList[EBasePass_MAX];
|
|
/** Base pass draw list - self shadowed translucency*/
|
|
TStaticMeshDrawList<TBasePassDrawingPolicy<FSelfShadowedTranslucencyPolicy> > BasePassSelfShadowedTranslucencyDrawList[EBasePass_MAX];
|
|
TStaticMeshDrawList<TBasePassDrawingPolicy<FSelfShadowedCachedPointIndirectLightingPolicy> > BasePassSelfShadowedCachedPointIndirectTranslucencyDrawList[EBasePass_MAX];
|
|
|
|
/** hit proxy draw list (includes both opaque and translucent objects) */
|
|
TStaticMeshDrawList<FHitProxyDrawingPolicy> HitProxyDrawList;
|
|
|
|
/** hit proxy draw list, with only opaque objects */
|
|
TStaticMeshDrawList<FHitProxyDrawingPolicy> HitProxyDrawList_OpaqueOnly;
|
|
|
|
/** draw list for motion blur velocities */
|
|
TStaticMeshDrawList<FVelocityDrawingPolicy> VelocityDrawList;
|
|
|
|
/** Draw list used for rendering whole scene shadow depths. */
|
|
TStaticMeshDrawList<FShadowDepthDrawingPolicy<false> > WholeSceneShadowDepthDrawList;
|
|
|
|
/** Draw list used for rendering whole scene reflective shadow maps. */
|
|
TStaticMeshDrawList<FShadowDepthDrawingPolicy<true> > WholeSceneReflectiveShadowMapDrawList;
|
|
|
|
/** Maps a light-map type to the appropriate base pass draw list. */
|
|
template<typename LightMapPolicyType>
|
|
TStaticMeshDrawList<TBasePassDrawingPolicy<LightMapPolicyType> >& GetBasePassDrawList(EBasePassDrawListType DrawType);
|
|
|
|
/** Forward shading base pass draw lists */
|
|
TStaticMeshDrawList<TBasePassForForwardShadingDrawingPolicy<FNoLightMapPolicy> > BasePassForForwardShadingNoLightMapDrawList[EBasePass_MAX];
|
|
TStaticMeshDrawList< TBasePassForForwardShadingDrawingPolicy< TLightMapPolicy<LQ_LIGHTMAP> > > BasePassForForwardShadingLowQualityLightMapDrawList[EBasePass_MAX];
|
|
TStaticMeshDrawList< TBasePassForForwardShadingDrawingPolicy< TDistanceFieldShadowsAndLightMapPolicy<LQ_LIGHTMAP> > > BasePassForForwardShadingDistanceFieldShadowMapLightMapDrawList[EBasePass_MAX];
|
|
TStaticMeshDrawList<TBasePassForForwardShadingDrawingPolicy< FSimpleDirectionalLightAndSHIndirectPolicy > > BasePassForForwardShadingDirectionalLightAndSHIndirectDrawList[EBasePass_MAX];
|
|
TStaticMeshDrawList<TBasePassForForwardShadingDrawingPolicy< FSimpleDirectionalLightAndSHDirectionalIndirectPolicy > > BasePassForForwardShadingDirectionalLightAndSHDirectionalIndirectDrawList[EBasePass_MAX];
|
|
TStaticMeshDrawList<TBasePassForForwardShadingDrawingPolicy< FSimpleDirectionalLightAndSHDirectionalCSMIndirectPolicy > > BasePassForForwardShadingDirectionalLightAndSHDirectionalCSMIndirectDrawList[EBasePass_MAX];
|
|
TStaticMeshDrawList<TBasePassForForwardShadingDrawingPolicy< FMovableDirectionalLightLightingPolicy > > BasePassForForwardShadingMovableDirectionalLightDrawList[EBasePass_MAX];
|
|
TStaticMeshDrawList<TBasePassForForwardShadingDrawingPolicy< FMovableDirectionalLightCSMLightingPolicy > > BasePassForForwardShadingMovableDirectionalLightCSMDrawList[EBasePass_MAX];
|
|
TStaticMeshDrawList<TBasePassForForwardShadingDrawingPolicy< FMovableDirectionalLightWithLightmapLightingPolicy> > BasePassForForwardShadingMovableDirectionalLightLightmapDrawList[EBasePass_MAX];
|
|
TStaticMeshDrawList<TBasePassForForwardShadingDrawingPolicy< FMovableDirectionalLightCSMWithLightmapLightingPolicy> > BasePassForForwardShadingMovableDirectionalLightCSMLightmapDrawList[EBasePass_MAX];
|
|
|
|
/** Maps a light-map type to the appropriate base pass draw list. */
|
|
template<typename LightMapPolicyType>
|
|
TStaticMeshDrawList<TBasePassForForwardShadingDrawingPolicy<LightMapPolicyType> >& GetForwardShadingBasePassDrawList(EBasePassDrawListType DrawType);
|
|
|
|
/**
|
|
* The following arrays are densely packed primitive data needed by various
|
|
* rendering passes. PrimitiveSceneInfo->PackedIndex maintains the index
|
|
* where data is stored in these arrays for a given primitive.
|
|
*/
|
|
|
|
/** Packed array of primitives in the scene. */
|
|
TArray<FPrimitiveSceneInfo*> Primitives;
|
|
/** Packed array of primitive bounds. */
|
|
TArray<FPrimitiveBounds> PrimitiveBounds;
|
|
/** Packed array of precomputed primitive visibility IDs. */
|
|
TArray<FPrimitiveVisibilityId> PrimitiveVisibilityIds;
|
|
/** Packed array of primitive occlusion flags. See EOcclusionFlags. */
|
|
TArray<uint8> PrimitiveOcclusionFlags;
|
|
/** Packed array of primitive occlusion bounds. */
|
|
TArray<FBoxSphereBounds> PrimitiveOcclusionBounds;
|
|
/** Packed array of primitive components associated with the primitive. */
|
|
TArray<FPrimitiveComponentId> PrimitiveComponentIds;
|
|
|
|
/** The lights in the scene. */
|
|
TSparseArray<FLightSceneInfoCompact> Lights;
|
|
|
|
/**
|
|
* Lights in the scene which are invisible, but still needed by the editor for previewing.
|
|
* Lights in this array cannot be in the Lights array. They also are not fully set up, as AddLightSceneInfo_RenderThread is not called for them.
|
|
*/
|
|
TSparseArray<FLightSceneInfoCompact> InvisibleLights;
|
|
|
|
/** The mobile quality level for which static draw lists have been built. */
|
|
bool bStaticDrawListsMobileHDR;
|
|
bool bStaticDrawListsMobileHDR32bpp;
|
|
|
|
/** Whether the early Z pass was force enabled when static draw lists were built. */
|
|
int32 StaticDrawListsEarlyZPassMode;
|
|
|
|
/** True if a change to SkyLight / Lighting has occurred that requires static draw lists to be updated. */
|
|
bool bScenesPrimitivesNeedStaticMeshElementUpdate;
|
|
|
|
/** The scene's sky light, if any. */
|
|
FSkyLightSceneProxy* SkyLight;
|
|
|
|
/** Used to track the order that skylights were enabled in. */
|
|
TArray<FSkyLightSceneProxy*> SkyLightStack;
|
|
|
|
/** The directional light to use for simple dynamic lighting, if any. */
|
|
FLightSceneInfo* SimpleDirectionalLight;
|
|
|
|
/** The sun light for atmospheric effect, if any. */
|
|
FLightSceneInfo* SunLight;
|
|
|
|
/** The decals in the scene. */
|
|
TSparseArray<FDeferredDecalProxy*> Decals;
|
|
|
|
/** State needed for the reflection environment feature. */
|
|
FReflectionEnvironmentSceneData ReflectionSceneData;
|
|
|
|
/**
|
|
* 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;
|
|
|
|
/** Scene state of distance field AO. NULL if the scene doesn't use the feature. */
|
|
class FSurfaceCacheResources* SurfaceCacheResources;
|
|
|
|
/** Distance field object scene data. */
|
|
FDistanceFieldSceneData DistanceFieldSceneData;
|
|
|
|
/** Preshadows that are currently cached in the PreshadowCache render target. */
|
|
TArray<TRefCountPtr<FProjectedShadowInfo> > CachedPreshadows;
|
|
|
|
/** Texture layout that tracks current allocations in the PreshadowCache render target. */
|
|
FTextureLayout PreshadowCacheLayout;
|
|
|
|
/** The static meshes in the scene. */
|
|
TSparseArray<FStaticMesh*> StaticMeshes;
|
|
|
|
/** The exponential fog components in the scene. */
|
|
TArray<FExponentialHeightFogSceneInfo> ExponentialFogs;
|
|
|
|
/** The atmospheric fog components in the scene. */
|
|
FAtmosphericFogSceneInfo* AtmosphericFog;
|
|
|
|
/** The wind sources in the scene. */
|
|
TArray<class FWindSourceSceneProxy*> WindSources;
|
|
|
|
/** SpeedTree wind objects in the scene. FLocalVertexFactoryShaderParameters needs to lookup by FVertexFactory, but wind objects are per tree (i.e. per UStaticMesh)*/
|
|
TMap<const UStaticMesh*, struct FSpeedTreeWindComputation*> SpeedTreeWindComputationMap;
|
|
TMap<FVertexFactory*, const UStaticMesh*> SpeedTreeVertexFactoryMap;
|
|
|
|
/** The attachment groups in the scene. The map key is the attachment group's root primitive. */
|
|
TMap<FPrimitiveComponentId,FAttachmentGroupSceneInfo> AttachmentGroups;
|
|
|
|
/** Precomputed visibility data for the scene. */
|
|
const FPrecomputedVisibilityHandler* PrecomputedVisibilityHandler;
|
|
|
|
/** An octree containing the shadow casting lights in the scene. */
|
|
FSceneLightOctree LightOctree;
|
|
|
|
/** An octree containing the primitives in the scene. */
|
|
FScenePrimitiveOctree PrimitiveOctree;
|
|
|
|
/** Indicates whether this scene requires hit proxy rendering. */
|
|
bool bRequiresHitProxies;
|
|
|
|
/** Whether this is an editor scene. */
|
|
bool bIsEditorScene;
|
|
|
|
/** Set by the rendering thread to signal to the game thread that the scene needs a static lighting build. */
|
|
volatile mutable int32 NumUncachedStaticLightingInteractions;
|
|
|
|
FLinearColor UpperDynamicSkylightColor;
|
|
FLinearColor LowerDynamicSkylightColor;
|
|
|
|
FMotionBlurInfoData MotionBlurInfoData;
|
|
|
|
/** Uniform buffers for parameter collections with the corresponding Ids. */
|
|
TMap<FGuid, FUniformBufferRHIRef> ParameterCollections;
|
|
|
|
/** LOD Tree Holder for massive LOD system */
|
|
FLODSceneTree SceneLODHierarchy;
|
|
|
|
/** Initialization constructor. */
|
|
FScene(UWorld* InWorld, bool bInRequiresHitProxies,bool bInIsEditorScene, bool bCreateFXSystem, ERHIFeatureLevel::Type InFeatureLevel);
|
|
|
|
virtual ~FScene();
|
|
|
|
// FSceneInterface interface.
|
|
virtual void AddPrimitive(UPrimitiveComponent* Primitive) override;
|
|
virtual void RemovePrimitive(UPrimitiveComponent* Primitive) override;
|
|
virtual void ReleasePrimitive(UPrimitiveComponent* Primitive) override;
|
|
virtual void UpdatePrimitiveTransform(UPrimitiveComponent* Primitive) override;
|
|
virtual void UpdatePrimitiveAttachment(UPrimitiveComponent* Primitive) override;
|
|
virtual void AddLight(ULightComponent* Light) override;
|
|
virtual void RemoveLight(ULightComponent* Light) override;
|
|
virtual void AddInvisibleLight(ULightComponent* Light) override;
|
|
virtual void SetSkyLight(FSkyLightSceneProxy* Light) override;
|
|
virtual void DisableSkyLight(FSkyLightSceneProxy* Light) override;
|
|
virtual void AddDecal(UDecalComponent* Component) override;
|
|
virtual void RemoveDecal(UDecalComponent* Component) override;
|
|
virtual void UpdateDecalTransform(UDecalComponent* Decal) override;
|
|
virtual void AddReflectionCapture(UReflectionCaptureComponent* Component) override;
|
|
virtual void RemoveReflectionCapture(UReflectionCaptureComponent* Component) override;
|
|
virtual void GetReflectionCaptureData(UReflectionCaptureComponent* Component, class FReflectionCaptureFullHDRDerivedData& OutDerivedData) override;
|
|
virtual void UpdateReflectionCaptureTransform(UReflectionCaptureComponent* Component) override;
|
|
virtual void ReleaseReflectionCubemap(UReflectionCaptureComponent* CaptureComponent) override;
|
|
virtual void UpdateSceneCaptureContents(class USceneCaptureComponent2D* CaptureComponent) override;
|
|
virtual void UpdateSceneCaptureContents(class USceneCaptureComponentCube* CaptureComponent) override;
|
|
virtual void AllocateReflectionCaptures(const TArray<UReflectionCaptureComponent*>& NewCaptures) override;
|
|
virtual void UpdateSkyCaptureContents(const USkyLightComponent* CaptureComponent, bool bCaptureEmissiveOnly, FTexture* OutProcessedTexture, FSHVectorRGB3& OutIrradianceEnvironmentMap) override;
|
|
virtual void AddPrecomputedLightVolume(const class FPrecomputedLightVolume* Volume) override;
|
|
virtual void RemovePrecomputedLightVolume(const class FPrecomputedLightVolume* Volume) override;
|
|
virtual void UpdateLightTransform(ULightComponent* Light) override;
|
|
virtual void UpdateLightColorAndBrightness(ULightComponent* Light) override;
|
|
virtual void UpdateDynamicSkyLight(const FLinearColor& UpperColor, const FLinearColor& LowerColor) override;
|
|
virtual void AddExponentialHeightFog(UExponentialHeightFogComponent* FogComponent) override;
|
|
virtual void RemoveExponentialHeightFog(UExponentialHeightFogComponent* FogComponent) override;
|
|
virtual void AddAtmosphericFog(UAtmosphericFogComponent* FogComponent) override;
|
|
virtual void RemoveAtmosphericFog(UAtmosphericFogComponent* FogComponent) override;
|
|
virtual FAtmosphericFogSceneInfo* GetAtmosphericFogSceneInfo() override { return AtmosphericFog; }
|
|
virtual void AddWindSource(UWindDirectionalSourceComponent* WindComponent) override;
|
|
virtual void RemoveWindSource(UWindDirectionalSourceComponent* WindComponent) override;
|
|
virtual const TArray<FWindSourceSceneProxy*>& GetWindSources_RenderThread() const override;
|
|
virtual void GetWindParameters(const FVector& Position, FVector& OutDirection, float& OutSpeed, float& OutMinGustAmt, float& OutMaxGustAmt) const override;
|
|
virtual void GetDirectionalWindParameters(FVector& OutDirection, float& OutSpeed, float& OutMinGustAmt, float& OutMaxGustAmt) const override;
|
|
virtual void AddSpeedTreeWind(FVertexFactory* VertexFactory, const UStaticMesh* StaticMesh) override;
|
|
virtual void RemoveSpeedTreeWind(FVertexFactory* VertexFactory, const UStaticMesh* StaticMesh) override;
|
|
virtual void RemoveSpeedTreeWind_RenderThread(FVertexFactory* VertexFactory, const UStaticMesh* StaticMesh) override;
|
|
virtual void UpdateSpeedTreeWind(double CurrentTime) override;
|
|
virtual FUniformBufferRHIParamRef GetSpeedTreeUniformBuffer(const FVertexFactory* VertexFactory) override;
|
|
virtual void DumpUnbuiltLightIteractions( FOutputDevice& Ar ) const override;
|
|
virtual void DumpStaticMeshDrawListStats() const override;
|
|
virtual void SetClearMotionBlurInfoGameThread() override;
|
|
virtual void UpdateParameterCollections(const TArray<FMaterialParameterCollectionInstanceResource*>& InParameterCollections) override;
|
|
|
|
/** Determines whether the scene has dynamic sky lighting. */
|
|
bool HasDynamicSkyLighting() const
|
|
{
|
|
return (!UpperDynamicSkylightColor.Equals(FLinearColor::Black) || !LowerDynamicSkylightColor.Equals(FLinearColor::Black));
|
|
}
|
|
|
|
/** Determines whether the scene has atmospheric fog and sun light. */
|
|
bool HasAtmosphericFog() const
|
|
{
|
|
return (AtmosphericFog != NULL); // Use default value when Sun Light is not existing
|
|
}
|
|
|
|
/**
|
|
* Retrieves the lights interacting with the passed in primitive and adds them to the out array.
|
|
*
|
|
* @param Primitive Primitive to retrieve interacting lights for
|
|
* @param RelevantLights [out] Array of lights interacting with primitive
|
|
*/
|
|
virtual void GetRelevantLights( UPrimitiveComponent* Primitive, TArray<const ULightComponent*>* RelevantLights ) const override;
|
|
|
|
/** Sets the precomputed visibility handler for the scene, or NULL to clear the current one. */
|
|
virtual void SetPrecomputedVisibility(const FPrecomputedVisibilityHandler* PrecomputedVisibilityHandler) override;
|
|
|
|
/** Sets shader maps on the specified materials without blocking. */
|
|
virtual void SetShaderMapsOnMaterialResources(const TMap<FMaterial*, class FMaterialShaderMap*>& MaterialsToUpdate) override;
|
|
|
|
/** Updates static draw lists for the given set of materials. */
|
|
virtual void UpdateStaticDrawListsForMaterials(const TArray<const FMaterial*>& Materials) override;
|
|
|
|
virtual void Release() override;
|
|
virtual UWorld* GetWorld() const override { return World; }
|
|
|
|
/** Finds the closest reflection capture to a point in space. */
|
|
const FReflectionCaptureProxy* FindClosestReflectionCapture(FVector Position) const;
|
|
|
|
/**
|
|
* Gets the scene's cubemap array and index into that array for the given reflection proxy.
|
|
* If the proxy was not found in the scene's reflection state, the outputs are not written to.
|
|
*/
|
|
void GetCaptureParameters(const FReflectionCaptureProxy* ReflectionProxy, FTextureRHIParamRef& ReflectionCubemapArray, int32& ArrayIndex) const;
|
|
|
|
/**
|
|
* Marks static mesh elements as needing an update if necessary.
|
|
*/
|
|
void ConditionalMarkStaticMeshElementsForUpdate();
|
|
|
|
/**
|
|
* @return true if hit proxies should be rendered in this scene.
|
|
*/
|
|
virtual bool RequiresHitProxies() const override;
|
|
|
|
SIZE_T GetSizeBytes() const;
|
|
|
|
/**
|
|
* Return the scene to be used for rendering
|
|
*/
|
|
virtual class FScene* GetRenderScene() override
|
|
{
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the FX system associated with the scene.
|
|
*/
|
|
virtual void SetFXSystem( class FFXSystemInterface* InFXSystem ) override;
|
|
|
|
/**
|
|
* Get the FX system associated with the scene.
|
|
*/
|
|
virtual class FFXSystemInterface* GetFXSystem() override;
|
|
|
|
/**
|
|
* Exports the scene.
|
|
*
|
|
* @param Ar The Archive used for exporting.
|
|
**/
|
|
virtual void Export( FArchive& Ar ) const override;
|
|
|
|
FUniformBufferRHIParamRef GetParameterCollectionBuffer(const FGuid& InId) const
|
|
{
|
|
const FUniformBufferRHIRef* ExistingUniformBuffer = ParameterCollections.Find(InId);
|
|
|
|
if (ExistingUniformBuffer)
|
|
{
|
|
return *ExistingUniformBuffer;
|
|
}
|
|
|
|
return FUniformBufferRHIParamRef();
|
|
}
|
|
|
|
virtual void ApplyWorldOffset(FVector InOffset) override;
|
|
|
|
virtual void OnLevelAddedToWorld(FName InLevelName) override;
|
|
|
|
virtual bool HasAnyLights() const override
|
|
{
|
|
check(IsInGameThread());
|
|
return NumVisibleLights_GameThread > 0 || NumEnabledSkylights_GameThread > 0;
|
|
}
|
|
|
|
virtual bool IsEditorScene() const override { return bIsEditorScene; }
|
|
|
|
virtual ERHIFeatureLevel::Type GetFeatureLevel() const override { return FeatureLevel; }
|
|
|
|
bool ShouldRenderSkylight() const
|
|
{
|
|
return SkyLight && !SkyLight->bHasStaticLighting && GSupportsRenderTargetFormat_PF_FloatRGBA;
|
|
}
|
|
|
|
virtual TArray<FPrimitiveComponentId> GetScenePrimitiveComponentIds() const override
|
|
{
|
|
return PrimitiveComponentIds;
|
|
}
|
|
|
|
private:
|
|
|
|
/**
|
|
* Ensures the packed primitive arrays contain the same number of elements.
|
|
*/
|
|
void CheckPrimitiveArrays();
|
|
|
|
/**
|
|
* Retrieves the lights interacting with the passed in primitive and adds them to the out array.
|
|
* Render thread version of function.
|
|
* @param Primitive Primitive to retrieve interacting lights for
|
|
* @param RelevantLights [out] Array of lights interacting with primitive
|
|
*/
|
|
void GetRelevantLights_RenderThread( UPrimitiveComponent* Primitive, TArray<const ULightComponent*>* RelevantLights ) const;
|
|
|
|
/**
|
|
* Adds a primitive to the scene. Called in the rendering thread by AddPrimitive.
|
|
* @param PrimitiveSceneInfo - The primitive being added.
|
|
*/
|
|
void AddPrimitiveSceneInfo_RenderThread(FRHICommandListImmediate& RHICmdList, FPrimitiveSceneInfo* PrimitiveSceneInfo);
|
|
|
|
/**
|
|
* Removes a primitive from the scene. Called in the rendering thread by RemovePrimitive.
|
|
* @param PrimitiveSceneInfo - The primitive being removed.
|
|
*/
|
|
void RemovePrimitiveSceneInfo_RenderThread(FPrimitiveSceneInfo* PrimitiveSceneInfo);
|
|
|
|
/** Updates a primitive's transform, called on the rendering thread. */
|
|
void UpdatePrimitiveTransform_RenderThread(FRHICommandListImmediate& RHICmdList, FPrimitiveSceneProxy* PrimitiveSceneProxy, const FBoxSphereBounds& WorldBounds, const FBoxSphereBounds& LocalBounds, const FMatrix& LocalToWorld, const FVector& OwnerPosition);
|
|
|
|
/** Updates a single primitive's lighting attachment root. */
|
|
void UpdatePrimitiveLightingAttachmentRoot(UPrimitiveComponent* Primitive);
|
|
|
|
/**
|
|
* Adds a light to the scene. Called in the rendering thread by AddLight.
|
|
* @param LightSceneInfo - The light being added.
|
|
*/
|
|
void AddLightSceneInfo_RenderThread(FLightSceneInfo* LightSceneInfo);
|
|
/**
|
|
* Adds a decal to the scene. Called in the rendering thread by AddDecal or RemoveDecal.
|
|
* @param Component - The object that should being added or removed.
|
|
* @param bAdd true:add, FASLE:remove
|
|
*/
|
|
void AddOrRemoveDecal_RenderThread(FDeferredDecalProxy* Component, bool bAdd);
|
|
|
|
/**
|
|
* Removes a light from the scene. Called in the rendering thread by RemoveLight.
|
|
* @param LightSceneInfo - The light being removed.
|
|
*/
|
|
void RemoveLightSceneInfo_RenderThread(FLightSceneInfo* LightSceneInfo);
|
|
|
|
void UpdateLightTransform_RenderThread(FLightSceneInfo* LightSceneInfo, const struct FUpdateLightTransformParameters& Parameters);
|
|
|
|
/**
|
|
* Updates the contents of the given reflection capture by rendering the scene.
|
|
* This must be called on the game thread.
|
|
*/
|
|
void UpdateReflectionCaptureContents(UReflectionCaptureComponent* CaptureComponent);
|
|
|
|
/** Updates the contents of all reflection captures in the scene. Must be called from the game thread. */
|
|
void UpdateAllReflectionCaptures();
|
|
|
|
/** Sets shader maps on the specified materials without blocking. */
|
|
void SetShaderMapsOnMaterialResources_RenderThread(FRHICommandListImmediate& RHICmdList, const FMaterialsToUpdateMap& MaterialsToUpdate);
|
|
|
|
/** Updates static draw lists for the given materials. */
|
|
void UpdateStaticDrawListsForMaterials_RenderThread(FRHICommandListImmediate& RHICmdList, const TArray<const FMaterial*>& Materials);
|
|
|
|
/**
|
|
* Shifts scene data by provided delta
|
|
* Called on world origin changes
|
|
*
|
|
* @param InOffset Delta to shift scene by
|
|
*/
|
|
void ApplyWorldOffset_RenderThread(FVector InOffset);
|
|
|
|
/**
|
|
* Notification from game thread that level was added to a world
|
|
*
|
|
* @param InLevelName Level name
|
|
*/
|
|
void OnLevelAddedToWorld_RenderThread(FName InLevelName);
|
|
|
|
/**
|
|
* Builds a FSceneRenderer instance for a given view and render target. Helper function for Scene capture code.
|
|
*
|
|
* @param SceneCaptureComponent - The scene capture component for which to create a scene renderer.
|
|
* @param TextureTarget - render target to draw to.
|
|
* @param ViewRotationMatrix - Camera rotation matrix.
|
|
* @param ViewLocation - Camera location.
|
|
* @param FOV - Camera field of view.
|
|
* @param MaxViewDistance - Far draw distance.
|
|
* @param bCaptureSceneColour if true the returned scenerenderer will ignore post process operations as only the raw scene color is used.
|
|
* @param PostProcessSettings - pointer to post process structure, NULL for no effect.
|
|
* @param PostProcessBlendWeight - Blendweight for PostProcessSettings.
|
|
* @return pointer to a configured SceneRenderer instance.
|
|
*/
|
|
FSceneRenderer* CreateSceneRenderer(USceneCaptureComponent* SceneCaptureComponent, UTextureRenderTarget* TextureTarget, const FMatrix& ViewRotationMatrix, const FVector& ViewLocation, float FOV, float MaxViewDistance, bool bCaptureSceneColour = true, FPostProcessSettings* PostProcessSettings = NULL, float PostProcessBlendWeight = 0);
|
|
|
|
private:
|
|
/**
|
|
* The number of visible lights in the scene
|
|
* Note: This is tracked on the game thread!
|
|
*/
|
|
int32 NumVisibleLights_GameThread;
|
|
|
|
/**
|
|
* Whether the scene has a valid sky light.
|
|
* Note: This is tracked on the game thread!
|
|
*/
|
|
int32 NumEnabledSkylights_GameThread;
|
|
|
|
/** This scene's feature level */
|
|
ERHIFeatureLevel::Type FeatureLevel;
|
|
};
|
|
|
|
#include "BasePassRendering.inl"
|
|
|
|
#endif // __SCENEPRIVATE_H__
|