如何使用GPU基于VertexBuffer与IndexBuffer绘制Mesh
解决方案
你触发报错是因为DrawProcedural系列接口的入参仅支持传入绘制数量、实例数这类整型参数,本身不支持直接传入GraphicsBuffer对象,该接口的设计场景为无索引缓冲、或需在Shader内手动采样顶点缓冲的绘制需求。
Unity原生提供了完全不需要CPU参与、可直接绑定自定义GraphicsBuffer类型顶点/索引缓冲的绘制方案,具体实现如下:
1. 推荐方案(Unity 2020.1+)
使用Graphics.RenderPrimitivesIndexed系列接口,绘制流程全程在GPU侧完成,无需构造Mesh对象、无需回读缓冲区数据:
- 提前构造对应类型的
GraphicsBuffer:顶点缓冲需指定GraphicsBuffer.Target.Vertex标记,索引缓冲需指定GraphicsBuffer.Target.Index标记 - 绘制前调用
Graphics.SetVertexBuffer(0, 你的顶点缓冲对象)完成顶点缓冲绑定 - 调用
Graphics.SetIndexBuffer(你的索引缓冲对象)完成索引缓冲绑定 - 最后调用
Graphics.RenderPrimitivesIndexed(拓扑类型, 索引数量, 索引格式, 0, 0)完成绘制,所有参数可直接从已有的索引缓冲属性中读取,无需额外CPU计算
2. 低版本兼容方案(Unity 2020之前)
通过CommandBuffer实现同等效果,示例代码如下:
CommandBuffer drawCmd = new CommandBuffer(); // 绑定自定义顶点、索引缓冲 drawCmd.SetVertexBuffer(0, customVertexBuffer); drawCmd.SetIndexBuffer(customIndexBuffer); // 执行绘制:拓扑为三角形,起始索引偏移0,顶点起始偏移0,实例数1,绘制批次为索引数/3 drawCmd.DrawIndexedPrimitives(MeshTopology.Triangles, 0, 0, customVertexBuffer.count, 0, customIndexBuffer.count / 3); // 执行命令缓冲并释放 Graphics.ExecuteCommandBuffer(drawCmd); drawCmd.Release();
注意事项
- 顶点缓冲的字段顺序、数据格式必须和Shader中
appdata输入结构体的定义完全匹配,否则会出现绘制错乱 - 索引缓冲的格式(16位/32位)需要和绘制接口传入的
IndexFormat参数保持一致,避免索引读取错误 - 如需实例化绘制可使用对应
RenderPrimitivesIndexedIndirect接口,配合存储绘制参数的GraphicsBuffer即可实现全GPU侧的绘制逻辑,全程不需要CPU介入计算
内容的提问来源于stack exchange,提问作者Orry
相关产品推荐
相关产品推荐

