计算机图形学·4 OpenGL编程1 背景知识
本文是记录专业课“计算机图形学”的部分笔记,参考教材为Angel的第八版交互式计算机图形学——基于WebGL 2.0的自顶向下方法。
1、如果想了解API发展历史的话,大致看来是1973年IFIPS(国际信息处理学会联合会)的GKS(远远落后于硬件进展)——>从CAD社区诞生的PHIGS(程序员级的交互式层次图形系统,带有保留图形的数据库模型)、X Window System(带有图形的客户端-服务器架构)与PEX(网络窗口环境下的PHIGS)——>1982年的SGI(Silicon Graphics,通过在硬件中实现流水线来优化图形工作站)以及为了访问该系统诞生的GL库——>1992年的跨平台OpenGL(贴近硬件、强调绘制、平台独立),其体系结构审查委员会(ARB)在2006年被Khronos取代。
2、在现代OpenGL中,我们通过着色器(shaders)来控制GPU,应用程序的任务是将数据发送到GPU,而GPU负责所有绘制工作。本课堂中使用OpenGL 3.1的版本,它的特性有:①完全基于着色器(无默认着色器,每个应用程序都必须同时提供一个顶点着色器和一个片元着色器);②无立即模式;③状态机减少;④大多数2.5版本的函数被弃用;⑤不必向后兼容。
3、其他的如OpenGL ES是服务嵌入式系统的、WebGL是用于网页的OpenGL ES 2.0的JavaScript实现(支持较新版本的浏览器)、OpenGL 4.1和4.2添加了几何着色器和网格器。那么Direct X呢?它的优点是能更好地控制资源、访问高级功能,缺点是新版本不向后兼容、仅限Windows,不过着色器的最新进展正使其与OpenGL趋于一致。
4、OpenGL Libraries介绍如图。其中需要特别说明的是OpenGL Utility Toolkit (GLUT,实用程序工具包),它提供所有窗口系统共有的功能(如Open a window、Get input from mouse and keyboard、Menus、Event-driven),其代码具有可移植性,但GLUT牺牲了针对特定平台的优秀工具包的功能(如slide bars)。

不过GLUT是老东西了,虽然很奇妙它居然还能在OpenGL 3.1上运行,但还是有些功能无法运行。FreeGLUT是GLUT的更新,新增了一些功能以及上下文检查。
5、此外,OpenGL Extension Wrangler Library(扩展库,glew库)也需要额外说明,它使得访问特定系统上可用的OpenGL扩展变得容易、避免了在Windows代码中设置特定的入口点,应用程序只需包含glew.h并运行glewInit()即可。比如,针对window只支持OpenGL1.1的函数的问题(如果要使用后续版本OpenGL的高级特性,就必须下载最新的扩展)、不同的显卡公司会发布一些只有自家显卡才支持的扩展函数的问题(不得不去寻找最新的glext.h),都可以用一个glew.h头文件解决,你就能使用gl、glu、glext、wgl、glx的全部函数。
6、OpenGL架构示意图如下图所示,这里的Polynomial Evaluator是多项式求值器。

OpenGL的软件架构如下图所示,"Motif"特指 1980 年代的 UNIX 图形标准(现为开源工具包),Widget则指界面控件元素。



硬件实现和上图几乎一样,就是Software改成Hardware,Hardware的出箭头指向Display Device,且新增了Display Device到GDI的箭头。
7、OpenGL是一个状态机,其函数有两类:①Primitive generating图元生成(实现可见图元的输出,负责顶点如何被处理以及图元的外观如何被状态控制);②State changing状态改变(如Transformation functions变换函数和Attribute functions属性函数,在3.1版本大多数状态变量由应用程序定义,并发送给着色器)。其他如控制(GLUT)、输入(GLUT)、Query查询这里不做讨论。
8、需要注意的是,OpenGL不是面向对象的,因此对于给定的逻辑功能,存在多个函数,如glVertex3f、glVertex2i、glVertex3dv。不过它们的底层存储模式是相同的,在C++中创建重载函数也很容易,但问题是效率问题。具体的,函数格式如图所示:

对于#define,大多数常量是在包含文件gl.h、glu.h和glut.h中定义的,而#include <GL/glut.h> 会自动包含其他头文件,如glBegin(GL_POLYGON)、glClear(GL_COLOR_BUFFER_BIT)。include文件当然还定义了OpenGL的数据类型如GLfloat、GLdouble等等。
9、首先让我们实现一个最简单的程序,在纯色背景上生成一个正方形:

可以看到,该程序定义了一个名为mydisplay的显示回调函数(display callback),每个glut程序都必须有一个显示回调函数,每当OpenGL判断必须刷新显示时,例如当窗口打开时,就会执行显示回调。主函数结束时,程序进入事件消息循环(event loop)。
不过这个例子有些太简单了,我们大量使用了状态变量的默认值,如Viewing、颜色(设置背景颜色为纯白色 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);)、窗口参数。
10、如果想要自己配置环境,我们推荐Visual C++,可以从网上获取glut.h、glut32.lib和glut32.dll文件、创建一个控制台应用程序、直接将opengl32.lib、glut32.lib添加到项目中。


