OpenGL超级宝典7th简体中文-第一章:简介

NOTE

简书传送门

第一章

简介

我们从这章能学到什么

  • 什么是图形管线(Graphics Pipeline)以及OpenGL如何与它关联
  • OpenGL的起源以及它如何演变成现在的模样
  • 我们在全书中都会使用到的一些基本概念

OpenGL是一种接口,在我们的应用程序中可以用它来访问或者控制它所运行的设备的图形子系统。它所运行的设备可以从一个高端图形工作站到商用台式机、视频游戏主机甚至是一台智能手机。将这些设备的接口标准化到一个子系统可以增强移植性并且可以让软件开发者集中精力创作高品质的产品、制作更有有趣的内容以及关心他们的应用的整体效能,而不是陷于他们想要应用运行的平台的细节中。这些标准接口被称为Apllication Programming Interfaces(or APIs),OpenGL是其中之一。这一章简要介绍OpenGL,描述它如何与底层的图形子系统关联,并且提供一些OpenGL的起源和演化历史。

OpenGL和图形管线

生成一个高效能并且高容量的产品通常需要两个东西:可伸缩性(scalability)和并行性(parallelism)。在工厂中,这两个东西通过使用产品线(production lines)来达成。说来就是一个工人安装汽车的引擎,另一个安装车门,再另一个安装车轮。通过将产品的生产阶段进行重叠,每一个阶段都由一个专业的专家来专门完成这个任务,这样每一个阶段就变得更高效,然后整体生产效率就会提升。同样,通过在同一时间制作很多汽车,一个工厂可以让多个工人专门安装引擎,或者多个工人专门安装车轮,这样多辆汽车可以同时运作在产品线上,每辆车都处在完工的不同阶段。

计算机图形是同样的道理。我们的程序发送命令给OpenGL,然后OpenGL以一种尽可能高效的方式将命令发送给底层的图形硬件来产生预期的结果。在图形硬件上可能有很多命令排队等待执行(专业术语称为in flight),其中一些命令可能是完成了一部分的。一个处于后续阶段的命令可以和一个处于前期阶段的命令被并发执行,这样它们的执行就重叠了。此外,计算机图形通常由很多非常相似的重复性任务组成(例如计算一个像素该为什么颜色)并且这些任务都彼此独立–意即,一个像素的颜色与另外一个像素的颜色没有任何关系。就好像一个车间可以同时制造多个汽车,所以OpenGL可以把你给他的工作拆解开然后用它的基础元素并行完成。通过组合管线(pipelining)和并行(parallelism),现代图形处理器超乎想象的性能就被实现了。

OpenGL的目的是在我们的应用程序和底层的图形子系统中间提供一个抽象层(abstraction layer),图形子系统通常是一个硬件加速器(由一个或多个自定义的高性能处理器和专用内存、显示输出等等构成)。这个抽象层可以使我们的应用程序不必知晓谁是制造的图形处理器(或者叫GPU - 图形处理单元)、它如何工作、它工作得好不好。当然我们的应用程序仍然可以获知这些信息,重要的是我们的应用程序不必如此。

作为一个设计原则,OpenGL必须在抽象层次的过高与过低之间取得平衡。一方面,它必须隐藏不同制造商的产品的区别(或者同一厂商的不同产品)和平台相关的特性,比如:显示屏分辨率、处理器架构、安装的操作系统等等。另一方面,它的抽象层次要低到可以让程序员获得底层硬件的访问权限并且充分利用它。如果OpenGL展现过高的抽象层次,这样它就可以很容易地用来创造符合它的样式的程序,但却很难使用到它未包含的图形硬件的高级特性。这种高层次抽象的样式有一些软件用到,如:游戏引擎–为了让基于它构建的游戏访问到新的图形硬件特性通常需要对引擎做出很大量的改变。如果抽象层次过低,应用程序需要关心它们所运行的平台的架构特性。低层次抽象在比如视频游戏主机中比较普遍,但这种抽象层次的图形库不能跨平台支持从移动手机到游戏的个人电脑甚至高性能专业的图形工作站。

随着技术的发展,计算机图形进行了越来越多的研究,最佳实践被开发出来,瓶颈和需求在变化,所以OpenGL也必须不断变化赶上时代。

大多数OpenGL实现都基于当前最先进的图形处理单元,可进行多个每秒万亿次浮点运算的运算能力、拥有好多G每秒吞吐量好几百G的内存、并且可以驱动多个几百万像素高频刷新的显示器。GPU也超级灵活,以至于可以处理跟图形完全不沾边的任务,比如:物理模拟、人工智能、甚至音频处理。

如今的GPU由大量的小型可编程处理器(被称为shader cores)组成,这些shader cores运行一种叫做着色器(shaders)的迷你程序。每个core有相对较低的吞吐量、在一个或多个时钟周期内处理shader的一条指令,并且一般缺少高级的特性,比如: 无序执行、分支预测、超标量技术等等。但每个GPU都可能包含从几十个到几千个这样的core,当它们聚集在一起时可以完成一个巨量的工作。图形系统被分解为多个阶段(stages),每个阶段被用一个shader或者固定功能函数(fixed-function)、可能可配置的处理区块表示。图示1.1展示了一个精简的图形管线的概要。

在图示1.1中,圆角矩形框(如Vertex fetch)表示固定功能函数阶段,而方角矩形表示可编程的阶段,意即它们会执行你提供的着色器。实际上有些固定功能函数阶段或者全部的也会真正使用着色器代码来实现–只不过不是我们提供的代码,而是通常由GPU厂商当做驱动程序的一部分、固件或者其他系统性软件提供。

OpenGL的起源和演化

OpenGL起源于Silicon Graphics公司和它的IRIS GL。当时GL表示(现在仍表示)图形库(Graphics Library)的意思并且在很多现代的OpenGL文档中你会看到术语”the GL”,它表示特定图形库(“the graphics library”),这也是源于当时。Silicon Graphics曾经是一家高端图形工作站生厂商。曾有非常昂贵并且私有专利性的图形API。很多其他生厂商制造更便宜的解决方案运行于兼容其他生厂商的API之上。90年代早期,SGI意识到可移植性的重要性,于是他们决意清理IRIS GL,移除API中与特定系统关联的部分并把它当做一种开放标准进行发行,这个开放标准可被任何人无须专利地进行实做。初见成型的OpenGL第一个版本在1992年6月发行并被标记为OpenGL 1.0。

同年,SGI帮助成立了OpenGL架构评审委员会(OpenGL Architectural Review Board - ARB),原始的成员包含有Compaq,DEC,IBM,Intel以及Microsoft。很快,其他公司,诸如: Hewlett Packard, Sun Microsystem, Evans&Sutherland以及Intergraph也加入到委员会中。OpenGL ARB是设计、控制并且创作OpenGL标准的主体,现在它是Khronos Group的一部分,Khronos Group是一个更大的多家公司的联合机构用以监督很多开放标准的开发。这些原始成员的一些有的不存在了(可能退出商业市场或者被其他公司收购或合并),有的退出了ARB。

本书创作的当时,OpenGL已发行有19个版本。它们的版本号和发行日期如下(本书讲述版本4.5):

Version                         Publication Date
OpenGL 1.0                      1992.1
OpenGL 1.1                      1997.1
OpenGL 1.2                      1998.3
OpenGL 1.2.1                    1998.10
OpenGL 1.3                      2001.8
OpenGL 1.4                      2002.7
OpenGL 1.5                      2003.7
OpenGL 2.0                      2004.9
OpenGL 2.1                      2006.7
OpenGL 3.0                      2008.8
OpenGL 3.1                      2009.3
OpenGL 3.2                      2009.8
OpenGL 3.3                      2010.3
OpenGL 4.0                      2010.3
OpenGL 4.1                      2010.7
OpenGL 4.2                      2011.8
OpenGL 4.3                      2012.8
OpenGL 4.4                      2013.7
OpenGL 4.5                      2014.8

OpenGL核心档案(Core Profile)

在刀刃技术(电子芯片切割)的开发中,20年是一个很长的时间。在1992年,顶尖的Intel CPU是80486,数学协处理器还是可选的,并且奔腾(Pentium)也还未发明(至少没发行)。苹果电脑还在使用摩托罗拉68K衍生处理器,后来切换到的PowerPC处理器是1992年下半年才可用。在商用家用计算机上高性能图形加速基本什么也不是。如果你没有一台高性能图形工作站,你可能不会想用OpenGL来干什么事。软件渲染主宰世界,Future Crew的Unreal示例赢得Assembly的1992示例聚会。对于一台家用计算机,你能期望的最好的渲染能力就是一些填充的多边形或者精灵。1992的家用计算3D图形艺术的状态如图示1.2:

随着时间的推移,图形硬件的价格走低,性能上升以及可用于家用计算机的廉价加速板卡和视频游戏主机性能提升的一些因素,新的功能和能力在不太昂贵的图形处理器上展现出来并加入到OpenGL。这些功能的极大一部分由OpenGL ARB成员在扩展(extensions)中进行提案。有一些扩展与其他的扩展和OpenGL现有的功能可以很好的交互,有一些不能。同时,新的、更好的榨干图形系统性能的手段被发明,它们都被加入到OpenGL,于是做同一件事有了多种方案。

长久以来,ARB向后兼容上花了很大力气,现在仍然如此。但是,这种向后兼容带来一个可观的消耗。在1990年代中期可以很好工作或者其实不是瓶颈的图形硬件并不能很好适应如今的图形处理器。指定新的功能如何与旧的传统的功能交互并不容易,而且很多时候使得干净地引入一个新功能到OpenGL几近不可能。对于实做OpenGL来说,这种兼容性也变成了一项艰巨的任务,它导致驱动程式更容易出错,而且图形厂商也需要花费可观的精力来维护所有的传统功能,而这些功能对图形技术的发展和变革没有任何用处。

基于这些原因,在2008年,ARB决意将OpenGL标准变更为两份档案(profile)。第一个为核心档案(core profile),它移除了许多传统功能,只保留了如今的图形硬件真正会加速的功能。这份标准比旧的标准少了好几百页,旧的标准称为兼容档案(compatibility profile)。兼容档案维护了从1.0到现今的所有版本的兼容性。意即1992年编写的软体应能编译并且以几千倍的效率提升运行于现今的图形卡上。

不过兼容档案的存在可以让软体开发者为传统的应用添加新功能而不必为了迁移到新的API白费好些年的努力。然而核心档案是大多数OpenGL专家推荐新的应用使用的档案。特别是在某些平台上,新的功能只能在核心档案下使用,从其他方面来讲,使用核心档案的应用通常会快于兼容档案,即使应用不经过任何修改,仅仅是请求兼容档案,甚至于只使用核心档案的功能。总而言之,如果一个功能在兼容档案中但从核心档案中被移除,我们最好就不要使用这个功能。

本书只会涉及到核心档案。

图元(Primitives)、管线(pipelines)、像素(pixels)

正如我们讨论过的,OpenGL的模型就好比一条生产线或者管线。数据流在这个模型中通常是单一路经的,数据通过我们的程式调用的命令进入管线的开端,然后流过一个一个阶段直到管线的末端。在这个路经当中,管线中的着色器或者固定功能函数可以从缓冲区(buffers)或者材质(textures)提取更多的数据,缓冲区和材质是用来在渲染中存取信息的结构。管线中有一些阶段甚至可能会向缓冲区或者材质存入数据,从而让应用读写数据甚至反馈发生了什么。

OpenGL中基本的渲染单元称为图元(primitive)。OpenGL支持许多图元类型,但三种基本的可渲染图元为:点(points)、线(lines)、三角形(triangles)。我们在荧屏上看到的渲染的任何东西都是点、线和三角形的集合。在应用中一般会把复杂的表面(surfaces)拆解成许多三角形然后发送给OpenGL通过一个叫做光栅器(rasterizer)的硬件加速器进行渲染。三角形相对来说是非常容易绘制的。对于多边形、三角形通常是凸面的,所以填充规则很容易设计和遵循。凹多边形总是能拆解成两个或多个三角形,所以硬件天然地支持直接渲染三角形并且依赖其他子系统将复杂几何形体拆解为三角形。光栅器是专门用来将三维形式的三角形转换为在荧屏上进行渲染的像素的硬件。

点、线以及三角形分别是由一个、两个或者三个顶点(vertices)集合组成的。一个顶点(vertex)就是一个坐标空间的点。在我们的场景中,我们主要考虑一个三维坐标空间。图形管线被拆解为主要的两部分。第一部分是前端(front end),处理顶点和图元,最后把它们组成为点、线和三角形传递给光栅器。这个过程被称为图元组装(primitive assembly)。光栅器处理之后,几何图形已经被转变成大量的独立的像素。这些都是交给后端的(back end)的,它包括深度(depth)测试和模板(sencil)测试,片段着色(fragment shading),混合(blending)以及更新输出图像。

随着我们阅读本书,我们会看到如何让OpenGL开始为我们所用。我们会看到如何创建缓冲区和材质并和我们的程式关联。我们会看到如何编写着色器来处理我们的数据以及如何配置OpenGL的固定功能函数块来做我们想做的。OpenGL其实就是一大串非常简单的概念,它们互相依存。拥有坚实的基础以及对这个系统的概览是很非常重要的,在接下来的几个章节,我们将提供这些。

总结

在这一章我们简单介绍了OpenGL并了解了它的一点起源、历史、状态和方向。我们已经看到了OpenGL管线以及本书如何构成。我们提及了一些将会贯穿本书的专业术语。在接下来的几个章节,我们会创建第一个OpenGL程式,稍微深入到OpenGL管线的各个阶段,并打下一些在计算机图形世界非常有用的数学基础。

你可能感兴趣的:(Game,C)