Files
UnrealEngineUWP/Engine/Source/Runtime/Renderer/Private/PostProcess/PostProcessMotionBlur.cpp
Gil Gribb f2a51068c0 Copying //UE4/Dev-Rendering to //UE4/Dev-Main (Source: //UE4/Dev-Rendering @ 2998063)
#lockdown nick.penwarden

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

Change 2981877 on 2016/05/18 by Rolando.Caloca

	DR - Fix some PVS warnings
	- Removed 'uniform' as a keyword on hlslcc as it's ignored/causes issues/doesn't really optimize
	#jira UE-30996

Change 2981966 on 2016/05/18 by Rolando.Caloca

	DR - Fix OpenGL crash quitting editor
	#jira UE-25549

Change 2982072 on 2016/05/18 by Uriel.Doyon

	Fixed a "Build Texture Streaming" crash related to custom outputs.
	Fixed issue with debug view mode and translucent primitives
	Fix bug with visibility that made some texture low res.
	Enabled per instance visibility in the texture streaming order (in game only).
	Improved InvestigateTexture Logs.
	Tweaked the mip computations from screen size.

Change 2982077 on 2016/05/18 by Uriel.Doyon

	Removed debug options!

Change 2982108 on 2016/05/18 by Olaf.Piesche

	#jira UE-30772
	moving AMD hacks to console variables

Change 2982422 on 2016/05/18 by Gil.Gribb

	UE4 - Potential crash fix on foliage occlusion queries and reflection captures.

Change 2982547 on 2016/05/18 by Martin.Mittring

	UE-26409 Crash when Light Propagation Volume Plugin is disabled on a Project

Change 2982548 on 2016/05/18 by Martin.Mittring

	Refactored MRT and outer Pixel Shader output to a struct
	to allow it passed in/out of functions allowing for a more readable code (less #ifdefs, reducing the boolean hell)
	Needed for upcoming MeshDecals

Change 2982601 on 2016/05/18 by Daniel.Wright

	Movable skylight now matches stationary for subsurface shading models
	* Two sided was broken in 4.11, Subsurface had never been handled

Change 2982603 on 2016/05/18 by Daniel.Wright

	DrawMaterialToRenderTarget / BeginDrawCanvasToRenderTarget now work correctly with material parameter collections and Time
	* FCanvas stores an optional scene to render to, UWorld caches the UCanvas needed for implementing these functions

Change 2982618 on 2016/05/18 by Daniel.Wright

	Better categories for some Rendering project settings

Change 2982619 on 2016/05/18 by Daniel.Wright

	Scene capture 2d improvements
	* Orthographic projection supported
	* Opacity is now captured in alpha, allows partial rendering in a scene capture and compositing into another scene later
	* Various GBuffer attributes are now available to be captured, including depth
	* Changed Blueprint capture function to CaptureScene, which happens immediately (was previously deferred), allowing multiple captures with different parameters

Change 2982664 on 2016/05/18 by Daniel.Wright

	Fading out planar reflections based on roughness since they don't have support for variable roughness (fade starts at .2 roughness, ends at .3)

Change 2982684 on 2016/05/18 by Martin.Mittring

	polish ImageValidator

Change 2982685 on 2016/05/18 by Martin.Mittring

	show testimage on sm4 as well

Change 2982736 on 2016/05/18 by Uriel.Doyon

	Improved overbudget retention logic.
	Updated ListStreamingTextures stats.

Change 2982854 on 2016/05/18 by Martin.Mittring

	ImageValidator can now save/load IVxml file

Change 2982863 on 2016/05/18 by Daniel.Wright

	Fixed shader compile error

Change 2982864 on 2016/05/18 by Daniel.Wright

	Removed deprecation message

Change 2982927 on 2016/05/18 by Martin.Mittring

	ImageValidator is now sorting by time

Change 2983743 on 2016/05/19 by Chris.Bunner

	Saturated tri-planar UV function outputs to prevent negative blending
	#jira UE-30964

Change 2983747 on 2016/05/19 by Martin.Wilson

	Fix for morph curves not getting applied to meshes in cooked builds (smart names were not being corrected).

Change 2984008 on 2016/05/19 by Brian.Karis

	New contact shadows feature.

	Hair uses ray cast for nonshadow lights

Change 2984009 on 2016/05/19 by Brian.Karis

	changed to ShadowedBits

Change 2984054 on 2016/05/19 by Brian.Karis

	Deleted old motion blur

Change 2984420 on 2016/05/19 by Daniel.Wright

	Shorter display name for WorldPosition material node

Change 2984423 on 2016/05/19 by Daniel.Wright

	Fixed WorldPosition and ScreenPosition for downsampled separate translucency by scaling SvPosition before those computations.  The View uniform buffer still contains incorrect buffer sizes for this pass.

Change 2984432 on 2016/05/19 by Rolando.Caloca

	DR - Disable PPCombineLUT for Vulkan to work around glslang issue (will need to be reenabled when adding SM4/5 path)

Change 2985415 on 2016/05/20 by Daniel.Wright

	Added a Texture2D exporter for .hdr
	Texture2D exporters now implement SupportsObject properly, so you only see extensions that are valid based on the format

Change 2985439 on 2016/05/20 by Daniel.Wright

	Scene color alpha clear value validation

Change 2987173 on 2016/05/23 by Martin.Mittring

	ImageValidator Report with Thumbnail (cannot be copied and pasted into email), non Thumbnail version could be.

Change 2987248 on 2016/05/23 by Martin.Mittring

	ImageValidator: added Summary, removed timer hack

Change 2987369 on 2016/05/23 by Martin.Mittring

	ImageValidator polish

Change 2987390 on 2016/05/23 by Brian.Karis

	Improvement to temporal aa sharpness and speed.

Change 2988038 on 2016/05/24 by Gil.Gribb

	Merging //UE4/Dev-Main@2987977 to Dev-Rendering (//UE4/Dev-Rendering)

Change 2988304 on 2016/05/24 by Martin.Mittring

	added const to prevent coding errors

Change 2988332 on 2016/05/24 by Brian.Karis

	Fixed motion blur crash on SM4

Change 2988446 on 2016/05/24 by Martin.Mittring

	nicer UI

Change 2988990 on 2016/05/24 by Martin.Mittring

	fixed UE-31227 Building lighting produces bad results
	#jira:UE-31227

Change 2989729 on 2016/05/25 by Uriel.Doyon

	Fixed lightmaps and shadowmaps having low resolutions after building the lighting.
	#jira UE-31254

Change 2989752 on 2016/05/25 by Olaf.Piesche

	CVar to disable/freeze GPU particle simulation

Change 2989811 on 2016/05/25 by Daniel.Wright

	Making use of MATERIALBLENDING_ANY_TRANSLUCENT

Change 2989812 on 2016/05/25 by Daniel.Wright

	Hide DFGI show flags from UI

Change 2989901 on 2016/05/25 by Daniel.Wright

	Height fog now works properly in planar reflections
	* The ray used for computing fog is first clipped by the reflection plane

Change 2989904 on 2016/05/25 by Daniel.Wright

	Always use PF_FloatRGBA for LightAccumulation to guarantee alpha channel and negative range

Change 2989991 on 2016/05/25 by Daniel.Wright

	Improved usability for DBuffer Decals
	* 'Show Decals' works correctly, previously would fetch from uninitialized textures
	* DBuffer being enabled forces a full prepass, previously decals would render incorrectly unless correct settings of r.EarlyZPass were used
	* Improved the PrePass draw event to indicate whether it's full or partial
	* Materials using DBuffer blend modes will fail to compile when the DBuffer project setting is disabled, instead of just being invisible
	* r.EarlyZPass can now be changed at runtime, which is useful for profiling

Change 2990008 on 2016/05/25 by Daniel.Wright

	Fixed capsule shadows on skeletal meshes with scaling

Change 2990274 on 2016/05/25 by Daniel.Wright

	Fixed DFAO (from cl 2961310)

Change 2990304 on 2016/05/25 by Martin.Mittring

	OR-22233 GPU Sprites invisible unless solo'd
	#jira:OR-22233

Change 2990309 on 2016/05/25 by Martin.Mittring

	Added SubDSurface actor (using CPU code of OpenSubDiv), component, asset as starting point for more work in that direction,
	(Early work in progress)

Change 2990363 on 2016/05/25 by Daniel.Wright

	Spreading precomputed visibility to neighbors now uses a 2d grid to find neighbors, speeds up the process for 800k cells from 40 mins to 20s

Change 2990392 on 2016/05/25 by Daniel.Wright

	Added r.AOSpecularOcclusionMode, which determines how specular should be occluded by DFAO
	0: Apply non-directional AO to specular.
	1: (default) Intersect the reflection cone with the unoccluded cone produced by DFAO.  This gives more accurate occlusion than 0, but can bring out DFAO sampling artifacts.
	2: (experimental) Cone trace through distance fields along the reflection vector.  Costs about the same as DFAO again because more cone tracing is done, but produces more accurate occlusion.

Change 2990454 on 2016/05/25 by Martin.Mittring

	polish readme

Change 2990610 on 2016/05/25 by Martin.Mittring

	fixed building with VS2015, the right OpenSubDiv .lib files are missing, temporarily disabled the relevant code
	#code_review:Shane.Caudle

Change 2990754 on 2016/05/25 by Zabir.Hoque

	Fix compiler warning: C4456: declaration of 'NewStaticMesh' hides previous local declaration.

	#CodeReview: Martin.Mittring

Change 2990801 on 2016/05/25 by Zabir.Hoque

	Only allocate reflection capture cubemaps if we are actually doing a reflection capture. The old approach always allocated based on CVar and worked with a warning on D3D since if SRC was larger than the DST, the extra SRC area was dropped. New approach only allocates when necessary and is correctly sized everytime. Also hardened access to CVar and what users are allowed to set.

	#CodeReview Marcus.Wassmer, Rolando.Caloca, Daniel.Wright, Martin.Mittring

Change 2991169 on 2016/05/26 by Martin.Mittring

	fixed compiler warning
	WARNING: Non-editor build cannot depend on non-redistributable modules. Details:
	#lockdown: gil.gribb

Change 2991238 on 2016/05/26 by Martin.Mittring

	fixed build
	fatal error C1083: Cannot open include file: 'RawMesh.h': No such file or directory  (when RawMesh is not part of PrivateDependencyModuleNames in Engine.Build.cs)
	#lockdown:Gil.Gribb

Change 2991726 on 2016/05/26 by Daniel.Wright

	Subsurface materials are now handled with simple forward shading
	#jira OR-22237
	#lockdown gil.gribb

Change 2991727 on 2016/05/26 by Daniel.Wright

	Emissive decals are now supported with simple forward shading
	#jira OR-22282
	#lockdown Gil.Gribb

Change 2994849 on 2016/05/31 by Daniel.Wright

	Disabled fix for WorldPosition and ScreenPosition in downsampled separate translucency, since it breaks GetScreenAlignedUV (used in DepthFade), since the uniform buffer still contains full res buffer sizes
	#lockdown Gil.Gribb

Change 2997243 on 2016/06/01 by Gil.Gribb

	Merging //UE4/Dev-Main@2996565 to Dev-Rendering (//UE4/Dev-Rendering)
	#lockdown nick.penwarden

[CL 2998067 by Gil Gribb in Main branch]
2016-06-02 13:13:43 -04:00

963 lines
34 KiB
C++

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
/*=============================================================================
PostProcessMotionBlur.cpp: Post process MotionBlur implementation.
=============================================================================*/
#include "RendererPrivate.h"
#include "ScenePrivate.h"
#include "SceneFilterRendering.h"
#include "PostProcessAmbientOcclusion.h"
#include "PostProcessMotionBlur.h"
#include "PostProcessAmbientOcclusion.h"
#include "PostProcessing.h"
#include "SceneUtils.h"
#include "GPUSkinVertexFactory.h"
#include "../../Engine/Private/SkeletalRenderGPUSkin.h"
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
static TAutoConsoleVariable<int32> CVarMotionBlurFiltering(
TEXT("r.MotionBlurFiltering"),
0,
TEXT("Useful developer variable\n")
TEXT("0: off (default, expected by the shader for better quality)\n")
TEXT("1: on"),
ECVF_Cheat | ECVF_RenderThreadSafe);
#endif
static TAutoConsoleVariable<float> CVarMotionBlur2ndScale(
TEXT("r.MotionBlur2ndScale"),
1.0f,
TEXT(""),
ECVF_Cheat | ECVF_RenderThreadSafe);
FIntPoint GetNumTiles16x16( FIntPoint PixelExtent )
{
uint32 TilesX = (PixelExtent.X + 15) / 16;
uint32 TilesY = (PixelExtent.Y + 15) / 16;
return FIntPoint( TilesX, TilesY );
}
FVector4 GetMotionBlurParameters( const FViewInfo& View, float Scale = 1.0f )
{
const float TileSize = 16.0f;
const float SizeX = View.ViewRect.Width();
const float SizeY = View.ViewRect.Height();
const float AspectRatio = SizeY / SizeX;
const FSceneViewState* ViewState = (FSceneViewState*) View.State;
float MotionBlurTimeScale = ViewState ? ViewState->MotionBlurTimeScale : 1.0f;
float MotionBlurScale = 0.5f * MotionBlurTimeScale * View.FinalPostProcessSettings.MotionBlurAmount;
// 0:no 1:full screen width, percent conversion
float MaxVelocity = View.FinalPostProcessSettings.MotionBlurMax / 100.0f;
// Scale by 0.5 due to blur samples going both ways
float PixelScale = Scale * SizeX * 0.5f;
FVector4 MotionBlurParameters(
AspectRatio,
PixelScale * MotionBlurScale, // Scale for pixels
PixelScale * MotionBlurScale / TileSize,// Scale for tiles
FMath::Abs( PixelScale ) * MaxVelocity // Max velocity pixels
);
return MotionBlurParameters;
}
class FPostProcessVelocityFlattenCS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FPostProcessVelocityFlattenCS, Global);
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5);
}
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
}
FPostProcessVelocityFlattenCS() {}
public:
FShaderParameter OutVelocityFlat; // UAV
FShaderParameter OutMaxTileVelocity; // UAV
FPostProcessVelocityFlattenCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
PostprocessParameter.Bind(Initializer.ParameterMap);
MotionBlurParameters.Bind(Initializer.ParameterMap, TEXT("MotionBlurParameters"));
OutVelocityFlat.Bind(Initializer.ParameterMap, TEXT("OutVelocityFlat"));
OutMaxTileVelocity.Bind(Initializer.ParameterMap, TEXT("OutMaxTileVelocity"));
}
void SetCS( FRHICommandList& RHICmdList, const FRenderingCompositePassContext& Context, const FSceneView& View )
{
const FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
FGlobalShader::SetParameters(RHICmdList, ShaderRHI, Context.View);
PostprocessParameter.SetCS(ShaderRHI, Context, Context.RHICmdList, TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
SetUniformBufferParameter(RHICmdList, ShaderRHI, GetUniformBufferParameter<FCameraMotionParameters>(), CreateCameraMotionParametersUniformBuffer(Context.View));
SetShaderValue(Context.RHICmdList, ShaderRHI, MotionBlurParameters, GetMotionBlurParameters( Context.View ) );
}
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << PostprocessParameter;
Ar << MotionBlurParameters;
Ar << OutVelocityFlat;
Ar << OutMaxTileVelocity;
return bShaderHasOutdatedParameters;
}
private:
FPostProcessPassParameters PostprocessParameter;
FShaderParameter MotionBlurParameters;
};
IMPLEMENT_SHADER_TYPE(,FPostProcessVelocityFlattenCS,TEXT("PostProcessVelocityFlatten"),TEXT("VelocityFlattenMain"),SF_Compute);
FRCPassPostProcessVelocityFlatten::FRCPassPostProcessVelocityFlatten()
{}
void FRCPassPostProcessVelocityFlatten::Process(FRenderingCompositePassContext& Context)
{
SCOPED_DRAW_EVENT(Context.RHICmdList, VelocityFlatten);
const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0);
if(!InputDesc)
{
// input is not hooked up correctly
return;
}
const FSceneView& View = Context.View;
const FSceneViewFamily& ViewFamily = *(View.Family);
const FSceneRenderTargetItem& DestRenderTarget0 = PassOutputs[0].RequestSurface(Context);
const FSceneRenderTargetItem& DestRenderTarget1 = PassOutputs[1].RequestSurface(Context);
TShaderMapRef< FPostProcessVelocityFlattenCS > ComputeShader( Context.GetShaderMap() );
SetRenderTarget(Context.RHICmdList, FTextureRHIRef(), FTextureRHIRef());
Context.SetViewportAndCallRHI( View.ViewRect );
Context.RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
// set destination
Context.RHICmdList.SetUAVParameter(ComputeShader->GetComputeShader(), ComputeShader->OutVelocityFlat.GetBaseIndex(), DestRenderTarget0.UAV);
Context.RHICmdList.SetUAVParameter(ComputeShader->GetComputeShader(), ComputeShader->OutMaxTileVelocity.GetBaseIndex(), DestRenderTarget1.UAV);
ComputeShader->SetCS(Context.RHICmdList, Context, View);
FIntPoint ThreadGroupCountValue = GetNumTiles16x16(View.ViewRect.Size());
DispatchComputeShader(Context.RHICmdList, *ComputeShader, ThreadGroupCountValue.X, ThreadGroupCountValue.Y, 1);
// void FD3D11DynamicRHI::RHIGraphicsWaitOnAsyncComputeJob( uint32 FenceIndex )
Context.RHICmdList.FlushComputeShaderCache();
// un-set destination
Context.RHICmdList.SetUAVParameter(ComputeShader->GetComputeShader(), ComputeShader->OutVelocityFlat.GetBaseIndex(), NULL);
Context.RHICmdList.SetUAVParameter(ComputeShader->GetComputeShader(), ComputeShader->OutMaxTileVelocity.GetBaseIndex(), NULL);
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget0.TargetableTexture, DestRenderTarget0.ShaderResourceTexture, false, FResolveParams());
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget1.TargetableTexture, DestRenderTarget1.ShaderResourceTexture, false, FResolveParams());
}
FPooledRenderTargetDesc FRCPassPostProcessVelocityFlatten::ComputeOutputDesc(EPassOutputId InPassOutputId) const
{
if( InPassOutputId == ePId_Output0 )
{
// Flattened velocity
FPooledRenderTargetDesc Ret = GetInput(ePId_Input0)->GetOutput()->RenderTargetDesc;
Ret.Reset();
Ret.ClearValue = FClearValueBinding::None;
Ret.Format = PF_FloatR11G11B10;
Ret.TargetableFlags |= TexCreate_UAV;
Ret.TargetableFlags |= TexCreate_RenderTargetable;
Ret.DebugName = TEXT("VelocityFlat");
return Ret;
}
else
{
// Max tile velocity
FPooledRenderTargetDesc UnmodifiedRet = GetInput(ePId_Input0)->GetOutput()->RenderTargetDesc;
UnmodifiedRet.Reset();
FIntPoint PixelExtent = UnmodifiedRet.Extent;
FIntPoint TileCount = GetNumTiles16x16(PixelExtent);
FPooledRenderTargetDesc Ret(FPooledRenderTargetDesc::Create2DDesc(TileCount, PF_FloatRGBA, FClearValueBinding::None, TexCreate_None, TexCreate_RenderTargetable | TexCreate_UAV, false));
Ret.DebugName = TEXT("MaxVelocity");
return Ret;
}
}
class FScatterQuadIndexBuffer : public FIndexBuffer
{
public:
virtual void InitRHI() override
{
const uint32 Size = sizeof(uint16) * 6 * 8;
const uint32 Stride = sizeof(uint16);
FRHIResourceCreateInfo CreateInfo;
void* Buffer = nullptr;
IndexBufferRHI = RHICreateAndLockIndexBuffer( Stride, Size, BUF_Static, CreateInfo, Buffer );
uint16* Indices = (uint16*)Buffer;
for (uint32 SpriteIndex = 0; SpriteIndex < 8; ++SpriteIndex)
{
Indices[SpriteIndex*6 + 0] = SpriteIndex*4 + 0;
Indices[SpriteIndex*6 + 1] = SpriteIndex*4 + 3;
Indices[SpriteIndex*6 + 2] = SpriteIndex*4 + 2;
Indices[SpriteIndex*6 + 3] = SpriteIndex*4 + 0;
Indices[SpriteIndex*6 + 4] = SpriteIndex*4 + 1;
Indices[SpriteIndex*6 + 5] = SpriteIndex*4 + 3;
}
RHIUnlockIndexBuffer( IndexBufferRHI );
}
};
TGlobalResource< FScatterQuadIndexBuffer > GScatterQuadIndexBuffer;
class FPostProcessVelocityScatterVS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FPostProcessVelocityScatterVS,Global);
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5);
}
/** Default constructor. */
FPostProcessVelocityScatterVS() {}
public:
FPostProcessPassParameters PostprocessParameter;
FShaderParameter DrawMax;
FShaderParameter MotionBlurParameters;
/** Initialization constructor. */
FPostProcessVelocityScatterVS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
PostprocessParameter.Bind(Initializer.ParameterMap);
DrawMax.Bind(Initializer.ParameterMap, TEXT("bDrawMax"));
MotionBlurParameters.Bind( Initializer.ParameterMap, TEXT("MotionBlurParameters") );
}
// FShader interface.
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << PostprocessParameter << DrawMax << MotionBlurParameters;
return bShaderHasOutdatedParameters;
}
/** to have a similar interface as all other shaders */
void SetParameters(const FRenderingCompositePassContext& Context, int32 bDrawMax)
{
const FVertexShaderRHIParamRef ShaderRHI = GetVertexShader();
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
PostprocessParameter.SetVS(ShaderRHI, Context, TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
SetShaderValue(Context.RHICmdList, ShaderRHI, DrawMax, bDrawMax);
SetShaderValue(Context.RHICmdList, ShaderRHI, MotionBlurParameters, GetMotionBlurParameters( Context.View ) );
}
static const TCHAR* GetSourceFilename()
{
return TEXT("PostProcessMotionBlur");
}
static const TCHAR* GetFunctionName()
{
return TEXT("VelocityScatterVS");
}
};
class FPostProcessVelocityScatterPS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FPostProcessVelocityScatterPS, Global);
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5);
}
/** Default constructor. */
FPostProcessVelocityScatterPS() {}
public:
/** Initialization constructor. */
FPostProcessVelocityScatterPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{}
void SetParameters(const FRenderingCompositePassContext& Context)
{
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
}
};
IMPLEMENT_SHADER_TYPE(,FPostProcessVelocityScatterVS,TEXT("PostProcessMotionBlur"),TEXT("VelocityScatterVS"),SF_Vertex);
IMPLEMENT_SHADER_TYPE(,FPostProcessVelocityScatterPS,TEXT("PostProcessMotionBlur"),TEXT("VelocityScatterPS"),SF_Pixel);
void FRCPassPostProcessVelocityScatter::Process(FRenderingCompositePassContext& Context)
{
SCOPED_DRAW_EVENT(Context.RHICmdList, VelocityScatter);
const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0);
if(!InputDesc)
{
// input is not hooked up correctly
return;
}
const FSceneView& View = Context.View;
FIntPoint SrcSize = InputDesc->Extent;
FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent;
FIntPoint TileCount = GetNumTiles16x16( View.ViewRect.Size() );
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
TRefCountPtr<IPooledRenderTarget> DepthTarget;
FPooledRenderTargetDesc Desc( FPooledRenderTargetDesc::Create2DDesc( DestSize, PF_ShadowDepth, FClearValueBinding::DepthOne, TexCreate_None, TexCreate_DepthStencilTargetable, false ) );
GRenderTargetPool.FindFreeElement(Context.RHICmdList, Desc, DepthTarget, TEXT("VelocityScatterDepth") );
// Set the view family's render target/viewport.
FRHIRenderTargetView ColorView(DestRenderTarget.TargetableTexture, 0, -1, ERenderTargetLoadAction::ELoad, ERenderTargetStoreAction::EStore);
FRHIDepthRenderTargetView DepthView(DepthTarget->GetRenderTargetItem().TargetableTexture, ERenderTargetLoadAction::EClear, ERenderTargetStoreAction::EStore, ERenderTargetLoadAction::ELoad, ERenderTargetStoreAction::EStore);
FRHISetRenderTargetsInfo RTInfo(1, &ColorView, DepthView);
// clear depth
// Max >= Min so no need to clear on second pass
Context.RHICmdList.SetRenderTargetsAndClear(RTInfo);
Context.SetViewportAndCallRHI(0, 0, 0.0f, TileCount.X, TileCount.Y, 1.0f);
// Min,Max
for( int i = 0; i < 2; i++ )
{
if( i == 0 )
{
// min
Context.RHICmdList.SetBlendState( TStaticBlendStateWriteMask< CW_RGBA >::GetRHI() );
Context.RHICmdList.SetRasterizerState( TStaticRasterizerState<>::GetRHI() );
Context.RHICmdList.SetDepthStencilState( TStaticDepthStencilState< true, CF_Less >::GetRHI() );
}
else
{
// max
Context.RHICmdList.SetBlendState( TStaticBlendStateWriteMask< CW_BA >::GetRHI() );
Context.RHICmdList.SetRasterizerState( TStaticRasterizerState<>::GetRHI() );
Context.RHICmdList.SetDepthStencilState( TStaticDepthStencilState< true, CF_Greater >::GetRHI() );
}
TShaderMapRef< FPostProcessVelocityScatterVS > VertexShader(Context.GetShaderMap());
TShaderMapRef< FPostProcessVelocityScatterPS > PixelShader(Context.GetShaderMap());
static FGlobalBoundShaderState BoundShaderState;
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
VertexShader->SetParameters( Context, i );
PixelShader->SetParameters( Context );
// needs to be the same on shader side (faster on NVIDIA and AMD)
int32 QuadsPerInstance = 8;
Context.RHICmdList.SetStreamSource(0, NULL, 0, 0);
Context.RHICmdList.DrawIndexedPrimitive(GScatterQuadIndexBuffer.IndexBufferRHI, PT_TriangleList, 0, 0, 32, 0, 2 * QuadsPerInstance, FMath::DivideAndRoundUp(TileCount.X * TileCount.Y, QuadsPerInstance));
}
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
}
FPooledRenderTargetDesc FRCPassPostProcessVelocityScatter::ComputeOutputDesc(EPassOutputId InPassOutputId) const
{
FPooledRenderTargetDesc Ret = GetInput(ePId_Input0)->GetOutput()->RenderTargetDesc;
Ret.Reset();
Ret.DebugName = TEXT("ScatteredMaxVelocity");
return Ret;
}
class FPostProcessVelocityGatherCS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FPostProcessVelocityGatherCS, Global);
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5);
}
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
}
/** Default constructor. */
FPostProcessVelocityGatherCS() {}
public:
FShaderParameter OutScatteredMaxVelocity;
/** Initialization constructor. */
FPostProcessVelocityGatherCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
PostprocessParameter.Bind(Initializer.ParameterMap);
MotionBlurParameters.Bind(Initializer.ParameterMap, TEXT("MotionBlurParameters"));
OutScatteredMaxVelocity.Bind(Initializer.ParameterMap, TEXT("OutScatteredMaxVelocity"));
}
// FShader interface.
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << PostprocessParameter;
Ar << MotionBlurParameters;
Ar << OutScatteredMaxVelocity;
return bShaderHasOutdatedParameters;
}
void SetParameters(const FRenderingCompositePassContext& Context)
{
const FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
PostprocessParameter.SetCS(ShaderRHI, Context, Context.RHICmdList, TStaticSamplerState<SF_Point, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI());
SetShaderValue(Context.RHICmdList, ShaderRHI, MotionBlurParameters, GetMotionBlurParameters( Context.View ) );
}
private:
FPostProcessPassParameters PostprocessParameter;
FShaderParameter MotionBlurParameters;
};
IMPLEMENT_SHADER_TYPE(,FPostProcessVelocityGatherCS,TEXT("PostProcessVelocityFlatten"),TEXT("VelocityGatherCS"),SF_Compute);
void FRCPassPostProcessVelocityGather::Process(FRenderingCompositePassContext& Context)
{
SCOPED_DRAW_EVENT(Context.RHICmdList, VelocityDilate);
const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0);
if(!InputDesc)
{
// input is not hooked up correctly
return;
}
const FSceneView& View = Context.View;
FIntPoint TileCount = GetNumTiles16x16( View.ViewRect.Size() );
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
SetRenderTarget(Context.RHICmdList, FTextureRHIRef(), FTextureRHIRef());
Context.SetViewportAndCallRHI( 0, 0, 0.0f, TileCount.X, TileCount.Y, 1.0f );
TShaderMapRef< FPostProcessVelocityGatherCS > ComputeShader( Context.GetShaderMap() );
Context.RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
// set destination
Context.RHICmdList.SetUAVParameter( ComputeShader->GetComputeShader(), ComputeShader->OutScatteredMaxVelocity.GetBaseIndex(), DestRenderTarget.UAV );
ComputeShader->SetParameters( Context );
FIntPoint GroupCount = GetNumTiles16x16( TileCount );
DispatchComputeShader(Context.RHICmdList, *ComputeShader, GroupCount.X, GroupCount.Y, 1);
// un-set destination
Context.RHICmdList.SetUAVParameter( ComputeShader->GetComputeShader(), ComputeShader->OutScatteredMaxVelocity.GetBaseIndex(), NULL );
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
}
FPooledRenderTargetDesc FRCPassPostProcessVelocityGather::ComputeOutputDesc(EPassOutputId InPassOutputId) const
{
FPooledRenderTargetDesc Ret = GetInput(ePId_Input0)->GetOutput()->RenderTargetDesc;
Ret.Reset();
Ret.TargetableFlags |= TexCreate_UAV;
Ret.TargetableFlags |= TexCreate_RenderTargetable;
Ret.DebugName = TEXT("ScatteredMaxVelocity");
return Ret;
}
/**
* @param Quality 0: visualize, 1:low, 2:medium, 3:high, 4:very high
*/
template< uint32 Quality >
class FPostProcessMotionBlurPS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FPostProcessMotionBlurPS, Global);
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5);
}
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Platform,OutEnvironment);
OutEnvironment.SetDefine(TEXT("MOTION_BLUR_QUALITY"), Quality);
}
/** Default constructor. */
FPostProcessMotionBlurPS() {}
public:
FPostProcessPassParameters PostprocessParameter;
FDeferredPixelShaderParameters DeferredParameters;
FShaderParameter MotionBlurParameters;
/** Initialization constructor. */
FPostProcessMotionBlurPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
PostprocessParameter.Bind(Initializer.ParameterMap);
DeferredParameters.Bind(Initializer.ParameterMap);
MotionBlurParameters.Bind(Initializer.ParameterMap, TEXT("MotionBlurParameters"));
}
// FShader interface.
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << PostprocessParameter << DeferredParameters << MotionBlurParameters;
return bShaderHasOutdatedParameters;
}
void SetParameters(const FRenderingCompositePassContext& Context, float Scale)
{
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
DeferredParameters.Set(Context.RHICmdList, ShaderRHI, Context.View);
{
bool bFiltered = false;
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
bFiltered = CVarMotionBlurFiltering.GetValueOnRenderThread() != 0;
#endif // !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if(bFiltered)
{
//PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Border,AM_Border,AM_Clamp>::GetRHI());
FSamplerStateRHIParamRef Filters[] =
{
TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(),
TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(),
TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(),
TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(),
};
PostprocessParameter.SetPS( ShaderRHI, Context, 0, eFC_0000, Filters );
}
else
{
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
}
}
SetShaderValue(Context.RHICmdList, ShaderRHI, MotionBlurParameters, GetMotionBlurParameters( Context.View, Scale ) );
}
static const TCHAR* GetSourceFilename()
{
return TEXT("PostProcessMotionBlur");
}
static const TCHAR* GetFunctionName()
{
return TEXT("MainPS");
}
};
// #define avoids a lot of code duplication
#define VARIATION1(A) typedef FPostProcessMotionBlurPS<A> FPostProcessMotionBlurPS##A; \
IMPLEMENT_SHADER_TYPE2(FPostProcessMotionBlurPS##A, SF_Pixel);
VARIATION1(1) VARIATION1(2) VARIATION1(3) VARIATION1(4)
#undef VARIATION1
// @param Quality 0: visualize, 1:low, 2:medium, 3:high, 4:very high
template< uint32 Quality >
static void SetMotionBlurShaderNewTempl( const FRenderingCompositePassContext& Context, float Scale )
{
TShaderMapRef< FPostProcessVS > VertexShader( Context.GetShaderMap() );
TShaderMapRef< FPostProcessMotionBlurPS< Quality > > PixelShader( Context.GetShaderMap() );
static FGlobalBoundShaderState BoundShaderState;
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
VertexShader->SetParameters(Context);
PixelShader->SetParameters(Context, Scale);
}
void FRCPassPostProcessMotionBlur::Process(FRenderingCompositePassContext& Context)
{
const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0);
if(!InputDesc)
{
// input is not hooked up correctly
return;
}
const FSceneView& View = Context.View;
// we assume the input and output is full resolution
FIntPoint SrcSize = InputDesc->Extent;
FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent;
// e.g. 4 means the input texture is 4x smaller than the buffer size
uint32 ScaleFactor = FSceneRenderTargets::Get(Context.RHICmdList).GetBufferSizeXY().X / SrcSize.X;
FIntRect SrcRect = View.ViewRect / ScaleFactor;
FIntRect DestRect = SrcRect;
SCOPED_DRAW_EVENTF(Context.RHICmdList, MotionBlurNew, TEXT("MotionBlur %dx%d"), SrcRect.Width(), SrcRect.Height());
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
// Set the view family's render target/viewport.
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef());
Context.SetViewportAndCallRHI(SrcRect);
// is optimized away if possible (RT size=view size, )
//Context.RHICmdList.Clear(true, FLinearColor::Black, false, 1.0f, false, 0, SrcRect);
// set the state
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI());
float BlurScaleLUT[] =
{
1.0f - 0.5f / 4.0f,
1.0f - 0.5f / 6.0f,
1.0f - 0.5f / 8.0f,
1.0f - 0.5f / 16.0f,
1.0f / 4.0f * CVarMotionBlur2ndScale.GetValueOnRenderThread(),
1.0f / 6.0f * CVarMotionBlur2ndScale.GetValueOnRenderThread(),
1.0f / 8.0f * CVarMotionBlur2ndScale.GetValueOnRenderThread(),
1.0f / 16.0f * CVarMotionBlur2ndScale.GetValueOnRenderThread(),
};
float Scale = Pass >= 0 ? BlurScaleLUT[ (Pass * 4) + (Quality - 1) ] : 1.0f;
if(Quality == 1)
{
SetMotionBlurShaderNewTempl<1>( Context, Scale );
}
else if(Quality == 2)
{
SetMotionBlurShaderNewTempl<2>( Context, Scale );
}
else if(Quality == 3 || Pass > 0 )
{
SetMotionBlurShaderNewTempl<3>( Context, Scale );
}
else
{
check(Quality == 4);
SetMotionBlurShaderNewTempl<4>( Context, Scale );
}
TShaderMapRef<FPostProcessVS> VertexShader(Context.GetShaderMap());
DrawPostProcessPass(
Context.RHICmdList,
0, 0,
SrcRect.Width(), SrcRect.Height(),
SrcRect.Min.X, SrcRect.Min.Y,
SrcRect.Width(), SrcRect.Height(),
SrcRect.Size(),
SrcSize,
*VertexShader,
View.StereoPass,
Context.HasHmdMesh(),
EDRF_UseTriangleOptimization);
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
}
FPooledRenderTargetDesc FRCPassPostProcessMotionBlur::ComputeOutputDesc(EPassOutputId InPassOutputId) const
{
FPooledRenderTargetDesc Ret = GetInput(ePId_Input0)->GetOutput()->RenderTargetDesc;
Ret.Reset();
Ret.Format = PF_FloatRGB;
Ret.DebugName = TEXT("MotionBlur");
Ret.AutoWritable = false;
return Ret;
}
class FPostProcessVisualizeMotionBlurPS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FPostProcessVisualizeMotionBlurPS, Global);
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM4);
}
/** Default constructor. */
FPostProcessVisualizeMotionBlurPS() {}
public:
FPostProcessPassParameters PostprocessParameter;
FDeferredPixelShaderParameters DeferredParameters;
FShaderParameter PrevViewProjMatrix;
/** Initialization constructor. */
FPostProcessVisualizeMotionBlurPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
PostprocessParameter.Bind(Initializer.ParameterMap);
DeferredParameters.Bind(Initializer.ParameterMap);
PrevViewProjMatrix.Bind(Initializer.ParameterMap, TEXT("PrevViewProjMatrix"));
}
// FShader interface.
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << PostprocessParameter << DeferredParameters << PrevViewProjMatrix;
return bShaderHasOutdatedParameters;
}
void SetParameters(const FRenderingCompositePassContext& Context)
{
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
DeferredParameters.Set(Context.RHICmdList, ShaderRHI, Context.View);
SetUniformBufferParameter(Context.RHICmdList, ShaderRHI, GetUniformBufferParameter<FCameraMotionParameters>(), CreateCameraMotionParametersUniformBuffer(Context.View));
{
bool bFiltered = false;
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
bFiltered = CVarMotionBlurFiltering.GetValueOnRenderThread() != 0;
#endif // !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if(bFiltered)
{
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Border,AM_Border,AM_Clamp>::GetRHI());
}
else
{
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Point,AM_Border,AM_Border,AM_Clamp>::GetRHI());
}
}
if( Context.View.Family->EngineShowFlags.CameraInterpolation )
{
// Instead of finding the world space position of the current pixel, calculate the world space position offset by the camera position,
// then translate by the difference between last frame's camera position and this frame's camera position,
// then apply the rest of the transforms. This effectively avoids precision issues near the extents of large levels whose world space position is very large.
FVector ViewOriginDelta = Context.View.ViewMatrices.ViewOrigin - Context.View.PrevViewMatrices.ViewOrigin;
SetShaderValue(Context.RHICmdList, ShaderRHI, PrevViewProjMatrix, FTranslationMatrix(ViewOriginDelta) * Context.View.PrevViewRotationProjMatrix);
}
else
{
SetShaderValue(Context.RHICmdList, ShaderRHI, PrevViewProjMatrix, Context.View.ViewMatrices.GetViewRotationProjMatrix());
}
}
static const TCHAR* GetSourceFilename()
{
return TEXT("PostProcessMotionBlur");
}
static const TCHAR* GetFunctionName()
{
return TEXT("VisualizeMotionBlurPS");
}
};
IMPLEMENT_SHADER_TYPE3(FPostProcessVisualizeMotionBlurPS, SF_Pixel);
void FRCPassPostProcessVisualizeMotionBlur::Process(FRenderingCompositePassContext& Context)
{
SCOPED_DRAW_EVENT(Context.RHICmdList, VisualizeMotionBlur);
const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0);
if(!InputDesc)
{
// input is not hooked up correctly
return;
}
const FSceneView& View = Context.View;
const FSceneViewFamily& ViewFamily = *(View.Family);
FIntPoint TexSize = InputDesc->Extent;
// we assume the input and output is full resolution
FIntPoint SrcSize = InputDesc->Extent;
FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent;
// e.g. 4 means the input texture is 4x smaller than the buffer size
uint32 ScaleFactor = FSceneRenderTargets::Get(Context.RHICmdList).GetBufferSizeXY().X / SrcSize.X;
FIntRect SrcRect = FIntRect::DivideAndRoundUp(View.ViewRect, ScaleFactor);
FIntRect DestRect = SrcRect;
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
// Set the view family's render target/viewport.
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef());
// is optimized away if possible (RT size=view size, )
Context.RHICmdList.Clear(true, FLinearColor::Black, false, 1.0f, false, 0, SrcRect);
Context.SetViewportAndCallRHI(SrcRect);
// set the state
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI());
TShaderMapRef<FPostProcessVS> VertexShader(Context.GetShaderMap());
TShaderMapRef<FPostProcessVisualizeMotionBlurPS> PixelShader(Context.GetShaderMap());
static FGlobalBoundShaderState BoundShaderState;
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
VertexShader->SetParameters(Context);
PixelShader->SetParameters(Context);
// Draw a quad mapping scene color to the view's render target
DrawRectangle(
Context.RHICmdList,
0, 0,
SrcRect.Width(), SrcRect.Height(),
SrcRect.Min.X, SrcRect.Min.Y,
SrcRect.Width(), SrcRect.Height(),
SrcRect.Size(),
SrcSize,
*VertexShader,
EDRF_UseTriangleOptimization);
// this is a helper class for FCanvas to be able to get screen size
class FRenderTargetTemp : public FRenderTarget
{
public:
const FSceneView& View;
const FTexture2DRHIRef Texture;
FRenderTargetTemp(const FSceneView& InView, const FTexture2DRHIRef InTexture)
: View(InView), Texture(InTexture)
{
}
virtual FIntPoint GetSizeXY() const
{
return View.ViewRect.Size();
};
virtual const FTexture2DRHIRef& GetRenderTargetTexture() const
{
return Texture;
}
} TempRenderTarget(View, (const FTexture2DRHIRef&)DestRenderTarget.TargetableTexture);
FCanvas Canvas(&TempRenderTarget, NULL, ViewFamily.CurrentRealTime, ViewFamily.CurrentWorldTime, ViewFamily.DeltaWorldTime, Context.GetFeatureLevel());
float X = 20;
float Y = 38;
const float YStep = 14;
const float ColumnWidth = 200;
FString Line;
Line = FString::Printf(TEXT("Visualize MotionBlur"));
Canvas.DrawShadowedString(X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 0));
static const auto MotionBlurDebugVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.MotionBlurDebug"));
const int32 MotionBlurDebug = MotionBlurDebugVar ? MotionBlurDebugVar->GetValueOnRenderThread() : 0;
Line = FString::Printf(TEXT("%d, %d"), ViewFamily.FrameNumber, MotionBlurDebug);
Canvas.DrawShadowedString(X, Y += YStep, TEXT("FrameNo, r.MotionBlurDebug:"), GetStatsFont(), FLinearColor(1, 1, 0));
Canvas.DrawShadowedString(X + ColumnWidth, Y, *Line, GetStatsFont(), FLinearColor(1, 1, 0));
static const auto VelocityTestVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.VelocityTest"));
const int32 VelocityTest = VelocityTestVar ? VelocityTestVar->GetValueOnRenderThread() : 0;
extern bool IsParallelVelocity();
Line = FString::Printf(TEXT("%d, %d, %d"), ViewFamily.bWorldIsPaused, VelocityTest, IsParallelVelocity());
Canvas.DrawShadowedString(X, Y += YStep, TEXT("Paused, r.VelocityTest, Parallel:"), GetStatsFont(), FLinearColor(1, 1, 0));
Canvas.DrawShadowedString(X + ColumnWidth, Y, *Line, GetStatsFont(), FLinearColor(1, 1, 0));
const FScene* Scene = (const FScene*)View.Family->Scene;
Canvas.DrawShadowedString(X, Y += YStep, TEXT("MotionBlurInfoData (per object):"), GetStatsFont(), FLinearColor(1, 1, 0));
Canvas.DrawShadowedString(X + ColumnWidth, Y, *Scene->MotionBlurInfoData.GetDebugString(), GetStatsFont(), FLinearColor(1, 1, 0));
const FSceneViewState *SceneViewState = (const FSceneViewState*)View.State;
Line = FString::Printf(TEXT("View=%.4x PrevView=%.4x"),
View.ViewMatrices.ViewMatrix.ComputeHash() & 0xffff,
SceneViewState->PrevViewMatrices.ViewMatrix.ComputeHash() & 0xffff);
Canvas.DrawShadowedString(X, Y += YStep, TEXT("ViewMatrix:"), GetStatsFont(), FLinearColor(1, 1, 0));
Canvas.DrawShadowedString(X + ColumnWidth, Y, *Line, GetStatsFont(), FLinearColor(1, 1, 0));
Canvas.Flush_RenderThread(Context.RHICmdList);
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
}
FPooledRenderTargetDesc FRCPassPostProcessVisualizeMotionBlur::ComputeOutputDesc(EPassOutputId InPassOutputId) const
{
FPooledRenderTargetDesc Ret = GetInput(ePId_Input0)->GetOutput()->RenderTargetDesc;
Ret.Reset();
Ret.DebugName = TEXT("MotionBlur");
Ret.AutoWritable = false;
return Ret;
}