URP源码学习(六)后处理

7 篇文章 2 订阅

URP把后处理分成了两个pass,finalPass只在相机抗锯齿模式为FastApproximateAntialiasing时调用。

开启条件,在ForwardRenderer判断

  • lastCameraInTheSatck。
    • 这名字有误导性,取的值是RenderingData的resolveFinalTarget,而resolveFinalTarget是在InitializeRenderingData函数设置的,取的值是requiresBlitToBackbuffer,InitializeRenderingData被RenderSingleCamera调用。requiresBlitToBackbuffer会在scene相机渲染,以及stack的最后一个相机设为true。
    • 这个参数的真正意义,我的理解是表示这个相机是否要渲染到屏幕上,如果要渲染到屏幕,再去判断相机是否开启后处理。
    • 后处理已经把画面渲染到屏幕上了,所以finalBlitPass不需要执行。
bool applyFinalPostProcessing = anyPostProcessing && lastCameraInTheStack &&renderingData.cameraData.antialiasing == AntialiasingMode.FastApproximateAntialiasing; 
  • applyFinalPostProcessing:
    • 为true的条件,相机开启后处理,并且lastCameraInTheStack为true、抗锯齿模式为FastApproximateAntialiasing。
  • applyPostProcessing:
    • 只要相机开启后处理就为true。
    • 如果lastCameraInTheStack为true,会设置渲染目标rt,并设置是否需要对sRGB做转换。

PostProcessPass,驱动各个后处理shader

数据

  • MaterialLibrary:定义实现各个效果的material。
  • PostProcessData:ScriptableObject,配置shader和贴图。在editor可以创建ScriptableObject的实例,但是并不能编辑shader,可能是个未开发完的功能。
  • ShaderConstants:缓存shader名字对应的id。

RenderFinalPass,渲染final pass

var material = m_Materials.finalPass; 

获取material,用于后续渲染。

if (cameraData.antialiasing == AntialiasingMode.FastApproximateAntialiasing)     
    material.EnableKeyword(ShaderKeywordStrings.Fxaa); 

逻辑上来说判断抗锯齿模式是多余的,只有fxaa才会用这个分支渲染。

SetupGrain(cameraData, material); 
SetupDithering(cameraData, material); 

如果对应效果开启,设置shader关键字或贴图,shader用的是finalPass。这俩并不对应具体的shader。

Render函数

Render函数里有个有趣的写法,int GetSource() => source;类似这种,在函数内定义函数。

这个函数按顺序渲染各个后处理效果,简单看下流程。

cmd.Blit(GetSource(), BlitDstDiscardContent(cmd, GetDestination()), m_Materials.stopNaN); 
  • 最先渲染的是一个特殊的NaNshader,可选的,作用是将不合法的颜色值用自定义的颜色输出,应该是调试用的,判断颜色是否合法的代码在CoreRP的Common.hlsl文件。
DoSubpixelMorphologicalAntialiasing(ref cameraData, cmd, GetSource(), GetDestination()); 
  • 处理SubpixelMorphological模式的抗锯齿,消耗较大,移动平台使用要看情况。
DoDepthOfField(cameraData.camera, cmd, GetSource(), GetDestination(), cameraData.pixelRect); 
  • 对scene camera不开启。Gaussian和Bokeh两种模式
DoMotionBlur(cameraData.camera, cmd, GetSource(), GetDestination()); 
  • 对scene camera不开启。是相机的运动模糊,物体运动是没有效果的。
DoPaniniProjection(cameraData.camera, cmd, GetSource(), GetDestination()); 
  • 对scene camera不开启。帕尼尼投影,一种圆柱形投影,效果是扭曲两侧,突出中间,在渲染大视角的时候提供更好的效果。

后面的都和UberPost shader相关

void SetupBloom(CommandBuffer cmd, int source, Material uberMaterial) 
  • 先按分辨率大小计算模糊次数,每次水平竖直分别模糊,没吃降低一倍分辨率,然后在执行Upsample,完成bloom。
  • 设置bloom相关参数和贴图到UberPost shader。设置lens dirtiness相关参数到uber。
SetupLensDistortion(m_Materials.uber, cameraData.isSceneViewCamera); 
  • 镜头扭曲效果,设置uber shader的参数。
SetupChromaticAberration(m_Materials.uber); 
  • 比较高性能的色差效果。
SetupVignette(m_Materials.uber); 
  • 图像边缘的色调变暗,突出中间部分。
SetupColorGrading(cmd, ref renderingData, m_Materials.uber); 
  • 改变或矫正最终图像的颜色和亮度,处理lut、hdr、tonemapping
SetupGrain(cameraData, m_Materials.uber); 
SetupDithering(cameraData, m_Materials.uber); 
  • 在不是final pass的情况下执行。
cmd.SetGlobalTexture("_BlitTex", GetSource()); 
  • rt设置给_BlitTex。
cmd.SetRenderTarget(cameraTarget, colorLoadAction, RenderBufferStoreAction.Store, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.DontCare); 
  • 设置rt为相机,完成渲染。

这些常见的后处理效果,都有比较成熟的算法,具体逻辑就不细看了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值