2 OpenGL

来源:互联网 发布:管家婆支持远程网络吗 编辑:程序博客网 时间:2024/06/05 08:39
本文译自www.learnopengl.com,作者Joey de Vries.

在开始我们的旅程之前,我们首先要明确什么是OpenGL。OpenGL主要被认为是为我们提供了用来操作图形和图片的一系列函数的API(Application Programming Interface应用程序编程接口)。然而,OpenGL本身却不是一个API,它仅仅Khronos Group开发维护的一个规范(译注:GL代表Graphics Library,图形库,所以OpenGL代表开放图形库)。

openglOpenGL规范定义了每个函数应该如何执行以及返回什么结果。开发者需要实现这个规范的函数的具体内容。由于OpenGL规范不会为我们提供实现细节,这样OpenGL的实际开发版本就允许拥有不同的实现同时存在,只要它们遵守这个规范就可以了(对使用者来说也是一样的)。

OpenGL库实际的开发者通常是显卡厂商。你所购买的每个显卡支持的是特定的OpenGL版本,这个版本是为这个显卡(系列)开发的特定OpenGL版本。用一个苹果系统时,OpenGL库就由苹果自己维护,Linux下,同时存在着显卡供应商的版本和爱好者适配的这些库。这也意味着,无论何时,如果OpenGL本身出现奇怪的行为都是不可能的,如果出现了,那么极有可能是显卡厂商的错(或者开发/维护库的人)。

由于大多数实现都是由显卡厂商创建的。所以任何时候实现中都存在bug,这通常可以通过更新显卡驱动来解决;这些驱动包含你的显卡所支持的OpenGL最新版本。这就是建议偶尔更新一下显卡驱动的原因。

Khronos公开提供所有OpenGL版本的规范文档。感兴趣的读者可以从这里获得OpenGL3.3规范文档(这是我们所使用的),如果你想研究OpenGL细节,这是很好的材料(需要注意的是,它们基本上是描述结果而不是实现它)。这个规范为我们找到某个函数的工作方式,也提供了一个很好的参考。

 

Core-profile和快速模式(Immediate mode)

在过去,使用OpenGL就意味着在快速模式下开发(fixed function pipeline也称为固定函数输送管道),这是一种简单易用的绘图方式。OpenGL的大多数功能隐藏在库中,开发者没有用自己的方式去计算的自由。后来开发者对具有更多的伸缩性的功能非常期待,随着时间的推移,规范变得更加灵活,开发者获得了更多的图形控制权。快速模式很容易使用,而且容易理解,但是效率低下。正是这个原因,从3.2版起,快速模式开始成为不建议使用的功能了,规范转而鼓励开发者使用OpenGL的core-profile模式,这种模式是OpenGL规范的一个子集,它移除了所有过时的不建议使用的功能。

当使用OpenGL的core-profile模式时,OpenGL强制我们使用现代函数。无论何时何地,如果我们使用不被推荐的函数,OpenGL就会发出一个错误并停止绘制。学习现代模式的一个好处是它非常灵活高效,但是也带来了难学的问题。OpenGL快速模式对实际运行的操作做了非常多的抽象,所以学起来容易掌握OpenGL的背后的工作原理却比较难。现代方式需要开发者不仅真正懂得OpenGL,而且也要掌握图形编程,这是难点所在。它提供了更高的灵活性和效率,更重要的是让我们更好的理解图形编程。

这也是我们的教程把目标定在OpenGL3.3版core-profile模式的原因。尽管更难,但是值得去做。

如今,更高版本的OpenGL也发布了(写作本文时是4.5),你可能会问:4.5发布了,为什么我们还要学3.3?这个问题的答案很简单。所有新版本的OpenGL都是以3.3为基础,添加了额外的有用特性,OpenGL的核心机理并没有发生变化;新版稍微引进了一些更高效或有用的方式来完成同样的任务。结果就是只要是现代OpenGL的版本,所有的理念和技术便都一致的,所以学习OpenGL3.3完美无缺。一旦你已经足够熟练,你可以轻松使用OpenGL近期最新版本获得新功能。

使用最新版OpenGL中的功能时,只有最新的显卡才支持。开发者通常将目标锁定于低版本OpenGL、选择性地支持高版本。

在一些教程里,你有时会从这种注释方式中发现更多的现代特征。

 

扩展

OpenGL的一大特性是它支持扩展。任何时候,一个显卡厂商推出了一个新技术或者是巨大的渲染优化,都可以在驱动中发现扩展实现。如果一个应用运行在支持这样一个扩展的硬件上,开发者就可以使用扩展里所提供的功能,以获得更高级或高效的图形处理能力。通过这种方式,图形开发者无需等待新版本OpenGL发布,仍然可以使用最新的渲染技术,只要简单地检查一下显卡是否支持就行了。通常,当一个扩展被证明很流行或者很有用,它就会变成未来的OpenGL版本的一部分。

像这样来使用扩展:

对于大多数技术来说,使用OpenGL3.3已经足够了,我们几乎不需要用到扩展,但是如果某处需要扩展的支持,我们会提供说明。

 

状态机

OpenGL本身是个大状态机:一系列定义了OpenGL该如何操作的变量。OpenGL的状态通常被称为OpenGL环境(context)。当使用OpenGL时,我们经常设置一些选项,操作一些缓冲,改变它们的状态,然后使用当前的环境渲染

比如,当我们告诉OpenGL,我们现在想要绘制线了,不再绘制三角形了,我们就改变一些环境变量来改变OpenGL的状态,这些变量设置了OpenGL该如何绘制。我们告诉了OpenGL应该绘制线,也就是改变了它的状态,下面的绘制命令将会以绘线替代绘制三角形。

当使用OpenGL的时候,我们会遇到多种状态改变函数,这些函数改变环境;也会遇到多个状态使用函数,这些函数基于当前OpenGL的状态执行一些操作。只要你记着OpenGL就是一个大状态机,大多数功能看上去会变得更有意义起来

 

对象

OpenGL的库是用C写的,也允许其他语言中的派生的存在,但是它的内核仍然是一个C库。由于C语言不能表达出其他更高级语言的概念(理念)。OpenGL便开发出了几种自己特有的抽象概念对象就是这些抽象概念中的一个。

OpenGL的对象就是一个可选项的集合,而此集合是OpenGL状态的一个子集。比方,我们现在有一个对象,这个对象指代渲染所用的窗口的设置的一切;我们可以设置它的尺寸,所支持的颜色等等。可以把对象想象为C语言中的结构体:

自有类型

注意,当时用OpenGL的时候,建议使用OpenGL定义的自有类型。在写float的时候在前面加GL;对于int、char、bool也同样处理。各种操作系统可能对于各自的类型有不同的内存布局,而OpenGL的GL自有类型的内存布局是跨平台的。所以使用OpenGL的自有类型可以保证你的应用可以跨平台。

无论何时何处,我们都这样使用对象(OpenGL的环境可以想象为一个大结构体):

上面的代码是在OpenGL中会频繁遇到工作流。我们先创建一个对象,把它的引用储存为一个id(真实的对象数据在场景后台储存)。然后我们把对象绑定到环境(contex)的目标(target)位置(例子窗口对象的目标位置定义为GL_WINDOW_TARGET)。下一步我们设置窗口选项,最后把窗口目标的当前对象id设置为0解绑对象。我们设置的选项被储存在对象的引用objectId上面,把对象解绑,GL_WINDOW_TARGET立刻恢复。

目前提供的代码只是描述OpenGL操作原理;通读教程,你会见到到实际例子。

使用这些对象的好处是,在我们的应用中,可以定义多个对象,分别设置它们的选项,然后当我们进行某个操作,需要使用OpenGL的状态的时候,我们只需绑定带有我们需要的某些设置的对象。例如有几个箱子(一匹马或者一个人物)对象作为3D模型数据,当我们想绘制出它们中的一个的时候,我们就把我们想要绘制的箱子对象(我们先要创建对象,并设置这些对象的选项)进行绑定。有多个模型对象被定义,当我们想要绘制特定的模型时,只要在绘制前简单绑定相应的对象,就不用再设置它们的选项了。

 

让我们开始吧

你现在已经知道OpenGL是一个规范和库,OpenGL通用操作,和一点使用OpenGL的惯用技巧。没有理解其中全部也不要担心;通过教程,我们会掌握每一步,你会看到足够的例子来掌握OpenGL。如果你准备好开始下一步了,我们就来创建一个OpenGL环境,下一节内容在这里。

 

附加资源

  • opengl.org:OpenGL官方网站
  • OpenGL registry:寄存着所有版本的OpenGL规范和扩展

①译注:OpenGL的状态机是为人所诟病的主要问题,用现在的眼光看是相当过时的,并不难,但是有点怪。

②译注:这些抽象概念虽与你平时所见的流行概念用词一致但实际含义并不一致,这点需要注意。


转载自:点击打开链接

0 0
原创粉丝点击