简述OpenGL渲染管线过程
- 准备向OpenGL传输数据
OpenGL需要将所有的数据都保存到缓存对象(buffer object)中,它相当于OpenGL服务端维护的一块内存区域。
- 将数据传输到OpenGL
在缓存初始化完成之后,通过调用绘制命令将顶点数据传送到OpenGL服务端。我们可以将一个顶点视为一个需要统一处理的数据包。这个包中的数据可以是我们需要的任何数据。
- 顶点着色(vertex shading stage)
该阶段将接收你顶点缓存中给出的顶点数据。对于绘制命令传输的每个点,OpenGL都会用一个顶点着色器来处理顶点相关的数据(至少会计算出每个顶点经过建模和观察投影变换后在裁剪空间的坐标)。传递着色器会将数据复制并传递到下一个着色阶段。对于复杂的场景也会有相应的着色方式。
- 细分着色(tessellation shading stage)
这是一个可选阶段,与应用程序中显式地指定几何图元的方法不同,它会在OpenGL管线内部生成新的几何体。这个阶段启用之后,会收到来自顶点着色器阶段的输出数据,并且对收到的数据进一步处理。
- 几何着色(geometry shading stage)
该阶段也是一个可选阶段,假如启用了该阶段,它会收到来自顶点着色或者细分着色(如果它也被启用)的数据,然后在OpenGL管线内部对几乎所有的几何图形进行修改。几何着色器不同于前两个着色器,它不仅仅只能修改输入数据,甚至可以创建新的图元交给后续的流水线处理。该阶段作用于每个独立的几何图元。
- 图元装配
该阶段会将这些顶点与相关的集合图元之间组织起来,准备下一步的剪切和光栅化工作。
- 剪切
该阶段用来保证相关的像素不会在窗口之外进行绘制。也就是说将不能被窗口显示的部分去除。
- 光栅化
图元信息最终被传递给光栅化单元,生成对应的片元。
- 片元着色(fragment shading stage)
这是最后一个可以通过编程控制屏幕显示颜色的阶段。在这个阶段中会使用着色器来计算片元的最终颜色和它的深度值。(顶点着色决定了一个图元应该处于屏幕的什么位置,片元着色决定了某个片元的颜色应该是什么)。
- 片元操作
在该阶段会使用深度测试和模版测试的方式来决定一个片元是否是可见的。如果一个片元成功的通过了所有激活的测试,那么他就可以直接被绘制到帧缓存中了,它所对应的像素的颜色值会被更新,如果开启了融合模式,那么对应的片元颜色会与该像素的颜色相叠加,形成一个新的颜色并写入帧缓存中。
什么是model,view,project矩阵
世界矩阵(World Matrix)、视图矩阵(View Matrix)以及投影矩阵(Projection Matirx)。
- 世界矩阵确定一个统一的世界坐标,用于组织独立的物体形成一个完整的场景。
- 视图矩阵就是我们能看到的那部分场景,由虚拟摄像机负责拍摄。
- 投影矩阵就是3维物体的平面影射.把三维场景在一个二维的平面上显示。
三种旋转表示(四元数,欧拉角,矩阵)
- 矩阵旋转
优点:旋转轴可以是任意向量。
缺点:旋转其实只需要知道一个向量+一个角度(共4个信息值),但矩阵却用了16个元素(矩阵法消耗时间和内存)。
- 欧拉角旋转
优点:容易理解,形象直观;表示更方便,只需要三个值(分别对应x、y、z轴的旋转角度)。
缺点:欧拉角这种方法是要按照一个固定的坐标轴的顺序旋转的,因此 不同的顺序会造成不同结果 ;欧拉角旋转 会造成万向锁现象 ,这种现象的发生就是由于上述固定的坐标轴旋转顺序造成的。理论上,欧拉角旋转可以靠这种顺序让一个物体旋转到任何一个想要的方向,但如果在旋转中不幸让某些坐标轴重合,就会发生万向锁现象,这时就会丢失一个方向上的旋转能力(两个旋转轴(环)重叠),也就是说在这种状态下,我们无论怎么旋转(还是按照原先的旋转顺序),都不可能得到某些想要的结果,除非打破原先的旋转顺序或者同时旋转三个轴。
- 四元数旋转
优点:可以避免万向锁;只需要一个4维的四元数就可以执行绕任意过原点的向量的旋转,方便快捷,在某些实现下比旋转矩阵效率更高;而且四元数旋转可以提供平滑插值。
缺点:比欧拉旋转稍微复杂了一点,因为多了一个维度,理解更困难,不直观。