OpenGL学习(1)

OpenGL学习

实验室师兄有项目是做3D虚拟环境,而我对这一方面也比MRCP强烈许多(捂脸)。现在所在的无人系统实验室,我所在的方向是脑电方向。但发现我对这一块其实并没有太大兴趣,而更偏向具有实质性效果的研究,比如机器学习、大数据这块。废话一下说了好多,现在就开始学习吧。

我所使用的学习教程是https://learnopengl-cn.github.io,据说很不错。和Linux学习一样,同样基本按照教程走,记录自己觉得重要的地方,有时候全部摘抄。

OpenGL

OpenGL一般被认为是一个API(Application Programming Inerface,应用程序编程接口),包括了一系列可以操作图形、图像的函数。然而,OpenGL本身并不是API,而仅仅是一个由Khronos组织制定并维护的规范(Specification)。

OpenGL规范严格规定了每个函数该如何执行,以及它们的输出值。而内部具体每个函数的实现,则是由OpenGL库的开发者自行决定。实际的OpenGL库的开发者通常是显卡的生产商。比如Apple系统、Linux系统,均由不同开发商维护。由于OpenGL的大多数实现都是由显卡厂商编写的,当产生一个bug时通常可以通过升级显卡驱动来解决。这些驱动会包括你的显卡能支持的最新版本的OpenGL。

核心模式与立即渲染模式

早期OpenGL使用立即渲染模式(固定渲染管线),这个模式下绘制图形很方便。但由于随着时间推移,开发者对绘图细节有了更多掌控,而立即渲染模式效率太低,因此如今规范文档鼓励开发者在核心模式下进行开发。

当使用OpenGL的核心模式时,OpenGL迫使我们使用现代的函数。现代函数要求使用者真正理解OpenGL和图形编程,它有一些难度,然而提供了更多的灵活性,更高的效率,更重要的是可以更深入的理解图形编程。

扩展

OpenGL的一大特性是对扩展的支持。当一个显卡公司提出一个新特性或者渲染上的优化,通常以扩展的方式在驱动中实现。使用扩展的代码大多看上去如下:

1
2
3
4
5
6
if(GL_ARB_extension_name){
//使用硬件支持的全新的现代特性
}
else{
//不支持此扩展,用旧的方式去做。
}

状态机

OpenGL自身是一个巨大的状态机:一系列的变量描述OpenGL此刻应当如何运行。OpenGL的状态通常被称为OpenGL上下文(Context)。我们通常使用如下途径来更改OpenGL状态:设置选项,操作缓冲。最后,使用当前OpenGL上下文来渲染。

假设我们想告诉OpenGL画线段而不是三角形时,通过改变上下文变量来改变OpenGL状态,从而告知其如何绘图。一旦我们改变了OpenGL状态为绘制线段,下一个绘制命令就会绘制线段而不是三角形。

当使用OpenGL的时候,我们会遇到一些状态设置函数(State-changing Function),这类函数将会改变上下文。以及状态使用函数(State-using Function),这类函数会根据当前OpenGL的状态执行一些操作。

对象

OpenGL库是用C语言写的,同时也支持多种语言的派生,但其内核仍然是一个C库。由于C的一些语言结构不易被翻译到其他高级语言,因此OpenGL开发时引入抽象层,如对象(Object)。

在OpenGL中一个对象是指一些选项的集合,它代表OpenGL状态的一个子集。比如,我们可以用一个对象来代表绘图窗口的设置,之后就可以设置其大小、支持的颜色位数等等,可以把对象看作一个C风格的结构体(Struct):

1
2
3
4
5
struct object_name{
float option1;
int option2;
char[] name;
};

当我们使用一个对象时,通常看起来如下(把OpenGL上下文看作一个大的结构体):

1
2
3
4
5
6
//OpenGL的状态
struct OpenGL_Context{
...
object* object_window_Target;
...
};
1
2
3
4
5
6
7
8
9
10
//创建对象
unsigned int objectId=0;
glGenObject(1, &objectId);
//绑定对象至上下文
glBindObject(GL_WINDOW_TARGET, objectId);
//设置当前绑定到 GL_WINDOW_TARGET 的对象的一些选项
glSetObjectOption(GL_WINDOW_TARGET, GL_OPTION_WINDOW_WIDTH, 800);
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状态的操作时,只需要绑定含有需要的设置的对象即可。比如说我们有一些作为3D模型数据(一栋房子或一个人物)的容器对象,在我们想绘制其中任何一个模型的时候,只需绑定一个包含对应模型数据的对象就可以了(当然,我们需要先创建并设置对象的选项)。

理论知识基本介绍完毕。

http://blog.csdn.net/wangdingqiaoit/article/category/2107037/2 这个博客可留作补充学习。