@@ -7,7 +7,7 @@
校对 | Geequlim
在开始这段旅程之前我们先了解一下OpenGL到底是什么。一般它被认为是一个API(** Application Programming Interface** , 应用程序编程接口), 包含了一系列可以操作图形、图像的函数。然而, OpenGL本身并不是一个API, 它仅仅是一个由[Khronos组织 ](http://www.khronos.org/ )制定并维护的规范(Specification)。
在开始这段旅程之前我们先了解一下OpenGL到底是什么。一般它被认为是一个API(< def > Application Programming Interface</ def > , 应用程序编程接口), 包含了一系列可以操作图形、图像的函数。然而, OpenGL本身并不是一个API, 它仅仅是一个由[Khronos组织 ](http://www.khronos.org/ )制定并维护的规范(Specification)。
< img alt = "OpenGL Logo" src = "../../img/01/01/opengl.jpg" class = "right" />
@@ -23,7 +23,7 @@ OpenGL规范严格规定了每个函数该如何执行, 以及它们的输出
## 核心模式与立即渲染模式
早期的OpenGL使用**立即渲染模式**( Immediate mode, 也就是**固定渲染管线** ) , 这个模式下绘制图形很方便。OpenGL的大多数功能都被库隐藏起来, 开发者很少能控制OpenGL如何进行计算的自由。而开发者迫切希望能有更多的灵活性。随着时间推移, 规范越来越灵活, 开发者对绘图细节有了更多的掌控。立即渲染模式确实容易使用和理解, 但是效率太低。因此从OpenGL3.2开始,规范文档开始废弃立即渲染模式,推出核心模式 (Core-profile),这个模式完全移除了旧的特性。
早期的OpenGL使用< def > 立即渲染模式</ def > ( Immediate mode, 也就是< def > 固定渲染管线</ def > ) , 这个模式下绘制图形很方便。OpenGL的大多数功能都被库隐藏起来, 开发者很少能控制OpenGL如何进行计算的自由。而开发者迫切希望能有更多的灵活性。随着时间推移, 规范越来越灵活, 开发者对绘图细节有了更多的掌控。立即渲染模式确实容易使用和理解, 但是效率太低。因此从OpenGL3.2开始,规范文档开始废弃立即渲染模式,推出< def > 核心模式</ def > (Core-profile),这个模式完全移除了旧的特性。
当使用OpenGL的核心模式时, OpenGL迫使我们使用现代的函数。当我们试图使用一个已废弃的函数时, OpenGL会抛出一个错误并终止绘图。现代函数的优势是更高的灵活性和效率, 然而也更难于学习。立即渲染模式从OpenGL**实际**运作中抽象掉了很多细节, 因而它易于学习的同时, 也很难去把握OpenGL具体是如何运作的。现代函数要求使用者真正理解OpenGL和图形编程, 它有一些难度, 然而提供了更多的灵活性, 更高的效率, 更重要的是可以更深入的理解图形编程。
@@ -39,7 +39,7 @@ OpenGL规范严格规定了每个函数该如何执行, 以及它们的输出
## 扩展
OpenGL的一大特性就是对扩展(Extension)的支持,当一个显卡公司提出一个新特性或者渲染上的大优化,通常会以**扩展** 的方式在驱动中实现。如果一个程序在支持这个扩展的显卡上运行, 开发者可以使用这个扩展提供的一些更先进更有效的图形功能。通过这种方式, 开发者不必等待一个新的OpenGL规范面世, 就可以使用这些新的渲染特性了, 只需要简单地检查一下显卡是否支持此扩展。通常, 当一个扩展非常流行或者非常有用的时候, 它将最终成为未来的OpenGL规范的一部分。
OpenGL的一大特性就是对扩展(Extension)的支持,当一个显卡公司提出一个新特性或者渲染上的大优化,通常会以< def > 扩展</ def > 的方式在驱动中实现。如果一个程序在支持这个扩展的显卡上运行, 开发者可以使用这个扩展提供的一些更先进更有效的图形功能。通过这种方式, 开发者不必等待一个新的OpenGL规范面世, 就可以使用这些新的渲染特性了, 只需要简单地检查一下显卡是否支持此扩展。通常, 当一个扩展非常流行或者非常有用的时候, 它将最终成为未来的OpenGL规范的一部分。
使用扩展的代码大多看上去如下:
@@ -58,17 +58,17 @@ else
## 状态机
OpenGL自身是一个巨大的状态机(State Machine): 一系列的变量描述OpenGL此刻应当如何运行。OpenGL的状态通常被称为OpenGL**上下文 (Context)** 。我们通常使用如下途径去更改OpenGL状态: 设置选项, 操作缓冲。最后, 我们使用当前OpenGL上下文来渲染。
OpenGL自身是一个巨大的状态机(State Machine): 一系列的变量描述OpenGL此刻应当如何运行。OpenGL的状态通常被称为OpenGL<def>上下文</def> (Context)。我们通常使用如下途径去更改OpenGL状态: 设置选项, 操作缓冲。最后, 我们使用当前OpenGL上下文来渲染。
假设当我们想告诉OpenGL去画线段而不是三角形的时候, 我们通过改变一些上下文变量来改变OpenGL状态, 从而告诉OpenGL如何去绘图。一旦我们改变了OpenGL的状态为绘制线段, 下一个绘制命令就会画出线段而不是三角形。
当使用OpenGL的时候, 我们会遇到一些**状态设置** 函数(State-changing Function),这类函数将会改变上下文。以及**状态应用** 函数(State-using Function), 这类函数会根据当前OpenGL的状态执行一些操作。只要你记住OpenGL本质上是个大状态机, 就能更容易理解它的大部分特性。
当使用OpenGL的时候, 我们会遇到一些<def>状态设置</def> 函数(State-changing Function),这类函数将会改变上下文。以及<def>状态应用</def> 函数(State-using Function), 这类函数会根据当前OpenGL的状态执行一些操作。只要你记住OpenGL本质上是个大状态机, 就能更容易理解它的大部分特性。
## 对象
OpenGL库是用C语言写的, 同时也支持多种语言的派生, 但其内核仍是一个C库。由于C的一些语言结构不易被翻译到其它的高级语言, 因此OpenGL开发的时候引入了一些抽象层。“对象(Object)”就是其中一个。
在OpenGL中一个**对象** 是指一些选项的集合, 它代表OpenGL状态的一个子集。比如, 我们可以用一个对象来代表绘图窗口的设置, 之后我们就可以设置它的大小、支持的颜色位数等等。可以把对象看做一个C风格的结构体(Struct):
在OpenGL中一个<def>对象</def> 是指一些选项的集合, 它代表OpenGL状态的一个子集。比如, 我们可以用一个对象来代表绘图窗口的设置, 之后我们就可以设置它的大小、支持的颜色位数等等。可以把对象看做一个C风格的结构体(Struct):
` ``c++
struct object_name {
@@ -109,7 +109,7 @@ glSetObjectOption(GL_WINDOW_TARGET, GL_OPTION_WINDOW_HEIGHT, 600);
glBindObject(GL_WINDOW_TARGET, 0);
` ``
这一小段代码展现了你以后使用OpenGL时常见的工作流。我们首先创建一个对象, 然后用一个id保存它的引用( 实际数据被储存在后台) 。然后我们将对象绑定至上下文的目标位置( 例子中窗口对象目标的位置被定义成` GL_WINDOW_TARGET` ) 。接下来我们设置窗口的选项。最后我们将目标位置的对象id设回0, 解绑这个对象。设置的选项将被保存在` objectId` 所引用的对象中,一旦我们重新绑定这个对象到` GL_WINDOW_TARGET` 位置,这些选项就会重新生效。
这一小段代码展现了你以后使用OpenGL时常见的工作流。我们首先创建一个对象, 然后用一个id保存它的引用( 实际数据被储存在后台) 。然后我们将对象绑定至上下文的目标位置( 例子中窗口对象目标的位置被定义成< var > GL_WINDOW_TARGET</ var > ) 。接下来我们设置窗口的选项。最后我们将目标位置的对象id设回0, 解绑这个对象。设置的选项将被保存在< var > objectId</ var > 所引用的对象中,一旦我们重新绑定这个对象到< var > GL_WINDOW_TARGET</ var > 位置,这些选项就会重新生效。
!!! attention