什么是GPU渲染流水线
在OpenGL中,任何事物都在3D空间中,而屏幕和窗口却是2D像素数组,这导致OpenGL大部分工作都是关于把3D坐标转变为适应屏幕的2D像素。3D坐标转为2D坐标的处理过程是由OpenGL的图形渲染管线(Graphics Pipeline,大多译为管线,指的是一堆原始图形数据途经一个输送管道,期间经过各种变化处理最终出现在屏幕的过程)管理的。图形渲染管线可以被划分为两个主要部分:第一部分把你的3D坐标转换为2D坐标(几何阶段);第二部分是把2D坐标转变为实际的有颜色的像素(光栅化阶段)。
渲染流程
渲染流水线是cpu和gpu配合渲染一帧的过程,其中渲染流程主要分为3个阶段:应用阶段,几何阶段, 光栅化阶段。

CPU控制阶段
应用阶段属于CPU控制阶段
1.准备场景数据,把数据加载到显存中去。
2.设置渲染状态,material,texture,shader等。
3.调用DrawCall,输出渲染图元到gpu。
GPU控制阶段
GPU控制阶段分为2个部分,几何阶段和光栅化阶段,这两个阶段又可以细分成若干个更小的流水线阶段,每个阶段GPU提供了不同的可配置性和可编程性,具体如下图所示:

一.几何阶段:
1.顶点着色器:顶点变换,逐顶点光照,输出后续阶段所需的数据。
2.图元装配:将顶点着色器输出的所有顶点作为输入(如果是GL_POINTS,那么就是一个顶点),并所有的点装配成指定图元的形状。
3.几何着色器(可选):产生新顶点构造出新的图元来生成其他形状。
4.裁剪:将不在摄像机视野内的顶点剔除掉,并剔除某些三角图元的面片。
5.屏幕映射:将每个图元的ndc坐标转换到屏幕坐标系中。
二.光栅化阶段:
1.三角形设置:得到三角形边界的表示方式,计算图元覆盖了哪些像素。
2.三角形遍历:判断三角网格覆盖了哪些像素,基于三角形顶点信息对整个覆盖区域像素进行插值,输出片元。
3.片元着色器:纹理采样,片元着色。
4.逐片元操作:决定片元的可见性,深度测试,alpha,模板测试等,测试不通过的片元会被舍弃,测试通过的片元在开启混合时会和像素缓冲区的颜色进行混合,最后将像素缓冲区中的颜色进行替换成该片元最终的颜色。
如下图以一个三角形为例展示下渲染管线的每个阶段,蓝色部分代表的是我们可以自定义的着色器部分。

顶点变换
不同坐标系之间的变换,一个渲染顶点,要想让它呈现在屏幕上的某个位置,是需要让这个顶点经过一个个坐标系的变换来进行的,每经过一个坐标系,它的坐标就会使用矩阵来执行一次变换,最终变换到屏幕上的位置。Opengl顶点变换过程如下图所示:

世界变换
即我们所说的仿射变化,包括位移、旋转、缩放。



相机变换
以相机作为坐标原点的一个参考系,把物体从世界坐标系,变换到相机为原点的相机坐标系。
假设摄像机的位置为(Px,Py,Pz),以(θ,0,0)进行旋转。
首先需要把相机平移到世界坐标原点,变换矩阵如下:

然后进行旋转变换,变换矩阵如下:

透视变换
经过前面两轮变换,物体坐标已经变为以相机为原点的坐标了,之后我们要进行投影变换(以透视投影为例)。

透视变换矩阵为

透视除法
将齐次裁剪空间坐标转为标准设备空间,实现比较简单,用齐次坐标的w去除以x,y, z分量,经过透视除法后剪裁空间会变换到一个立方体内,变换后的坐标x,y,z范围在[-1,1].
视口变换
将标准设备空间坐标转换到屏幕坐标,计算公式如下:
screenX = (1+Px)/2*screenWidth
screenY = (1+Py)/2*screenHeight
为什么使用齐次坐标
1.平移不是线性变换,3*3矩阵不能表示平移变换。
2.将平移,旋转,缩放操作全部使用矩阵运算表示,统一格式,提高效率。
3. 以坐标中的W作为透视距离的依据,满足透视需要。