2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
/*=============================================================================
PostProcessMotionBlur . cpp : Post process MotionBlur implementation .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
# include "RendererPrivate.h"
# include "ScenePrivate.h"
# include "SceneFilterRendering.h"
2015-02-23 00:44:20 -05:00
# include "PostProcessAmbientOcclusion.h"
2014-03-14 14:13:41 -04:00
# include "PostProcessMotionBlur.h"
2015-03-04 08:31:40 -05:00
# include "PostProcessAmbientOcclusion.h"
2014-03-14 14:13:41 -04:00
# include "PostProcessing.h"
2014-08-21 06:03:00 -04:00
# include "SceneUtils.h"
2015-04-23 17:35:40 -04:00
# include "GPUSkinVertexFactory.h"
# include "../../Engine/Private/SkeletalRenderGPUSkin.h"
2014-03-14 14:13:41 -04:00
2014-06-25 05:47:33 -04:00
# 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
2014-03-14 14:13:41 -04:00
2015-02-24 16:28:47 -05:00
static TAutoConsoleVariable < int32 > CVarMotionBlurSmoothMax (
TEXT ( " r.MotionBlurSmoothMax " ) ,
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 ) ;
2014-03-14 14:13:41 -04:00
2014-09-05 17:47:58 -04:00
/** Encapsulates the post processing motion blur vertex shader. */
class FPostProcessMotionBlurSetupVS : public FGlobalShader
{
DECLARE_SHADER_TYPE ( FPostProcessMotionBlurSetupVS , Global ) ;
static bool ShouldCache ( EShaderPlatform Platform )
{
2014-09-08 04:39:14 -04:00
return IsFeatureLevelSupported ( Platform , ERHIFeatureLevel : : SM4 ) ;
2014-09-05 17:47:58 -04:00
}
/** Default constructor. */
FPostProcessMotionBlurSetupVS ( ) { }
// FShader interface.
2015-04-01 07:20:55 -04:00
virtual bool Serialize ( FArchive & Ar ) override
2014-09-05 17:47:58 -04:00
{
bool bShaderHasOutdatedParameters = FGlobalShader : : Serialize ( Ar ) ;
Ar < < PostprocessParameter ;
return bShaderHasOutdatedParameters ;
}
/** to have a similar interface as all other shaders */
void SetParameters ( const FRenderingCompositePassContext & Context )
{
const auto ShaderRHI = GetVertexShader ( ) ;
FGlobalShader : : SetParameters ( Context . RHICmdList , ShaderRHI , Context . View ) ;
PostprocessParameter . SetVS ( ShaderRHI , Context , TStaticSamplerState < SF_Point , AM_Clamp , AM_Clamp , AM_Clamp > : : GetRHI ( ) ) ;
}
public :
FPostProcessPassParameters PostprocessParameter ;
/** Initialization constructor. */
FPostProcessMotionBlurSetupVS ( const ShaderMetaType : : CompiledShaderInitializerType & Initializer )
: FGlobalShader ( Initializer )
{
PostprocessParameter . Bind ( Initializer . ParameterMap ) ;
}
} ;
IMPLEMENT_SHADER_TYPE ( , FPostProcessMotionBlurSetupVS , TEXT ( " PostProcessMotionBlur " ) , TEXT ( " SetupVS " ) , SF_Vertex ) ;
2014-03-14 14:13:41 -04:00
/** Encapsulates the post processing motion blur pixel shader. */
class FPostProcessMotionBlurSetupPS : public FGlobalShader
{
DECLARE_SHADER_TYPE ( FPostProcessMotionBlurSetupPS , Global ) ;
static bool ShouldCache ( EShaderPlatform Platform )
{
2014-08-25 14:41:54 -04:00
return IsFeatureLevelSupported ( Platform , ERHIFeatureLevel : : SM4 ) ;
2014-03-14 14:13:41 -04:00
}
/** Default constructor. */
FPostProcessMotionBlurSetupPS ( ) { }
public :
FPostProcessPassParameters PostprocessParameter ;
FShaderParameter VelocityScale ;
/** Initialization constructor. */
FPostProcessMotionBlurSetupPS ( const ShaderMetaType : : CompiledShaderInitializerType & Initializer )
: FGlobalShader ( Initializer )
{
PostprocessParameter . Bind ( Initializer . ParameterMap ) ;
VelocityScale . Bind ( Initializer . ParameterMap , TEXT ( " VelocityScale " ) ) ;
}
// FShader interface.
2015-04-01 07:20:55 -04:00
virtual bool Serialize ( FArchive & Ar ) override
2014-03-14 14:13:41 -04:00
{
bool bShaderHasOutdatedParameters = FGlobalShader : : Serialize ( Ar ) ;
Ar < < PostprocessParameter < < VelocityScale ;
return bShaderHasOutdatedParameters ;
}
2014-06-12 07:13:34 -04:00
void SetParameters ( const FRenderingCompositePassContext & Context )
2014-03-14 14:13:41 -04:00
{
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader ( ) ;
2014-06-12 07:13:34 -04:00
FGlobalShader : : SetParameters ( Context . RHICmdList , ShaderRHI , Context . View ) ;
2014-03-14 14:13:41 -04:00
2014-06-12 07:13:34 -04:00
PostprocessParameter . SetPS ( ShaderRHI , Context , TStaticSamplerState < SF_Point , AM_Clamp , AM_Clamp , AM_Clamp > : : GetRHI ( ) ) ;
2014-03-14 14:13:41 -04:00
{
const float SizeX = Context . View . ViewRect . Width ( ) ;
const float SizeY = Context . View . ViewRect . Height ( ) ;
const float InvAspectRatio = SizeY / SizeX ;
const FSceneViewState * ViewState = ( FSceneViewState * ) Context . View . State ;
const float MotionBlurTimeScale = ViewState ? ViewState - > MotionBlurTimeScale : 1.0f ;
const float ViewMotionBlurScale = 0.5f * MotionBlurTimeScale * Context . View . FinalPostProcessSettings . MotionBlurAmount ;
// 0:no 1:full screen width
float MaxVelocity = Context . View . FinalPostProcessSettings . MotionBlurMax / 100.0f ;
float InvMaxVelocity = 1.0f / MaxVelocity ;
float ObjectScaleX = ViewMotionBlurScale * InvMaxVelocity ;
float ObjectScaleY = ViewMotionBlurScale * InvMaxVelocity * InvAspectRatio ;
2014-06-12 07:13:34 -04:00
SetShaderValue ( Context . RHICmdList , ShaderRHI , VelocityScale , FVector4 ( ObjectScaleX , - ObjectScaleY , 0 , 0 ) ) ;
2014-03-14 14:13:41 -04:00
}
}
} ;
IMPLEMENT_SHADER_TYPE ( , FPostProcessMotionBlurSetupPS , TEXT ( " PostProcessMotionBlur " ) , TEXT ( " SetupPS " ) , SF_Pixel ) ;
void FRCPassPostProcessMotionBlurSetup : : Process ( FRenderingCompositePassContext & Context )
{
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( Context . RHICmdList , MotionBlurSetup ) ;
2014-03-14 14:13:41 -04:00
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 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 = GSceneRenderTargets . GetBufferSizeXY ( ) . X / SrcSize . X ;
FIntRect SrcRect = View . ViewRect / ScaleFactor ;
// Viewport size not even also causes issue
FIntRect DestRect = FIntRect : : DivideAndRoundUp ( SrcRect , 2 ) ;
const FSceneRenderTargetItem & DestRenderTarget0 = PassOutputs [ 0 ] . RequestSurface ( Context ) ;
const FSceneRenderTargetItem & DestRenderTarget1 = PassOutputs [ 1 ] . RequestSurface ( Context ) ;
// Set the view family's render target/viewport.
FTextureRHIParamRef RenderTargets [ ] =
{
DestRenderTarget0 . TargetableTexture ,
DestRenderTarget1 . TargetableTexture
} ;
2014-06-12 07:13:34 -04:00
SetRenderTargets ( Context . RHICmdList , ARRAY_COUNT ( RenderTargets ) , RenderTargets , FTextureRHIParamRef ( ) , 0 , NULL ) ;
2014-03-14 14:13:41 -04:00
// is optimized away if possible (RT size=view size, )
FLinearColor ClearColors [ 2 ] = { FLinearColor ( 0 , 0 , 0 , 0 ) , FLinearColor ( 0 , 0 , 0 , 0 ) } ;
2014-06-12 07:13:34 -04:00
Context . RHICmdList . ClearMRT ( true , 2 , ClearColors , false , 1.0f , false , 0 , DestRect ) ;
2014-03-14 14:13:41 -04:00
Context . SetViewportAndCallRHI ( 0 , 0 , 0.0f , DestSize . X , DestSize . Y , 1.0f ) ;
// set the state
2014-06-12 07:13:34 -04:00
Context . RHICmdList . SetBlendState ( TStaticBlendState < > : : GetRHI ( ) ) ;
Context . RHICmdList . SetRasterizerState ( TStaticRasterizerState < > : : GetRHI ( ) ) ;
Context . RHICmdList . SetDepthStencilState ( TStaticDepthStencilState < false , CF_Always > : : GetRHI ( ) ) ;
2014-06-05 16:38:54 -04:00
2014-09-05 17:47:58 -04:00
TShaderMapRef < FPostProcessMotionBlurSetupVS > VertexShader ( Context . GetShaderMap ( ) ) ;
2014-03-14 14:13:41 -04:00
2014-09-05 17:47:58 -04:00
{
2014-08-28 06:22:54 -04:00
TShaderMapRef < FPostProcessMotionBlurSetupPS > PixelShader ( Context . GetShaderMap ( ) ) ;
2014-03-14 14:13:41 -04:00
static FGlobalBoundShaderState BoundShaderState ;
2014-06-27 11:07:13 -04:00
2014-03-14 14:13:41 -04:00
2014-08-19 10:41:34 -04:00
SetGlobalBoundShaderState ( Context . RHICmdList , Context . GetFeatureLevel ( ) , BoundShaderState , GFilterVertexDeclaration . VertexDeclarationRHI , * VertexShader , * PixelShader ) ;
2014-03-14 14:13:41 -04:00
2014-06-12 07:13:34 -04:00
PixelShader - > SetParameters ( Context ) ;
VertexShader - > SetParameters ( Context ) ;
2014-03-14 14:13:41 -04:00
}
// Draw a quad mapping scene color to the view's render target
DrawRectangle (
2014-06-12 07:13:34 -04:00
Context . RHICmdList ,
2014-03-14 14:13:41 -04:00
DestRect . Min . X , DestRect . Min . Y ,
DestRect . Width ( ) , DestRect . Height ( ) ,
SrcRect . Min . X , SrcRect . Min . Y ,
SrcRect . Width ( ) , SrcRect . Height ( ) ,
DestSize ,
SrcSize ,
2014-04-23 17:26:59 -04:00
* VertexShader ,
2014-03-14 14:13:41 -04:00
EDRF_UseTriangleOptimization ) ;
2014-06-12 07:13:34 -04:00
Context . RHICmdList . CopyToResolveTarget ( DestRenderTarget0 . TargetableTexture , DestRenderTarget0 . ShaderResourceTexture , false , FResolveParams ( ) ) ;
Context . RHICmdList . CopyToResolveTarget ( DestRenderTarget1 . TargetableTexture , DestRenderTarget1 . ShaderResourceTexture , false , FResolveParams ( ) ) ;
2014-03-14 14:13:41 -04:00
}
FPooledRenderTargetDesc FRCPassPostProcessMotionBlurSetup : : ComputeOutputDesc ( EPassOutputId InPassOutputId ) const
{
if ( InPassOutputId = = ePId_Output0 )
{
// downsampled velocity
FPooledRenderTargetDesc Ret = PassInputs [ 0 ] . GetOutput ( ) - > RenderTargetDesc ;
Ret . Reset ( ) ;
Ret . Extent / = 2 ;
Ret . Extent . X = FMath : : Max ( 1 , Ret . Extent . X ) ;
Ret . Extent . Y = FMath : : Max ( 1 , Ret . Extent . Y ) ;
// we need at least a format in the range 0..1 with RGB channels, A is unused
// Ret.Format = PF_A2B10G10R10;
// we need alpha to renormalize
Ret . Format = PF_FloatRGBA ;
Ret . TargetableFlags & = ~ TexCreate_UAV ;
Ret . TargetableFlags | = TexCreate_RenderTargetable ;
Ret . DebugName = TEXT ( " MotionBlurSetup0 " ) ;
return Ret ;
}
else
{
check ( InPassOutputId = = ePId_Output1 ) ;
// scene color with depth in alpha
FPooledRenderTargetDesc Ret = PassInputs [ 1 ] . GetOutput ( ) - > RenderTargetDesc ;
Ret . Reset ( ) ;
Ret . Extent / = 2 ;
Ret . Extent . X = FMath : : Max ( 1 , Ret . Extent . X ) ;
Ret . Extent . Y = FMath : : Max ( 1 , Ret . Extent . Y ) ;
Ret . Format = PF_FloatRGBA ;
Ret . TargetableFlags & = ~ TexCreate_UAV ;
Ret . TargetableFlags | = TexCreate_RenderTargetable ;
Ret . DebugName = TEXT ( " MotionBlurSetup1 " ) ;
return Ret ;
}
}
/**
* @ param Quality 0 : visualize , 1 : low , 2 : medium , 3 : high , 4 : very high
* Encapsulates a MotionBlur pixel shader .
*/
template < uint32 Quality >
class FPostProcessMotionBlurPS : public FGlobalShader
{
DECLARE_SHADER_TYPE ( FPostProcessMotionBlurPS , Global ) ;
static bool ShouldCache ( EShaderPlatform Platform )
{
return IsFeatureLevelSupported ( Platform , ERHIFeatureLevel : : SM4 ) ;
}
static void ModifyCompilationEnvironment ( EShaderPlatform Platform , FShaderCompilerEnvironment & OutEnvironment )
{
2014-06-05 16:38:54 -04:00
FGlobalShader : : ModifyCompilationEnvironment ( Platform , OutEnvironment ) ;
2014-03-14 14:13:41 -04:00
OutEnvironment . SetDefine ( TEXT ( " MOTION_BLUR_QUALITY " ) , Quality ) ;
}
/** Default constructor. */
FPostProcessMotionBlurPS ( ) { }
public :
FPostProcessPassParameters PostprocessParameter ;
FDeferredPixelShaderParameters DeferredParameters ;
FShaderParameter PrevViewProjMatrix ;
FShaderParameter TextureViewMad ;
FShaderParameter MotionBlurParameters ;
2015-04-23 17:35:40 -04:00
FShaderResourceParameter BoneMatrices0 ;
FShaderResourceParameter BoneMatrices1 ;
2014-03-14 14:13:41 -04:00
/** Initialization constructor. */
FPostProcessMotionBlurPS ( const ShaderMetaType : : CompiledShaderInitializerType & Initializer )
: FGlobalShader ( Initializer )
{
PostprocessParameter . Bind ( Initializer . ParameterMap ) ;
DeferredParameters . Bind ( Initializer . ParameterMap ) ;
PrevViewProjMatrix . Bind ( Initializer . ParameterMap , TEXT ( " PrevViewProjMatrix " ) ) ;
TextureViewMad . Bind ( Initializer . ParameterMap , TEXT ( " TextureViewMad " ) ) ;
MotionBlurParameters . Bind ( Initializer . ParameterMap , TEXT ( " MotionBlurParameters " ) ) ;
2015-04-23 17:35:40 -04:00
BoneMatrices0 . Bind ( Initializer . ParameterMap , TEXT ( " BoneMatrices0 " ) ) ;
BoneMatrices1 . Bind ( Initializer . ParameterMap , TEXT ( " BoneMatrices1 " ) ) ;
2014-03-14 14:13:41 -04:00
}
// FShader interface.
2015-04-01 07:20:55 -04:00
virtual bool Serialize ( FArchive & Ar ) override
2014-03-14 14:13:41 -04:00
{
bool bShaderHasOutdatedParameters = FGlobalShader : : Serialize ( Ar ) ;
2015-04-23 17:35:40 -04:00
Ar < < PostprocessParameter < < DeferredParameters < < PrevViewProjMatrix < < TextureViewMad < < MotionBlurParameters < < BoneMatrices0 < < BoneMatrices1 ;
2014-03-14 14:13:41 -04:00
return bShaderHasOutdatedParameters ;
}
2014-06-12 07:13:34 -04:00
void SetParameters ( const FRenderingCompositePassContext & Context )
2014-03-14 14:13:41 -04:00
{
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader ( ) ;
2014-06-12 07:13:34 -04:00
FGlobalShader : : SetParameters ( Context . RHICmdList , ShaderRHI , Context . View ) ;
2014-03-14 14:13:41 -04:00
2014-06-12 07:13:34 -04:00
DeferredParameters . Set ( Context . RHICmdList , ShaderRHI , Context . View ) ;
2014-03-14 14:13:41 -04:00
{
bool bFiltered = false ;
# if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
2014-06-25 05:47:33 -04:00
bFiltered = CVarMotionBlurFiltering . GetValueOnRenderThread ( ) ! = 0 ;
2014-03-14 14:13:41 -04:00
# endif // !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if ( bFiltered )
{
2014-06-12 07:13:34 -04:00
PostprocessParameter . SetPS ( ShaderRHI , Context , TStaticSamplerState < SF_Bilinear , AM_Border , AM_Border , AM_Clamp > : : GetRHI ( ) ) ;
2014-03-14 14:13:41 -04:00
}
else
{
2014-06-12 07:13:34 -04:00
PostprocessParameter . SetPS ( ShaderRHI , Context , TStaticSamplerState < SF_Point , AM_Border , AM_Border , AM_Clamp > : : GetRHI ( ) ) ;
2014-03-14 14:13:41 -04:00
}
}
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 ;
2014-06-12 07:13:34 -04:00
SetShaderValue ( Context . RHICmdList , ShaderRHI , PrevViewProjMatrix , FTranslationMatrix ( ViewOriginDelta ) * Context . View . PrevViewRotationProjMatrix ) ;
2014-03-14 14:13:41 -04:00
}
else
{
2014-06-12 07:13:34 -04:00
SetShaderValue ( Context . RHICmdList , ShaderRHI , PrevViewProjMatrix , Context . View . ViewMatrices . GetViewRotationProjMatrix ( ) ) ;
2014-03-14 14:13:41 -04:00
}
TRefCountPtr < IPooledRenderTarget > InputPooledElement = Context . Pass - > GetInput ( ePId_Input0 ) - > GetOutput ( ) - > RequestInput ( ) ;
// to mask out samples from outside of the view
{
FIntPoint BufferSize = GSceneRenderTargets . GetBufferSizeXY ( ) ;
FVector2D InvBufferSize ( 1.0f / BufferSize . X , 1.0f / BufferSize . Y ) ;
FIntRect ClipRect = Context . View . ViewRect ;
// to avoid leaking in content from the outside because of bilinear filtering, shrink
ClipRect . InflateRect ( - 1 ) ;
FVector2D MinUV ( ClipRect . Min . X * InvBufferSize . X , ClipRect . Min . Y * InvBufferSize . Y ) ;
FVector2D MaxUV ( ClipRect . Max . X * InvBufferSize . X , ClipRect . Max . Y * InvBufferSize . Y ) ;
FVector2D SizeUV = MaxUV - MinUV ;
FVector2D Mul ( 1.0f / SizeUV . X , 1.0f / SizeUV . Y ) ;
FVector2D Add = - MinUV * Mul ;
FVector4 TextureViewMadValue ( Mul . X , Mul . Y , Add . X , Add . Y ) ;
2014-06-12 07:13:34 -04:00
SetShaderValue ( Context . RHICmdList , ShaderRHI , TextureViewMad , TextureViewMadValue ) ;
2014-03-14 14:13:41 -04:00
}
{
const float SizeX = Context . View . ViewRect . Width ( ) ;
const float SizeY = Context . View . ViewRect . Height ( ) ;
const float AspectRatio = SizeX / SizeY ;
const float InvAspectRatio = SizeY / SizeX ;
const FSceneViewState * ViewState = ( FSceneViewState * ) Context . View . State ;
float MotionBlurTimeScale = ViewState ? ViewState - > MotionBlurTimeScale : 1.0f ;
float ViewMotionBlurScale = 0.5f * MotionBlurTimeScale * Context . View . FinalPostProcessSettings . MotionBlurAmount ;
// MotionBlurInstanceScale was needed to hack some cases where motion blur wasn't working well, this shouldn't be needed any more, can clean this up later
float MotionBlurInstanceScale = 1 ;
float ObjectMotionBlurScale = MotionBlurInstanceScale * ViewMotionBlurScale ;
// 0:no 1:full screen width, percent conversion
float MaxVelocity = Context . View . FinalPostProcessSettings . MotionBlurMax / 100.0f ;
float InvMaxVelocity = 1.0f / MaxVelocity ;
// *2 to convert to -1..1 -1..1 screen space
// / MaxFraction to map screenpos to -1..1 normalized MaxFraction
FVector4 MotionBlurParametersValue (
ObjectMotionBlurScale * InvMaxVelocity ,
- ObjectMotionBlurScale * InvMaxVelocity * InvAspectRatio ,
MaxVelocity * 2 ,
- MaxVelocity * 2 * AspectRatio ) ;
2014-06-12 07:13:34 -04:00
SetShaderValue ( Context . RHICmdList , ShaderRHI , MotionBlurParameters , MotionBlurParametersValue ) ;
2014-03-14 14:13:41 -04:00
}
2015-04-23 17:35:40 -04:00
SetSRVParameter ( Context . RHICmdList , ShaderRHI , BoneMatrices0 , GPrevPerBoneMotionBlur . GetBoneDataVertexBuffer ( 0 ) - > BoneBuffer . VertexBufferSRV ) ;
SetSRVParameter ( Context . RHICmdList , ShaderRHI , BoneMatrices1 , GPrevPerBoneMotionBlur . GetBoneDataVertexBuffer ( 1 ) - > BoneBuffer . VertexBufferSRV ) ;
2014-03-14 14:13:41 -04:00
}
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 ( 0 ) 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 >
2014-06-12 07:13:34 -04:00
static void SetMotionBlurShaderTempl ( const FRenderingCompositePassContext & Context )
2014-03-14 14:13:41 -04:00
{
2014-08-28 06:22:54 -04:00
TShaderMapRef < FPostProcessVS > VertexShader ( Context . GetShaderMap ( ) ) ;
TShaderMapRef < FPostProcessMotionBlurPS < Quality > > PixelShader ( Context . GetShaderMap ( ) ) ;
2014-03-14 14:13:41 -04:00
static FGlobalBoundShaderState BoundShaderState ;
2014-06-27 11:07:13 -04:00
2014-08-19 10:41:34 -04:00
SetGlobalBoundShaderState ( Context . RHICmdList , Context . GetFeatureLevel ( ) , BoundShaderState , GFilterVertexDeclaration . VertexDeclarationRHI , * VertexShader , * PixelShader ) ;
2014-03-14 14:13:41 -04:00
2014-06-12 07:13:34 -04:00
VertexShader - > SetParameters ( Context ) ;
PixelShader - > SetParameters ( Context ) ;
2014-03-14 14:13:41 -04:00
}
FRCPassPostProcessMotionBlur : : FRCPassPostProcessMotionBlur ( uint32 InQuality )
: Quality ( InQuality )
{
// internal error
check ( Quality > = 1 & & Quality < = 4 ) ;
}
void FRCPassPostProcessMotionBlur : : Process ( FRenderingCompositePassContext & Context )
{
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( Context . RHICmdList , MotionBlur ) ;
2014-03-14 14:13:41 -04:00
const FPooledRenderTargetDesc * InputDesc = GetInputDesc ( ePId_Input0 ) ;
if ( ! InputDesc )
{
// input is not hooked up correctly
return ;
}
const FSceneView & View = Context . View ;
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 = GSceneRenderTargets . 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.
2014-06-12 07:13:34 -04:00
SetRenderTarget ( Context . RHICmdList , DestRenderTarget . TargetableTexture , FTextureRHIRef ( ) ) ;
2014-03-14 14:13:41 -04:00
// is optimized away if possible (RT size=view size, )
2014-06-12 07:13:34 -04:00
Context . RHICmdList . Clear ( true , FLinearColor : : Black , false , 1.0f , false , 0 , SrcRect ) ;
2014-03-14 14:13:41 -04:00
Context . SetViewportAndCallRHI ( SrcRect ) ;
// set the state
2014-06-12 07:13:34 -04:00
Context . RHICmdList . SetBlendState ( TStaticBlendState < > : : GetRHI ( ) ) ;
Context . RHICmdList . SetRasterizerState ( TStaticRasterizerState < > : : GetRHI ( ) ) ;
Context . RHICmdList . SetDepthStencilState ( TStaticDepthStencilState < false , CF_Always > : : GetRHI ( ) ) ;
2014-03-14 14:13:41 -04:00
if ( Quality = = 1 )
{
2014-06-12 07:13:34 -04:00
SetMotionBlurShaderTempl < 1 > ( Context ) ;
2014-03-14 14:13:41 -04:00
}
else if ( Quality = = 2 )
{
2014-06-12 07:13:34 -04:00
SetMotionBlurShaderTempl < 2 > ( Context ) ;
2014-03-14 14:13:41 -04:00
}
else if ( Quality = = 3 )
{
2014-06-12 07:13:34 -04:00
SetMotionBlurShaderTempl < 3 > ( Context ) ;
2014-03-14 14:13:41 -04:00
}
else
{
check ( Quality = = 4 ) ;
2014-06-12 07:13:34 -04:00
SetMotionBlurShaderTempl < 4 > ( Context ) ;
2014-03-14 14:13:41 -04:00
}
2014-08-28 06:22:54 -04:00
TShaderMapRef < FPostProcessVS > VertexShader ( Context . GetShaderMap ( ) ) ;
2014-04-23 17:26:59 -04:00
2014-03-14 14:13:41 -04:00
// Draw a quad mapping scene color to the view's render target
DrawRectangle (
2014-06-12 07:13:34 -04:00
Context . RHICmdList ,
2014-03-14 14:13:41 -04:00
0 , 0 ,
SrcRect . Width ( ) , SrcRect . Height ( ) ,
SrcRect . Min . X , SrcRect . Min . Y ,
SrcRect . Width ( ) , SrcRect . Height ( ) ,
SrcRect . Size ( ) ,
SrcSize ,
2014-04-23 17:26:59 -04:00
* VertexShader ,
2014-03-14 14:13:41 -04:00
EDRF_UseTriangleOptimization ) ;
2014-06-12 07:13:34 -04:00
Context . RHICmdList . CopyToResolveTarget ( DestRenderTarget . TargetableTexture , DestRenderTarget . ShaderResourceTexture , false , FResolveParams ( ) ) ;
2014-03-14 14:13:41 -04:00
}
FPooledRenderTargetDesc FRCPassPostProcessMotionBlur : : ComputeOutputDesc ( EPassOutputId InPassOutputId ) const
{
FPooledRenderTargetDesc Ret = PassInputs [ 0 ] . GetOutput ( ) - > RenderTargetDesc ;
Ret . Reset ( ) ;
Ret . DebugName = TEXT ( " MotionBlur " ) ;
return Ret ;
}
/** Encapsulates a MotionBlur recombine pixel shader. */
class FPostProcessMotionBlurRecombinePS : public FGlobalShader
{
DECLARE_SHADER_TYPE ( FPostProcessMotionBlurRecombinePS , Global ) ;
static bool ShouldCache ( EShaderPlatform Platform )
{
return IsFeatureLevelSupported ( Platform , ERHIFeatureLevel : : SM4 ) ;
}
static void ModifyCompilationEnvironment ( EShaderPlatform Platform , FShaderCompilerEnvironment & OutEnvironment )
{
FGlobalShader : : ModifyCompilationEnvironment ( Platform , OutEnvironment ) ;
}
/** Default constructor. */
FPostProcessMotionBlurRecombinePS ( ) { }
public :
FPostProcessPassParameters PostprocessParameter ;
/** Initialization constructor. */
FPostProcessMotionBlurRecombinePS ( const ShaderMetaType : : CompiledShaderInitializerType & Initializer )
: FGlobalShader ( Initializer )
{
PostprocessParameter . Bind ( Initializer . ParameterMap ) ;
}
// FShader interface.
2015-04-01 07:20:55 -04:00
virtual bool Serialize ( FArchive & Ar ) override
2014-03-14 14:13:41 -04:00
{
bool bShaderHasOutdatedParameters = FGlobalShader : : Serialize ( Ar ) ;
Ar < < PostprocessParameter ;
return bShaderHasOutdatedParameters ;
}
2015-04-23 17:35:40 -04:00
void SetParameters ( const FRenderingCompositePassContext & Context , bool bBilinear )
2014-03-14 14:13:41 -04:00
{
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader ( ) ;
2014-06-12 07:13:34 -04:00
FGlobalShader : : SetParameters ( Context . RHICmdList , ShaderRHI , Context . View ) ;
2014-03-14 14:13:41 -04:00
2015-04-23 17:35:40 -04:00
if ( bBilinear )
{
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 ( ) ) ;
}
2014-03-14 14:13:41 -04:00
}
} ;
IMPLEMENT_SHADER_TYPE ( , FPostProcessMotionBlurRecombinePS , TEXT ( " PostProcessMotionBlur " ) , TEXT ( " MainRecombinePS " ) , SF_Pixel ) ;
void FRCPassPostProcessMotionBlurRecombine : : Process ( FRenderingCompositePassContext & Context )
{
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( Context . RHICmdList , MotionBlurRecombine ) ;
2014-03-14 14:13:41 -04:00
const FPooledRenderTargetDesc * InputDesc = GetInputDesc ( ePId_Input0 ) ;
if ( ! InputDesc )
{
// input is not hooked up correctly
return ;
}
const FSceneView & View = Context . View ;
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 = GSceneRenderTargets . GetBufferSizeXY ( ) . X / SrcSize . X ;
FIntRect SrcRect = View . ViewRect / ScaleFactor ;
FIntRect DestRect = SrcRect ;
const FSceneRenderTargetItem & DestRenderTarget = PassOutputs [ 0 ] . RequestSurface ( Context ) ;
// Set the view family's render target/viewport.
2014-06-12 07:13:34 -04:00
SetRenderTarget ( Context . RHICmdList , DestRenderTarget . TargetableTexture , FTextureRHIRef ( ) ) ;
2014-03-14 14:13:41 -04:00
// is optimized away if possible (RT size=view size, )
2014-06-12 07:13:34 -04:00
Context . RHICmdList . Clear ( true , FLinearColor : : Black , false , 1.0f , false , 0 , SrcRect ) ;
2014-03-14 14:13:41 -04:00
Context . SetViewportAndCallRHI ( SrcRect ) ;
// set the state
2014-06-12 07:13:34 -04:00
Context . RHICmdList . SetBlendState ( TStaticBlendState < > : : GetRHI ( ) ) ;
Context . RHICmdList . SetRasterizerState ( TStaticRasterizerState < > : : GetRHI ( ) ) ;
Context . RHICmdList . SetDepthStencilState ( TStaticDepthStencilState < false , CF_Always > : : GetRHI ( ) ) ;
2014-03-14 14:13:41 -04:00
2014-08-28 06:22:54 -04:00
TShaderMapRef < FPostProcessVS > VertexShader ( Context . GetShaderMap ( ) ) ;
TShaderMapRef < FPostProcessMotionBlurRecombinePS > PixelShader ( Context . GetShaderMap ( ) ) ;
2014-03-14 14:13:41 -04:00
static FGlobalBoundShaderState BoundShaderState ;
2014-06-27 11:07:13 -04:00
2014-08-19 10:41:34 -04:00
SetGlobalBoundShaderState ( Context . RHICmdList , Context . GetFeatureLevel ( ) , BoundShaderState , GFilterVertexDeclaration . VertexDeclarationRHI , * VertexShader , * PixelShader ) ;
2014-03-14 14:13:41 -04:00
2015-04-23 17:35:40 -04:00
// with point filtering we can better debug in Visualize MotionBlur
const bool bBilinear = ! View . Family - > EngineShowFlags . VisualizeMotionBlur ;
2014-06-12 07:13:34 -04:00
VertexShader - > SetParameters ( Context ) ;
2015-04-23 17:35:40 -04:00
PixelShader - > SetParameters ( Context , bBilinear ) ;
2014-03-14 14:13:41 -04:00
// Draw a quad mapping scene color to the view's render target
DrawRectangle (
2014-06-12 07:13:34 -04:00
Context . RHICmdList ,
2014-03-14 14:13:41 -04:00
0 , 0 ,
SrcRect . Width ( ) , SrcRect . Height ( ) ,
SrcRect . Min . X , SrcRect . Min . Y ,
SrcRect . Width ( ) , SrcRect . Height ( ) ,
SrcRect . Size ( ) ,
SrcSize ,
2014-04-23 17:26:59 -04:00
* VertexShader ,
2014-03-14 14:13:41 -04:00
EDRF_UseTriangleOptimization ) ;
2014-06-12 07:13:34 -04:00
Context . RHICmdList . CopyToResolveTarget ( DestRenderTarget . TargetableTexture , DestRenderTarget . ShaderResourceTexture , false , FResolveParams ( ) ) ;
2014-03-14 14:13:41 -04:00
}
FPooledRenderTargetDesc FRCPassPostProcessMotionBlurRecombine : : ComputeOutputDesc ( EPassOutputId InPassOutputId ) const
{
FPooledRenderTargetDesc Ret = PassInputs [ 0 ] . GetOutput ( ) - > RenderTargetDesc ;
Ret . Reset ( ) ;
// we don't need the alpha channel and 32bit is faster and costs less memory
Ret . Format = PF_FloatRGB ;
Ret . DebugName = TEXT ( " MotionBlurRecombine " ) ;
return Ret ;
}
2015-02-22 17:53:26 -05:00
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 ) ;
OutEnvironment . SetDefine ( TEXT ( " THREADGROUP_SIZEX " ) , FRCPassPostProcessVelocityFlatten : : ThreadGroupSizeX ) ;
OutEnvironment . SetDefine ( TEXT ( " THREADGROUP_SIZEY " ) , FRCPassPostProcessVelocityFlatten : : ThreadGroupSizeY ) ;
OutEnvironment . CompilerFlags . Add ( CFLAG_StandardOptimization ) ;
}
FPostProcessVelocityFlattenCS ( ) { }
public :
FShaderParameter OutVelocityFlat ;
FShaderParameter OutPackedVelocityDepth ;
FShaderParameter OutMaxTileVelocity ;
FPostProcessVelocityFlattenCS ( const ShaderMetaType : : CompiledShaderInitializerType & Initializer )
: FGlobalShader ( Initializer )
{
PostprocessParameter . Bind ( Initializer . ParameterMap ) ;
CameraMotionParams . Bind ( Initializer . ParameterMap ) ;
OutVelocityFlat . Bind ( Initializer . ParameterMap , TEXT ( " OutVelocityFlat " ) ) ;
OutPackedVelocityDepth . Bind ( Initializer . ParameterMap , TEXT ( " OutPackedVelocityDepth " ) ) ;
OutMaxTileVelocity . Bind ( Initializer . ParameterMap , TEXT ( " OutMaxTileVelocity " ) ) ;
ViewDimensions . Bind ( Initializer . ParameterMap , TEXT ( " ViewDimensions " ) ) ;
}
void SetCS ( FRHICommandList & RHICmdList , const FRenderingCompositePassContext & Context , const FSceneView & View )
{
const FComputeShaderRHIParamRef ShaderRHI = GetComputeShader ( ) ;
FGlobalShader : : SetParameters ( RHICmdList , ShaderRHI , Context . View ) ;
PostprocessParameter . SetCS ( ShaderRHI , Context , TStaticSamplerState < SF_Point , AM_Clamp , AM_Clamp , AM_Clamp > : : GetRHI ( ) ) ;
CameraMotionParams . Set ( RHICmdList , Context . View , ShaderRHI ) ;
SetShaderValue ( RHICmdList , ShaderRHI , ViewDimensions , View . ViewRect ) ;
}
2015-04-01 07:20:55 -04:00
virtual bool Serialize ( FArchive & Ar ) override
2015-02-22 17:53:26 -05:00
{
bool bShaderHasOutdatedParameters = FGlobalShader : : Serialize ( Ar ) ;
Ar < < PostprocessParameter ;
Ar < < CameraMotionParams ;
Ar < < OutVelocityFlat ;
Ar < < OutPackedVelocityDepth ;
Ar < < OutMaxTileVelocity ;
Ar < < ViewDimensions ;
return bShaderHasOutdatedParameters ;
}
private :
FPostProcessPassParameters PostprocessParameter ;
FCameraMotionParameters CameraMotionParams ;
FShaderParameter ViewDimensions ;
} ;
IMPLEMENT_SHADER_TYPE ( , FPostProcessVelocityFlattenCS , TEXT ( " PostProcessVelocityFlatten " ) , TEXT ( " VelocityFlattenMain " ) , SF_Compute ) ;
void FRCPassPostProcessVelocityFlatten : : Process ( FRenderingCompositePassContext & Context )
{
SCOPED_DRAW_EVENT ( Context . RHICmdList , PostProcessVelocityFlatten ) ;
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 ) ;
//const FSceneRenderTargetItem& DestRenderTarget2 = PassOutputs[2].RequestSurface(Context);
TShaderMapRef < FPostProcessVelocityFlattenCS > ComputeShader ( Context . GetShaderMap ( ) ) ;
Context . RHICmdList . SetComputeShader ( ComputeShader - > GetComputeShader ( ) ) ;
SetRenderTarget ( Context . RHICmdList , FTextureRHIRef ( ) , FTextureRHIRef ( ) ) ;
// set destination
Context . RHICmdList . SetUAVParameter ( ComputeShader - > GetComputeShader ( ) , ComputeShader - > OutVelocityFlat . GetBaseIndex ( ) , DestRenderTarget0 . UAV ) ;
//Context.RHICmdList.SetUAVParameter( ComputeShader->GetComputeShader(), ComputeShader->OutPackedVelocityDepth.GetBaseIndex(), DestRenderTarget1.UAV );
Context . RHICmdList . SetUAVParameter ( ComputeShader - > GetComputeShader ( ) , ComputeShader - > OutMaxTileVelocity . GetBaseIndex ( ) , DestRenderTarget1 . UAV ) ;
ComputeShader - > SetCS ( Context . RHICmdList , Context , View ) ;
FIntPoint ThreadGroupCountValue = ComputeThreadGroupCount ( View . ViewRect . Size ( ) ) ;
DispatchComputeShader ( Context . RHICmdList , * ComputeShader , ThreadGroupCountValue . X , ThreadGroupCountValue . Y , 1 ) ;
// un-set destination
Context . RHICmdList . SetUAVParameter ( ComputeShader - > GetComputeShader ( ) , ComputeShader - > OutVelocityFlat . GetBaseIndex ( ) , NULL ) ;
//Context.RHICmdList.SetUAVParameter( ComputeShader->GetComputeShader(), ComputeShader->OutPackedVelocityDepth.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 ( ) ) ;
//Context.RHICmdList.CopyToResolveTarget(DestRenderTarget1.TargetableTexture, DestRenderTarget2.ShaderResourceTexture, false, FResolveParams());
}
FIntPoint FRCPassPostProcessVelocityFlatten : : ComputeThreadGroupCount ( FIntPoint PixelExtent )
{
uint32 ThreadGroupCountX = ( PixelExtent . X + TileSizeX - 1 ) / TileSizeX ;
uint32 ThreadGroupCountY = ( PixelExtent . Y + TileSizeY - 1 ) / TileSizeY ;
return FIntPoint ( ThreadGroupCountX , ThreadGroupCountY ) ;
}
FPooledRenderTargetDesc FRCPassPostProcessVelocityFlatten : : ComputeOutputDesc ( EPassOutputId InPassOutputId ) const
{
if ( InPassOutputId = = ePId_Output0 )
{
// Flattened velocity
FPooledRenderTargetDesc Ret = PassInputs [ 0 ] . GetOutput ( ) - > RenderTargetDesc ;
Ret . Reset ( ) ;
Ret . TargetableFlags | = TexCreate_UAV ;
Ret . TargetableFlags | = TexCreate_RenderTargetable ;
Ret . DebugName = TEXT ( " VelocityFlat " ) ;
return Ret ;
}
/*else if( InPassOutputId == ePId_Output1 )
{
// Packed VelocityLength, Depth
FPooledRenderTargetDesc Ret = PassInputs [ 0 ] . GetOutput ( ) - > RenderTargetDesc ;
Ret . Reset ( ) ;
Ret . Format = PF_R8G8 ;
Ret . TargetableFlags | = TexCreate_UAV ;
Ret . TargetableFlags | = TexCreate_RenderTargetable ;
Ret . DebugName = TEXT ( " PackedVelocityDepth " ) ;
return Ret ;
} */
else
{
// Max tile velocity
FPooledRenderTargetDesc UnmodifiedRet = PassInputs [ 0 ] . GetOutput ( ) - > RenderTargetDesc ;
UnmodifiedRet . Reset ( ) ;
FIntPoint PixelExtent = UnmodifiedRet . Extent ;
FIntPoint ThreadGroupCount = ComputeThreadGroupCount ( PixelExtent ) ;
FIntPoint NewSize = ThreadGroupCount ;
// format can be optimized later
FPooledRenderTargetDesc Ret ( FPooledRenderTargetDesc : : Create2DDesc ( NewSize , PF_G16R16F , TexCreate_None , TexCreate_RenderTargetable | TexCreate_UAV , false ) ) ;
Ret . DebugName = TEXT ( " MaxVelocity " ) ;
return Ret ;
}
}
2015-02-24 16:28:47 -05:00
class FScatterQuadIndexBuffer : public FIndexBuffer
{
public :
virtual void InitRHI ( ) override
{
const uint32 Size = sizeof ( uint16 ) * 6 * 8 ;
const uint32 Stride = sizeof ( uint16 ) ;
FRHIResourceCreateInfo CreateInfo ;
IndexBufferRHI = RHICreateIndexBuffer ( Stride , Size , BUF_Static , CreateInfo ) ;
uint16 * Indices = ( uint16 * ) RHILockIndexBuffer ( IndexBufferRHI , 0 , Size , RLM_WriteOnly ) ;
for ( uint32 SpriteIndex = 0 ; SpriteIndex < 8 ; + + SpriteIndex )
{
# if PLATFORM_MAC // Avoid a driver bug on OSX/NV cards that causes driver to generate an unwound index buffer
Indices [ SpriteIndex * 6 + 0 ] = SpriteIndex * 6 + 0 ;
Indices [ SpriteIndex * 6 + 1 ] = SpriteIndex * 6 + 1 ;
Indices [ SpriteIndex * 6 + 2 ] = SpriteIndex * 6 + 2 ;
Indices [ SpriteIndex * 6 + 3 ] = SpriteIndex * 6 + 3 ;
Indices [ SpriteIndex * 6 + 4 ] = SpriteIndex * 6 + 4 ;
Indices [ SpriteIndex * 6 + 5 ] = SpriteIndex * 6 + 5 ;
# else
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 ;
# endif
}
RHIUnlockIndexBuffer ( IndexBufferRHI ) ;
}
} ;
TGlobalResource < FScatterQuadIndexBuffer > GScatterQuadIndexBuffer ;
class FPostProcessVelocityScatterVS : public FGlobalShader
{
DECLARE_SHADER_TYPE ( FPostProcessVelocityScatterVS , Global ) ;
static bool ShouldCache ( EShaderPlatform Platform )
{
return IsFeatureLevelSupported ( Platform , ERHIFeatureLevel : : SM4 ) ;
}
/** Default constructor. */
FPostProcessVelocityScatterVS ( ) { }
public :
FPostProcessPassParameters PostprocessParameter ;
FShaderParameter TileCount ;
/** Initialization constructor. */
FPostProcessVelocityScatterVS ( const ShaderMetaType : : CompiledShaderInitializerType & Initializer )
: FGlobalShader ( Initializer )
{
PostprocessParameter . Bind ( Initializer . ParameterMap ) ;
TileCount . Bind ( Initializer . ParameterMap , TEXT ( " TileCount " ) ) ;
}
// FShader interface.
2015-04-01 07:20:55 -04:00
virtual bool Serialize ( FArchive & Ar ) override
2015-02-24 16:28:47 -05:00
{
bool bShaderHasOutdatedParameters = FGlobalShader : : Serialize ( Ar ) ;
Ar < < PostprocessParameter < < TileCount ;
return bShaderHasOutdatedParameters ;
}
/** to have a similar interface as all other shaders */
void SetParameters ( const FRenderingCompositePassContext & Context , FIntPoint TileCountValue )
{
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 , TileCount , TileCountValue ) ;
}
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 : : SM4 ) ;
}
/** 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 , PassPostProcessVelocityScatter ) ;
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 ;
// e.g. 4 means the input texture is 4x smaller than the buffer size
uint32 ScaleFactor = GSceneRenderTargets . GetBufferSizeXY ( ) . X / SrcSize . X ;
FIntRect SrcRect = FIntRect : : DivideAndRoundUp ( View . ViewRect , ScaleFactor ) ;
FIntRect DestRect = SrcRect ;
const FSceneRenderTargetItem & DestRenderTarget = PassOutputs [ 0 ] . RequestSurface ( Context ) ;
TRefCountPtr < IPooledRenderTarget > DepthTarget ;
2015-03-04 08:31:40 -05:00
FPooledRenderTargetDesc Desc ( FPooledRenderTargetDesc : : Create2DDesc ( DestSize , PF_ShadowDepth , TexCreate_None , TexCreate_DepthStencilTargetable , false ) ) ;
2015-02-24 16:28:47 -05:00
GRenderTargetPool . FindFreeElement ( Desc , DepthTarget , TEXT ( " VelocityScatterDepth " ) ) ;
// Set the view family's render target/viewport.
SetRenderTarget ( Context . RHICmdList , DestRenderTarget . TargetableTexture , DepthTarget - > GetRenderTargetItem ( ) . TargetableTexture ) ;
Context . RHICmdList . Clear ( true , FLinearColor : : Black , true , 0.0f , false , 0 , FIntRect ( ) ) ;
Context . SetViewportAndCallRHI ( SrcRect ) ;
// set the state
Context . RHICmdList . SetBlendState ( TStaticBlendState < > : : GetRHI ( ) ) ;
Context . RHICmdList . SetRasterizerState ( TStaticRasterizerState < > : : GetRHI ( ) ) ;
2015-04-01 10:53:07 -04:00
//@todo-briank: Should this be CF_DepthNear?
static_assert ( ( int32 ) ERHIZBuffer : : IsInverted ! = 0 , " Should this be CF_DepthNear? " ) ;
2015-02-24 16:28:47 -05:00
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 ) ;
FIntPoint TileCount = SrcRect . Size ( ) ;
VertexShader - > SetParameters ( Context , TileCount ) ;
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 = PassInputs [ 0 ] . GetOutput ( ) - > RenderTargetDesc ;
Ret . Reset ( ) ;
Ret . DebugName = TEXT ( " ScatteredMaxVelocity " ) ;
return Ret ;
}
class FPostProcessVelocityDilatePS : public FGlobalShader
{
DECLARE_SHADER_TYPE ( FPostProcessVelocityDilatePS , Global ) ;
static bool ShouldCache ( EShaderPlatform Platform )
{
return IsFeatureLevelSupported ( Platform , ERHIFeatureLevel : : SM4 ) ;
}
static void ModifyCompilationEnvironment ( EShaderPlatform Platform , FShaderCompilerEnvironment & OutEnvironment )
{
FGlobalShader : : ModifyCompilationEnvironment ( Platform , OutEnvironment ) ;
}
/** Default constructor. */
FPostProcessVelocityDilatePS ( ) { }
public :
FPostProcessPassParameters PostprocessParameter ;
/** Initialization constructor. */
FPostProcessVelocityDilatePS ( const ShaderMetaType : : CompiledShaderInitializerType & Initializer )
: FGlobalShader ( Initializer )
{
PostprocessParameter . Bind ( Initializer . ParameterMap ) ;
}
// FShader interface.
2015-04-01 07:20:55 -04:00
virtual bool Serialize ( FArchive & Ar ) override
2015-02-24 16:28:47 -05:00
{
bool bShaderHasOutdatedParameters = FGlobalShader : : Serialize ( Ar ) ;
Ar < < PostprocessParameter ;
return bShaderHasOutdatedParameters ;
}
void SetParameters ( const FRenderingCompositePassContext & Context )
{
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 ( ) ) ;
}
} ;
IMPLEMENT_SHADER_TYPE ( , FPostProcessVelocityDilatePS , TEXT ( " PostProcessMotionBlur " ) , TEXT ( " VelocityDilatePS " ) , SF_Pixel ) ;
void FRCPassPostProcessVelocityDilate : : 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 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 = GSceneRenderTargets . 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 < FPostProcessVelocityDilatePS > 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 ) ;
Context . RHICmdList . CopyToResolveTarget ( DestRenderTarget . TargetableTexture , DestRenderTarget . ShaderResourceTexture , false , FResolveParams ( ) ) ;
}
FPooledRenderTargetDesc FRCPassPostProcessVelocityDilate : : ComputeOutputDesc ( EPassOutputId InPassOutputId ) const
{
FPooledRenderTargetDesc Ret = PassInputs [ 0 ] . GetOutput ( ) - > RenderTargetDesc ;
Ret . Reset ( ) ;
Ret . DebugName = TEXT ( " DilatedMaxVelocity " ) ;
return Ret ;
}
2015-02-22 17:53:26 -05:00
/**
* @ param Quality 0 : visualize , 1 : low , 2 : medium , 3 : high , 4 : very high
*/
template < uint32 Quality >
class FPostProcessMotionBlurNewPS : public FGlobalShader
{
DECLARE_SHADER_TYPE ( FPostProcessMotionBlurNewPS , 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 ( " MOTION_BLUR_QUALITY " ) , Quality ) ;
}
/** Default constructor. */
FPostProcessMotionBlurNewPS ( ) { }
public :
FPostProcessPassParameters PostprocessParameter ;
FDeferredPixelShaderParameters DeferredParameters ;
FShaderParameter MotionBlurParameters ;
/** Initialization constructor. */
FPostProcessMotionBlurNewPS ( const ShaderMetaType : : CompiledShaderInitializerType & Initializer )
: FGlobalShader ( Initializer )
{
PostprocessParameter . Bind ( Initializer . ParameterMap ) ;
DeferredParameters . Bind ( Initializer . ParameterMap ) ;
MotionBlurParameters . Bind ( Initializer . ParameterMap , TEXT ( " MotionBlurParameters " ) ) ;
}
// FShader interface.
2015-04-01 07:20:55 -04:00
virtual bool Serialize ( FArchive & Ar ) override
2015-02-22 17:53:26 -05:00
{
bool bShaderHasOutdatedParameters = FGlobalShader : : Serialize ( Ar ) ;
Ar < < PostprocessParameter < < DeferredParameters < < MotionBlurParameters ;
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 ) ;
{
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 [ ] =
{
2015-02-23 15:16:20 -05:00
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 ( ) ,
2015-02-24 16:28:47 -05:00
TStaticSamplerState < SF_Point , AM_Clamp , AM_Clamp , AM_Clamp > : : GetRHI ( ) ,
} ;
PostprocessParameter . SetPS ( ShaderRHI , Context , 0 , false , Filters ) ;
}
else if ( CVarMotionBlurSmoothMax . GetValueOnRenderThread ( ) )
{
FSamplerStateRHIParamRef Filters [ ] =
{
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 ( ) ,
TStaticSamplerState < SF_Bilinear , AM_Clamp , AM_Clamp , AM_Clamp > : : GetRHI ( ) ,
2015-02-22 17:53:26 -05:00
} ;
PostprocessParameter . SetPS ( ShaderRHI , Context , 0 , false , Filters ) ;
}
else
{
2015-02-23 15:16:20 -05:00
PostprocessParameter . SetPS ( ShaderRHI , Context , TStaticSamplerState < SF_Point , AM_Clamp , AM_Clamp , AM_Clamp > : : GetRHI ( ) ) ;
2015-02-22 17:53:26 -05:00
}
}
TRefCountPtr < IPooledRenderTarget > InputPooledElement = Context . Pass - > GetInput ( ePId_Input0 ) - > GetOutput ( ) - > RequestInput ( ) ;
{
const float SizeX = Context . View . ViewRect . Width ( ) ;
const float SizeY = Context . View . ViewRect . Height ( ) ;
const float AspectRatio = SizeX / SizeY ;
const float InvAspectRatio = SizeY / SizeX ;
const FSceneViewState * ViewState = ( FSceneViewState * ) Context . View . State ;
const float MotionBlurTimeScale = ViewState ? ViewState - > MotionBlurTimeScale : 1.0f ;
const float ViewMotionBlurScale = 0.5f * MotionBlurTimeScale * Context . View . FinalPostProcessSettings . MotionBlurAmount ;
// 0:no 1:full screen width
float MaxVelocity = Context . View . FinalPostProcessSettings . MotionBlurMax / 100.0f ;
float InvMaxVelocity = 1.0f / MaxVelocity ;
// *2 to convert to -1..1 -1..1 screen space
// / MaxFraction to map screenpos to -1..1 normalized MaxFraction
FVector4 MotionBlurParametersValue (
ViewMotionBlurScale ,
AspectRatio ,
MaxVelocity ,
InvMaxVelocity ) ;
SetShaderValue ( Context . RHICmdList , ShaderRHI , MotionBlurParameters , MotionBlurParametersValue ) ;
}
}
static const TCHAR * GetSourceFilename ( )
{
return TEXT ( " PostProcessMotionBlur " ) ;
}
static const TCHAR * GetFunctionName ( )
{
return TEXT ( " MainNewPS " ) ;
}
} ;
// #define avoids a lot of code duplication
# define VARIATION1(A) typedef FPostProcessMotionBlurNewPS<A> FPostProcessMotionBlurNewPS##A; \
IMPLEMENT_SHADER_TYPE2 ( FPostProcessMotionBlurNewPS # # A , SF_Pixel ) ;
VARIATION1 ( 0 ) 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 )
{
TShaderMapRef < FPostProcessVS > VertexShader ( Context . GetShaderMap ( ) ) ;
TShaderMapRef < FPostProcessMotionBlurNewPS < Quality > > PixelShader ( Context . GetShaderMap ( ) ) ;
static FGlobalBoundShaderState BoundShaderState ;
SetGlobalBoundShaderState ( Context . RHICmdList , Context . GetFeatureLevel ( ) , BoundShaderState , GFilterVertexDeclaration . VertexDeclarationRHI , * VertexShader , * PixelShader ) ;
VertexShader - > SetParameters ( Context ) ;
PixelShader - > SetParameters ( Context ) ;
}
FRCPassPostProcessMotionBlurNew : : FRCPassPostProcessMotionBlurNew ( uint32 InQuality )
: Quality ( InQuality )
{
// internal error
check ( Quality > = 1 & & Quality < = 4 ) ;
}
void FRCPassPostProcessMotionBlurNew : : Process ( FRenderingCompositePassContext & Context )
{
SCOPED_DRAW_EVENT ( Context . RHICmdList , MotionBlur ) ;
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 = GSceneRenderTargets . GetBufferSizeXY ( ) . X / SrcSize . X ;
2015-02-24 16:28:47 -05:00
FIntRect SrcRect = View . ViewRect / ScaleFactor ;
2015-02-22 17:53:26 -05:00
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 ( ) ) ;
if ( Quality = = 1 )
{
SetMotionBlurShaderNewTempl < 1 > ( Context ) ;
}
else if ( Quality = = 2 )
{
SetMotionBlurShaderNewTempl < 2 > ( Context ) ;
}
else if ( Quality = = 3 )
{
SetMotionBlurShaderNewTempl < 3 > ( Context ) ;
}
else
{
check ( Quality = = 4 ) ;
SetMotionBlurShaderNewTempl < 4 > ( Context ) ;
}
TShaderMapRef < FPostProcessVS > VertexShader ( Context . GetShaderMap ( ) ) ;
// 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 ) ;
Context . RHICmdList . CopyToResolveTarget ( DestRenderTarget . TargetableTexture , DestRenderTarget . ShaderResourceTexture , false , FResolveParams ( ) ) ;
}
FPooledRenderTargetDesc FRCPassPostProcessMotionBlurNew : : ComputeOutputDesc ( EPassOutputId InPassOutputId ) const
{
FPooledRenderTargetDesc Ret = PassInputs [ 0 ] . GetOutput ( ) - > RenderTargetDesc ;
Ret . Reset ( ) ;
// we don't need the alpha channel and 32bit is faster and costs less memory
Ret . Format = PF_FloatRGB ;
Ret . DebugName = TEXT ( " MotionBlur " ) ;
return Ret ;
}
2014-03-14 14:13:41 -04:00
void FRCPassPostProcessVisualizeMotionBlur : : Process ( FRenderingCompositePassContext & Context )
{
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( Context . RHICmdList , VisualizeMotionBlur ) ;
2014-03-14 14:13:41 -04:00
const FPooledRenderTargetDesc * InputDesc = GetInputDesc ( ePId_Input0 ) ;
if ( ! InputDesc )
{
// input is not hooked up correctly
return ;
}
const FSceneView & View = Context . View ;
2015-04-21 13:44:06 -04:00
const FSceneViewFamily & ViewFamily = * ( View . Family ) ;
2014-03-14 14:13:41 -04:00
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 = GSceneRenderTargets . 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.
2014-06-12 07:13:34 -04:00
SetRenderTarget ( Context . RHICmdList , DestRenderTarget . TargetableTexture , FTextureRHIRef ( ) ) ;
2014-03-14 14:13:41 -04:00
// is optimized away if possible (RT size=view size, )
2014-06-12 07:13:34 -04:00
Context . RHICmdList . Clear ( true , FLinearColor : : Black , false , 1.0f , false , 0 , SrcRect ) ;
2014-03-14 14:13:41 -04:00
Context . SetViewportAndCallRHI ( SrcRect ) ;
// set the state
2014-06-12 07:13:34 -04:00
Context . RHICmdList . SetBlendState ( TStaticBlendState < > : : GetRHI ( ) ) ;
Context . RHICmdList . SetRasterizerState ( TStaticRasterizerState < > : : GetRHI ( ) ) ;
Context . RHICmdList . SetDepthStencilState ( TStaticDepthStencilState < false , CF_Always > : : GetRHI ( ) ) ;
2014-03-14 14:13:41 -04:00
// Quality 0: visualize
2014-06-12 07:13:34 -04:00
SetMotionBlurShaderTempl < 0 > ( Context ) ;
2014-03-14 14:13:41 -04:00
// Draw a quad mapping scene color to the view's render target
2014-08-28 06:22:54 -04:00
TShaderMapRef < FPostProcessVS > VertexShader ( Context . GetShaderMap ( ) ) ;
2014-04-23 17:26:59 -04:00
2014-03-14 14:13:41 -04:00
DrawRectangle (
2014-06-12 07:13:34 -04:00
Context . RHICmdList ,
2014-03-14 14:13:41 -04:00
0 , 0 ,
SrcRect . Width ( ) , SrcRect . Height ( ) ,
SrcRect . Min . X , SrcRect . Min . Y ,
SrcRect . Width ( ) , SrcRect . Height ( ) ,
SrcRect . Size ( ) ,
SrcSize ,
2014-04-23 17:26:59 -04:00
* VertexShader ,
2014-03-14 14:13:41 -04:00
EDRF_UseTriangleOptimization ) ;
2015-04-21 13:44:06 -04:00
// 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 ( ) ) ;
2015-04-27 17:12:21 -04:00
float X = 20 ;
2015-04-21 13:44:06 -04:00
float Y = 8 ;
const float YStep = 14 ;
2015-04-27 17:12:21 -04:00
const float ColumnWidth = 200 ;
2015-04-21 13:44:06 -04:00
FString Line ;
Line = FString : : Printf ( TEXT ( " Visualize MotionBlur " ) ) ;
2015-04-23 17:35:40 -04:00
Canvas . DrawShadowedString ( X , Y + = YStep , * Line , GetStatsFont ( ) , FLinearColor ( 1 , 1 , 0 ) ) ;
2015-04-21 13:44:06 -04:00
2015-04-24 17:43:35 -04:00
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 ) ;
2015-04-27 17:12:21 -04:00
Canvas . DrawShadowedString ( X , Y + = YStep , TEXT ( " FrameNo, r.MotionBlurDebug: " ) , GetStatsFont ( ) , FLinearColor ( 1 , 1 , 0 ) ) ;
2015-04-23 17:35:40 -04:00
Canvas . DrawShadowedString ( X + ColumnWidth , Y , * Line , GetStatsFont ( ) , FLinearColor ( 1 , 1 , 0 ) ) ;
2015-04-21 13:44:06 -04:00
2015-04-24 17:43:35 -04:00
static const auto VelocityTestVar = IConsoleManager : : Get ( ) . FindTConsoleVariableDataInt ( TEXT ( " r.VelocityTest " ) ) ;
const int32 VelocityTest = VelocityTestVar ? VelocityTestVar - > GetValueOnRenderThread ( ) : 0 ;
extern bool IsParallelVelocity ( ) ;
2015-04-27 17:12:21 -04:00
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 ) ) ;
2015-04-23 17:35:40 -04:00
Canvas . DrawShadowedString ( X + ColumnWidth , Y , * Line , GetStatsFont ( ) , FLinearColor ( 1 , 1 , 0 ) ) ;
2015-04-27 14:32:32 -04:00
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 ) ) ;
2015-04-27 17:12:21 -04:00
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 ) ) ;
2015-04-23 17:35:40 -04:00
for ( uint32 BufferId = 0 ; BufferId < 2 ; + + BufferId )
{
const TCHAR * Usage = TEXT ( " unused " ) ;
if ( BufferId = = GPrevPerBoneMotionBlur . GetReadBufferIndex ( ) )
{
Usage = TEXT ( " read " ) ;
}
else if ( BufferId = = GPrevPerBoneMotionBlur . GetWriteBufferIndex ( ) )
{
Usage = TEXT ( " write " ) ;
}
Line = FString : : Printf ( TEXT ( " BoneBuffer %d: %s " ) , BufferId , Usage ) ;
// LeftTop.y + (LinesPerBuffer + GapBetweenBuffers) * Scale
2015-04-27 17:12:21 -04:00
Canvas . DrawShadowedString ( 4 , 98 + BufferId * ( 48 + 8 ) * 3 , * Line , GetStatsFont ( ) , FLinearColor ( 1 , 1 , 0 ) ) ;
2015-04-23 17:35:40 -04:00
}
2015-04-21 13:44:06 -04:00
Canvas . Flush_RenderThread ( Context . RHICmdList ) ;
2014-06-12 07:13:34 -04:00
Context . RHICmdList . CopyToResolveTarget ( DestRenderTarget . TargetableTexture , DestRenderTarget . ShaderResourceTexture , false , FResolveParams ( ) ) ;
2014-03-14 14:13:41 -04:00
}
FPooledRenderTargetDesc FRCPassPostProcessVisualizeMotionBlur : : ComputeOutputDesc ( EPassOutputId InPassOutputId ) const
{
FPooledRenderTargetDesc Ret = PassInputs [ 0 ] . GetOutput ( ) - > RenderTargetDesc ;
Ret . Reset ( ) ;
Ret . DebugName = TEXT ( " MotionBlur " ) ;
return Ret ;
2015-04-01 07:20:55 -04:00
}