渲染管线是整个渲染中的核心部分。渲染管线的主要目的是将3D描述的世界绘制成2D屏幕上显示的像素。可想而知其中的复杂度。
渲染管线在早期通常实现在CPU端,称之为软渲染,即整个渲染管线的处理都交给CPU处理。软渲染可行,CPU不仅要处理游戏逻辑,还要处理渲染逻辑,其负重极大,影响FPS(Frame Per Second),对于游戏而言,帧率非常重要,需要达到30-60FPS才能让玩家感受到画面的流畅度。在VR上,则要达到90FPS。
如今很少有直接使用软渲染(Software Renderer)的地方,通常将渲染逻辑放在硬件端,即GPU,这称为硬件加速渲染。硬件加速是从CPU任务流中剥离了渲染任务,转移到了硬件中,这样减轻了CPU负载,CPU可腾出空间专职处理游戏逻辑,这加速了游戏逻辑更新到帧显示之间的速度,即称为硬件加速。
无论是软渲染还是硬件加速渲染,其实质工作目标是一致的。虽然显卡硬件的发展历经了SM1.0-SM4.0的发展,但其本质目标没变。
现如今,CPU与GPU分工合作,CPU负责游戏逻辑,GPU负责渲染管线。可喜的是,了解渲染管线,无需了解GPU的构造、工作原理。
渲染管线如同工厂流水线,输入的数据是游戏世界中的模型数据,输出的是屏幕像素。我们会在后续章节中,陆续深入了解渲染管线的每个过程以及每个过程中涉及到的图形学概念。
现在,让我们看看渲染管线的大致流程:
大致分为3个阶段:Game -> Vertex -> Rasterization -> Fragement
Game阶段也成为应用程序阶段,在CPU中准备好顶点数据和要渲染的必备前提条件,然后通过总线(Bus是计算机各种功能部件之间传送信息的公共通信干线)将这些数据送到GPU。GPU得到这些数据后,立即进行渲染管线处理。
Vertex阶段,也成为顶点管线,主要是对顶点进行加工、剔除,形成最终处于当前观察点所需的顶点数据,通常称为图元(Primitive),然后送入Rasterization。
Rasterization(光栅化)是通常是GPU中固定的处理部分,主要的工作即将最终顶点,扫描成屏幕上的片段(这里使用Fragment而非使用通常所说的Pixel,主要原因是目前它尚不是最终屏幕上的Pixel)。光栅化主要是根据顶点信息,按照屏幕扫描线形式,以片段填充图元,然后送入Fragment阶段。
Fragment阶段是渲染管线后期处理部分,有时候也称为后期处理(PostProcess)。Fragment具有最终屏幕Pixel包含的全部信息,但此时,我们还可以对Fragment进行处理,例如Alpha、Blend、Fog等,让整个屏幕效果更加美观或特殊。处理完之后,此时,即生成Pixel,可直接应用于屏幕上,呈现出我们的游戏场景。
至此,渲染管线完成一帧的最终处理。
当完成一帧后,这一帧会先存在FrameBuffer中,再从FrameBuffer中显示在屏幕上。FrameBuffer用于平滑显示多帧的情况,在早期,屏幕是根据扫描线来显示图像,如果不设帧缓存,那么所有的像素数据一旦得到,即会显示在屏幕上,而且屏幕采用惰性更新,只绘制发生改变的地方。那么会造成前一图像未擦除,后一图像部分显示的情形;或者在前。帧缓冲的概念,来源于双缓冲区,即,前一帧显示后,从缓冲区取图像数据,有则擦屏,无则不变,然后将图像绘制在屏幕上。这样做,1渲染管线处理下一帧快时,可暂存,不破坏当前帧;2渲染管线处理下一帧慢时,可通过判断缓冲区有无数据,而不会含糊擦除屏幕。
这里可以插入一个概念,VSync(Vertical Sync) 垂直同步。显示器有自己的更新频率,而游戏也有自己的更新频率。最常见的是显卡帧率可达120FPS,而显示器只有60FPS。当显卡帧率大于显示器帧率时,会有多张图像供显示器显示,此时会造成图像上半段是下一帧数据,下半段是上一帧数据的情况,即常言的画面撕裂。那么垂直同步可以保证显卡和显示器同步执行,可保证图像的稳定性(即,无撕裂),但这会大大降低显卡的工作效率。
在FPS保持90情况下,GPU需要保证在1秒内处理90帧。所以,往往游戏引擎中关于渲染的优化,必须是在了解渲染管线的情况下,才能找准病根,进行根治。人云亦云的优化手段,虽有一定道理,但不可盲目跟随。
渲染优化的最终目的,是要能保证帧率,这是亘古不变的。
术语自检
- CPU:Central Processing Unit,是计算机中最核心的部件,用来处理指令。
- GPU: Graphics Processing Unit,是显卡中的图形处理单元,主要负责矩阵、矢量等数据计算。
- FPS: Frame Per Second,帧每秒,即所谓的帧率。当游戏需要达到60FPS,那么1帧处理完成需时1/60s,~1.16ms
- SM:Shader Model,主要对应的是硬件的发展,所带动的可编程渲染管线技术水平。由最初的固定管线,到现在的支持4个可编程着色器组(Vertex Shader,Tessellation,Geometry Shader,Fragment Shader)
- Vertex: 顶点,这里的顶点并非几何上的点,只包含坐标信息的点,顶点不仅包含位置信息,还可包含其他属性,如纹理、颜色、法线等
- Fragment: 片段,与像素不同,屏幕上的像素仅包含颜色信息,但Fragment不仅包含颜色信息,还可包含如深度等属性
- Pixel: 像素,屏幕像素,具有位置和颜色两个属性,可供显示器显示。
- VSync: 垂直同步,显示器绘制一帧,是从上往下绘制,当一帧绘制完毕之后,会重新回到上部往下绘制。VSync是确保显示器显示完一帧后,再通知显卡获取下一帧数据。