OpenGL渲染流水线
1、固定功能渲染流水线
以前OpenGL对程序员提出的各种绘制图元或者属性的请求都采用固定的方式来处理。这种实现方式称为固定功能渲染流水线(fixed-function rendering pipeline)。也是前面一段时间我们学习的OpenGL流水线的实现方式。实现OpenGL最初的内部流程是一组有序的处理步骤,如下:
流水线阶段是固定的,它们无论接受什么样的输入数据都会执行特定的操作。不同类型的信息都被上图所示的流水线中的上半或者下半部分处理。几何图元由图中的上半部分进行处理,而像素由下半部分处理。
在几何流水线中,图元被描述为一些顶点的集合,同时还包含额外的属性信息,如材质、纹理坐标、法向量等。顶点操作和图元装配阶段对这些信息进行大量的处理。顶点经过了建模和观察变换。如果允许自动生成纹理的话,将会用计算出的新的纹理坐标来代替顶点中记录的初始纹理坐标的标值。在裁剪和阴影计算之后,进一步完成光照计算。最后图元被光栅化,即确定每个图元转换为哪些位置的像素。
处理像素信息的方式也是类似的。像素数据从主存、像素缓存、纹理缓存或帧缓存中取得。对这些数据进行处理后将结果写入纹理内存(如果正在进行纹理映射)或者重新光栅化。
完全光栅化的几何和像素数据被合并到一起,并构成一组”片元”fragment。片元的数据结构就是记录每个像素,包含了所有需要随时更新并记入帧缓存的信息。片元一旦被创建,就交给片元处理阶段,在这个阶段完成最终的向显示格式的转换。如果一个片元完成了纹理映射,它就会包含那些通过纹理内存中的信息生成的纹素;在需要的时候还可以进行雾气和反走样处理。最后完成深度缓存测试,片元的最终处理结果被写入帧缓存。
2、可编程功能渲染流水线
传统的固定功能流水线的一个问题是它不能很好地处理与现代图形硬件工作方式相配合。下图所示,固定的顶点操作和片元操作阶段被可由用户编程控制的处理阶段替代。
着色语言(GLSL)
OpenGL着色语言(GLSL)看上去很像C语言,它由OpenGL实现进行编译和连接,并且(经常是)完全在图形硬件使能够运行。基本着色器架构如下图:
OpenGL实现了我们通常所说的渲染光线(rendering pipeline),它是一系列数据处理过程,并且将应用程序的数据转换到最终渲染的图像。如下图所示
对于OpenGL应用程序而言,着色器扮演了一个最主要的角色。所有的OpenGL程序都需要这两个着色器:一个顶点着色器、一个片段着色器。所以一个用来渲染图像的OpenGL程序需要执行的主要操作如下:
从OpenGL的几何图元中设置数据,用于构建形状。
使用不同的着色器(shader)对输入的图元数据执行计算操作,判断它们的位置、颜色,以及其他渲染属性。
将输入图元的数学描述转化为与屏幕位置对应的像素片元(fragment)。这一步也称为光栅化(rasterization)。
最后,针对光栅化过程产生的每个片元,执行片元着色器(fragment shader),从而决定这个片元的最终颜色和位置。
如果有必要,还需要对每个片元执行一些额外的操作,例如判断片元对应的对象是否可见,或者将片元的颜色与当前屏幕位置的颜色进行融合。