Unity自定义渲染管线(Scriptable Render Pipeline)架构设计与实现指南

一、SRP技术体系概述

1. 核心设计理念

  • 全托管渲染控制:通过C#脚本完全掌控渲染流程

  • 模块化架构:将渲染流程拆分为可组合的RenderPass

  • GPU友好设计:支持CommandBuffer与Compute Shader混合编程

  • 对惹,这里有一个游戏开发交流小组,希望大家可以点击进来一起交流一下开发经验呀

2. 与传统管线对比

特性内置管线SRP
流程控制黑盒模式全脚本可编程
渲染策略固定前向/延迟自由组合多Pass
性能优化有限批处理深度控制资源生命周期
跨平台支持自动适配需手动实现变体

二、核心架构设计

1. 分层架构图

graph TB
    A[SRP Asset] -->|配置参数| B[RenderPipeline]
    B -->|调度| C[CameraRenderer]
    C -->|组织| D[RenderPass]
    D -->|执行| E[CommandBuffer]
    E -->|提交| F[GPU]

2. 核心组件职责

  • SRP Asset:管线全局配置(质量等级、Shader变体等)

  • RenderPipeline:主入口类,负责每帧调度

  • CameraRenderer:单相机渲染流程控制器

  • RenderPass:最小渲染单元(如阴影Pass、光照Pass)


三、基础管线实现

1. SRP Asset创建

[CreateAssetMenu(menuName = "Rendering/Custom RP")]
public class CustomRenderPipelineAsset : RenderPipelineAsset {
    public bool useDynamicBatching = true;
    public bool useGPUInstancing = true;
    
    protected override RenderPipeline CreatePipeline() {
        return new CustomRenderPipeline(this);
    }
}

2. 主渲染管线类

public class CustomRenderPipeline : RenderPipeline {
    private CameraRenderer renderer = new CameraRenderer();
    private bool useDynamicBatching;
    private bool useGPUInstancing;

    public CustomRenderPipeline(CustomRenderPipelineAsset asset) {
        useDynamicBatching = asset.useDynamicBatching;
        useGPUInstancing = asset.useGPUInstancing;
    }

    protected override void Render(
        ScriptableRenderContext context, 
        Camera[] cameras
    ) {
        foreach (var camera in cameras) {
            renderer.Render(context, camera, useDynamicBatching, useGPUInstancing);
        }
    }
}

3. 相机渲染器

public class CameraRenderer {
    static ShaderTagId unlitShaderTagId = new ShaderTagId("SRPDefaultUnlit");
    
    public void Render(
        ScriptableRenderContext context, 
        Camera camera,
        bool useDynamicBatching,
        bool useGPUInstancing
    ) {
        // 设置相机矩阵
        context.SetupCameraProperties(camera);
        
        // 清除渲染目标
        var cmd = new CommandBuffer { name = camera.name };
        cmd.ClearRenderTarget(true, true, Color.clear);
        context.ExecuteCommandBuffer(cmd);
        cmd.Clear();
        
        // 物体排序与绘制
        var sortingSettings = new SortingSettings(camera) {
            criteria = SortingCriteria.CommonOpaque
        };
        var drawingSettings = new DrawingSettings(
            unlitShaderTagId, 
            sortingSettings
        ) {
            enableDynamicBatching = useDynamicBatching,
            enableInstancing = useGPUInstancing
        };
        
        // 执行绘制
        var filterSettings = new FilteringSettings(RenderQueueRange.opaque);
        context.DrawRenderers(
            cullingResults, ref drawingSettings, ref filterSettings
        );
        
        context.Submit();
    }
}

四、高级渲染功能实现

1. 多Pass渲染架构

public class LightingPass : ScriptableRenderPass {
    public override void Configure(
        CommandBuffer cmd, 
        RenderTextureDescriptor cameraTextureDescriptor
    ) {
        // 创建临时RT
        cmd.GetTemporaryRT(
            Shader.PropertyToID("_LightBuffer"),
            1024, 1024, 24, FilterMode.Bilinear
        );
    }

    public override void Execute(
        ScriptableRenderContext context, 
        ref RenderingData renderingData
    ) {
        // 绘制光照几何体
        cmd.DrawMesh(lightMesh, matrix, lightMaterial);
        context.ExecuteCommandBuffer(cmd);
    }

    public override void FrameCleanup(CommandBuffer cmd) {
        // 释放临时RT
        cmd.ReleaseTemporaryRT(Shader.PropertyToID("_LightBuffer"));
    }
}

2. 延迟渲染路径实现

G-Buffer生成Shader
struct GBufferOutput {
    float4 albedo   : SV_Target0; // RGB:BaseColor, A:Smoothness
    float4 normal   : SV_Target1; // RGB:WorldNormal, A:Metallic
    float4 emission : SV_Target2; // RGB:Emission, A:Occlusion
};

GBufferOutput FragGBuffer(Varyings input) {
    GBufferOutput output;
    // 采样材质属性...
    output.albedo = float4(baseColor, smoothness);
    output.normal = float4(normalWS * 0.5 + 0.5, metallic);
    output.emission = float4(emission, occlusion);
    return output;
}
光照计算Pass
public class DeferredLightingPass : ScriptableRenderPass {
    private Material lightingMat;
    
    public override void Execute(...) {
        // 设置G-Buffer纹理
        cmd.SetGlobalTexture("_AlbedoBuffer", albedoRT);
        cmd.SetGlobalTexture("_NormalBuffer", normalRT);
        
        // 全屏四边形绘制光照
        cmd.DrawProcedural(
            Matrix4x4.identity, lightingMat, 0,
            MeshTopology.Triangles, 3, 1
        );
    }
}

五、性能优化技术

1. SRP Batcher优化

// Shader中声明PerObject数据
CBUFFER_START(UnityPerMaterial)
float4 _BaseColor;
float _Metallic;
CBUFFER_END

// C#端启用SRP Batcher
GraphicsSettings.useScriptableRenderPipelineBatching = true;

2. GPU Driven Rendering

ComputeBuffer argsBuffer = new ComputeBuffer(
    5, sizeof(uint), ComputeBufferType.IndirectArguments
);

// 通过Compute Shader生成绘制参数
computeShader.Dispatch(kernel, groupCount, 1, 1);

// 间接绘制
cmd.DrawMeshInstancedIndirect(
    mesh, 0, material, bounds, argsBuffer
);

3. 多线程渲染支持

// 创建并行上下文
var renderThread = new RenderThread();
renderThread.Start();

// 提交渲染任务
renderThread.Schedule(() => {
    context.SetupCameraProperties(camera);
    context.DrawRenderers(...);
    context.Submit();
});

六、实战案例:卡通渲染管线

1. 架构设计

功能模块技术方案
轮廓描边法线扩展+深度检测
色阶着色颜色量化+LUT映射
高光处理各向异性高光模型

2. 关键Shader代码

// 轮廓Pass
Pass {
    Cull Front
    HLSLPROGRAM
    float _OutlineWidth;
    
    Varyings VertOutline(Varyings input) {
        float3 normal = input.normal * _OutlineWidth;
        input.positionOS += normal;
        return input;
    }
    ENDHLSL
}

// 色阶处理
float3 QuantizeColor(float3 color) {
    float levels = 3.0;
    return floor(color * levels) / levels;
}

七、调试与优化工具

1. 帧调试器扩展

[MenuItem("Custom RP/Debug/Show Light Count")]
static void ToggleLightCountDebug() {
    Shader.EnableKeyword("_DEBUG_LIGHT_COUNT");
}

2. 性能分析标记

using (new ProfilingScope(cmd, 
    new ProfilingSampler("Lighting Pass"))) 
{
    // 光照计算代码...
}

八、完整项目参考

Unlit渲染管线全流程详解


通过自定义渲染管线,开发者可突破Unity默认渲染的限制,实现从移动端到主机的全平台优化方案。核心在于:1) 合理设计RenderPass执行顺序;2) 利用CommandBuffer精细控制GPU资源;3) 结合Compute Shader实现GPU Driven架构。建议将常用渲染功能(如阴影、后处理)模块化封装,便于不同项目间复用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/984286.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

openharmory-鸿蒙生态设备之间文件互传发现、接入认证和文件传输

软件版本 OpenHarmony系统版本基线:基于 OpenHarmony-v5.0.0-Release。 图库应用版本:基于OpenHarmony-v5.0.0-Release。 文件管理器应用版本:基于OpenHarmony-v5.0.0-Release。 7 用户历程图 8 设备发现 8.1 设备交互流程图 8.2 设备发…

Linux系统编程--线程同步

目录 一、前言 二、线程饥饿 三、线程同步 四、条件变量 1、cond 2、条件变量的使用 五、条件变量与互斥锁 一、前言 上篇文章我们讲解了线程互斥的概念,为了防止多个线程同时访问一份临界资源而出问题,我们引入了线程互斥,线程互斥其实…

【HarmonyOS Next】鸿蒙加固方案调研和分析

【HarmonyOS Next】鸿蒙加固方案调研和分析 一、前言 根据鸿蒙应用的上架流程,本地构建app文件后,上架到AGC平台,平台会进行解析。根据鸿蒙系统的特殊设置,仿照IOS的生态闭环方案。只能从AGC应用市场下载app进行安装。这样的流程…

# 深入理解RNN(一):循环神经网络的核心计算机制

深入理解RNN:循环神经网络的核心计算机制 RNN示意图 引言 在自然语言处理、时间序列预测、语音识别等涉及序列数据的领域,循环神经网络(RNN)一直扮演着核心角色。尽管近年来Transformer等架构逐渐成为主流,RNN的基本原理和思想依然对于理…

深度学习实战车道线检测

深度学习实战车道线检测 这里写目录标题 车道线原理整体架构设计核心原理步骤1. 特征提取(骨干网络)2. 特征融合3. 车道线表示与分类4. 损失函数5. 后处理 速度优势的来源 软件实现安装环境与文件说明实验测试 结束语 车道线原理 Lane - Detection是一种…

【redis】五种数据类型和编码方式

文章目录 五种数据类型编码方式stringhashlistsetzset查询内部编码 五种数据类型 字符串:Java 中的 String哈希:Java 中的 HashMap列表:Java 中的 List集合:Java 中的 Set有序集合:除了存 member 之外,还有…

Next.js Server Action 提交 vs 前端 Fetch 提交:核心区别与优劣分析

在使用 Next.js 开发时,开发者经常会面临一个问题:前端的数据提交应该直接 Fetch 调用 API 还是使用 Next.js 提供的 Server Action 提交? 本文将深度解析: ✅ Server Action 提交数据的工作原理✅ 前端 Fetch 提交数据的优缺点…

DeepSeek开启AI办公新模式,WPS/Office集成DeepSeek-R1本地大模型!

从央视到地方媒体,已有多家媒体机构推出AI主播,最近杭州文化广播电视集团的《杭州新闻联播》节目,使用AI主持人进行新闻播报,且做到了0失误率,可见AI正在逐渐取代部分行业和一些重复性的工作,这一现象引发很…

混合存储HDD+SSD机型磁盘阵列,配上SSD缓存功能,性能提升300%

企业日常运行各种文件无处不在,文档、报告、视频、应用数据......面对成千上万的文件,团队之间需要做到无障碍协作,员工能够即时快速访问、共享处理文件。随着业务增长,数字化办公不仅需要大容量,快速高效的文件访问越…

【AI】什么是Embedding向量模型?我们应该如何选择?

我们之前讲的搭建本地知识库,基本都是使用检索增强生成(RAG)技术来搭建,Embedding模型则是RAG的核心,同时也是大模型落地必不可少的技术。那么今天我们就来聊聊Embedding向量模型: 一、Embedding模型是什么? Embedding模型是一种将离散数据(如文本、图像、用户行为等)…

Java在小米SU7 Ultra汽车中的技术赋能

目录 一、智能驾驶“大脑”与实时数据 场景一:海量数据的分布式计算 场景二:实时决策的毫秒级响应 场景三:弹性扩展与容错机制 技术隐喻: 二、车载信息系统(IVI)的交互 场景一:Android Automo…

【Python 数据结构 8.串】

目录 一、串的基本概念 1.串的概念 2.获取串的长度 3.串的拷贝 4.串的比较 5.串的拼接 6.串的索引 二、Python中串的使用 1.串的定义 2.串的拼接 3.获取串的长度 4.获取子串位置 5.获取字符串的索引 6.字符串的切片 7.字符串反转 8.字符串的比较 9.字符串的赋值 三、实战 1.344…

计算机视觉cv2入门之图像的读取,显示,与保存

在计算机视觉领域,Python的cv2库是一个不可或缺的工具,它提供了丰富的图像处理功能。作为OpenCV的Python接口,cv2使得图像处理的实现变得简单而高效。 示例图片 目录 opencv获取方式 图像基本知识 颜色空间 RGB HSV 图像格式 BMP格式 …

LLM 学习(二 完结 Multi-Head Attention、Encoder、Decoder)

文章目录 LLM 学习(二 完结 Multi-Head Attention、Encoder、Decoder)Self-Attention (自注意力机制)结构多头注意力 EncoderAdd & Norm 层Feed Forward 层 EncoderDecoder的第一个Multi-Head AttentionMasked 操作Teacher Fo…

006-获取硬件序列号

获取硬件序列号 我将从跨平台角度系统讲解如何通过C获取硬件序列号的核心技术&#xff0c;并提供可移植性代码实现。 一、处理器序列号获取 Windows平台 #include <windows.h> #include <intrin.h>std::string GetCPUSerial_Win() {DWORD cpuInfo[2] { 0 };__c…

GDB调试技巧:多线程案例分析(保姆级)

在软件开发的复杂世界里&#xff0c;高效的调试工具是解决问题的关键利器。今天&#xff0c;我们将深入探讨强大的调试工具 ——GDB&#xff08;GNU Debugger&#xff09;。GDB 为开发者提供了一种深入程序内部运行机制、查找错误和优化性能的有效途径。让我们一同开启 GDB 的调…

OSPF的各种LSA类型,多区域及特殊区域

一、OSPF的LSA类型 OSPF&#xff08;开放最短路径优先&#xff09;协议使用多种LSA&#xff08;链路状态通告&#xff09;类型来交换网络拓扑信息。以下是主要LSA类型的详细分类及其作用&#xff1a; 1. Type 1 LSA&#xff08;路由器LSA Router LSA&#xff09; 生成者&…

JavaScript系列06-深入理解 JavaScript 事件系统:从原生事件到 React 合成事件

JavaScript 事件系统是构建交互式 Web 应用的核心。本文从原生 DOM 事件到 React 的合成事件&#xff0c;内容涵盖&#xff1a; JavaScript 事件基础&#xff1a;事件类型、事件注册、事件对象事件传播机制&#xff1a;捕获、目标和冒泡阶段高级事件技术&#xff1a;事件委托、…

字节跳动C++客户端开发实习生内推-抖音基础技术

智能手机爱好者和使用者&#xff0c;追求良好的用户体验&#xff1b; 具有良好的编程习惯&#xff0c;代码结构清晰&#xff0c;命名规范&#xff1b; 熟练掌握数据结构与算法、计算机网络、操作系统、编译原理等课程&#xff1b; 熟练掌握C/C/OC/Swift一种或多种语言&#xff…

MySQL进阶-关联查询优化

采用左外连接 下面开始 EXPLAIN 分析 EXPLAIN SELECT SQL_NO_CACHE * FROM type LEFT JOIN book ON type.card book.card; 结论&#xff1a;type 有All ,代表着全表扫描&#xff0c;效率较差 添加索引优化 ALTER TABLE book ADD INDEX Y ( card); #【被驱动表】&#xff0…