URP DepthPrepass探索 & Shader不显示问题分析

由问题“URP 下通过右键菜单创建的 Shader 不显示任何内容”发散而来,引申出对 URP DepthPrepass 的讨论。

上述问题原因

URP 默认 Pipeline 下,渲染不透明物体前,如有下述情况之一,会执行深度写入 Pass:

  • RenderFeature需要Depth Texture/Normal Texture
  • 相机选中DepthTexture(强制开启或 Pipeline Asset 勾选 DepthTexture)
  • DepthPrimingMode && Forward Rendering && RenderType Base && CameraType != Reflection

Unity 把这个过程叫做 DepthPrepass。

接下来,渲染不透明物体时:

  • 未开启Depth Priming Mode
    • 如果没有特别声明,采用ZTest LessEqual的方式剔除片元
    • 不利用 Depth Texture
  • 开启Depth Priming Mode
    • 默认使用ZTest Equal,结合Depth Texture来剔除片元
    • 对不透明队列 Overdraw 的优化

如果不透明物体的 Shader 不包含 DepthPrepass 指定的 Pass,那 Prepass 不会写入当前物体的深度。

由于没有写深度,DepthPrimingMode下片元深度始终不 Equal 深度图,片元自然就被剔除了。

新版 URP 默认勾选了DepthPrimingMode,因此右键创建的 Shader 文件渲染不显示任何内容。

指定的 Pass 及调用时机

URP 默认 Pipeline 下,使用 Pass Tag 名硬编码了两组 Pass:

  • DepthOnlyPass: DepthOnly
  • DepthNormalOnlyPass: DepthNormals/DepthNormalsOnly

默认 Pipeline 中,选择 DepthOnlyPass 还是 DepthNormalOnlyPass 的逻辑如下:

if(requiresDepthPrepass)
{
    if(renderPassInputs.requiresNormalsTexture)
    {
        if(this.actualRenderingMode == RenderingMode.Deferred)
        {
            //其他内容略...
            m_DepthNormalPrepass.Setup(xxx);
        }else
        {
            m_DepthNormalPrepass.Setup(xxx);
        }
        EnqueuePass(m_DepthNormalPrepass);
    }else
    {
        if(this.actualRenderingMode != RenderingMode.Deferred)
        {
            m_DepthPrepass.Setup(xxx);
            EnqueuePass(m_DepthPrepass);
        }
    }
}

根据 URP 源码可知,当 RenderFeature(如 SSAO)启用了 Normal 时,会执行 DepthNormalOnlyPass,否则执行 DepthOnlyPass。

有什么用

上面已经说到了,该举是为了优化不透明队列的 OverDraw 问题。

虽然我们期望不透明队列从前往后渲染,但这个排序是对 Mesh 的大致排序,而不是针对图片或片元的排序(CPU 端不可能去逐图元或片元处理),OverDraw 总会存在。

使用 ZTest Equal 结合深度图,不透明队列的 Overdraw 会得到明显优化。

开头问题的解决方法

无所谓做法

关掉Depth Priming Mode,反正Depth Priming Mode + MSAA在 TBR GPU 上的收益不一定大。

稳妥的方法

不透明物体老老实实补全相关的 Pass,深度 Pass 只为写深度,内容不要太复杂。

如果没有顶点或片元位移,照搬 URP Lit 的 Pass 就行。

梓喵出没博客(azimiao.com)版权所有,转载请注明链接:https://www.azimiao.com/10070.html
欢迎加入梓喵出没博客交流群:313732000

我来吐槽

*

*