看完OpenGL 编程指南(第八版)已经有一段时间了,一直想整理一下这本书的知识。我将会按书中的章节,每一章一篇博客,讲述一下书中一些对于初学者难理解的点。
书中有很多例子,随书的源代码实现的例子并不多,而且很多例子有些错误没法运行。我用VS2015重新对随书源代码进行里整理,全部使用VS2015运行测试通过。对于书中很多没有实现的例子,我也进行了实现。
OpenGL 编程指南学习资料以及我整理的代码下载地址https://pan.baidu.com/s/1bqrcspD
文中提到的代码为下载文件中的“OpenGL编程指南 VS2015代码.zip”文件,代码也可以到github上下载:https://github.com/Kylewlk/OpenGL-Programming-Guide-8th-Edition-Code
1 OpenGL概述
OpenGL是一套跨平台图形接口API规范。OpenGL之所以跨平台是因为各个平台都有根据OpenGL规范实现相应的API接口,在Windows,Linux,Mac OS X等平台都有各自的实现,各个平台会提供OpenGL的程序接口。OpenGL提供了一套图形接口API,而图形主要由显卡控制,所以OpenGL相当于一套操作显卡的API接口,显卡厂商(NVidia,ATI等)会对提供OpenGL的驱动,使用OpenGL也就是对显卡设备进行编程。并不存在一个OpenGL开发的SDK程序包,因为OpenGL只是一套规范,具体的实现与平台相关,且与显卡厂商相关。
使用OpenGL
创建窗口和事件处理
OpenGL只是一套图形接口,并没有包含窗口的创建,鼠标键盘事件的处理,这些本身与平台相关而且复杂繁琐。为了处理这部分工作,我们使用了一个免费开源跨平台库freegult(https://sourceforge.net/projects/freeglut/),使用freegult可以很简单的创建OpenGL窗口处理窗口事件。Freegult官网提供可源代码,源代码使用的是cmake工程,我们可以使用cmake生成我们想要的工程文件,如VS2010,VS2015,makefile等等。
OpenGLAPI访问
因为OpenGL规范是不断在更新的,而操作系统更新并没有这么频繁,所以平台提供的OpenGL头文件和lib文件(windows上为gl.h和opengl32.lib)很难与最新版本OpenGL一致。为了防止编译链接错误,所以采用函数指针的方式访问OpenGL API。在Windows平台上用来获取OpenGL API函数指针的函数为wglGetProcAddress(LPCSTR),只需要提供一个Opengl函数名,如果平台支持,该函数会返回相应的函数指针,如何不支持则返回空指针。这部分工作也跟平台相关,且需要考虑各个OpenGL的版本,为了处理这部分工作我们使用了另一个开源跨平台库glew(http://glew.sourceforge.net/)。该库可以自动识别平台和OpenGL版本,并加载相应的函数。因为该库代代码量不多,文件(glew.h/glew.c)很少,我一般直接将该库代码包含到项目中使用。
本书中所有例子都使用了这两个库,Freegult和Glew。
绘制流水线
虚线框中的步骤是可以省略,其他步骤每次渲染都会有,各个过程具体内容参见书籍。
程序例子分析
程序运行结果,如下图,绘制了两个三角形,具体代码分析见书籍。
这是一个很简单的例子,例子使用了上文提到的Freegult和Glew两个库。
例子的绘制管线如下,重点关注三个红框中的步骤,其他步骤书本后续有讲解:
顶点数据
OpenGL使用的是规格化设备坐标(NormalizedDevice Coordinate, NDC),规格化设备坐标的范围为[-1.0, 1.0]之间,即OpenGL中x, y, z的坐标必须在[-1.0, 1.0]之间,超出范围的片元(目前可以把片元理解为像素)会被剪切掉,不会显示。Z轴这里不讨论,先讨论x, y轴。例子中x, y数据具体与绘制窗口(视口viewport)对应如下,窗口中心为(0,0)点:
例子中绘制了两个三角形,三角形的数据如下:
GLfloat vertices[NumVertices][2] = {
{-0.9f,-0.9f},
{0.85f,-0.90f},
{-0.90f,0.85f},
{0.90f,-0.85f},
{0.90f,0.90f},
{-0.85f,0.90f} };
三角形1的数据为(0.90, -0.85), (0.90, 0.90), (-0.85, 0.90)
三角形2的数据为(-0.9,-0.9), (0.85,-0.90), (-0.90, 0.85)
顶点着色器
例子中有6个顶点数据,所以每次渲染会执行6次顶点着色器,每个顶点执行一次。
片元着色器
片元着色器执行次数与两个三角形覆盖的片元(像素)个数有关,每个片元会执行一次,肯定远大于6次。
着色器程序都是在显卡中执行,显卡一般都几百上千个处理单元,可以同时并行执行一个过程的着色器程序,所以不用担心顶点和片元着色器的速度问题。