赞
踩
在GDC2014上,UE4就提出了它移动端后期处理管线设计(参考Next_Generation_Mobile_Rendering 文章)
流程大致是
降低分辨率(Smart Reduction)(在各个Pass里处理,没有直接降低RT分辨率)->
景深(Depth of Field) (可有可无) ->
模糊(Bloom)->
光轴(LightShaft)->
混合(Vignette +Bloom + Light Shafts)->
色调映射(Tonemapping)->
抗锯齿(Anti-Aliasing)
移动端后期处理
代码在FPostProcessing::ProcessES2中
先定义了2个上下文
FRenderingCompositePassContext CompositeContext(RHICmdList, View);
FPostprocessContext Context(RHICmdList, CompositeContext.Graph, View);
CompositeContext其实其中有个后期处理Pass列表,把需要做的后期处理全部缓存在其中,然后一起运行(Processs)
FRenderingCompositePass 最基础Pass的基类
virtual const FRenderingCompositeOutputRef* GetInput(EPassInputId InPassInputId) const = 0;
virtual void SetInput(EPassInputId InPassInputId, const FRenderingCompositeOutputRef& InOutputRef) = 0;
virtual void Process(FRenderingCompositePassContext& Context) = 0;
包含Input 对象是个FRenderingCompositeOutputRef
类型,也就是其他Pass 渲染完输出的结果可以作为Input传入,在此基础上绘制
真正的Pass列表是FRenderingCompositionGraph
//注册Pass
template
T* RegisterPass(T* InPass)
{
check(InPass);
Nodes.Add(InPass);
return InPass;
}
//pass节点列表
TArray Nodes;
//迭代运行pass
void RecursivelyProcess(const FRenderingCompositeOutputRef& InOutputRef, FRenderingCompositePassContext& Context)const;
最终会执行到RecursivelyProcess方法
后面代码就是加入各种Pass加入后期自定义材质Pass
AddPostProcessMaterial(Context, BL_BeforeTranslucency, nullptr);
AddPostProcessMaterial(Context, BL_BeforeTonemapping, nullptr);
加入BloomSetUp Pass
FRenderingCompositePass* Pass= Context.Graph.RegisterPass(new(FMemStack::Get()) FRCPassPostProcessBloomSetupES2(FinalOutputViewRect, bViewRectSource));
Pass->SetInput(ePId_Input0, Context.FinalOutput);
PostProcessBloomSetup = FRenderingCompositeOutputRef(Pass);加入DOF Pass
加入7个Bloom Pass
注意每个Bloom Pass 传入的Input不一样,窗口大小(ViewportSize)也不一样
// Downsample by 2
{
FRenderingCompositePass* Pass = Context.Graph.RegisterPass(new(FMemStack::Get()) FRCPassPostProcessBloomDownES2(PrePostSourceViewportSize/4,DownScale));
Pass->SetInput(ePId_Input0, PostProcessBloomSetup);
PostProcessDownsample2 = FRenderingCompositeOutputRef(Pass);
}
// Downsample by 2
{
FRenderingCompositePass* Pass = Context.Graph.RegisterPass(new(FMemStack::Get()) FRCPassPostProcessBloomDownES2(PrePostSourceViewportSize/8, DownScale));
//使用前一个Pass
Pass->SetInput(ePId_Input0, PostProcessDownsample2);
PostProcessDownsample3 = FRenderingCompositeOutputRef(Pass);
}
加入LightShaft Pass
加入separate translucency
如果启用了SeparateTranslucency加入 SeparateTranslucency Pass
if (IsMobileSeparateTranslucencyActive(Context.View))
{
FRCSeparateTranslucensyPassES2* Pass = (FRCSeparateTranslucensyPassES2*)Context.Graph.RegisterPass(new(FMemStack::Get()) FRCSeparateTranslucensyPassES2());
Pass->SetInput(ePId_Input0, Context.FinalOutput);
Context.FinalOutput = FRenderingCompositeOutputRef(Pass);
}
加入Tonemap Pass
加入AA Pass
根据DebugViewShaderMode 类型 加入对应的Pass最后执行Pass 也就是执行RecursivelyProcess
GRenderTargetPool.CreateUntrackedElement(Desc, Temp, Item);
OverrideRenderTarget(Context.FinalOutput, Temp, Desc);
CompositeContext.Process(Context.FinalOutput.GetPass(), TEXT("PostProcessingES2"));
Pass降低分辨率方法
通过DrawRectangle设置Dst大小是Src大小 的1/4,通过降低绘制分辨率,提高性能
void FRCPassPostProcessBloomSetupES2::Process(FRenderingCompositePassContext& Context)
{
//目标是PrePostSourceViewportSize大小的一半
uint32 DstX = FMath::Max(1, PrePostSourceViewportSize.X/2);
uint32 DstY = FMath::Max(1, PrePostSourceViewportSize.Y/2);
FIntRect DstRect;
DstRect.Min.X = 0;
DstRect.Min.Y = 0;
DstRect.Max.X = DstX;
DstRect.Max.Y = DstY;
FIntPoint DstSize = PrePostSourceViewportSize / 2;
FIntPoint SrcSize;
FIntRect SrcRect;
if(bUseViewRectSource)
{
// Mobile with framebuffer fetch uses view rect as source.
const FSceneView& View = Context.View;
SrcSize = InputDesc->Extent;
// SrcRect 就是原先大小
SrcRect = PrePostSourceViewportRect;
}
…
//通过DrawRectangle缩放
DrawRectangle(
Context.RHICmdList,
0,
0,
DstX, DstY,
SrcRect.Min.X, SrcRect.Min.Y,
SrcRect.Width(), SrcRect.Height(),
DstSize,
SrcSize,
*VertexShader,
EDRF_UseTriangleOptimization);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。