图形学最基本,也是最全局的问题,渲染管线,渲染和绘制同意(rendering),因为个人习惯,本文皆用绘制一词来表述。图形绘制管线分三大步,分别是应用部分、几何部分和光栅化部分。下图描述了几何部分和光栅化部分的大致流程,左侧是经典的ES 2.0管线,右边为引入了几何细分和几何两个着色器的新管线。

应用部分
图形是由一些基本的数据元素组成的,如顶点、面(顶点之间的连接关系),颜色和材料等。应用部分首先包括了这些数据的IO,用户交互的处理,对数据的预处理等等,通常都是在CPU上进行的。数据的IO主要是从文件中根据不同文件格式(常见格式.ply, .obj和.stl等)的定义将图形的各种数据元素读入内存。
用户交互的处理主要是记录并计算用户的交互动作,例如用户鼠标移动后,我们根据鼠标移动的距离和方向,计算出图形需要旋转的角度。用户交互可以包括旋转、平移、缩放、光照变化等各种因素,均有程序员在CPU上根据一定的逻辑进行处理。
数据的预处理主要指图形的处理,例如平滑,简化,碰撞检测等等,这些主要针对特定的逻辑需求来设计。
应用部分将顶点、面、颜色和模型变换矩阵等信息传入GPU后,进行后面的几何部分和光栅化部分操作。
应用部分将基本图元的数据以合理的顺序组织好后(如三角形各顶点的顺序)设置为VAO(顶点顺序和连接方式)和VBO(顶点数据),传入GPU,进入后续的几何部分和光栅化部分。
几何部分
几何部分首先是对顶点的处理,即顶点着色器(vertex shader)。顶点数据传入GPU后,顶点着色器中的代码执行,顶点着色器中的代码是针对每一个顶点执行的。通常包括MVP变换,注意缩放旋转平移的顺序是先缩放、再旋转、再平移。

MVP变换中的Model变换实现模型坐标到世界坐标的变换,View变换实现世界坐标到相机坐标的变换(注意的是,相机右手边是X正方向,头顶是Y正方向,穿心方向是Z正方向。),Projection变换实现了从相机坐标到其次坐标的变换。M和V都是简单的旋转平移缩放矩阵,而P矩阵则较难理解,P矩阵的参数包括FoV(视域角度)、长宽比、近平面和远平面,具体的理解和推导可以参考此文和此文。
(可选)顶点着色器后有一个细分曲面着色器(tessellation shader),是OpenGL ES4.0以后新增的部分,它使用新的数据结构patch来描述经过顶点着色器处理后的几何图元,从而达到更平滑真实的效果。
(可选)细分曲面着色器后面还有几何着色器(geometry shader)的选项,是针对基本图元的操作,例如三角形或者patch,而不像顶点着色器那样是对顶点进行操作,它的输入是图元,输出也是图元(未必一一对应)。
在完成上述三个着色器(顶点、细分曲面和几何)后,进入顶点后处理阶段,GPU对顶点进行一些额外的处理,例如裁剪和视口变换。顶点后处理之后,是图元装配阶段,将之前处理过的顶点装配城基本图元,并做(可选)可见面剔除,经过剔除后的图元就进入光栅化阶段。
光栅化部分
在光栅化阶段,几何图元被插值采样成像素,片段着色器(fragment shader)就是对每个像素进行操作。通常在片段着色器中我们对片段(像素)的颜色进行计算,包括纹理映射和光照等。片段着色器的输出,是每个片段(像素)的颜色值、深度值和模板(stencil)值。
在片段着色器之后的逐样本(像素)操作中,GPU根据深度值和模板值进行(可选)深度测试和(可选)模板测试,通过深度测试和模板测试的像素颜色将被保留,否则将被舍弃。
最后,经过上面的应用、几何和光栅化三个阶段,一个与屏幕(窗口)大小相同的二维矩阵颜色值,将被写入帧缓存,也就是最后绘制完成的图像。
参考
OpenGL Rendering Pipeline Overview
章节:矩阵 - Learn OpenGL 中文版
The Perspective and Orthographic Projection Matrix
【光能蜗牛的图形学之旅】OpenGL顶点变换全体流程以及投影矩阵推导
网友评论