【转载】UE4 Post Processing

Spread the love

UE4 Post Processing


  • A global singleton of FPostProcessing

  • Caller of GPostProcessing

    • FDeferredShadingSceneRenderer::Render() calls GPostProcessing::Process()


  • the context used to setup a post-process pass

  • holds refs of a RHICmdList, RenderingCompositionGraph, FViewInfo

  • holds refs of a scene color RCPass, a scene depth RCPass

  • holds a ref of final output RCPass

  • can get SceneColor and SceneDepth from RHICmdList???


  • holds ptrs/refs of RHICmdList, FViewInfo, render rect, view state

  • the owner of a RenderingCompositionGraph

  • holds ptr of a RCPass which is set to be the root of the graph after processed

  • Process() takes a pointer to an array of RC passes

    • calls its RC graph’s RecursiveProcess(), which sets its RCPass member to be the root (no dependency), then recursively call RCPass->Proce


  • The CompositeContext is created first

  • The PostprocessContext is created using a ref of CompositeContext.Graph

  • create and register psses to the graph

  • set input of each pass; don’t need to set output, its set from the FRCPass’s Process() method

  • set the context’s FinalOutput

  • CompositeContext.process()


  • Contains a TArray of FRenderingCompositePass as Nodes

  • To register a pass is to add them in the Nodes array


  • An interface class, to allow interactions from the graph, context etc

  • to be implemented as an input/output pass or a pass with specific I/O and Process() and Release() etc methods


  • A template implementation for FRenderingCompositePass, with InputCount and OutputCount as template arguments

  • has FRenderingCompositeOutputRef[] as PassInputs

  • has FRenderingCompositeOutput[] as PassOutputs


  • An implementation of TRenderingCompositePass with 0 input and 1 output

  • An IPooledRenderTarget is the Data

  • Process()

    • PassOutputs[0].PooledRenderTarget = Data;

  • The purpose of this pass is to get a reference to an external render target to be accessed from the subsequent nodes. No draw call is submitted here.


  • An implementation of TRenderingCompositePass with 1 input and 1 output

  • An IPooledRenderTarget as ExternalRenderTarget

  • Process() does passthrough and set the external render target

    • Input is ePId_Input0

    • Passing the input’s output render target to the its ExternalRenderTarget (overwritting the content of this pointer).

  • The purpose of this node is to set set the value of an external render target. No draw call is submitted here.

 // in FRCPassPostProcessOutput::Process()
 PassOutputs[0].PooledRenderTarget = Input->GetOutput()->PooledRenderTarget;
 *ExternalRenderTarget = PassOutputs[0].PooledRenderTarget;


  • a struct containing an IPooledRenderTarget and its dependency count

  • RequestSurface() is the function to transit current render target / get free render target from the pool.

 const FSceneRenderTargetItem& FRenderingCompositeOutput::RequestSurface(const FRenderingCompositePassContext& Context)
         Context.RHICmdList.TransitionResource(EResourceTransitionAccess::EWritable, PooledRenderTarget->GetRenderTargetItem().TargetableTexture);
         return PooledRenderTarget->GetRenderTargetItem();
         // useful to use the CompositingGraph dependency resolve but pass the data between nodes differently
         static FSceneRenderTargetItem Null;
         return Null;
         GRenderTargetPool.FindFreeElement(Context.RHICmdList, RenderTargetDesc, PooledRenderTarget, RenderTargetDesc.DebugName);
     FSceneRenderTargetItem& RenderTargetItem = PooledRenderTarget->GetRenderTargetItem();
     return RenderTargetItem;


  • a structure holding a ptr of a FRCPass as the Source and its id

  • GetOutput() returns the Source->GetOutput()


  • Encapsulates the render targets used for scene rendering

ESceneColorFormatType and CurrentShadingPath

  • EShadingPath::Mobile -> ESceneColorFormatType::Moble

  • EShadingPath::Deferred && require alpha -> ESceneColorFormatType::HighEndWithAlpha

  • EShadingPath::Deferred && not require alpha -> ESceneColorFormatType::HighEnd


 Renderer/Private/SystemTextures.h` `Renderer/Private/SystemTextures.cpp
  • a global FSystemTextures, holding a bunch of IPooledRenderTarget.


  • holds an FSceneRenderTargetItem

  • For the IPooledRenderTargets in a FSystemTextures, see FSystemTextures::InitializeCommonTextures()


  • Single render target item consists of a render surface and its resolve texture, Render thread side

  • containing FTextureRHIRef (render target or resolve target) with mip refs FShaderResourceViewRHIRef array

FTextureRHIRef / TRefCountPtr

FShaderResourceViewRHIRef / TRefCountPtr



To get a full dump of the post processing graph:

  • r.CompositionGraphDebug can log the graph into the console

To turn off effects on the deferred pipeline:

  • use global post processing volume

  • turn on/off the post process effects from the voulme, eg TAA

  • or set intensity of the effect to zero, eg SSR

  • the engine will skip related render passes


  • A template class, creating a smart pointer of the object (ReferencedType)

  • When creating an instance of this class, the ReferecedType will call the its AddRef() method; when deleting an instance, the ReferencedType will call its Release() method.

Connecting the result of PostProcessing to View.Family->RenderTarget

Suppose that FRCPassPostProcessUpscale is the last node in the RCGraph. In FPostProcessing::Process():

 FRenderingCompositePass* Node =
     Context.Graph.RegisterPass(new(FMemStack::Get()) FRCPassPostProcessUpscale(View, UpscaleQuality, PaniniConfig));
 // Node->SetInput...
 // ...
 Context.FinalOutput = FRenderingCompositeOutputRef(Node);

In FRCPassPostProcessUpscale, RequestSurface() is called, meaning that a render target resource is allocated. But the node is not further connected to a FRCPassPostProcessOutput. The RT resource is passed outside the PostProcessing context to View.Family->RenderTarget using the following setup:

 TRefCountPtr<IPooledRenderTarget> Temp;
 FSceneRenderTargetItem Item;
 Item.TargetableTexture = (FTextureRHIRef&)View.Family->RenderTarget->GetRenderTargetTexture();
 Item.ShaderResourceTexture = (FTextureRHIRef&)View.Family->RenderTarget->GetRenderTargetTexture();
 // settings...
 FPooledRenderTargetDesc Desc;
 // ...
 Desc.DebugName = TEXT("FinalPostProcessColor");
 // ...
 // creating a temp RenderTargetItem who holds the View.Family->RenderTarget's ref on frame
 GRenderTargetPool.CreateUntrackedElement(Desc, Temp, Item);
 // Overwrite UpscalePass's output's PooledRenderTarget and RTDesc
 // This essentially set the View.Family->RenderTarget's texture to refer to the Upscale pass's render target resource
 // Might be able to achieve the same
 // using an FRCPassPostProcessOutput which holds the View.Family->RenderTarget as external RT. Not sure.
 OverrideRenderTarget(Context.FinalOutput, Temp, Desc);
 TArray<FRenderingCompositePass*> TargetedRoots;
 // add other roots...
 // execute the graph/DAG
 // "roots" are actually the end-points in the graph.
 CompositeContext.Process(TargetedRoots, TEXT("PostProcessing"));

Post-process Quality

The View -> Engine Scalability Settings -> Post Processing option adjusts the quality of the Post Processing effects in accordance with the settings found in the BaseScalaiblity.ini file located in [UE4_InstallPath]/Engine/Config folder. With the Low setting equating to sg.ShadowQuality 0 and Epic to sg.ShadowQuality 3.


FRCPass RT extent resizing

Resize in FRCPass::ComputeOutputDesc()

BokehDOFSetup pass

Output extent area is 1/4 of ePId_Input0 (usually the SceneColor).

 FPooledRenderTargetDesc FRCPassPostProcessBokehDOFSetup::ComputeOutputDesc(EPassOutputId InPassOutputId) const
     FPooledRenderTargetDesc Ret = GetInput(ePId_Input0)->GetOutput()->RenderTargetDesc;
     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.DebugName = TEXT("BokehDOFSetup");
     Ret.TargetableFlags &= ~(TexCreate_RenderTargetable | TexCreate_UAV);
     Ret.TargetableFlags |= bIsComputePass ? TexCreate_UAV : TexCreate_RenderTargetable;
     Ret.Flags |= GFastVRamConfig.BokehDOF;
     return Ret;
 // In FRCPassPostProcessBokehDOFSetup::Process()
 FIntPoint SrcSize = InputDesc->Extent;
 FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent;
 // Use these sizes to calculate Rect used in DrawClearQuad() and DrawPostProcessPass()
 // ...

Composition graph debug, showing the change in RT size.

 Node#0 'SceneColorSubsurface'
    ePId_Output0 (2D 1008x492 PF_FloatRGBA RT) SceneColorSubsurface Dep: 3
 Node#4 'BokehDOFSetup'
    ePId_Input0: Node#0 @ ePId_Output0 'SceneColorSubsurface'
    ePId_Input1: Node#1 @ ePId_Output0 'SceneDepthZ'
    ePId_Output0 (2D 504x246 PF_FloatRGBA RT VRam) BokehDOFSetup Dep: 1

Upscale pass

The View.Family->RenderTarget’s extent is used to set a property OutputExtent. View family RT’s extent is the viewport resolution.

 // FRCPassPostProcessUpscale::FRCPassPostProcessUpscale()
 OutputExtent.X = InView.Family->RenderTarget->GetRenderTargetTexture()->GetSizeX();
 OutputExtent.Y = InView.Family->RenderTarget->GetRenderTargetTexture()->GetSizeY();

The property is then used in ComputeOutputDesc:

 // FRCPassPostProcessUpscale::ComputeOutputDesc()
 FPooledRenderTargetDesc Ret = GetInput(ePId_Input0)->GetOutput()->RenderTargetDesc;
 Ret.DebugName = TEXT("Upscale");
 Ret.Extent = OutputExtent;
 Ret.Flags |= GFastVRamConfig.Upscale;
 return Ret;


电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.