OpenGL,是一种 3D 图形库的规范。我们可以直接使用 OpenGL 简单、高效地在屏幕上绘制图形
因此,OpenGL 可用于以下方面:
……的图形显示部分。再加上自行编写的或第三方库的代码才可以组成一个完整的程序
虽然 OpenGL 一般是用 C 编写的,但它却是面向对象的
但是,几乎所有的对象在使用前,都必须先自行绑定
同时每种对象能够绑定的数量是固定的(一般是1个)。绑定新的就会令旧的失效
请体会以下代码:
obj a;
obj b;
bind(a);
objDoSomething();// 这里操作的是 a
bind(b);
objDoSomething();// 这里操作的是 b
低情商:全局变量;高情商:状态机
基于此,对象的绑定,成为了学习的一大问题。比如在未绑定对象的情况下操作对象,什么也不会发生
因此,需要小心翼翼地使用原本的代码,或者自行封装
比如这样:
obj a;
obj b;
a.doSomething();
b.doSomething();
...
void obj::doSomething()
{
bind(a);
objDoSomething();
bind(NULL);
}
另外一点,就是对这些对象的理解
一开始,接触VAO、着色器、FBO这些概念令人眼花缭乱。如何理解这些对象也是一个问题
模型,由各个顶点,以及顶点所携带的信息构成
比如,我们可以这样表示一个三角形
float[] triangle
{
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f
};
这些数据是什么意思?事实上,这需要由你自己决定
VBO(顶点缓冲对象),用于将数据保存到某个可以高效读取的位置
而 VAO(顶点数组对象), 则是用来表示如何读取这些数据的
使用的效果大致是这样的:
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);// 前文提到的绑定来了
glBufferData(GL_ARRAY_BUFFER, sizeof(triangle), triangle, GL_STATIC_DRAW);// 没有上一行的绑定,这一行就什么也不做
GLuint vao;
glGenVertexArrays(1, &vao);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
具体来说VAO就是通过 glVertexAttribPointer
这一函数来指示数据的存储方式的。比如上文中的参数表示的是:
顶点的第0个属性由2个 float 组成,两个顶点属性之间相距2 * sizeof(float)
,第一个顶点直接从头((void*)0
)开始读取
至此,我们已经有了一个表示模型数据的对象了
有了模型,我们应该如何渲染模型呢?
OpenGL 通过程序员自定的着色器与管线来绘制模型
大致地说,管线由多个着色器组成,每个着色器负责处理不同的信息
有2个着色器是必须由程序员自己定义的
还有一个默认提供,但可以自行设置的图元着色器,可以把某种图元处理成其他图元
比如把点处理成一个三角形
有了管线,我们就可以把它和 VAO 一起使用,绘制图形了
(严谨地说,程序员将以上着色器(Shader)合并成 Program,由管线使用 Program)
之前我们只提到了模型的坐标、颜色等内容,其实我们也可以通过着色器将图片中的颜色附着到模型上
而这种方式需要用到的就是 OpenGL 中的材质(Texture)
类似于 VAO,我们需要把图片读取到程序中,并绑定和设定信息
之后我们就可以像用 VAO 一样地使用 Texture 了
不过 VAO 同时只能绑定1个,而 Texture 可以绑定 32 个甚至更多
(相当于开了个全局变量存绑定的 VAO,而开了个全局数组存绑定的 Texture)
另外除了用于存储图片的颜色,配合 FBO(下面会提到)使用,Texture 可以作为缓冲存储颜色以外的信息
比如深度——图元在空间中的前后关系
接下来简单介绍一下上面没有提及到的对象
还有一些特性用于解放程序员的双手
有些技术虽然 OpenGL 没有直接包含,但编写代码时又用得上的技术。这些技术需要自己去编(C)写(V):
一个简单的 OpenGL 程序的结构,大致上是下面这样的:
初始化();
创建模型();
创建着色器();
创建材质();
while(程序未退出())
{
获取输入();
处理信息();
绘制图形();
}
可以看到,有些函数与 OpenGL 无关,比如获取输入(用 GLFW 实现)、处理信息(自己写)
模型、着色器、材质的创建顺序一般是无所谓的
主要是循环中的内容,几乎所有的游戏、模拟软件,都是通过这种方法实现绘制的
下面提一下自己编写代码时遇到的问题:
Q:为什么绘制不出图形
有以下可能
Q:绘制带材质的图形时,只绘制了一个白色的矩形或者黑色的图形
Q:绘制带材质图形时,图形是花的
图片通道与材质通道不匹配,比如图片有4个通道,材质却指定为 GL_RGB
(3个通道)
Q: 绘制带材质图形时,图形是歪的
请看这篇文章
Q:绘制带材质图形时,图形莫名其妙偏移了一段距离,换台电脑就没问题
请检查你编写的着色器中有没有出现未定义就直接使用的变量。有的显卡驱动会直接把未定义局部变量初始化为零,有的不会。以下是例子
float a;// 应该这样写:float a = 0.0f;
a += 0.5;// Oops...
Q:我的 OpenGL 怎么没有各向异性相关的宏?
这个需要作为扩展自行添加(比如 GLAD 的下载页面中就可以指定需要这个扩展)
学习 OpenGL,不仅仅是学习 OpenGL 本身那么简单,或多或少地还涉及到以下内容(括号内是现成的库):
此外,如果是制作游戏的话,还需要有音效(OpenAL),等等
另外,即使是 OpenGL 本身,也还有许许多多的特性在上文没有提及(比如OpenGL 4的特性)。需要学习的地方还有很多
原文:https://www.cnblogs.com/rrtwo/p/14938918.html