什么是OpenGL/DirectX
OpenGL/DirectX 是图像应用编程接口,用来渲染二维,三维图形。如果没有 OpenGL/DirectX 想要访问GPU是很麻烦的,可能要和各种寄存器,显存打交道。OpenGL/DirectX将上层应用程序与底层GPU之间架起一座“桥梁”。
当应用程序通过上面编程接口后,这些接口会依次向显卡驱动发送渲染命令。显卡驱动会将OpenGL/DirectX中的函数翻译成GPU能懂的语言,实现与GPU的通讯。显卡驱动同时也会将纹理等数据转换为GPU支持的格式。
¶HLSL,GLSL,CG的关系
HLSL,GLSL,CG是三种常见的着色器语言,用来编写着色器。这些语言会被编译为与机器无关的汇编语言(中间语言),中间语言再交给显卡翻译为真正的机器语言,即GPU可以理解的语言。
¶三者区别
HLSL基于DirectX,由微软控制,在版本相同时,不同平台编译的结果是一样的,但几乎只支持微软家产品,如: Windows,Xbox 360,PS3等。
GLSL基于OpenGL,优点在于跨平台性,只要显卡驱动支持即可正常工作,可以在Windows,Mac,Linux,移动平台工作。但是由于OpenGL不提供着色器编译器,而是由显卡驱动完成着色器编译,导致GLSL的编译结果取决于不用的显卡硬件厂商,进而导致编译结果不尽相同。
CG基于Nvidia,真正意义上的跨平台。根据不同的平台生成不同的中间语言。(Unity中首选,会编译成HLSL或GLSL)
什么是渲染管线?
将素材通过一系列的加工最终显示在屏幕上,一系列的加工如同流水线一般。
渲染管线
渲染管线的工作是将一个三维场景出发,渲染成一张二维图像。这个过程由CPU,GPU共同完成。渲染流程分三个阶段:
¶应用阶段
应用阶段分三个任务(CPU负责实现)
- 准备好场景数据。如场景所有GameObject信息,光照信息等。将数据加载到显存中。
硬盘-> RAM -> 显存
- 为了提高渲染性能,将相机不可见的物体剔除,这样就不用交给几何阶段处理了。
- 设置每个模型的渲染状态,如使用的材质,纹理,Shader等。输出渲染所需的几何信息,即:渲染图元,渲染图元可以是点,线,三角面等。这些渲染图元将会传递到下一个阶段。(调用DrawCall)
¶几何阶段(GPU)
几何阶段是用于处理所有要绘制的集合相关的事情。将上个阶段传递的渲染图元进行逐顶点,多边形进行处理。输出屏幕空间的二维顶点坐标,以及每个顶点的深度值,主色等相关信息,然后传递给光栅化阶段。这一阶段在GPU上进行。
¶光栅化阶段(GPU)
光栅化阶段会将上一阶段传递过来的数据生成对应屏幕上的像素,并渲染出最终图像。这一阶段也是在GPU上进行。
CPU与GPU的通信
渲染管线的起点是CPU,即应用阶段。应用阶段分为三个任务:
- 把数据加载到显存中。所有的渲染需要从硬盘(HDD)加载到内存(RAM)中,然后网格和纹理等数据又被加载到显存中,因为大多数显卡不能直接访问RAM,而且显卡读取显存速度也很快。当数据加载到显存后,RAM中一些CPU不再访问的数据即可移除掉了。但是之后还要使用的数据不能移除掉,毕竟从HDD加载到RAM还是很耗时的。之后通过CPU设置渲染状态进而指导GPU进行渲染。
- 设置渲染状态。渲染状态就是定义了场景中的网格该被如何渲染。如使用哪些顶点/片元着色器,光源属性,材质等。之后CPU调用DrawCall命令告诉GPU开始渲染。
- 调用DrawCall。DrawCall是一个渲染命令,由CPU发起,GPU接收。这个命令只会只想一个需要渲染的图元列表。当GPU收到DrawCall后,会根据渲染状态和顶点数据进行计算(GPU的流水线),最终显示到屏幕上。