You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3134663 on 2016/09/21 by Chris.Bunner Merging Dev-MaterialLayers to Dev-Rendering, CL 3134208. Initial material attribute extensibility changes. #jira UE-34347 Change 3142292 on 2016/09/27 by Rolando.Caloca DR - hlslcc - Fix for warning X3206: implicit truncation of vector type causing error #jira UE-31438 Change 3143557 on 2016/09/28 by Rolando.Caloca DR - Back out changelist 3142292 Change 3145354 on 2016/09/29 by Benjamin.Hyder Updating Tm-ContactShadows Change 3154832 on 2016/10/07 by Rolando.Caloca DR - vk - Fix crash on framebuffers with missing textures Change 3154838 on 2016/10/07 by Rolando.Caloca DR - vk - Enable clip distance Change 3154840 on 2016/10/07 by Rolando.Caloca DR - Remove branch per codereview Change 3155118 on 2016/10/07 by Rolando.Caloca DR - vk - Compute pipeline fixes Change 3155129 on 2016/10/07 by Rolando.Caloca DR - Added draw events for reflection captures Change 3155167 on 2016/10/07 by Rolando.Caloca DR - Use shader clear for platforms that can't use viewport or scissor Change 3155168 on 2016/10/07 by Rolando.Caloca DR - vk - Added submit gpu - Some fixes for Geometry and Compute Change 3155595 on 2016/10/07 by Rolando.Caloca DR - vk - Use new render pass system Change 3155720 on 2016/10/07 by Rolando.Caloca DR - vk - static analysis fix Change 3155732 on 2016/10/07 by Rolando.Caloca DR - Fix clears for platforms that can't use viewports, excluderects or scissor on clear Change 3156787 on 2016/10/10 by Rolando.Caloca DR - Fix mem leaks Change 3156805 on 2016/10/10 by Rolando.Caloca DR - Improve check msg per licensee Change 3156815 on 2016/10/10 by Rolando.Caloca DR - Fix infinite recursion Change 3157041 on 2016/10/10 by Rolando.Caloca DR - vk - Fix key access from multiple threads Change 3158253 on 2016/10/11 by Rolando.Caloca DR - Fix comment #jira UE-37128 PR #2852 Change 3158606 on 2016/10/11 by Rolando.Caloca DR - vk - Accessors Change 3160418 on 2016/10/12 by Daniel.Wright Lightmap textures are now outered to UMapBuildDataRegistry so that the UMapBuildDataRegistry can be moved in the content browser Change 3160644 on 2016/10/12 by Arne.Schober DR - [UE-32613] - OpenGL used to have custom code in the compiler to modify the source so that the same data and matricies can be used as DirectX, unfortunately that causes precission problem. Fortunately there is an extension available (glClipControl) which enables DirectX behaviour in OpenGL and it is widely supported. We only tested Linux and Windows and therfore only default enable on those platforms. Change 3161219 on 2016/10/13 by Luke.Thatcher [RENDERING] [!] Fix incorrect shader used in GPU Benchmark causing crash in OpenGL. Change 3161838 on 2016/10/13 by Daniel.Wright Fixed level getting added to the dirty list twice when legacy lightmaps are present Change3161884on 2016/10/13 by Arne.Schober DR - Fix Mac and DCC build Change 3162206 on 2016/10/13 by Chris.Bunner Merging Dev-MaterialLayers to Dev-Rendering, CL 3161593: Material expressions; Trig, fast-trig, saturate, round, truncate, pre-skinned normal. Added CustomEyeTangent to material attributes. Resolved some hard-coded attribute typing and other minor fixes. Change 3162491 on 2016/10/13 by Chris.Bunner Merging Dev-MaterialLayers to Dev-Rendering, CL 3162397: More fixed type-casting on material attributes. Swapped compiler::forcecast booleans to flags (and fixed a regression). Change 3163266 on 2016/10/14 by Daniel.Wright Fixed sublevels with legacy lighting data being added to the dirty packages list redundantly Change 3163524 on 2016/10/14 by Mark.Satterthwaite Bring over specific changes from Unicorn branch that increases the size of shader optional data so that it is considerably more useful. Change 3163529 on 2016/10/14 by Mark.Satterthwaite Move the Metal shader source code and compilation path into the newly enlarged shader optional data. Change3163553on 2016/10/14 by Mark.Satterthwaite Speculative fix for FORT-31590 also seen by a licensee - the Metal command buffer handler will be called from a dispatch queue thread that won't be registered with the stats system. #jira FORT-31590 Change 3163562 on 2016/10/14 by Mark.Satterthwaite Tidy up and extend the Metal debugging options: - Added rhi.Metal.BufferScribble which when enabled will fill freed buffer regions with 0xCD to help identify any areas where we are writing to a buffer while it is still being processed on the GPU. - Added rhi.Metal.BufferZeroFill which will zero-fill newly allocated buffer regions before any other data is read/written. Useful for catching cases where we might be reading uninitialised memory. - Added rhi.Metal.ResourcePurgeOnDelete which will purge the backing store of resources prior to releasing them back to the system or the respective pool. This will make any use-after-free conditions much more likely. - Added rhi.Metal.ResourceDeferDeleteNumFrames to defer releasing resources to the system or the resource pool by the specified number of frames (in addition to the current policy of waiting for the current end of frame & command-buffer completion). Useful for tracking down resource lifetime errors. - Fixed a number of bugs related to the modifications to vertex stream handling and addition of the SetShaderBytes API. - Track the start & end of FRingBuffer ranges - it appeared that the ring-buffer usage was invalid but it was in fact only my assumptions about the range that needed to be scribbled for rhi.Metal.BufferScribble. There is still the possibility that command-buffers that are implicitly parallelised by the driver may cause the ring-buffer range tracking to go awry - but with our data dependencies and the separation of the async. compute context I don't believe this is likely. - Fix up the "nometalv2" flag so that we can disable the features only available on iOS/tvOS-10/macOS-10.12 on newer devices to save having to reboot all the time. - Fixed the flickering geometry when enabling rhi.Metal.RuntimeDebugLevel=4 which breaks render passes into separate command-buffers - the occlusion query was waiting on the wrong command buffer in this case. Change 3163752 on 2016/10/14 by Mark.Satterthwaite Add missing parenthesis to fix compile error on iOS. Change 3164151 on 2016/10/16 by Benjamin.Hyder Submitting TM-AutoLOD level to QAGame #jira UE-29618 Change 3164190 on 2016/10/16 by Uriel.Doyon Materials now hold texture streaming data in the form of (UV scale X UV channel) for each texture. This data can be disabled through "r.Streaming.UseMaterialData" Defined a common framework in MeshComponent for texture streaming, used by both StaticMeshes and SkeletalMeshes. Simplified component interface for using the texture streaming build framework. Removed intermediate texture streaming build data from the static mesh components. Fixed shader compilation errors with the decals (from merge with main). Change 3164636 on 2016/10/17 by Rolando.Caloca DR - vk - Fix validation spam Change 3164679 on 2016/10/17 by Arne.Schober DR - [OR-28457] Part1, Scene View Refactoring - Removed Previous VewMatrices from SceneInfo and pass in Previous and Current ViewMatrices into Uniform Buffer creation to uniform UseCase for Shadows and CustomDepth, Fixed a Bug in Shadows with help of Daniel where the SceneView was copied unnecessary copied again. Also simplified the code in that area. Change 3164705 on 2016/10/17 by Daniel.Wright When new levels are loaded, only the Indirect Lighting Cache Allocations intersecting the level's light probes are updated to minimize hitches. This optimization requires a lighting build to compute PrecomputedLightVolume bounds. Change 3164834 on 2016/10/17 by Daniel.Wright Support directional light dynamic shadows in any channel with forward shading, which can happen with multiple shadow casting stationary directional lights (even though only the lighting of one will appear) Change 3164870 on 2016/10/17 by Arne.Schober DR - [OR-28457] Part2, Custom Depth Jitter - Allowed to overwite the viewconstant buffer in the custom depth pass. There ia also a new Project Setting available. The default constructor of the ContextDataType has been explicitly deleted to enforce compile errors when the templated code like the StaticMeshDrawList accidently tries to create a context without ViewUniformBuffer. Change 3164949 on 2016/10/17 by Rolando.Caloca DR - vk - First version of pooled occlusion queries Change 3165100 on 2016/10/17 by Rolando.Caloca DR - vk - Added driver version for Nvidia. AMD doesn't have one yet. Change 3165160 on 2016/10/17 by Rolando.Caloca DR - vk - Fix for queries not ready Change 3165230 on 2016/10/17 by Rolando.Caloca DR - vk - More fixes for occlusion queries Change 3165839 on 2016/10/18 by Rolando.Caloca DR - hlslcc - Fix default parameters getting wrong values Change 3166029 on 2016/10/18 by Rolando.Caloca DR - Switch some clears to DrawClearQuad() Change 3166066 on 2016/10/18 by Mark.Satterthwaite Update ShaderVersion due to CL #3163524 Change 3166067 on 2016/10/18 by Mark.Satterthwaite Update Mac hlslcc for RCO's 3165839. Change 3166370 on 2016/10/18 by Brian.Karis Improved hair AA Change 3166389 on 2016/10/18 by Uriel.Doyon Fixed lightmap having bigger resolutions than the engine can handle #jira UE-34737 #review-3166193 @daniel.wright Change 3166495 on 2016/10/18 by Rolando.Caloca DR - vk - Fix occlusion queries Change 3166516 on 2016/10/18 by Arne.Schober DR - Fix shaderbuild issue Change 3166650 on 2016/10/18 by Rolando.Caloca DR - vk - Enable GRHISupportsFirstInstance Change 3166799 on 2016/10/18 by Arne.Schober DR - [OR-28508] - The velocity Rendering pass was missing the adjustment for the PDO Change 3167855 on 2016/10/19 by Rolando.Caloca DR - vk - Implemented texture streaming Change 3168365 on 2016/10/19 by Rolando.Caloca DR - Fix static analysis Change 3168405 on 2016/10/19 by Mark.Satterthwaite Fix the optional shader data changes from Unicorn to prevent FindOptionalData from erronesouly testing against the trailing optional data size, which can match the tag for optional data entries if you are unlucky. #jira UE-37489 Change 3169467 on 2016/10/20 by Arne.Schober DR - UE-28039 - Fixed flickering cached shadows on dynamic objects: Adding preshadows whose depths are cached so that GatherDynamicMeshElements will still happen, which is necessary for preshadow receiver stenciling. Change 3169478 on 2016/10/20 by Arne.Schober DR - UE-28039 - missing comment Change 3169845 on 2016/10/20 by Arne.Schober DR - UE-35937 - readd Merged out check Change 3169859 on 2016/10/20 by Rolando.Caloca DR - vk - Stop popping up dialog on every run as the device name in the API doesn't match our driver database [CL 3170066 by Marcus Wassmer in Main branch]
943 lines
33 KiB
C++
943 lines
33 KiB
C++
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
PostProcessMotionBlur.cpp: Post process MotionBlur implementation.
|
|
=============================================================================*/
|
|
|
|
#include "RendererPrivate.h"
|
|
#include "ScenePrivate.h"
|
|
#include "SceneFilterRendering.h"
|
|
#include "PostProcessAmbientOcclusion.h"
|
|
#include "PostProcessMotionBlur.h"
|
|
#include "PostProcessAmbientOcclusion.h"
|
|
#include "PostProcessing.h"
|
|
#include "SceneUtils.h"
|
|
#include "GPUSkinVertexFactory.h"
|
|
#include "../../Engine/Private/SkeletalRenderGPUSkin.h"
|
|
|
|
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
static TAutoConsoleVariable<int32> CVarMotionBlurFiltering(
|
|
TEXT("r.MotionBlurFiltering"),
|
|
0,
|
|
TEXT("Useful developer variable\n")
|
|
TEXT("0: off (default, expected by the shader for better quality)\n")
|
|
TEXT("1: on"),
|
|
ECVF_Cheat | ECVF_RenderThreadSafe);
|
|
#endif
|
|
|
|
static TAutoConsoleVariable<float> CVarMotionBlur2ndScale(
|
|
TEXT("r.MotionBlur2ndScale"),
|
|
1.0f,
|
|
TEXT(""),
|
|
ECVF_Cheat | ECVF_RenderThreadSafe);
|
|
|
|
|
|
FIntPoint GetNumTiles16x16( FIntPoint PixelExtent )
|
|
{
|
|
uint32 TilesX = (PixelExtent.X + 15) / 16;
|
|
uint32 TilesY = (PixelExtent.Y + 15) / 16;
|
|
return FIntPoint( TilesX, TilesY );
|
|
}
|
|
|
|
FVector4 GetMotionBlurParameters( const FViewInfo& View, float Scale = 1.0f )
|
|
{
|
|
const float TileSize = 16.0f;
|
|
|
|
const float SizeX = View.ViewRect.Width();
|
|
const float SizeY = View.ViewRect.Height();
|
|
const float AspectRatio = SizeY / SizeX;
|
|
|
|
const FSceneViewState* ViewState = (FSceneViewState*) View.State;
|
|
float MotionBlurTimeScale = ViewState ? ViewState->MotionBlurTimeScale : 1.0f;
|
|
float MotionBlurScale = 0.5f * MotionBlurTimeScale * View.FinalPostProcessSettings.MotionBlurAmount;
|
|
|
|
// 0:no 1:full screen width, percent conversion
|
|
float MaxVelocity = View.FinalPostProcessSettings.MotionBlurMax / 100.0f;
|
|
|
|
// Scale by 0.5 due to blur samples going both ways
|
|
float PixelScale = Scale * SizeX * 0.5f;
|
|
|
|
FVector4 MotionBlurParameters(
|
|
AspectRatio,
|
|
PixelScale * MotionBlurScale, // Scale for pixels
|
|
PixelScale * MotionBlurScale / TileSize,// Scale for tiles
|
|
FMath::Abs( PixelScale ) * MaxVelocity // Max velocity pixels
|
|
);
|
|
|
|
return MotionBlurParameters;
|
|
}
|
|
|
|
class FPostProcessVelocityFlattenCS : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessVelocityFlattenCS, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
}
|
|
|
|
FPostProcessVelocityFlattenCS() {}
|
|
|
|
public:
|
|
FShaderParameter OutVelocityFlat; // UAV
|
|
FShaderParameter OutMaxTileVelocity; // UAV
|
|
|
|
FPostProcessVelocityFlattenCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
MotionBlurParameters.Bind(Initializer.ParameterMap, TEXT("MotionBlurParameters"));
|
|
OutVelocityFlat.Bind(Initializer.ParameterMap, TEXT("OutVelocityFlat"));
|
|
OutMaxTileVelocity.Bind(Initializer.ParameterMap, TEXT("OutMaxTileVelocity"));
|
|
}
|
|
|
|
void SetCS( FRHICommandList& RHICmdList, const FRenderingCompositePassContext& Context, const FSceneView& View )
|
|
{
|
|
const FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
|
|
|
|
FGlobalShader::SetParameters(RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetCS(ShaderRHI, Context, Context.RHICmdList, TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
|
|
SetUniformBufferParameter(RHICmdList, ShaderRHI, GetUniformBufferParameter<FCameraMotionParameters>(), CreateCameraMotionParametersUniformBuffer(Context.View));
|
|
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, MotionBlurParameters, GetMotionBlurParameters( Context.View ) );
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter;
|
|
Ar << MotionBlurParameters;
|
|
Ar << OutVelocityFlat;
|
|
Ar << OutMaxTileVelocity;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
|
|
private:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
FShaderParameter MotionBlurParameters;
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessVelocityFlattenCS,TEXT("PostProcessVelocityFlatten"),TEXT("VelocityFlattenMain"),SF_Compute);
|
|
|
|
|
|
FRCPassPostProcessVelocityFlatten::FRCPassPostProcessVelocityFlatten()
|
|
{}
|
|
|
|
void FRCPassPostProcessVelocityFlatten::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
SCOPED_DRAW_EVENT(Context.RHICmdList, VelocityFlatten);
|
|
const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0);
|
|
|
|
if(!InputDesc)
|
|
{
|
|
// input is not hooked up correctly
|
|
return;
|
|
}
|
|
|
|
const FSceneView& View = Context.View;
|
|
const FSceneViewFamily& ViewFamily = *(View.Family);
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget0 = PassOutputs[0].RequestSurface(Context);
|
|
const FSceneRenderTargetItem& DestRenderTarget1 = PassOutputs[1].RequestSurface(Context);
|
|
|
|
TShaderMapRef< FPostProcessVelocityFlattenCS > ComputeShader( Context.GetShaderMap() );
|
|
|
|
SetRenderTarget(Context.RHICmdList, FTextureRHIRef(), FTextureRHIRef());
|
|
|
|
Context.SetViewportAndCallRHI( View.ViewRect );
|
|
Context.RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
|
|
|
|
// set destination
|
|
Context.RHICmdList.SetUAVParameter(ComputeShader->GetComputeShader(), ComputeShader->OutVelocityFlat.GetBaseIndex(), DestRenderTarget0.UAV);
|
|
Context.RHICmdList.SetUAVParameter(ComputeShader->GetComputeShader(), ComputeShader->OutMaxTileVelocity.GetBaseIndex(), DestRenderTarget1.UAV);
|
|
|
|
ComputeShader->SetCS(Context.RHICmdList, Context, View);
|
|
|
|
FIntPoint ThreadGroupCountValue = GetNumTiles16x16(View.ViewRect.Size());
|
|
DispatchComputeShader(Context.RHICmdList, *ComputeShader, ThreadGroupCountValue.X, ThreadGroupCountValue.Y, 1);
|
|
|
|
// void FD3D11DynamicRHI::RHIGraphicsWaitOnAsyncComputeJob( uint32 FenceIndex )
|
|
Context.RHICmdList.FlushComputeShaderCache();
|
|
|
|
// un-set destination
|
|
Context.RHICmdList.SetUAVParameter(ComputeShader->GetComputeShader(), ComputeShader->OutVelocityFlat.GetBaseIndex(), NULL);
|
|
Context.RHICmdList.SetUAVParameter(ComputeShader->GetComputeShader(), ComputeShader->OutMaxTileVelocity.GetBaseIndex(), NULL);
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget0.TargetableTexture, DestRenderTarget0.ShaderResourceTexture, false, FResolveParams());
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget1.TargetableTexture, DestRenderTarget1.ShaderResourceTexture, false, FResolveParams());
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessVelocityFlatten::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
if( InPassOutputId == ePId_Output0 )
|
|
{
|
|
// Flattened velocity
|
|
FPooledRenderTargetDesc Ret = GetInput(ePId_Input0)->GetOutput()->RenderTargetDesc;
|
|
Ret.Reset();
|
|
Ret.ClearValue = FClearValueBinding::None;
|
|
Ret.Format = PF_FloatR11G11B10;
|
|
Ret.TargetableFlags |= TexCreate_UAV;
|
|
Ret.TargetableFlags |= TexCreate_RenderTargetable;
|
|
Ret.DebugName = TEXT("VelocityFlat");
|
|
|
|
return Ret;
|
|
}
|
|
else
|
|
{
|
|
// Max tile velocity
|
|
FPooledRenderTargetDesc UnmodifiedRet = GetInput(ePId_Input0)->GetOutput()->RenderTargetDesc;
|
|
UnmodifiedRet.Reset();
|
|
|
|
FIntPoint PixelExtent = UnmodifiedRet.Extent;
|
|
FIntPoint TileCount = GetNumTiles16x16(PixelExtent);
|
|
|
|
FPooledRenderTargetDesc Ret(FPooledRenderTargetDesc::Create2DDesc(TileCount, PF_FloatRGBA, FClearValueBinding::None, TexCreate_None, TexCreate_RenderTargetable | TexCreate_UAV, false));
|
|
|
|
Ret.DebugName = TEXT("MaxVelocity");
|
|
|
|
return Ret;
|
|
}
|
|
}
|
|
|
|
|
|
class FScatterQuadIndexBuffer : public FIndexBuffer
|
|
{
|
|
public:
|
|
virtual void InitRHI() override
|
|
{
|
|
const uint32 Size = sizeof(uint16) * 6 * 8;
|
|
const uint32 Stride = sizeof(uint16);
|
|
FRHIResourceCreateInfo CreateInfo;
|
|
void* Buffer = nullptr;
|
|
IndexBufferRHI = RHICreateAndLockIndexBuffer( Stride, Size, BUF_Static, CreateInfo, Buffer );
|
|
uint16* Indices = (uint16*)Buffer;
|
|
for (uint32 SpriteIndex = 0; SpriteIndex < 8; ++SpriteIndex)
|
|
{
|
|
Indices[SpriteIndex*6 + 0] = SpriteIndex*4 + 0;
|
|
Indices[SpriteIndex*6 + 1] = SpriteIndex*4 + 3;
|
|
Indices[SpriteIndex*6 + 2] = SpriteIndex*4 + 2;
|
|
Indices[SpriteIndex*6 + 3] = SpriteIndex*4 + 0;
|
|
Indices[SpriteIndex*6 + 4] = SpriteIndex*4 + 1;
|
|
Indices[SpriteIndex*6 + 5] = SpriteIndex*4 + 3;
|
|
}
|
|
RHIUnlockIndexBuffer( IndexBufferRHI );
|
|
}
|
|
};
|
|
|
|
TGlobalResource< FScatterQuadIndexBuffer > GScatterQuadIndexBuffer;
|
|
|
|
|
|
class FPostProcessVelocityScatterVS : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessVelocityScatterVS,Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5);
|
|
}
|
|
|
|
/** Default constructor. */
|
|
FPostProcessVelocityScatterVS() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
FShaderParameter DrawMax;
|
|
FShaderParameter MotionBlurParameters;
|
|
|
|
/** Initialization constructor. */
|
|
FPostProcessVelocityScatterVS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
DrawMax.Bind(Initializer.ParameterMap, TEXT("bDrawMax"));
|
|
MotionBlurParameters.Bind( Initializer.ParameterMap, TEXT("MotionBlurParameters") );
|
|
}
|
|
|
|
// FShader interface.
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter << DrawMax << MotionBlurParameters;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
|
|
/** to have a similar interface as all other shaders */
|
|
void SetParameters(const FRenderingCompositePassContext& Context, int32 bDrawMax)
|
|
{
|
|
const FVertexShaderRHIParamRef ShaderRHI = GetVertexShader();
|
|
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetVS(ShaderRHI, Context, TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, DrawMax, bDrawMax);
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, MotionBlurParameters, GetMotionBlurParameters( Context.View ) );
|
|
}
|
|
|
|
static const TCHAR* GetSourceFilename()
|
|
{
|
|
return TEXT("PostProcessMotionBlur");
|
|
}
|
|
|
|
static const TCHAR* GetFunctionName()
|
|
{
|
|
return TEXT("VelocityScatterVS");
|
|
}
|
|
};
|
|
|
|
class FPostProcessVelocityScatterPS : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessVelocityScatterPS, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5);
|
|
}
|
|
|
|
/** Default constructor. */
|
|
FPostProcessVelocityScatterPS() {}
|
|
|
|
public:
|
|
/** Initialization constructor. */
|
|
FPostProcessVelocityScatterPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{}
|
|
|
|
void SetParameters(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessVelocityScatterVS,TEXT("PostProcessMotionBlur"),TEXT("VelocityScatterVS"),SF_Vertex);
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessVelocityScatterPS,TEXT("PostProcessMotionBlur"),TEXT("VelocityScatterPS"),SF_Pixel);
|
|
|
|
|
|
void FRCPassPostProcessVelocityScatter::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
SCOPED_DRAW_EVENT(Context.RHICmdList, VelocityScatter);
|
|
|
|
const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0);
|
|
|
|
if(!InputDesc)
|
|
{
|
|
// input is not hooked up correctly
|
|
return;
|
|
}
|
|
|
|
const FSceneView& View = Context.View;
|
|
|
|
FIntPoint SrcSize = InputDesc->Extent;
|
|
FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent;
|
|
|
|
FIntPoint TileCount = GetNumTiles16x16( View.ViewRect.Size() );
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
|
|
|
|
TRefCountPtr<IPooledRenderTarget> DepthTarget;
|
|
FPooledRenderTargetDesc Desc( FPooledRenderTargetDesc::Create2DDesc( DestSize, PF_ShadowDepth, FClearValueBinding::DepthOne, TexCreate_None, TexCreate_DepthStencilTargetable, false ) );
|
|
GRenderTargetPool.FindFreeElement(Context.RHICmdList, Desc, DepthTarget, TEXT("VelocityScatterDepth") );
|
|
|
|
// Set the view family's render target/viewport.
|
|
FRHIRenderTargetView ColorView(DestRenderTarget.TargetableTexture, 0, -1, ERenderTargetLoadAction::ELoad, ERenderTargetStoreAction::EStore);
|
|
FRHIDepthRenderTargetView DepthView(DepthTarget->GetRenderTargetItem().TargetableTexture, ERenderTargetLoadAction::EClear, ERenderTargetStoreAction::EStore, ERenderTargetLoadAction::ELoad, ERenderTargetStoreAction::EStore);
|
|
FRHISetRenderTargetsInfo RTInfo(1, &ColorView, DepthView);
|
|
|
|
// clear depth
|
|
// Max >= Min so no need to clear on second pass
|
|
Context.RHICmdList.SetRenderTargetsAndClear(RTInfo);
|
|
Context.SetViewportAndCallRHI(0, 0, 0.0f, TileCount.X, TileCount.Y, 1.0f);
|
|
|
|
// Min,Max
|
|
for( int i = 0; i < 2; i++ )
|
|
{
|
|
if( i == 0 )
|
|
{
|
|
// min
|
|
Context.RHICmdList.SetBlendState( TStaticBlendStateWriteMask< CW_RGBA >::GetRHI() );
|
|
Context.RHICmdList.SetRasterizerState( TStaticRasterizerState<>::GetRHI() );
|
|
Context.RHICmdList.SetDepthStencilState( TStaticDepthStencilState< true, CF_Less >::GetRHI() );
|
|
}
|
|
else
|
|
{
|
|
// max
|
|
Context.RHICmdList.SetBlendState( TStaticBlendStateWriteMask< CW_BA >::GetRHI() );
|
|
Context.RHICmdList.SetRasterizerState( TStaticRasterizerState<>::GetRHI() );
|
|
Context.RHICmdList.SetDepthStencilState( TStaticDepthStencilState< true, CF_Greater >::GetRHI() );
|
|
}
|
|
|
|
TShaderMapRef< FPostProcessVelocityScatterVS > VertexShader(Context.GetShaderMap());
|
|
TShaderMapRef< FPostProcessVelocityScatterPS > PixelShader(Context.GetShaderMap());
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GEmptyVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
VertexShader->SetParameters( Context, i );
|
|
PixelShader->SetParameters( Context );
|
|
|
|
// needs to be the same on shader side (faster on NVIDIA and AMD)
|
|
int32 QuadsPerInstance = 8;
|
|
|
|
Context.RHICmdList.SetStreamSource(0, NULL, 0, 0);
|
|
Context.RHICmdList.DrawIndexedPrimitive(GScatterQuadIndexBuffer.IndexBufferRHI, PT_TriangleList, 0, 0, 32, 0, 2 * QuadsPerInstance, FMath::DivideAndRoundUp(TileCount.X * TileCount.Y, QuadsPerInstance));
|
|
}
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessVelocityScatter::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
FPooledRenderTargetDesc Ret = GetInput(ePId_Input0)->GetOutput()->RenderTargetDesc;
|
|
Ret.Reset();
|
|
|
|
Ret.DebugName = TEXT("ScatteredMaxVelocity");
|
|
|
|
return Ret;
|
|
}
|
|
|
|
|
|
class FPostProcessVelocityGatherCS : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessVelocityGatherCS, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
}
|
|
|
|
/** Default constructor. */
|
|
FPostProcessVelocityGatherCS() {}
|
|
|
|
public:
|
|
FShaderParameter OutScatteredMaxVelocity;
|
|
|
|
/** Initialization constructor. */
|
|
FPostProcessVelocityGatherCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
MotionBlurParameters.Bind(Initializer.ParameterMap, TEXT("MotionBlurParameters"));
|
|
OutScatteredMaxVelocity.Bind(Initializer.ParameterMap, TEXT("OutScatteredMaxVelocity"));
|
|
}
|
|
|
|
// FShader interface.
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter;
|
|
Ar << MotionBlurParameters;
|
|
Ar << OutScatteredMaxVelocity;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
|
|
void SetParameters(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
|
|
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
|
|
PostprocessParameter.SetCS(ShaderRHI, Context, Context.RHICmdList, TStaticSamplerState<SF_Point, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI());
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, MotionBlurParameters, GetMotionBlurParameters( Context.View ) );
|
|
}
|
|
|
|
private:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
FShaderParameter MotionBlurParameters;
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessVelocityGatherCS,TEXT("PostProcessVelocityFlatten"),TEXT("VelocityGatherCS"),SF_Compute);
|
|
|
|
void FRCPassPostProcessVelocityGather::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
SCOPED_DRAW_EVENT(Context.RHICmdList, VelocityDilate);
|
|
|
|
const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0);
|
|
|
|
if(!InputDesc)
|
|
{
|
|
// input is not hooked up correctly
|
|
return;
|
|
}
|
|
|
|
const FSceneView& View = Context.View;
|
|
|
|
FIntPoint TileCount = GetNumTiles16x16( View.ViewRect.Size() );
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
|
|
|
|
SetRenderTarget(Context.RHICmdList, FTextureRHIRef(), FTextureRHIRef());
|
|
Context.SetViewportAndCallRHI( 0, 0, 0.0f, TileCount.X, TileCount.Y, 1.0f );
|
|
|
|
TShaderMapRef< FPostProcessVelocityGatherCS > ComputeShader( Context.GetShaderMap() );
|
|
Context.RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
|
|
|
|
// set destination
|
|
Context.RHICmdList.SetUAVParameter( ComputeShader->GetComputeShader(), ComputeShader->OutScatteredMaxVelocity.GetBaseIndex(), DestRenderTarget.UAV );
|
|
|
|
ComputeShader->SetParameters( Context );
|
|
|
|
FIntPoint GroupCount = GetNumTiles16x16( TileCount );
|
|
DispatchComputeShader(Context.RHICmdList, *ComputeShader, GroupCount.X, GroupCount.Y, 1);
|
|
|
|
// un-set destination
|
|
Context.RHICmdList.SetUAVParameter( ComputeShader->GetComputeShader(), ComputeShader->OutScatteredMaxVelocity.GetBaseIndex(), NULL );
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessVelocityGather::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
FPooledRenderTargetDesc Ret = GetInput(ePId_Input0)->GetOutput()->RenderTargetDesc;
|
|
Ret.Reset();
|
|
|
|
Ret.TargetableFlags |= TexCreate_UAV;
|
|
Ret.TargetableFlags |= TexCreate_RenderTargetable;
|
|
Ret.DebugName = TEXT("ScatteredMaxVelocity");
|
|
|
|
return Ret;
|
|
}
|
|
|
|
|
|
/**
|
|
* @param Quality 0: visualize, 1:low, 2:medium, 3:high, 4:very high
|
|
*/
|
|
template< uint32 Quality >
|
|
class FPostProcessMotionBlurPS : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessMotionBlurPS, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform,OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("MOTION_BLUR_QUALITY"), Quality);
|
|
}
|
|
|
|
/** Default constructor. */
|
|
FPostProcessMotionBlurPS() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
FDeferredPixelShaderParameters DeferredParameters;
|
|
FShaderParameter MotionBlurParameters;
|
|
|
|
/** Initialization constructor. */
|
|
FPostProcessMotionBlurPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
DeferredParameters.Bind(Initializer.ParameterMap);
|
|
MotionBlurParameters.Bind(Initializer.ParameterMap, TEXT("MotionBlurParameters"));
|
|
}
|
|
|
|
// FShader interface.
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter << DeferredParameters << MotionBlurParameters;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
|
|
void SetParameters(const FRenderingCompositePassContext& Context, float Scale)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
|
|
DeferredParameters.Set(Context.RHICmdList, ShaderRHI, Context.View);
|
|
|
|
{
|
|
bool bFiltered = false;
|
|
|
|
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
bFiltered = CVarMotionBlurFiltering.GetValueOnRenderThread() != 0;
|
|
#endif // !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
|
|
if(bFiltered)
|
|
{
|
|
//PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Border,AM_Border,AM_Clamp>::GetRHI());
|
|
|
|
FSamplerStateRHIParamRef Filters[] =
|
|
{
|
|
TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(),
|
|
TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(),
|
|
TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(),
|
|
TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(),
|
|
};
|
|
|
|
PostprocessParameter.SetPS( ShaderRHI, Context, 0, eFC_0000, Filters );
|
|
}
|
|
else
|
|
{
|
|
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
}
|
|
}
|
|
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, MotionBlurParameters, GetMotionBlurParameters( Context.View, Scale ) );
|
|
}
|
|
|
|
static const TCHAR* GetSourceFilename()
|
|
{
|
|
return TEXT("PostProcessMotionBlur");
|
|
}
|
|
|
|
static const TCHAR* GetFunctionName()
|
|
{
|
|
return TEXT("MainPS");
|
|
}
|
|
};
|
|
|
|
// #define avoids a lot of code duplication
|
|
#define VARIATION1(A) typedef FPostProcessMotionBlurPS<A> FPostProcessMotionBlurPS##A; \
|
|
IMPLEMENT_SHADER_TYPE2(FPostProcessMotionBlurPS##A, SF_Pixel);
|
|
|
|
VARIATION1(1) VARIATION1(2) VARIATION1(3) VARIATION1(4)
|
|
#undef VARIATION1
|
|
|
|
|
|
|
|
// @param Quality 0: visualize, 1:low, 2:medium, 3:high, 4:very high
|
|
template< uint32 Quality >
|
|
static void SetMotionBlurShaderNewTempl( const FRenderingCompositePassContext& Context, float Scale )
|
|
{
|
|
TShaderMapRef< FPostProcessVS > VertexShader( Context.GetShaderMap() );
|
|
TShaderMapRef< FPostProcessMotionBlurPS< Quality > > PixelShader( Context.GetShaderMap() );
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
VertexShader->SetParameters(Context);
|
|
PixelShader->SetParameters(Context, Scale);
|
|
}
|
|
|
|
void FRCPassPostProcessMotionBlur::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0);
|
|
|
|
if(!InputDesc)
|
|
{
|
|
// input is not hooked up correctly
|
|
return;
|
|
}
|
|
|
|
const FSceneView& View = Context.View;
|
|
|
|
// we assume the input and output is full resolution
|
|
|
|
FIntPoint SrcSize = InputDesc->Extent;
|
|
FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent;
|
|
|
|
// e.g. 4 means the input texture is 4x smaller than the buffer size
|
|
uint32 ScaleFactor = FSceneRenderTargets::Get(Context.RHICmdList).GetBufferSizeXY().X / SrcSize.X;
|
|
|
|
FIntRect SrcRect = View.ViewRect / ScaleFactor;
|
|
FIntRect DestRect = SrcRect;
|
|
|
|
SCOPED_DRAW_EVENTF(Context.RHICmdList, MotionBlurNew, TEXT("MotionBlur %dx%d"), SrcRect.Width(), SrcRect.Height());
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
|
|
|
|
// Set the view family's render target/viewport.
|
|
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef());
|
|
Context.SetViewportAndCallRHI(SrcRect);
|
|
|
|
// is optimized away if possible (RT size=view size, )
|
|
//Context.RHICmdList.Clear(true, FLinearColor::Black, false, 1.0f, false, 0, SrcRect);
|
|
|
|
// set the state
|
|
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
|
|
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI());
|
|
|
|
float BlurScaleLUT[] =
|
|
{
|
|
1.0f - 0.5f / 4.0f,
|
|
1.0f - 0.5f / 6.0f,
|
|
1.0f - 0.5f / 8.0f,
|
|
1.0f - 0.5f / 16.0f,
|
|
1.0f / 4.0f * CVarMotionBlur2ndScale.GetValueOnRenderThread(),
|
|
1.0f / 6.0f * CVarMotionBlur2ndScale.GetValueOnRenderThread(),
|
|
1.0f / 8.0f * CVarMotionBlur2ndScale.GetValueOnRenderThread(),
|
|
1.0f / 16.0f * CVarMotionBlur2ndScale.GetValueOnRenderThread(),
|
|
};
|
|
float Scale = Pass >= 0 ? BlurScaleLUT[ (Pass * 4) + (Quality - 1) ] : 1.0f;
|
|
|
|
if(Quality == 1)
|
|
{
|
|
SetMotionBlurShaderNewTempl<1>( Context, Scale );
|
|
}
|
|
else if(Quality == 2)
|
|
{
|
|
SetMotionBlurShaderNewTempl<2>( Context, Scale );
|
|
}
|
|
else if(Quality == 3 || Pass > 0 )
|
|
{
|
|
SetMotionBlurShaderNewTempl<3>( Context, Scale );
|
|
}
|
|
else
|
|
{
|
|
check(Quality == 4);
|
|
SetMotionBlurShaderNewTempl<4>( Context, Scale );
|
|
}
|
|
|
|
TShaderMapRef<FPostProcessVS> VertexShader(Context.GetShaderMap());
|
|
|
|
|
|
DrawPostProcessPass(
|
|
Context.RHICmdList,
|
|
0, 0,
|
|
SrcRect.Width(), SrcRect.Height(),
|
|
SrcRect.Min.X, SrcRect.Min.Y,
|
|
SrcRect.Width(), SrcRect.Height(),
|
|
SrcRect.Size(),
|
|
SrcSize,
|
|
*VertexShader,
|
|
View.StereoPass,
|
|
Context.HasHmdMesh(),
|
|
EDRF_UseTriangleOptimization);
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessMotionBlur::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
FPooledRenderTargetDesc Ret = GetInput(ePId_Input0)->GetOutput()->RenderTargetDesc;
|
|
|
|
Ret.Reset();
|
|
Ret.Format = PF_FloatRGB;
|
|
Ret.DebugName = TEXT("MotionBlur");
|
|
Ret.AutoWritable = false;
|
|
|
|
return Ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
class FPostProcessVisualizeMotionBlurPS : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessVisualizeMotionBlurPS, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM4);
|
|
}
|
|
|
|
/** Default constructor. */
|
|
FPostProcessVisualizeMotionBlurPS() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
FDeferredPixelShaderParameters DeferredParameters;
|
|
FShaderParameter PrevViewProjMatrix;
|
|
|
|
/** Initialization constructor. */
|
|
FPostProcessVisualizeMotionBlurPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
DeferredParameters.Bind(Initializer.ParameterMap);
|
|
PrevViewProjMatrix.Bind(Initializer.ParameterMap, TEXT("PrevViewProjMatrix"));
|
|
}
|
|
|
|
// FShader interface.
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter << DeferredParameters << PrevViewProjMatrix;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
|
|
void SetParameters(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
|
|
DeferredParameters.Set(Context.RHICmdList, ShaderRHI, Context.View);
|
|
|
|
SetUniformBufferParameter(Context.RHICmdList, ShaderRHI, GetUniformBufferParameter<FCameraMotionParameters>(), CreateCameraMotionParametersUniformBuffer(Context.View));
|
|
|
|
{
|
|
bool bFiltered = false;
|
|
|
|
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
bFiltered = CVarMotionBlurFiltering.GetValueOnRenderThread() != 0;
|
|
#endif // !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
|
|
if(bFiltered)
|
|
{
|
|
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Border,AM_Border,AM_Clamp>::GetRHI());
|
|
}
|
|
else
|
|
{
|
|
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Point,AM_Border,AM_Border,AM_Clamp>::GetRHI());
|
|
}
|
|
}
|
|
|
|
if( Context.View.Family->EngineShowFlags.CameraInterpolation )
|
|
{
|
|
// Instead of finding the world space position of the current pixel, calculate the world space position offset by the camera position,
|
|
// then translate by the difference between last frame's camera position and this frame's camera position,
|
|
// then apply the rest of the transforms. This effectively avoids precision issues near the extents of large levels whose world space position is very large.
|
|
FVector ViewOriginDelta = Context.View.ViewMatrices.GetViewOrigin() - Context.View.PrevViewMatrices.GetViewOrigin();
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, PrevViewProjMatrix, FTranslationMatrix(ViewOriginDelta) * Context.View.PrevViewMatrices.ComputeViewRotationProjectionMatrix());
|
|
}
|
|
else
|
|
{
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, PrevViewProjMatrix, Context.View.ViewMatrices.ComputeViewRotationProjectionMatrix());
|
|
}
|
|
}
|
|
|
|
static const TCHAR* GetSourceFilename()
|
|
{
|
|
return TEXT("PostProcessMotionBlur");
|
|
}
|
|
|
|
static const TCHAR* GetFunctionName()
|
|
{
|
|
return TEXT("VisualizeMotionBlurPS");
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE3(FPostProcessVisualizeMotionBlurPS, SF_Pixel);
|
|
|
|
void FRCPassPostProcessVisualizeMotionBlur::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
SCOPED_DRAW_EVENT(Context.RHICmdList, VisualizeMotionBlur);
|
|
|
|
const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0);
|
|
|
|
if(!InputDesc)
|
|
{
|
|
// input is not hooked up correctly
|
|
return;
|
|
}
|
|
|
|
const FSceneView& View = Context.View;
|
|
const FSceneViewFamily& ViewFamily = *(View.Family);
|
|
|
|
FIntPoint TexSize = InputDesc->Extent;
|
|
|
|
// we assume the input and output is full resolution
|
|
|
|
FIntPoint SrcSize = InputDesc->Extent;
|
|
FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent;
|
|
|
|
// e.g. 4 means the input texture is 4x smaller than the buffer size
|
|
uint32 ScaleFactor = FSceneRenderTargets::Get(Context.RHICmdList).GetBufferSizeXY().X / SrcSize.X;
|
|
|
|
FIntRect SrcRect = FIntRect::DivideAndRoundUp(View.ViewRect, ScaleFactor);
|
|
FIntRect DestRect = SrcRect;
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
|
|
|
|
// Set the view family's render target/viewport.
|
|
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef());
|
|
|
|
// is optimized away if possible (RT size=view size, )
|
|
Context.RHICmdList.ClearColorTexture(DestRenderTarget.TargetableTexture, FLinearColor::Black, SrcRect);
|
|
|
|
Context.SetViewportAndCallRHI(SrcRect);
|
|
|
|
// set the state
|
|
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
|
|
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI());
|
|
|
|
TShaderMapRef<FPostProcessVS> VertexShader(Context.GetShaderMap());
|
|
TShaderMapRef<FPostProcessVisualizeMotionBlurPS> PixelShader(Context.GetShaderMap());
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
VertexShader->SetParameters(Context);
|
|
PixelShader->SetParameters(Context);
|
|
|
|
// Draw a quad mapping scene color to the view's render target
|
|
DrawRectangle(
|
|
Context.RHICmdList,
|
|
0, 0,
|
|
SrcRect.Width(), SrcRect.Height(),
|
|
SrcRect.Min.X, SrcRect.Min.Y,
|
|
SrcRect.Width(), SrcRect.Height(),
|
|
SrcRect.Size(),
|
|
SrcSize,
|
|
*VertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
|
|
FRenderTargetTemp TempRenderTarget(View, (const FTexture2DRHIRef&)DestRenderTarget.TargetableTexture);
|
|
FCanvas Canvas(&TempRenderTarget, NULL, ViewFamily.CurrentRealTime, ViewFamily.CurrentWorldTime, ViewFamily.DeltaWorldTime, Context.GetFeatureLevel());
|
|
|
|
float X = 20;
|
|
float Y = 38;
|
|
const float YStep = 14;
|
|
const float ColumnWidth = 200;
|
|
|
|
FString Line;
|
|
|
|
Line = FString::Printf(TEXT("Visualize MotionBlur"));
|
|
Canvas.DrawShadowedString(X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 0));
|
|
|
|
static const auto MotionBlurDebugVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.MotionBlurDebug"));
|
|
const int32 MotionBlurDebug = MotionBlurDebugVar ? MotionBlurDebugVar->GetValueOnRenderThread() : 0;
|
|
|
|
Line = FString::Printf(TEXT("%d, %d"), ViewFamily.FrameNumber, MotionBlurDebug);
|
|
Canvas.DrawShadowedString(X, Y += YStep, TEXT("FrameNo, r.MotionBlurDebug:"), GetStatsFont(), FLinearColor(1, 1, 0));
|
|
Canvas.DrawShadowedString(X + ColumnWidth, Y, *Line, GetStatsFont(), FLinearColor(1, 1, 0));
|
|
|
|
static const auto VelocityTestVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.VelocityTest"));
|
|
const int32 VelocityTest = VelocityTestVar ? VelocityTestVar->GetValueOnRenderThread() : 0;
|
|
|
|
extern bool IsParallelVelocity();
|
|
|
|
Line = FString::Printf(TEXT("%d, %d, %d"), ViewFamily.bWorldIsPaused, VelocityTest, IsParallelVelocity());
|
|
Canvas.DrawShadowedString(X, Y += YStep, TEXT("Paused, r.VelocityTest, Parallel:"), GetStatsFont(), FLinearColor(1, 1, 0));
|
|
Canvas.DrawShadowedString(X + ColumnWidth, Y, *Line, GetStatsFont(), FLinearColor(1, 1, 0));
|
|
|
|
const FScene* Scene = (const FScene*)View.Family->Scene;
|
|
|
|
Canvas.DrawShadowedString(X, Y += YStep, TEXT("MotionBlurInfoData (per object):"), GetStatsFont(), FLinearColor(1, 1, 0));
|
|
Canvas.DrawShadowedString(X + ColumnWidth, Y, *Scene->MotionBlurInfoData.GetDebugString(), GetStatsFont(), FLinearColor(1, 1, 0));
|
|
|
|
const FSceneViewState *SceneViewState = (const FSceneViewState*)View.State;
|
|
|
|
Line = FString::Printf(TEXT("View=%.4x PrevView=%.4x"),
|
|
View.ViewMatrices.GetViewMatrix().ComputeHash() & 0xffff,
|
|
SceneViewState->PrevViewMatrices.GetViewMatrix().ComputeHash() & 0xffff);
|
|
Canvas.DrawShadowedString(X, Y += YStep, TEXT("ViewMatrix:"), GetStatsFont(), FLinearColor(1, 1, 0));
|
|
Canvas.DrawShadowedString(X + ColumnWidth, Y, *Line, GetStatsFont(), FLinearColor(1, 1, 0));
|
|
|
|
Canvas.Flush_RenderThread(Context.RHICmdList);
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessVisualizeMotionBlur::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
FPooledRenderTargetDesc Ret = GetInput(ePId_Input0)->GetOutput()->RenderTargetDesc;
|
|
|
|
Ret.Reset();
|
|
Ret.DebugName = TEXT("MotionBlur");
|
|
Ret.AutoWritable = false;
|
|
|
|
return Ret;
|
|
}
|