Unity6 自定义渲染管线--RenderGraph 基础流程

2 阅读3分钟

www.bilibili.com/video/BV1px…

RenderGraph 基础流程

基础知识

原则:

  1. 不再直接处理资源,而是使用 RenderGraph 特定句柄,所有 RenderGraph API 都使用这些句柄操作资源。RenderGraph 管理的资源类型是 RTHandles、ComputeBuffers 和 RendererLists;
  2. 实际资源引用只能在 RenderPass 的执行代码中访问;该框架需要显示声明 RenderPass。每个 RenderPass 必须声明它的读取/写入哪些资源;RenderGraph 每次执行之间不存在持久性。这意味着你的 RenderGraph 的一次执行中创建的资源无法延续到下一次执行;对于需要持久性的资源(例如从一帧到另一帧),你可以在 RenderGraph 之外创建他们,然后将他们导入。在依赖项跟踪方面,他们的行为与任何其他 RenderGraph 资源类型类似,但 RenderGraph 不处理他们的生命周期;
  3. RenderGraph 主要用 RTHandles 纹理资源。这对于如何编写着色器代码以及如何设置他们有很多影响。

基本流程

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.RenderGraphModule;

namespace LiteRP
{
    public class LiteRenderPipeline : RenderPipeline
    {
        private readonly static ShaderTagId s_ShaderTagId = new ShaderTagId("SRPDefaultUnlit");

        private RenderGraph m_RenderGraph = null;  // 渲染图

        public LiteRenderPipeline()
        {
            InitializeRenderGraph();
        }

        protected override void Dispose(bool disposing)
        {
            CleanupRenderGraph();
            base.Dispose(disposing);
        }

        // 初始化渲染图
        private void InitializeRenderGraph()
        {
            m_RenderGraph = new RenderGraph("LiteRPRenderGraph");
        }

        private void CleanupRenderGraph()
        {
            m_RenderGraph?.Cleanup();
            m_RenderGraph = null;
        }

        protected override void Render(ScriptableRenderContext context, List<Camera> cameras)
        {
            // 开始渲染上下文
            BeginContextRendering(context, cameras);

            // 渲染相机
            for (int i = 0; i < cameras.Count; ++i)
            {
                Camera camera = cameras[i];
                RenderCamera(context, camera);
            }

            // 结束渲染上下文
            EndContextRendering(context, cameras);
        }

        private void RenderCamera(ScriptableRenderContext context, Camera camera)
        {
            // 开始渲染相机
            BeginCameraRendering(context, camera);

            // 获取相机剔除参数, 并进行剔除
            ScriptableCullingParameters cullingParameters;
            if (!camera.TryGetCullingParameters(out cullingParameters))
                return;
            CullingResults cullingResults = context.Cull(ref cullingParameters);

            // 为相机创建 CommandBuffer
            CommandBuffer cmd = CommandBufferPool.Get(camera.name);
            // 设置相机属性参数
            context.SetupCameraProperties(camera);

            
            
            // 提交命令缓冲区
            context.ExecuteCommandBuffer(cmd);
            // 释放命令缓冲区
            cmd.Clear();
            CommandBufferPool.Release(cmd);
            // 提交渲染上下文
            context.Submit();
            // 结束渲染相机
            EndCameraRendering(context, camera);
        }
    }
}

RenderGraph 时间线

  • 录制时间线
    • 声明输入和输出
    • 声明特殊标志(全局修改、传递剔除等)
    • 设置 Render 函数
    • 设置 Pass Data 以允许将外部参数传递到显示代码
  • 执行时间线
    • 根据最终的依赖项图,它不能保证运行,因为它可以被剔除
    • 读取在录制阶段设置的传递数据
    • 通过录制图形命令来呈现代码
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.RenderGraphModule;

namespace LiteRP
{
    public class LiteRenderPipeline : RenderPipeline
    {
        private readonly static ShaderTagId s_ShaderTagId = new ShaderTagId("SRPDefaultUnlit");

        private RenderGraph m_RenderGraph = null;  // 渲染图
        private LiteRenderGraphRecorder m_LiteRenderGraphRecorder = null;  // 渲染图记录器
        private ContextContainer m_ContextContainer = new ContextContainer();  // 上下文容器

        public LiteRenderPipeline()
        {
            InitializeRenderGraph();
        }

        protected override void Dispose(bool disposing)
        {
            CleanupRenderGraph();
            base.Dispose(disposing);
        }

        // 初始化渲染图
        private void InitializeRenderGraph()
        {
            m_RenderGraph = new RenderGraph("LiteRPRenderGraph");
            m_LiteRenderGraphRecorder = new LiteRenderGraphRecorder();
            m_ContextContainer = new ContextContainer();
        }

        private void CleanupRenderGraph()
        {
            m_ContextContainer?.Dispose();
            m_ContextContainer = null;
            m_LiteRenderGraphRecorder = null;
            m_RenderGraph?.Cleanup();
            m_RenderGraph = null;
        }

        protected override void Render(ScriptableRenderContext context, List<Camera> cameras)
        {
            // 开始渲染上下文
            BeginContextRendering(context, cameras);

            // 渲染相机
            for (int i = 0; i < cameras.Count; ++i)
            {
                Camera camera = cameras[i];
                RenderCamera(context, camera);
            }
            // 结束渲染图
            m_RenderGraph.EndFrame();
            // 结束渲染上下文
            EndContextRendering(context, cameras);
        }

        private void RenderCamera(ScriptableRenderContext context, Camera camera)
        {
            // 开始渲染相机
            BeginCameraRendering(context, camera);

            // 准备 FrameData
            if (!PrepareFrameData(context, camera))
                return;
            // 获取相机剔除参数, 并进行剔除
            ScriptableCullingParameters cullingParameters;
            if (!camera.TryGetCullingParameters(out cullingParameters))
                return;
            CullingResults cullingResults = context.Cull(ref cullingParameters);

            // 为相机创建 CommandBuffer
            CommandBuffer cmd = CommandBufferPool.Get(camera.name);
            // 设置相机属性参数
            context.SetupCameraProperties(camera);
            // 记录并执行渲染图
            RecordAndExecuteRenderGraph(context, camera, cmd);
            
            // 提交命令缓冲区
            context.ExecuteCommandBuffer(cmd);
            // 释放命令缓冲区
            cmd.Clear();
            CommandBufferPool.Release(cmd);
            // 提交渲染上下文
            context.Submit();
            // 结束渲染相机
            EndCameraRendering(context, camera);
        }

        private bool PrepareFrameData(ScriptableRenderContext context, Camera camera)
        {
            return true;
        }

        private void RecordAndExecuteRenderGraph(ScriptableRenderContext context, Camera camera, CommandBuffer cmd)
        {
            RenderGraphParameters renderGraphParameters = new RenderGraphParameters()
            {
                executionName = camera.name,
                commandBuffer = cmd,
                scriptableRenderContext = context,
                currentFrameIndex = Time.frameCount
            };

            m_RenderGraph.BeginRecording(renderGraphParameters);
            // 开启记录线
            m_LiteRenderGraphRecorder.RecordRenderGraph(m_RenderGraph, m_ContextContainer);
            m_RenderGraph.EndRecordingAndExecute();
        }
    }
}

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.RenderGraphModule;

namespace LiteRP
{
    public class LiteRenderGraphRecorder : IRenderGraphRecorder
    {
        public void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
        {
            throw new System.NotImplementedException();
        }
    }
}