2014-03-14 14:13:41 -04:00
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
/*=============================================================================
PostProcessMotionBlur . cpp : Post process MotionBlur implementation .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
# include "RendererPrivate.h"
# include "ScenePrivate.h"
# include "SceneFilterRendering.h"
# include "PostProcessMotionBlur.h"
# include "PostProcessing.h"
2014-08-21 06:03:00 -04:00
# include "SceneUtils.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
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.
virtual bool Serialize ( FArchive & Ar )
{
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.
virtual bool Serialize ( FArchive & Ar )
{
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 ;
/** 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 " ) ) ;
}
// FShader interface.
virtual bool Serialize ( FArchive & Ar )
{
bool bShaderHasOutdatedParameters = FGlobalShader : : Serialize ( Ar ) ;
Ar < < PostprocessParameter < < DeferredParameters < < PrevViewProjMatrix < < TextureViewMad < < MotionBlurParameters ;
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
}
}
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-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
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.
virtual bool Serialize ( FArchive & Ar )
{
bool bShaderHasOutdatedParameters = FGlobalShader : : Serialize ( Ar ) ;
Ar < < PostprocessParameter ;
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_Bilinear , 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-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
VertexShader - > SetParameters ( Context ) ;
PixelShader - > 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
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 ;
}
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 ;
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 ) ;
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 ;
}