第一章 OpenGL概述
标签(空格分隔): OpenGL
1.1 什么是OpenGL
OpenGLwikipedia是一种应用程序编程接口(API),它是一种可以对图形硬件设备特性进行访问的软件库。
一个用来渲染图像的OpenGL程序需要执行的主要操作如下:
1. 从OpenGL的几何图元中设置数据,用于构建形状。
2. 使用不同的着色器(shader)对输入的图元数据执行计算操作,判断它们的位置、颜色,以及其他渲染属性。
3. 将输入图元的数学描述转化为与屏幕位置对应的像素片元(fragment)。这一步也称为光栅化(rasterization)。
4. 最后,针对光栅化过程产生的每个片元,执行片元着色器(fragment shader),从而决定这个片元的最终颜色和位置。
5. 如果有必要,还需要对每个片元执行一些额外的操作,例如判断片元对应的对象是否可见,或者将片元的颜色与当前屏幕位置的颜色进行融合。
何为光栅化(rasterization)?
将输入图元的数学描述转换为与屏幕位置对应的像素片元,称为光栅化。
1.2 初识OpenGL程序
一些图形学名词:
1. 几何图元,包括点、线、三角形以及Patch。
2. 渲染(render),表示计算机从模型创建最终图像的过程。
3. 着色器(shader),专为图形处理单元(GPU)编译的一种小型程序。
4. 四种不同的着色阶段(shander stage),其中最常用的包括顶点着色器(vertex shader)以及片元着色器,前者用于处理顶点数据,后者用于处理光栅化后的片元数据。所有OpenGL程序都需要用到这两类着色器。
5. 帧缓存(framebuffer),像素(pixel),是显示器上最小的可见单元。计算机系统将所有的像素保存到帧缓存当中,后者是有图形硬件设备管理的一块独立内存区域,可以直接映射到最终的显示设备上。
例1.1 第一个OpenGL程序triangles.cpp
代码(坚果云)
在VS 2013上实现,其中包含了红书官网所提供的源文件中的头文件,以及其中的库文件。运行结果如下:
1.3 OpenGL语法
本书所使用的GLUT(OpenGL Utility Toolkit)版本为Freeglut,是原始GLUT库的一个新变种。
1.4 OpenGL渲染管线
rendering pipeline,它是一系列数据处理过程,并且将应用程序的数据转换到最终渲染的图像。下图为OpenGL4.3版本的管线。包括:
顶点数据,顶点着色器,细分着色器(细分控制着色器,细分计算着色器),几何着色器,图元设置,剪切,光栅化,片元着色器
1.4.1 准备向OpenGL传输数据
OpenGL需要将所有的数据都保存到缓存对象(buffer object)中。
我们可以使用多种方式创建这样的数据缓存,最常用的是glBufferData()wiki。
Buffer Objects are OpenGL Objects that store an array of unformatted memory allocated by the OpenGL context (aka: the GPU). These can be used to store vertex data, pixel data retrieved from images or the framebuffer, and a variety of other things.
–from wiki
1.4.2 将数据传输到OpenGL
当将缓存初始化完毕后,通过调用OpenGL的一个绘制命令来请求渲染几何图元。glDrawArrays()wiki就是一个常用的绘制命令。OpenGL的绘制通常就是将顶点数据传输到OpenGL服务端。
1.4.3 顶点着色
对于绘制命令传输的每个顶点,OpenGL都会调用一个顶点着色器来处理顶点相关的数据。
只是将数据复制并传递到下一个着色阶段,叫做传递着色器(pass-through shader)。
通常来说,一个复杂的应用程序可能包含许多顶点着色器,但在同一时刻只能有一个顶点着色器起作用。
1.4.4 细分着色
顶点着色器处理每个顶点的关联数据之后,如果同时激活了细分着色器,那么它将进一步处理这些数据。(第9章介绍)
细分着色器阶段会用到两个着色器来分别管理Patch数据并产生最终的形状。
1.4.5 几何着色
第10章介绍。
1.4.6 图元装配
图元装配将顶点及相关的集合图元之间组织起来,准备下一步剪切和光栅化操作。
1.4.7 剪切
顶点可能落在视口(viewport)之外,此时与顶点相关的图元会做出改动,以保证相关的像素不会在视口外绘制。剪切(clipping)由OpenGL自动完成。
1.4.8 光栅化
将更新后的图元(primitive)传递到光栅化单元,生成对应的片元(fragment)。我们将一个片元是为一个“候选的像素”。也就是可以放置在帧缓存(framebuffer)中的像素,但是它也可能被最终剔除,不再更新对应的像素位置。之后两个阶段将会执行片元的处理。
1.4.9 片元着色
最后一个可以通过编程控制屏幕上显示颜色的阶段。在Fragment Shader阶段中,我们使用着色器计算片元的最终颜色和它的深度值。
顶点着色器与片元着色器之间的区别:
顶点着色(包括细分和几何着色)决定了一个图元应该位于屏幕的什么位置,而片元着色使用这些信息来决定某个片元的颜色应该是什么。
1.4.10 逐片元的操作
在这个阶段会使用深度测试(depth test,或者通常也称为z-bufffering)和模板测试(stencil test)的方式来决定一个片元是否是可见的。
1.5 第一个程序:深入分析
1.5.1 进入main()函数
int main (int argc, char ** argv)
{
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_RGBA);
glutInitWindowSize (512, 512);
glutInitContextVersion (4, 3);
glutInitContextProfile (GLUT_CORE_PROFILE);
glutCreateWindow (argv[