课程中我已经将Shader的一些基本语法都向你介绍清楚了,这篇文章我们来聊聊OpenGL的性能优化。
我们使用GPU时,一个非常重要的优化点是CPU与GPU之间的数据传输。一个重要原则是:使用Shader时尽量不要在CPU与GPU之间频繁的传输数据。在CPU与GPU之间频繁的传输数据会大大降低程序的执行效率,严重时甚至不如直接使用CPU进行渲染。
为了解决这个问题,OpenGL为我们提供了几种优化方法,如VBO、EBO与VAO。每种方法都有其特定的应用场景,下面我们就分别讲解一下这几种方法该如何使用。
VBO
首先我们来看一下VBO(Vertex Buffer Object),其作用是在GPU中存放顶点数据。利用VBO技术,我们可以将主内存中的顶点数据一次性拷贝到GPU中,来提高处理效率。
具体操作步骤如下:
- 创建VBO ID,并将其绑定到GPU中
- 将主内存中的顶点数据复制到VBO中
- 从VBO中读取顶点数据绘制模型
- 解绑VBO对象
具体代码如下:
1 | ... |
上面的代码很简单,就是按照创建VBO对象、与GPU绑定、拷贝数据到GPU……这样一个步骤来实现的。代码中每一行的作用我都做了注释,通过注释相信你很容易理解每一行的作用了。
EBO
了解了VBO之后,接下来咱们再来看看EBO的作用。
EBO(Element Buffer Object)也称为IBO(Index Buffer Object),其作用是缓存顶点索引值。在OpenGL中,每个顶点对应一个索引值,而通过索引仠我们就可以找到某个顶点。
需要注意的是,使用EBO时,我们必须先使用VBO将顶点坐标保存到GPU中,这样索引值才能与顶点坐标一一对应。
EBO的使用与VBO是类似的,其使用步骤如下:
- 生成 EBO ID
- 将 EBO ID与GPU绑定
- 从主内存中拷贝数据到GPU
- 使用glDrawElement绘制模型
- 解绑EBO
具体代码如下:
1 | ... |
使用EBO与使用VBO非常类似,都是先创建EBO ID,之后绑定到GPU,再将顶点Index拷贝到GPU。最大的区别是绘制模型的触发函数,VBO使用的是glDrawArrays方法,而EBO使用的是glDrawElements方法。
VAO
最后我们来看一下VAO。VAO(Vertex Array Object)的作用是存放VBO ID,我们将多个VBO ID存入在VAO中。换句话说,你可以认为VAO是VBO的管理者。如果每个VBO是一个模型的话,那么VAO可以同时管理多个模型。
通过上面的描述我们可以知道,使用VAO的前提是先构建VBO,尤其是有多个VBO时使用VAO才有意义,否则没有必要使用VAO。
如何使用VAO呢?使用步骤如下:
- 创建 VAO ID
- 将 VAO ID 与GPU绑定
- 当创建并绑定VBO时,它会被自动保存到VAO中
- 绘制模型
- 解绑VAO
来看一下具体的例子:
1 | ... |
通过上面的代码我们可以知道,使用VAO与直接使用VBO差别不大,只是在一开始创建了VAO ID,并将它绑定到了GPU上,之后触发模型绘制之后解绑VAO就完事儿了。正如我们前面所介绍的,VAO就是用于存放VBO的,有了该对象可以让我们同时处理多个VBO,否则的话每次只能处理一个,就会很麻烦。
小结
上面我就将使用VBO、EBO和VAO提高Shader工作效率的方法向你介绍清楚了。通过这篇文章我们可以知道,EBO和VAO都是以VBO为基础的,如果不有VBO我们就使用不了EBO和VAO。
另外我们还要清楚,之所以使用VBO、EBO、VAO可以提高Shader的工作效率是因为它们会先将顶点数据拷贝到GPU中,这样以后每次用到顶点数据时可以直接从GPU获取,而不必频繁的在CPU与GPU之间传输数据,这才是VBO、EBO、VAO可以提升效率的原因。