《计算机图形学编程》笔记——第二章
OpenGL图像管线
现代3D图形学编程会使用管线的概念,在管线中,将3D场景转换为2D图形的过程被分成多个步骤。实际上,图形学做的事情,笔者是这样理解的:构建三维模型,随后采用虚拟相机对该模型进行拍摄,最终呈现在用户眼前。这个过程需要考虑成像原理、成像效果等。
图像管线介绍
采用GLSL进行编程,流程可以分为下列几步:
1. 顶点着色器
图形学中包含点、线、三角形等图元,多数3D模型通常都是由许多三角形的图元构成。图元由顶点组成,即我们所说的3D点,这些3D点的来源有多种:硬编码于程序中(即给定数组)或者从文件中载入缓冲区等方法。
不论顶点从何处传入,都会被传入顶点着色器,被逐一处理。
顶点着色器拥有一次操作一个顶点的能力。
2. 曲面细分着色器
OpenGL有一个可编程曲面细分阶段,提供一个曲面细分着色器用于生成大量三角形,通常是网格形状,同时提供各种方式操纵这些三角形的工具。
当在简单形状上需要很多顶点时,曲面细分着色器就能发挥作用了。
有时用GPU中的曲面细分着色器在硬件里生成三角形网格比在C++中生成要高效得多。
3. 几何着色器
按图元处理有很多用途,既可以让图元变形,比如拉伸或者缩小,还可以删除一些图元,从而在渲染的物体上产生“洞”——这是一种将简单模型转化为复杂模型的方法。
几何着色器拥有一次操作一个图元的能力(按图元处理)。
4. 光栅化
3D世界中的点、三角形、颜色等全都需要展现在一个2D显示器上。这个2D屏幕由光栅——矩阵像素阵列组成。
光栅化过程开始时先对三角形的每对顶点进行插值,比如渐变的颜色,实现真实光照等。
5.片段着色器
片段着色器用于为光栅化的像素指定颜色。
6. 像素操作
在绘制场景中的物体时,我们通常希望前面的物体挡住后面的物体。为了实现这个效果,我们需要隐藏面消除。
实现隐藏面消除的方法是使用两个缓冲区:颜色缓冲区和深度缓冲区实现。
代码及结果
这一讲中,我们将书中的代码进行整理并修改,使其适用于Linux系统。
详情可以参考代码:cg_book_practice/chapter_2/
我们对每一个测试代码都输出了可视化结果,可以查看README.md文件,方便大家理解我们代码做的事情。并且代码中关键的地方,笔者都参考课本以及查阅的资料做了注释,便于理解。
BUG
这一讲中提供了:检查OpenGL和GLSL错误 相关的内容,于是笔者对关键的部分进行了Bug检查。
1. GLEW初始化:glError:2080
值得注意的是,我们发现了一个glError:2080。通过查阅资料发现,这是一个无效枚举导致的错误,多次定位以后发现是在初始化GLEW时出现的。而这个问题,笔者查了很久,最后发现是版本的问题,具体的描述可以在官网上查到:OpenGL Loading Library,emmm…纯粹来恶心人的。
另外,在Linux下初始化GLEW之前,需要设置 glewExperimental=TRUE,否则程序会直接崩溃,emmm…这也是官网提供的要求,妈蛋困扰了笔者不少时间。
2. 颜色缓冲区刷新
在实现点的增大和缩小程序中,笔者在display函数中忽略了颜色缓冲区的刷新,导致点的缩小和变大显示错误,最后发现是因为颜色缓冲区没刷新。
首先采用清除颜色缓冲区,随后采用预设的颜色填充整个缓冲区,可以实现屏幕的刷新,防止色彩滞留,与下一帧的颜色重叠,导致显示出错。
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);