是否有必要每帧绑定所有VBO(和纹理)?

时间:2016-11-05 13:06:34

标签: c++ opengl vbo vao

我正在关注basic tutorial on OpenGL 3.0。我不清楚为什么/如果我必须绑定,启用和取消绑定/禁用每个帧的所有顶点缓冲区和纹理。

对我来说似乎有太多的gl ****来电,我猜有些开销。例如here,您会看到每个框架有几个块,如:

// do this for each mesh in scene
// vertexes
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glVertexAttribPointer(  0, 3, GL_FLOAT,GL_FALSE,0,(void*)0);
// normals
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, normal_buffer );
glVertexAttribPointer(  1, 3, GL_FLOAT,GL_FALSE,0,(void*)0);
// UVs
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, uv_buffer    );
glVertexAttribPointer(  2, 2, GL_FLOAT,GL_FALSE,0,(void*)0);

// ...
glDrawArrays(GL_TRIANGLES, 0, nVerts );
// ...
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);

想象你不仅有一个而是100个不同的网格,每个网格都有自己的顶点,标准,紫外线的VBO。我是否真的应该为每个人执行这个程序?当然我可以将这种复杂性封装到一些函数/对象中,但我担心这个gl ****函数调用的开销。

此机制的某些部分是否可能从per frame loop转移到scene setup

另外I read VAO是一种如何将一个对象的相应VBO打包在一起的方法。并且绑定VAO会自动绑定相应的VBO。所以我在想,每个网格(不是实例)可能只有一个VAO应该如何完成 - 但根据this answer它似乎不是这样吗?

2 个答案:

答案 0 :(得分:0)

您应该使用顶点数组对象(由glGenVertexArrays生成)。多亏了你,你不必每次都进行这些电话。顶点缓冲区对象存储:

  • 致电glEnableVertexAttribArrayglDisableVertexAttribArray
  • 通过glVertexAttribPointer进行顶点属性配置。
  • 通过调用与顶点属性关联的顶点缓冲区对象 glVertexAttribPointer

也许this会是更好的教程。

这样你就可以生成vao对象,然后绑定它,执行调用和取消绑定。现在在绘图循环中你只需要绑定vao。

实施例

  glUseProgram(shaderId);
  glBindVertexArray(vaoId);
  glDrawArrays(GL_TRIANGLES, 0, 3);
  glBindVertexArray(0);
  glUseProgram(0);

答案 1 :(得分:0)

首先要做的事情:通过引入顶点数组对象解决了对GL调用开销的担忧(参见@Criss的回答)。然而,您的思路的真正问题在于,您将VBO与几何网格等同,即为每个几何体提供自己的VBO。

这不是你应该如何看待和使用VBO。 VBO是大块的内存,你可以把几个对象的数据放到一个VBO中;你不必绘制整个东西,你可以限制绘制调用VBO的子集。 您可以使用相似或甚至相同的绘图设置来合并几何图形,并使用单个绘图调用一次性绘制它们。通过使用正确的顶点索引列表,或通过使用实例化。

说到纹理的绑定状态......好吧,是的,这有点烦人。切换纹理时,你真的必须完成整个绑定舞蹈。这就是为什么通常在绘制之前按纹理/着色器对几何体进行排序,以便最小化纹理切换量。

最后3或4代GPU(截至2016年末)确实支持无绑定纹理,您可以通过64位句柄访问纹理(实际上是某些地址空间)。然而,无绑定纹理尚未成为核心OpenGL标准,您必须使用供应商扩展来使用它。

另一种有趣的方法(由Id Tech 4推广)是虚拟纹理。您可以在其可寻址大小中分配 huge 的稀疏填充纹理对象,但只有部分实际填充了数据。在程序执行期间,您可以确定需要纹理的哪些区域,并根据需要交换所需的数据。