UE4 后期处理 PostProcess

UE4 后期处理 PostProcess

https://zhuanlan.zhihu.com/p/32593741

在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<class T>
T* RegisterPass(T* InPass)
{
check(InPass);
Nodes.Add(InPass);
return InPass;
}
//pass节点列表
TArray<FRenderingCompositePass*> 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);

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值