ue 添加后处理
1. shader 类
2.pass 类
class FPostProcessmgTestVS_ES2 : public FGlobalShader { DECLARE_SHADER_TYPE(FPostProcessmgTestVS_ES2, Global); static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return !IsConsolePlatform(Parameters.Platform); } /** Default constructor. */ FPostProcessmgTestVS_ES2() {} public: LAYOUT_FIELD(FPostProcessPassParameters, PostprocessParameter); /** Initialization constructor. */ FPostProcessmgTestVS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer) : FGlobalShader(Initializer) { PostprocessParameter.Bind(Initializer.ParameterMap); } void SetVS(const FRenderingCompositePassContext& Context) { FRHIVertexShader* ShaderRHI = Context.RHICmdList.GetBoundVertexShader(); FGlobalShader::SetParameters<FViewUniformShaderParameters>(Context.RHICmdList, ShaderRHI, Context.View.ViewUniformBuffer); PostprocessParameter.SetVS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI()); } }; IMPLEMENT_SHADER_TYPE(, FPostProcessmgTestVS_ES2, TEXT("/Engine/Private/mgTestShader.usf"), TEXT("mgTestVS"), SF_Vertex); ////// class FPostProcessmgTestPS_ES2 : public FGlobalShader { public: DECLARE_GLOBAL_SHADER(FPostProcessmgTestPS_ES2); SHADER_USE_PARAMETER_STRUCT(FPostProcessmgTestPS_ES2, FGlobalShader); BEGIN_SHADER_PARAMETER_STRUCT(FParameters, ) SHADER_PARAMETER_TEXTURE(Texture2D, InputTexture) SHADER_PARAMETER_SAMPLER(SamplerState, InputSampler) END_SHADER_PARAMETER_STRUCT() static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return true; } public: void SetPS(const FRenderingCompositePassContext& Context, const TShaderRef<FPostProcessmgTestPS_ES2>& Shader, FRHITexture* PostprocessInput0, FRHITexture* PostprocessInput1) { FRHIPixelShader* ShaderRHI = Context.RHICmdList.GetBoundPixelShader(); const FPostProcessSettings& Settings = Context.View.FinalPostProcessSettings; FParameters ShaderParameters; ShaderParameters.InputTexture = PostprocessInput0; ShaderParameters.InputSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI(); SetShaderParameters(Context.RHICmdList, Shader, ShaderRHI, ShaderParameters); } }; IMPLEMENT_GLOBAL_SHADER(FPostProcessmgTestPS_ES2, "/Engine/Private/mgTestShader.usf", "mgTestPS", SF_Pixel); void FRCPassPostProcessmgTestES2::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessMgtest); const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0); FIntPoint PrePostSourceViewportSize = PrePostSourceViewportRect.Size(); uint32 DstX = PrePostSourceViewportSize.X;//FMath::DivideAndRoundUp(PrePostSourceViewportSize.X, 4); uint32 DstY = PrePostSourceViewportSize.Y;// FMath::DivideAndRoundUp(PrePostSourceViewportSize.Y, 4); FIntRect DstRect; DstRect.Min.X = 0; DstRect.Min.Y = 0; DstRect.Max.X = DstX; DstRect.Max.Y = DstY; FIntPoint DstSize(DstX, DstY); FIntPoint SrcSize; FIntRect SrcRect; { // Otherwise using exact size texture. SrcSize = DstSize; SrcRect = DstRect; } const FSceneRenderTargetItem& DestRenderTarget0 = PassOutputs[0].RequestSurface(Context); const FSceneRenderTargetItem* DestRenderTarget1 = nullptr; const FSceneRenderTargetItem* DestRenderTarget2 = nullptr; int32 NumRenderTargets = 1; const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); FRHIRenderPassInfo RPInfo(DestRenderTarget0.TargetableTexture, ERenderTargetActions::DontLoad_Store); RPInfo.ColorRenderTargets[0].Action = ERenderTargetActions::DontLoad_Store; FRHITexture* InputRenderTarget0 = GetInput(ePId_Input0)->GetOutput()->PooledRenderTarget->GetRenderTargetItem().ShaderResourceTexture; //FRHITexture* InputRenderTarget1 = GetInput(ePId_Input1)->IsValid() ? GetInput(ePId_Input1)->GetOutput()->PooledRenderTarget->GetRenderTargetItem().ShaderResourceTexture : nullptr; Context.RHICmdList.BeginRenderPass(RPInfo, TEXT("PostProcessBloomSetupES2")); { Context.SetViewportAndCallRHI(0, 0, 0.0f, DstX, DstY, 1.0f); FGraphicsPipelineStateInitializer GraphicsPSOInit; Context.RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit); GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI(); GraphicsPSOInit.RasterizerState = TStaticRasterizerState<>::GetRHI(); GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always>::GetRHI(); TShaderMapRef<FPostProcessmgTestVS_ES2> VertexShader(Context.GetShaderMap()); //auto ShaderPermutationVector = FPostProcessBloomSetupPS_ES2::BuildPermutationVector(bUseBloom, bUseSun, bUseDof, bUseEyeAdaptation, bUseMetalMSAAHDRDecode); TShaderMapRef<FPostProcessmgTestPS_ES2> PixelShader(Context.GetShaderMap()); GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI; GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader(); GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader(); GraphicsPSOInit.PrimitiveType = PT_TriangleList; SetGraphicsPipelineState(Context.RHICmdList, GraphicsPSOInit); VertexShader->SetVS(Context); PixelShader->SetPS(Context, PixelShader, InputRenderTarget0, nullptr);// InputRenderTarget0, InputRenderTarget1); DrawRectangle( Context.RHICmdList, 0, 0, DstX, DstY, SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DstSize, SrcSize, VertexShader, EDRF_UseTriangleOptimization); } Context.RHICmdList.EndRenderPass(); if (DestRenderTarget0.TargetableTexture != nullptr) { Context.RHICmdList.TransitionResource(EResourceTransitionAccess::EReadable, DestRenderTarget0.TargetableTexture); } } FPooledRenderTargetDesc FRCPassPostProcessmgTestES2::ComputeOutputDesc(EPassOutputId InPassOutputId) const { FPooledRenderTargetDesc Ret; Ret.Depth = 0; Ret.ArraySize = 1; Ret.bIsArray = false; Ret.NumMips = 1; Ret.TargetableFlags = TexCreate_RenderTargetable | TexCreate_ShaderResource; Ret.bForceSeparateTargetAndShaderResource = false; Ret.Format = PF_FloatR11G11B10; Ret.NumSamples = 1; Ret.Extent.X = FMath::Max(1, PrePostSourceViewportRect.Width()); Ret.Extent.Y = FMath::Max(1, PrePostSourceViewportRect.Height()); Ret.DebugName = TEXT("mgTestRTV"); Ret.ClearValue = FClearValueBinding(FLinearColor::Red); return Ret; }
class FRCPassPostProcessmgTestES2 : public TRenderingCompositePassBase<1, 1> { public: FRCPassPostProcessmgTestES2(FIntRect InPrePostSourceViewportRect) : PrePostSourceViewportRect(InPrePostSourceViewportRect) { } virtual void Process(FRenderingCompositePassContext& Context) override; virtual FPooledRenderTargetDesc ComputeOutputDesc(EPassOutputId InPassOutputId) const override; virtual void Release() override { delete this; } private: FIntRect PrePostSourceViewportRect; };
3.shader资源
#include "Common.ush" #include "ScreenPass.ush" SCREEN_PASS_TEXTURE_VIEWPORT(Input) Texture2D InputTexture; SamplerState InputSampler; void mgTestVS( in float4 InPosition : ATTRIBUTE0, in float2 InTexCoord : ATTRIBUTE1, out float2 OutTexCoords : TEXCOORD0, out float4 OutPosition : SV_POSITION ) { DrawRectangle(InPosition, InTexCoord, OutPosition, InTexCoord); OutTexCoords = InTexCoord.xy; } void mgTestPS( float2 InUVs : TEXCOORD0, out half4 OutColor : SV_Target0 ) { float4 SceneColor = Texture2DSample(InputTexture, InputSampler, InUVs); OutColor = half4(1,1,0,1)+ SceneColor; }
4 加入管线
FRenderingCompositePass* Passmg; Passmg = Context.Graph.RegisterPass(new(FMemStack::Get()) FRCPassPostProcessmgTestES2(FinalOutputViewRect)); Passmg->SetInput(ePId_Input0, BloomOutput); FRenderingCompositeOutputRef mgTestOutput = FRenderingCompositeOutputRef(Passmg); static const auto VarTonemapperUpscale = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.MobileTonemapperUpscale")); bool bDisableUpscaleInTonemapper = !VarTonemapperUpscale || VarTonemapperUpscale->GetValueOnRenderThread() == 0; bool* DoScreenPercentageInTonemapperPtr = nullptr; FRenderingCompositePass* TonemapperPass = nullptr; if (bAllowFullPostProcess) { if (bUseTonemapperFilm) { //BloomOutput //@todo Ronin Set to EAutoExposureMethod::AEM_Basic for PC vk crash. FRCPassPostProcessTonemap* PostProcessTonemap = AddTonemapper(Context, mgTestOutput, PostProcessEyeAdaptation, AutoExposureMethod, false, false, bMetalMSAAHDRDecode, bUseMobileDof); // remember the tonemapper pass so we can check if it's last TonemapperPass = PostProcessTonemap; PostProcessTonemap->bDoScreenPercentageInTonemapper = false; DoScreenPercentageInTonemapperPtr = &PostProcessTonemap->bDoScreenPercentageInTonemapper; }