Files
UnrealEngineUWP/Engine/Source/Runtime/Renderer/Private/PostProcess/ScreenSpaceReflections.cpp
Gil Gribb 93047290bb Copying //UE4/Dev-Rendering to //UE4/Dev-Main (Source: //UE4/Dev-Rendering @ 3054480)
#lockdown Nick.Penwarden
#rb none

==========================
MAJOR FEATURES + CHANGES
==========================

Change 3045482 on 2016/07/11 by Zabir.Hoque

	DX12 Quries need to individually track their syncpoints. Only when resolving a query on the same frame should be stall.

Change 3045929 on 2016/07/12 by Simon.Tovey

	Removing some deprecated node types from Niagara

Change 3045951 on 2016/07/12 by Ben.Woodhouse

	D3D11 Log detailed live device info on shutdown if the debug layer is enabled (including resource types)

Change 3046019 on 2016/07/12 by Chris.Bunner

	Fixed typo in material input name.
	#jira UE-5575

Change 3046053 on 2016/07/12 by Rolando.Caloca

	DR - Fix GL4 shutdown
	#jira UE-32799

Change 3046055 on 2016/07/12 by Rolando.Caloca

	DR - vk - Fix NumInstances=0

Change 3046063 on 2016/07/12 by Rolando.Caloca

	DR - vk - Added flat to uint layouts per glslang
	- Fix bad extension on dumped shaders

Change 3046067 on 2016/07/12 by Rolando.Caloca

	DR - vk - Fix check when not using color RT
	- Added queue submit & present counters

Change 3046088 on 2016/07/12 by Ben.Woodhouse

	Live GPU stats
	A non-hierarchical realtime high level GPU profiler with support for cumulative stat recording.
	Stats are added with SCOPED_GPU_STAT macros, e.g. SCOPED_GPU_STAT(RHICmdList, Stat_GPU_Distortion)
	The bulk of the files in this change are simply instrumentation for the renderer. The core changes are in SceneUtils.cpp/h and D3D11Query.cpp (this is the XB1/DX11X implementation of timestamp RHI queries, which was missing)
	Note: this is currently disabled by default. Enable with the cvar r.gpustatsenabled
	Tested on PC, XB1, PS4

Change 3046128 on 2016/07/12 by Olaf.Piesche

	Max draw distance and fade range for lights, requested by JonL

Change 3046183 on 2016/07/12 by Ben.Woodhouse

	PR #2532: Fix SSAO being applied in unlit viewmode (Contributed by nick-penwarden)

Change 3046223 on 2016/07/12 by Luke.Thatcher

	Fix Scene Cube Captures. SceneCaptureSource flag on the ViewFamily was not set for cube components.

	#jira UE-32345

Change 3046228 on 2016/07/12 by Marc.Olano

	Add Voronoi noise to Noise material node.

	Four versions with differing speed/quality levels accessed through the Quality value in the material node. Tooltips give estimates of the cost of each.

	Also includes spiffy new Rand3DPCG16 and Rand3DPCG32 int3 to int3 hash functions, and a 20% improvement on the computed gradient noise.

Change 3046269 on 2016/07/12 by Rolando.Caloca

	DR - Skip flush on RHIDiscardRenderTargets and only use it on platforms that need it (ie OpenGL)

Change 3046294 on 2016/07/12 by Rolando.Caloca

	DR - Fix static analyisis
	warning C6326: Potential comparison of a constant with another constant.

Change 3046295 on 2016/07/12 by Rolando.Caloca

	DR - Fix the previous fix

Change 3046731 on 2016/07/12 by Marc.Olano

	Fix typo in shader random number constant: repeated extra digit made it too big.

Change 3046796 on 2016/07/12 by Uriel.Doyon

	The texture streaming manager now keeps a set of all valid textures.
	This is used to prevent from indirecting deleted memory upon SetTexturesRemovedTimestamp.
	#jira UE-33048

Change 3046800 on 2016/07/12 by Rolando.Caloca

	DR - vk - Added create image & renderpass dump

Change 3046845 on 2016/07/12 by John.Billon

	Forgot to apply MaxGPUSkinBones Cvar access changes in a few locations.

Change 3047023 on 2016/07/12 by Olaf.Piesche

	Niagara:
	-a bit of cleanup
	-now store and double buffer attributes individually, eliminating unnecessary copy of unused attributes
	-removed FNiagaraConstantMap, replaced with an instance of FNiagaraConstants
	-some code simplification
	-removed some deprecated structs and code used only by old content

Change 3047052 on 2016/07/12 by Zabir.Hoque

	Unshelved from pending changelist '3044062':

	PR #2588: Adding blend mode BLEND_AlphaComposite (4.12) (Contributed by moritz-wundke)

Change 3047727 on 2016/07/13 by Luke.Thatcher

	Fix Scene Capture Components only updating every other frame.
	#jira UE-32581

Change 3047919 on 2016/07/13 by Olaf.Piesche

	CMask decode, use in deferred decals, for PS4

Change 3047921 on 2016/07/13 by Uriel.Doyon

	"Build Texture Streaming" will now remove duplicate error msg when computing texcoord scales.
	Also, several texture messages are packed on the same line if they relate to the same material.

Change 3047952 on 2016/07/13 by Rolando.Caloca

	DR - vk - Initial prep pass for separating combined images & samplers

Change 3048648 on 2016/07/13 by Marcus.Wassmer

	Fix rare GPU hang when asynctexture reallocs would overlap with EndFrame

Change 3049058 on 2016/07/13 by Rolando.Caloca

	DR - vk - timestamps

Change 3049725 on 2016/07/14 by Marcus.Wassmer

	Fix autosdk bug where not having a platform directory sync'd at all would break manual SDK detection

Change 3049742 on 2016/07/14 by Rolando.Caloca

	DR - Fix warning

Change 3049902 on 2016/07/14 by Rolando.Caloca

	DR - Fix typo

Change 3050345 on 2016/07/14 by Olaf.Piesche

	UE-23925
	Clamping noise tessellation for beams at a high but sensible value; also making sure during beam index buffer building that we never get over 2^16 indices; this is a bit hokey, but there are so many variables that can influence triangle/index count, that this is the only way to be sure (short of nuking the entire site from orbit).

Change 3050409 on 2016/07/14 by Olaf.Piesche

	Replicating 3049049; missing break and check for active particles when resolving a source point to avoid a potential crash

Change 3050809 on 2016/07/14 by Rolando.Caloca

	DR - vk - Remove redundant validation layers

Change 3051319 on 2016/07/15 by Ben.Woodhouse

	Fix for world space camera position not being exposed in decal pixel shaders; also fixes decal lighting missing spec and reflection
	The fix was to calculate ResolvedView at the top of the shader. Previously this was not initialized
	#jira UE-31976

Change 3051692 on 2016/07/15 by Rolando.Caloca

	DR - vk - Enable RHI thread by default

Change 3052103 on 2016/07/15 by Uriel.Doyon

	Disabled depth offset in depth only pixel shaders when using debug view shaders (to prevent Z fighting).
	#jira UE-32765

Change 3052140 on 2016/07/15 by Rolando.Caloca

	DR - vk - Fix shader snafu

Change 3052495 on 2016/07/15 by Rolando.Caloca

	DR - Fix for Win32 compile
	#jira UE-33349

Change 3052536 on 2016/07/15 by Uriel.Doyon

	Fixed texture streaming overbudget warning when using per texture bias.

[CL 3054554 by Gil Gribb in Main branch]
2016-07-18 17:17:08 -04:00

538 lines
19 KiB
C++

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
/*=============================================================================
ScreenSpaceReflections.cpp: Post processing Screen Space Reflections implementation.
=============================================================================*/
#include "RendererPrivate.h"
#include "ScenePrivate.h"
#include "SceneFilterRendering.h"
#include "PostProcessing.h"
#include "ScreenSpaceReflections.h"
#include "PostProcessTemporalAA.h"
#include "PostProcessAmbientOcclusion.h"
#include "PostProcessHierarchical.h"
#include "SceneUtils.h"
static TAutoConsoleVariable<int32> CVarSSRQuality(
TEXT("r.SSR.Quality"),
3,
TEXT("Whether to use screen space reflections and at what quality setting.\n")
TEXT("(limits the setting in the post process settings which has a different scale)\n")
TEXT("(costs performance, adds more visual realism but the technique has limits)\n")
TEXT(" 0: off (default)\n")
TEXT(" 1: low (no glossy)\n")
TEXT(" 2: medium (no glossy)\n")
TEXT(" 3: high (glossy/using roughness, few samples)\n")
TEXT(" 4: very high (likely too slow for real-time)"),
ECVF_Scalability | ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarSSRTemporal(
TEXT("r.SSR.Temporal"),
0,
TEXT("Defines if we use the temporal smoothing for the screen space reflection\n")
TEXT(" 0 is off (for debugging), 1 is on (default)"),
ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarSSRStencil(
TEXT("r.SSR.Stencil"),
0,
TEXT("Defines if we use the stencil prepass for the screen space reflection\n")
TEXT(" 0 is off (default), 1 is on"),
ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarSSRCone(
TEXT("r.SSR.Cone"),
0,
TEXT("Defines if we use cone traced screen space reflection\n")
TEXT(" 0 is off (default), 1 is on"),
ECVF_RenderThreadSafe);
DECLARE_FLOAT_COUNTER_STAT(TEXT("ScreenSpace Reflections"), Stat_GPU_ScreenSpaceReflections, STATGROUP_GPU);
bool ShouldRenderScreenSpaceReflections(const FViewInfo& View)
{
if(!View.Family->EngineShowFlags.ScreenSpaceReflections)
{
return false;
}
if(!View.State)
{
// not view state (e.g. thumbnail rendering?), no HZB (no screen space reflections or occlusion culling)
return false;
}
int SSRQuality = CVarSSRQuality.GetValueOnRenderThread();
if(SSRQuality <= 0)
{
return false;
}
if(View.FinalPostProcessSettings.ScreenSpaceReflectionIntensity < 1.0f)
{
return false;
}
return true;
}
static float ComputeRoughnessMaskScale(const FRenderingCompositePassContext& Context, uint32 SSRQuality)
{
float MaxRoughness = FMath::Clamp(Context.View.FinalPostProcessSettings.ScreenSpaceReflectionMaxRoughness, 0.01f, 1.0f);
// f(x) = x * Scale + Bias
// f(MaxRoughness) = 0
// f(MaxRoughness/2) = 1
float RoughnessMaskScale = -2.0f / MaxRoughness;
return RoughnessMaskScale * (SSRQuality < 3 ? 2.0f : 1.0f);
}
FLinearColor ComputeSSRParams(const FRenderingCompositePassContext& Context, uint32 SSRQuality, bool bEnableDiscard)
{
float RoughnessMaskScale = ComputeRoughnessMaskScale(Context, SSRQuality);
float FrameRandom = 0;
if(Context.ViewState)
{
bool bTemporalAAIsOn = Context.View.FinalPostProcessSettings.AntiAliasingMethod == AAM_TemporalAA;
if(bTemporalAAIsOn)
{
// usually this number is in the 0..7 range but it depends on the TemporalAA quality
FrameRandom = Context.ViewState->GetCurrentTemporalAASampleIndex() * 1551;
}
else
{
// 8 aligns with the temporal smoothing, larger number will do more flickering (power of two for best performance)
FrameRandom = Context.ViewState->GetFrameIndexMod8() * 1551;
}
}
return FLinearColor(
FMath::Clamp(Context.View.FinalPostProcessSettings.ScreenSpaceReflectionIntensity * 0.01f, 0.0f, 1.0f),
RoughnessMaskScale,
(float)bEnableDiscard, // TODO
FrameRandom);
}
/**
* Encapsulates the post processing screen space reflections pixel shader stencil pass.
*/
class FPostProcessScreenSpaceReflectionsStencilPS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FPostProcessScreenSpaceReflectionsStencilPS, Global);
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM4);
}
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
OutEnvironment.SetDefine( TEXT("PREV_FRAME_COLOR"), uint32(0) );
OutEnvironment.SetDefine( TEXT("SSR_QUALITY"), uint32(0) );
}
/** Default constructor. */
FPostProcessScreenSpaceReflectionsStencilPS() {}
public:
FPostProcessPassParameters PostprocessParameter;
FDeferredPixelShaderParameters DeferredParameters;
FShaderParameter SSRParams;
/** Initialization constructor. */
FPostProcessScreenSpaceReflectionsStencilPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
PostprocessParameter.Bind(Initializer.ParameterMap);
DeferredParameters.Bind(Initializer.ParameterMap);
SSRParams.Bind(Initializer.ParameterMap, TEXT("SSRParams"));
}
void SetParameters(const FRenderingCompositePassContext& Context, uint32 SSRQuality, bool EnableDiscard)
{
const FFinalPostProcessSettings& Settings = Context.View.FinalPostProcessSettings;
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Point, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI());
DeferredParameters.Set(Context.RHICmdList, ShaderRHI, Context.View);
{
FLinearColor Value = ComputeSSRParams(Context, SSRQuality, EnableDiscard);
SetShaderValue(Context.RHICmdList, ShaderRHI, SSRParams, Value);
}
}
// FShader interface.
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << PostprocessParameter << DeferredParameters << SSRParams;
return bShaderHasOutdatedParameters;
}
};
IMPLEMENT_SHADER_TYPE(,FPostProcessScreenSpaceReflectionsStencilPS,TEXT("ScreenSpaceReflections"),TEXT("ScreenSpaceReflectionsStencilPS"),SF_Pixel);
static const uint32 SSRConeQuality = 5;
/**
* Encapsulates the post processing screen space reflections pixel shader.
* @param SSRQuality 0:Visualize Mask
*/
template<uint32 PrevFrame, uint32 SSRQuality >
class FPostProcessScreenSpaceReflectionsPS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FPostProcessScreenSpaceReflectionsPS, Global);
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM4);
}
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
OutEnvironment.SetDefine( TEXT("PREV_FRAME_COLOR"), PrevFrame );
OutEnvironment.SetDefine( TEXT("SSR_QUALITY"), SSRQuality );
OutEnvironment.SetDefine( TEXT("SSR_CONE_QUALITY"), SSRConeQuality );
}
/** Default constructor. */
FPostProcessScreenSpaceReflectionsPS() {}
public:
FPostProcessPassParameters PostprocessParameter;
FDeferredPixelShaderParameters DeferredParameters;
FShaderParameter SSRParams;
FShaderParameter HZBUvFactorAndInvFactor;
/** Initialization constructor. */
FPostProcessScreenSpaceReflectionsPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
PostprocessParameter.Bind(Initializer.ParameterMap);
DeferredParameters.Bind(Initializer.ParameterMap);
SSRParams.Bind(Initializer.ParameterMap, TEXT("SSRParams"));
HZBUvFactorAndInvFactor.Bind(Initializer.ParameterMap, TEXT("HZBUvFactorAndInvFactor"));
}
void SetParameters(const FRenderingCompositePassContext& Context)
{
const FFinalPostProcessSettings& Settings = Context.View.FinalPostProcessSettings;
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Point, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI());
DeferredParameters.Set(Context.RHICmdList, ShaderRHI, Context.View);
{
FLinearColor Value = ComputeSSRParams(Context, SSRQuality, false);
SetShaderValue(Context.RHICmdList, ShaderRHI, SSRParams, Value);
}
{
const FVector2D HZBUvFactor(
float(Context.View.ViewRect.Width()) / float(2 * Context.View.HZBMipmap0Size.X),
float(Context.View.ViewRect.Height()) / float(2 * Context.View.HZBMipmap0Size.Y)
);
const FVector4 HZBUvFactorAndInvFactorValue(
HZBUvFactor.X,
HZBUvFactor.Y,
1.0f / HZBUvFactor.X,
1.0f / HZBUvFactor.Y
);
SetShaderValue(Context.RHICmdList, ShaderRHI, HZBUvFactorAndInvFactor, HZBUvFactorAndInvFactorValue);
}
}
// FShader interface.
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << PostprocessParameter << DeferredParameters << SSRParams << HZBUvFactorAndInvFactor;
return bShaderHasOutdatedParameters;
}
};
// Typedef is necessary because the C preprocessor thinks the comma in the template parameter list is a comma in the macro parameter list.
#define IMPLEMENT_REFLECTION_PIXELSHADER_TYPE(A, B) \
typedef FPostProcessScreenSpaceReflectionsPS<A,B> FPostProcessScreenSpaceReflectionsPS##A##B; \
IMPLEMENT_SHADER_TYPE(template<>,FPostProcessScreenSpaceReflectionsPS##A##B,TEXT("ScreenSpaceReflections"),TEXT("ScreenSpaceReflectionsPS"),SF_Pixel)
IMPLEMENT_REFLECTION_PIXELSHADER_TYPE(0,0);
IMPLEMENT_REFLECTION_PIXELSHADER_TYPE(0,1);
IMPLEMENT_REFLECTION_PIXELSHADER_TYPE(1,1);
IMPLEMENT_REFLECTION_PIXELSHADER_TYPE(0,2);
IMPLEMENT_REFLECTION_PIXELSHADER_TYPE(1,2);
IMPLEMENT_REFLECTION_PIXELSHADER_TYPE(0,3);
IMPLEMENT_REFLECTION_PIXELSHADER_TYPE(1,3);
IMPLEMENT_REFLECTION_PIXELSHADER_TYPE(0,4);
IMPLEMENT_REFLECTION_PIXELSHADER_TYPE(1,4);
IMPLEMENT_REFLECTION_PIXELSHADER_TYPE(0,5); // SSRConeQuality
IMPLEMENT_REFLECTION_PIXELSHADER_TYPE(1,5); // SSRConeQuality
// --------------------------------------------------------
// @param Quality usually in 0..100 range, default is 50
// @return see CVarSSRQuality, never 0
static int32 ComputeSSRQuality(float Quality)
{
int32 Ret;
if(Quality >= 60.0f)
{
Ret = (Quality >= 80.0f) ? 4 : 3;
}
else
{
Ret = (Quality >= 40.0f) ? 2 : 1;
}
int SSRQualityCVar = FMath::Max(0, CVarSSRQuality.GetValueOnRenderThread());
return FMath::Min(Ret, SSRQualityCVar);
}
void FRCPassPostProcessScreenSpaceReflections::Process(FRenderingCompositePassContext& Context)
{
auto& RHICmdList = Context.RHICmdList;
FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
const FSceneView& View = Context.View;
const auto FeatureLevel = Context.GetFeatureLevel();
int32 SSRQuality = ComputeSSRQuality(View.FinalPostProcessSettings.ScreenSpaceReflectionQuality);
uint32 iPreFrame = bPrevFrame ? 1 : 0;
SSRQuality = FMath::Clamp(SSRQuality, 1, 4);
const bool VisualizeSSR = View.Family->EngineShowFlags.VisualizeSSR;
const bool SSRStencilPrePass = CVarSSRStencil.GetValueOnRenderThread() != 0 && !VisualizeSSR;
FRenderingCompositeOutputRef* Input2 = GetInput(ePId_Input2);
const bool SSRConeTracing = Input2 && Input2->GetOutput();
if (VisualizeSSR)
{
iPreFrame = 0;
SSRQuality = 0;
}
else if (SSRConeTracing)
{
SSRQuality = SSRConeQuality;
}
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
SCOPED_GPU_STAT(RHICmdList, Stat_GPU_ScreenSpaceReflections);
if (SSRStencilPrePass)
{ // ScreenSpaceReflectionsStencil draw event
SCOPED_DRAW_EVENTF(Context.RHICmdList, ScreenSpaceReflectionsStencil, TEXT("ScreenSpaceReflectionsStencil %dx%d"), View.ViewRect.Width(), View.ViewRect.Height());
TShaderMapRef< FPostProcessVS > VertexShader(Context.GetShaderMap());
TShaderMapRef< FPostProcessScreenSpaceReflectionsStencilPS > PixelShader(Context.GetShaderMap());
// bind the dest render target and the depth stencil render target
SetRenderTarget(RHICmdList, DestRenderTarget.TargetableTexture, SceneContext.GetSceneDepthSurface(), ESimpleRenderTargetMode::EUninitializedColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite);
Context.SetViewportAndCallRHI(View.ViewRect);
// Clear stencil to 0
RHICmdList.Clear(false, FLinearColor::White, false, (float)ERHIZBuffer::FarPlane, true, 0, View.ViewRect);
// bind shader
static FGlobalBoundShaderState BoundShaderState;
SetGlobalBoundShaderState(Context.RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
VertexShader->SetParameters(Context);
PixelShader->SetParameters(Context, SSRQuality, true);
// Clobers the stencil to pixel that should not compute SSR
RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always, true, CF_Always, SO_Replace, SO_Replace, SO_Replace>::GetRHI(), 0x80);
// Set rasterizer state to solid
RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
// disable blend mode
RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
DrawPostProcessPass(
Context.RHICmdList,
0, 0,
View.ViewRect.Width(), View.ViewRect.Height(),
View.ViewRect.Min.X, View.ViewRect.Min.Y,
View.ViewRect.Width(), View.ViewRect.Height(),
View.ViewRect.Size(),
SceneContext.GetBufferSizeXY(),
*VertexShader,
View.StereoPass,
Context.HasHmdMesh(),
EDRF_UseTriangleOptimization);
} // ScreenSpaceReflectionsStencil draw event
{ // ScreenSpaceReflections draw event
SCOPED_DRAW_EVENTF(Context.RHICmdList, ScreenSpaceReflections, TEXT("ScreenSpaceReflections %dx%d"), View.ViewRect.Width(), View.ViewRect.Height());
if (SSRStencilPrePass)
{
// set up the stencil test to match 0, meaning FPostProcessScreenSpaceReflectionsStencilPS has been discarded
RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always, true, CF_Equal, SO_Keep, SO_Keep, SO_Keep>::GetRHI(), 0);
}
else
{
// bind only the dest render target
SetRenderTarget(RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef());
Context.SetViewportAndCallRHI(View.ViewRect);
RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI());
}
// clear DestRenderTarget only outside of the view's rectangle
RHICmdList.Clear(true, FLinearColor::Black, false, (float)ERHIZBuffer::FarPlane, false, 0, View.ViewRect);
// set the state
RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
TShaderMapRef< FPostProcessVS > VertexShader(Context.GetShaderMap());
#define CASE(A, B) \
case (A + 2 * (B + 3 * 0 )): \
{ \
TShaderMapRef< FPostProcessScreenSpaceReflectionsPS<A, B> > PixelShader(Context.GetShaderMap()); \
static FGlobalBoundShaderState BoundShaderState; \
SetGlobalBoundShaderState(RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); \
VertexShader->SetParameters(Context); \
PixelShader->SetParameters(Context); \
}; \
break
switch (iPreFrame + 2 * (SSRQuality + 3 * 0))
{
CASE(0,0);
CASE(0,1); CASE(1,1);
CASE(0,2); CASE(1,2);
CASE(0,3); CASE(1,3);
CASE(0,4); CASE(1,4);
CASE(0,5); CASE(1,5); //SSRConeQuality
default:
check(!"Missing case in FRCPassPostProcessScreenSpaceReflections");
}
#undef CASE
DrawPostProcessPass(
RHICmdList,
0, 0,
View.ViewRect.Width(), View.ViewRect.Height(),
View.ViewRect.Min.X, View.ViewRect.Min.Y,
View.ViewRect.Width(), View.ViewRect.Height(),
View.ViewRect.Size(),
FSceneRenderTargets::Get(Context.RHICmdList).GetBufferSizeXY(),
*VertexShader,
View.StereoPass,
Context.HasHmdMesh(),
EDRF_UseTriangleOptimization);
RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
} // ScreenSpaceReflections
}
FPooledRenderTargetDesc FRCPassPostProcessScreenSpaceReflections::ComputeOutputDesc(EPassOutputId InPassOutputId) const
{
FPooledRenderTargetDesc Ret(FPooledRenderTargetDesc::Create2DDesc(FSceneRenderTargets::Get_FrameConstantsOnly().GetBufferSizeXY(), PF_FloatRGBA, FClearValueBinding::None, TexCreate_None, TexCreate_RenderTargetable, false));
Ret.DebugName = TEXT("ScreenSpaceReflections");
Ret.AutoWritable = false;
return Ret;
}
void RenderScreenSpaceReflections(FRHICommandListImmediate& RHICmdList, FViewInfo& View, TRefCountPtr<IPooledRenderTarget>& SSROutput)
{
FRenderingCompositePassContext CompositeContext(RHICmdList, View);
FPostprocessContext Context(RHICmdList, CompositeContext.Graph, View );
FSceneViewState* ViewState = (FSceneViewState*)Context.View.State;
FRenderingCompositePass* SceneColorInput = Context.Graph.RegisterPass( new FRCPassPostProcessInput( FSceneRenderTargets::Get(RHICmdList).GetSceneColor() ) );
FRenderingCompositePass* HZBInput = Context.Graph.RegisterPass( new FRCPassPostProcessInput( View.HZB ) );
FRenderingCompositePass* HCBInput = nullptr;
bool bPrevFrame = 0;
if( ViewState && ViewState->TemporalAAHistoryRT && !Context.View.bCameraCut )
{
SceneColorInput = Context.Graph.RegisterPass( new FRCPassPostProcessInput( ViewState->TemporalAAHistoryRT ) );
bPrevFrame = 1;
}
if (CVarSSRCone.GetValueOnRenderThread())
{
HCBInput = Context.Graph.RegisterPass( new FRCPassPostProcessBuildHCB() );
HCBInput->SetInput( ePId_Input0, SceneColorInput );
}
{
FRenderingCompositePass* TracePass = Context.Graph.RegisterPass( new FRCPassPostProcessScreenSpaceReflections( bPrevFrame ) );
TracePass->SetInput( ePId_Input0, SceneColorInput );
TracePass->SetInput( ePId_Input1, HZBInput );
TracePass->SetInput( ePId_Input2, HCBInput );
Context.FinalOutput = FRenderingCompositeOutputRef( TracePass );
}
const bool bTemporalFilter = View.FinalPostProcessSettings.AntiAliasingMethod != AAM_TemporalAA || CVarSSRTemporal.GetValueOnRenderThread() != 0;
if( ViewState && bTemporalFilter )
{
{
FRenderingCompositeOutputRef HistoryInput;
if( ViewState && ViewState->SSRHistoryRT && !Context.View.bCameraCut )
{
HistoryInput = Context.Graph.RegisterPass( new FRCPassPostProcessInput( ViewState->SSRHistoryRT ) );
}
else
{
// No history, use black
HistoryInput = Context.Graph.RegisterPass(new FRCPassPostProcessInput(GSystemTextures.BlackDummy));
}
FRenderingCompositePass* TemporalAAPass = Context.Graph.RegisterPass( new FRCPassPostProcessSSRTemporalAA );
TemporalAAPass->SetInput( ePId_Input0, Context.FinalOutput );
TemporalAAPass->SetInput( ePId_Input1, HistoryInput );
//TemporalAAPass->SetInput( ePId_Input2, VelocityInput );
Context.FinalOutput = FRenderingCompositeOutputRef( TemporalAAPass );
}
if( ViewState )
{
FRenderingCompositePass* HistoryOutput = Context.Graph.RegisterPass( new FRCPassPostProcessOutput( &ViewState->SSRHistoryRT ) );
HistoryOutput->SetInput( ePId_Input0, Context.FinalOutput );
Context.FinalOutput = FRenderingCompositeOutputRef( HistoryOutput );
}
}
{
FRenderingCompositePass* ReflectionOutput = Context.Graph.RegisterPass( new FRCPassPostProcessOutput( &SSROutput ) );
ReflectionOutput->SetInput( ePId_Input0, Context.FinalOutput );
Context.FinalOutput = FRenderingCompositeOutputRef( ReflectionOutput );
}
CompositeContext.Process(Context.FinalOutput.GetPass(), TEXT("ReflectionEnvironments"));
}