• URP(Universal Render Pipeline)渲染管线在使用中的一些分享


    本篇文章整理了URP管线使用中的一些简单的心得记述

    1.使用ScriptableRendererFeature自定义渲染特性

    在内建(Build-in)管线中可以使用CommandBuffer并添加到摄像机上来实现自定义的特性。在URP管线中,处理方法变成了RendererFeature

    RendererFeature不需要绑定到相机;而是挂载到渲染器(如ForwardRenderer)的设置里。

    在Project面板点击右键Create/Rendering/Universal Render Pipeline/Renderer Feature可以创建Renderer Feature模板。

    模板中Feature带有一个CustomRenderPass的嵌套类;并且在AddRenderPasses函数中被添加进pass队列。

    ScriptableRenderPass可以指定需要的渲染步骤,如:

    m_ScriptablePass.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;

    由于一个效果往往需要多个pass不同阶段处理;这样的方式显然比较友好。

    在之前内建的渲染管线中;CommandBuffer只能执行预先设定好的一些步骤,这样多少有些不方便。在自定义管线中CommandBuffer变成了立即执行,

    现在可以在ScriptableRenderPass中直接通过context来立即执行CommandBuffer:

    public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    {
        CommandBuffer cmd = CommandBufferPool.Get("MyCommandBuffer");
        //CommandBuffer的操作
        context.ExecuteCommandBuffer(cmd);
    
        CommandBufferPool.Release(cmd);
    }

    此外,标记Profiling后,可在FrameDebugger中直接查看标记Profiling的对象:

    {
        ProfilingSampler mProfilingSampler = new ProfilingSampler("Test1");
        CommandBuffer cmd = CommandBufferPool.Get("Test1 Cmd");
        using (new ProfilingScope(cmd, mProfilingSampler))
        {
            MeshRenderer meshRenderer = Resources.Load<MeshRenderer>("TestModel");
            cmd.DrawRenderer(meshRenderer, meshRenderer.sharedMaterial);
            context.ExecuteCommandBuffer(cmd);
            CommandBufferPool.Release(cmd);
        }
    }

    而打开了管线设置中的Debug Level后;可以通过这个参数看见更多的调试信息

    如UniversalRenderPipeline.cs的RenderSingleCamera方法里:

    static void RenderSingleCamera(...)
    {
    ...
    asset.debugLevel >= PipelineDebugLevel.Profiling ? ...

    这段代码在勾选这个设置后可以在FrameDebugger内显示不同的相机名。

    2.使用DrawRenderers进行大批量绘制

    在内建管线中,通常使用CommandBuffer.DrawRenderer来绘制一些指定的对象,

    不过绘制对象一多这样做就不太方便。

    在URP的自定义pass中可以使用ScriptableRenderContext上下文里的DrawRenderers接口进行批量绘制,

    它可以拿到当前相机的剔除结果(CullingResults),通过FilteringSettings参数再进行一次过滤。

    FilteringSettings里还可以设置renderingLayerMask,renderingLayerMask可在MeshRenderer、SkinnedMeshRenderer

    等渲染器组件中设置,独立于旧的Layer。

    借助传入的DrawingSettings,RenderStateBlock参数可指定是否写入Stencil、是否写深度等信息,最终完成绘制,如:

    context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref m_FilteringSettings,
        ref m_RenderStateBlock);

    如果要绘制的内容第一次相机剔除时没有,也可以再进行一次相机剔除:

    context.Cull(...)

    使用新的结果来绘制。

    以前抓取uGUI的绘制内容较为困难,现在也可以用这种办法把UI分成几部分绘制,并且控制每一部分是否写入指定RT了,

    并且还可以通过自定义的Feature和context.DrawRenderers把UI绘制的步骤单独挪出来自行控制(但是Stencil会丢掉,酌情使用)。

    还可以先修改RenderTarget再执行context.DrawRenderers绘制,这样就可以把内容批量绘制到指定RT上:

    public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    {
        CommandBuffer cmd = CommandBufferPool.Get("tempRt");
        int tmpRt = Shader.PropertyToID("_TempRt");
        cmd.GetTemporaryRT(tmpRt, mDesc);
        cmd.SetRenderTarget(tmpRt);
        context.ExecuteCommandBuffer(cmd);
        
        context.DrawRenderers(...);
        
        CommandBufferPool.Release(cmd);
    }

    (这里的RenderTexture应该在Configure中绑定)

    注意,内建管线中使用CommandBuffer时可以直接填写-1、-2等宽高参数获得1/2,1/3等大小的RenderTexture,在自定义管线中

    不再可用。

    更多的绘制方法可以参考Render Objects(Runtime/RendererFeatures/RenderObjects.cs)或

    DrawObjectsPass.cs(Runtime/Passes/DrawObjectsPass.cs)的做法。

    3.相较内建管线的优化

    在URP中单个对象支持的最大灯光数量是8盏;光照处理的操作在一个pass中完成。

    虽然有数量限制;但这样整个场景的Batches数量得到了控制,这一点体现较为明显。

    而阴影方面目前只能支持主光源平行光的阴影和聚光灯的阴影(v7.3.1)。

    其次就是SRP Batches等技术,这方面暂未深入了解。

  • 相关阅读:
    [PA2014]Muzeum
    [TJOI2015]概率论
    To Do List
    【洛谷4172】 [WC2006]水管局长(LCT)
    HNOI2019退役记
    hdu 2159 FATE
    USACO 2019 January Contest, Platinum 题解
    luogu4774 [NOI2018]屠龙勇士
    NOI 2019游记
    loj #3145. 「APIO 2019」桥梁
  • 原文地址:https://www.cnblogs.com/hont/p/14221019.html
Copyright © 2020-2023  润新知