【渲染流水线】[几何阶段]-[图元装配]以UnityURP为例

图元装配负责将离散顶点组装成完整几何图元(如点、线、三角形、三角形条带)

【从UnityURP开始探索游戏渲染】专栏-直达

输入数据‌

接收‌顶点着色器输出的离散顶点数据‌,包括:

  • 变换后的空间坐标(如裁剪空间位置)
  • 顶点属性(颜色、法线、纹理坐标等

输出数据‌

生成‌完整几何图元‌(Primitive),例如:

  • 三角形(GL_TRIANGLES)
  • 线段(GL_LINES)
  • 点(GL_POINTS)‌

在Unity中,图元装配的实现

主要通过‌网格拓扑(Mesh Topology) ‌和‌**索引缓冲区(Index Buffer)**‌完成。

顶点分组模式‌

  1. ‌索引分组模式 ‌通过索引数组(如Mesh.triangles或Mesh.GetIndices())定义顶点连接顺序,每个索引指向顶点缓冲区中的位置,按预设拓扑规则分组‌。例如:

    复制代码
    text
    索引数组 [0,1,2,3,4,5]
    三角形拓扑 → 分组为△(0,1,2)和△(3,4,5)
  2. ‌顺序分组模式‌无索引时直接按顶点提交顺序分组(如连续3顶点构成一个三角形)‌。


‌Unity支持的图元类型‌

‌图元类型‌ ‌描述‌
三角形(Triangles) 每3个独立顶点构成一个三角形,默认用于3D模型渲染‌。
三角形条带(TriangleStrip) 复用前2顶点与当前顶点生成新三角形,减少顶点重复提交‌。
四边形(Quads) 每4顶点构成一个四边形(实际渲染时拆分为2个三角形)。
线段(Lines) 每2顶点构成一条线段,用于线框渲染‌。
点(Points) 每个顶点独立渲染为屏幕上的点‌。

‌拓扑连接规则‌

  1. ‌缠绕顺序(Winding Order) ‌Unity默认使用‌顺时针顺序 ‌判定三角形正面,逆时针面会被剔除‌。例如:
    • 顶点顺序(v1,v2,v3)为顺时针 → 可见
    • 顺序(v1,v3,v2)为逆时针 → 剔除‌。
  2. ‌共享顶点优化 ‌索引数组可复用顶点(如[0,1,2,1,2,3]生成两个共享边(1,2)的三角形)。

‌关键实现接口‌

  1. ‌设置拓扑类型 ‌通过MeshTopology枚举指定图元类型(如MeshTopology.Triangles)‌。
  2. ‌索引缓冲区操作 ‌
    • Mesh.SetIndices():自定义索引分组规则
    • Mesh.triangles:直接设置三角形索引(旧API,效率较低)‌

URP中对图元装配的调用位置与示例

在Unity URP (Universal Render Pipeline) 中,几何阶段的图元装配是由底层渲染管线自动处理的,主要通过ScriptableRenderContext和CommandBuffer系统完成。

‌核心类与调用流程‌

  • ‌UniversalRenderPipeline.RenderSingleCamera ‌入口点,通过ScriptableRenderContext提交绘制命令
  • ‌ScriptableRenderContext.DrawRenderers‌触发几何处理,最终调用底层图形API (如OpenGL/D3D)
  • ‌CommandBuffer.DrawProcedural‌直接控制图元装配(手动模式)

图元装配示例代码‌

以下是不同图元类型的装配方式示例:

三角形 (Triangles)‌

csharp 复制代码
csharp
// 通过MeshFilter自动装配var meshFilter = GetComponent<MeshFilter>();
Graphics.DrawMesh(meshFilter.sharedMesh, transform.position, transform.rotation, material, 0);

三角形带 (Triangle Strip)‌

csharp 复制代码
csharp
// 手动通过CommandBuffer装配
CommandBuffer cmd = new CommandBuffer();
cmd.DrawProcedural(
    Matrix4x4.identity,
    material,
    0,
    MeshTopology.TriangleStrip,
    vertexCount: 4// 需要至少4个顶点形成2个三角形
);
context.ExecuteCommandBuffer(cmd);

四边形 (Quads)‌

csharp 复制代码
csharp
// URP中四边形会被拆分为三角形处理
Mesh quadMesh = new Mesh();
quadMesh.vertices = new Vector3[] {/* 4个顶点 */ };
quadMesh.SetIndices(new int[] {0,1,2, 0,2,3}, MeshTopology.Triangles, 0);
Graphics.DrawMesh(quadMesh, Matrix4x4.identity, material, 0);

线段 (Lines)‌

csharp 复制代码
csharp
// 使用GL.LINES或LineRenderer组件
CommandBuffer cmd = new CommandBuffer();
cmd.DrawProcedural(
    Matrix4x4.identity,
    lineMaterial,
    0,
    MeshTopology.Lines,
    vertexCount: 2
);

点 (Points)‌

csharp 复制代码
csharp
// 使用MeshTopology.Points
CommandBuffer cmd = new CommandBuffer();
cmd.DrawProcedural(
    Matrix4x4.identity,
    pointMaterial,
    0,
    MeshTopology.Points,
    vertexCount: 1
);

底层实现位置‌

  • ‌URP源码关键文件 ‌:UniversalRenderPipelineCore.cs → ExecuteRenderPass方法ScriptableRenderer.cs → EnqueuePass提交绘制命令
  • ‌Shader支持 ‌:在Shader中需声明正确的#pragma target和几何着色器(如需要)

调试

  1. 使用Frame Debugger查看实际提交的图元类型
  2. 在URP设置中启用Native Rendering Debugger
  3. 检查材质的Render Queue和Shader Pass设置

更深入的管线定制,可继承ScriptableRendererFeature实现自定义几何处理。


【从UnityURP开始探索游戏渲染】专栏-直达

(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)

相关推荐
阿松爱学习5 小时前
【Unity开发】Aspose.PDF的使用
unity·pdf·c#
淡海水7 小时前
02-04-原理篇-GC Roots与对象图遍历
算法·unity·c#·图·gc·遍历·roots
Martina_03215 天前
AI生成3D场景导入 Unity/Unreal 后,NPC 总串层?用6步检查导航高度与跨层连接
人工智能·游戏·数学建模·3d·unity·自然语言处理·aigc
小贺儿开发5 天前
Unity 局域网遥控幻灯片展示工具 3.0
科技·http·unity·工具·ppt·通信·网页
WarPigs7 天前
Unity对象不应该使用null传播的问题
unity
每日出拳老爷子8 天前
【VR】【Unity】抓走转放系列21|一天搭完门和抽屉工具槽:小场景按这个次序拼装
unity·vr·驱动·排错·snap zone
淡海水8 天前
02-02-原理篇-分代GC
算法·unity·c#·游戏引擎·.net·gc
小贺儿开发9 天前
Unity 文物新生 会讲故事的文物展墙
人工智能·科技·unity·ai·视频·互动·演示
淡海水9 天前
02-03-原理篇-大对象堆
unity·c#·游戏引擎·.net·gc
WarPigs9 天前
Unity在Create菜单添加创建自定义脚本模板选项
unity