3D应用、OpenGL/DirectX、显卡驱动的关系

OpenGL和DirectX

什么是HLSL、GLSL、Cg

这些都是高级着色语言(Shading Language)。

DirectX——HLSL(High Level Shading Language):支持它的平台多是微软自己的产品,在相同版本下编译结果是一样的

OpenGL——GLSL(OpenGL Shading Language):由显卡驱动来完成着色器编译,GLSL依赖硬件提供商,可能会造成编译结果不一致的情况。

Nvidia——Cg(C for Language):真正意义的跨平台,语法和HLSL很像,可能无法完全发挥出OpenGL的最新特性。

这些语言称为“高级”语言是相对汇编语言来说的,而不是像C#相对于C的高级那样。这些语言会被编译成与机器无关的汇编语言,被称为中间语言(Intermediate Language,IL),中间语言再交给显卡驱动来翻译成真正的机器语言。

在Unity中可以选择使用“Cg/HLSL”或者“GLSL”,Unity的着色语言和它们语法几乎一样,但是有一些不支持和不一样的地方。

DrawCall

Draw Call本身的含义就是CPU调用图像编程接口,如OpenGL中的GLDrawElements命令或者DirectX中的DrawIndexedPrimitive命令,以GPU进行渲染的操作。

命令缓冲区(Command Buffer)

命令缓冲区包含了一个命令队列,由CPU向其添加命令,GPU从中读取命令,添加和读取过程都是互相独立的。

Command Buffer中的命令有很多种类,而Draw Call是其中一种,其他命令还有改变渲染状态(例如改变使用的着色器,使用不同的纹理)等

CommandBuffer

改变渲染状态的命令往往更加耗时

Draw Call增加会影响CPU

GPU的渲染能力很强,200个还是2000个三角网格通常没有什么区别。渲染速度由CPU提交命令的速度决定,Draw Call太多会导致CPU过载。

减少DrawCall

办法有很多,批处理(Batching)是其中一种。批处理就是在内存中把相同渲染状态的网格合并成一个大网格,再发送给GPU。

批处理技术更适合静态(Unity中static)的物体,比如不会移动的大地、石头等。当然也有动态物体进行批处理的方法。

使用MeshBaker,在开发阶段提前将一些Mesh合并也是一种方法。

Batching

还有两点需要注意:

  1. 避免使用大量很小的网格。考虑是否可以合并小网格。
  2. 避免使用过多材质。尽量在不同网格之间公用一个材质。