// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. /*============================================================================= PostProcessNoiseBlur.cpp: Post processing down sample implementation. =============================================================================*/ #include "RendererPrivate.h" #include "ScenePrivate.h" #include "SceneFilterRendering.h" #include "PostProcessNoiseBlur.h" #include "PostProcessing.h" #include "SceneUtils.h" /** Encapsulates the post processing noise blur shader. */ template class FPostProcessNoiseBlurPS : public FGlobalShader { DECLARE_SHADER_TYPE(FPostProcessNoiseBlurPS, Global); static bool ShouldCache(EShaderPlatform Platform) { return true; } static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment) { FGlobalShader::ModifyCompilationEnvironment(Platform,OutEnvironment); OutEnvironment.SetDefine(TEXT("METHOD"), Method); } /** Default constructor. */ FPostProcessNoiseBlurPS() {} public: FPostProcessPassParameters PostprocessParameter; FDeferredPixelShaderParameters DeferredParameters; FShaderParameter NoiseParams; /** Initialization constructor. */ FPostProcessNoiseBlurPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer) : FGlobalShader(Initializer) { PostprocessParameter.Bind(Initializer.ParameterMap); DeferredParameters.Bind(Initializer.ParameterMap); NoiseParams.Bind(Initializer.ParameterMap, TEXT("NoiseParams")); } // FShader interface. virtual bool Serialize(FArchive& Ar) override { bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar); Ar << PostprocessParameter << DeferredParameters << NoiseParams; return bShaderHasOutdatedParameters; } void SetParameters(const FRenderingCompositePassContext& Context, float InRadius) { const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader(); FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View); DeferredParameters.Set(Context.RHICmdList, ShaderRHI, Context.View); PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState::GetRHI()); { FVector4 ColorScale(InRadius, 0, 0, 0); SetShaderValue(Context.RHICmdList, ShaderRHI, NoiseParams, ColorScale); } } static const TCHAR* GetSourceFilename() { return TEXT("PostProcessNoiseBlur"); } static const TCHAR* GetFunctionName() { return TEXT("MainPS"); } }; // #define avoids a lot of code duplication #define VARIATION1(A) typedef FPostProcessNoiseBlurPS FPostProcessNoiseBlurPS##A; \ IMPLEMENT_SHADER_TYPE2(FPostProcessNoiseBlurPS##A, SF_Pixel); VARIATION1(0) VARIATION1(1) VARIATION1(2) #undef VARIATION1 FRCPassPostProcessNoiseBlur::FRCPassPostProcessNoiseBlur(float InRadius, EPixelFormat InOverrideFormat, uint32 InQuality) : Radius(InRadius) , Quality(InQuality) , OverrideFormat(InOverrideFormat) { } template void SetNoiseBlurShader(const FRenderingCompositePassContext& Context, float InRadius) { TShaderMapRef VertexShader(Context.GetShaderMap()); TShaderMapRef > PixelShader(Context.GetShaderMap()); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(Context, InRadius); VertexShader->SetParameters(Context); } void FRCPassPostProcessNoiseBlur::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, NoiseBlur); 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; 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(0, 0, 0, 0), false, 1.0f, false, 0, DestRect); Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f ); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState::GetRHI()); if(Quality == 0) { SetNoiseBlurShader<0>(Context, Radius); } else if(Quality == 1) { SetNoiseBlurShader<1>(Context, Radius); } else { SetNoiseBlurShader<2>(Context, Radius); } // Draw a quad mapping scene color to the view's render target TShaderMapRef VertexShader(Context.GetShaderMap()); DrawRectangle( Context.RHICmdList, DestRect.Min.X, DestRect.Min.Y, DestRect.Width(), DestRect.Height(), SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DestSize, SrcSize, *VertexShader, EDRF_UseTriangleOptimization); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); } FPooledRenderTargetDesc FRCPassPostProcessNoiseBlur::ComputeOutputDesc(EPassOutputId InPassOutputId) const { FPooledRenderTargetDesc Ret = PassInputs[0].GetOutput()->RenderTargetDesc; Ret.Reset(); if(OverrideFormat != PF_Unknown) { Ret.Format = OverrideFormat; } Ret.TargetableFlags &= ~TexCreate_UAV; Ret.TargetableFlags |= TexCreate_RenderTargetable; Ret.DebugName = TEXT("NoiseBlur"); return Ret; }