1

我正在再次尝试 OpenGL,我想知道如何设计稍后呈现的类。现在,只有一种类型的形状,所以我创建了一个Shape带有静态 VAO 成员的类,该成员glGenVertexArrays(1, &vao)在创建第一个实例时调用Shape。现在有一个方法void Shape::render()

void Shape::render()
{
  glBindVertexArray(vao);
  glDrawArrays(GL_TRIANGLES, foo, bar);
}

这是一个好方法吗?我的意思是,当在实际程序中绘制 的所有实例时,Shape会反复调用 bind ,但我的猜测是,如果当前已经绑定Shape::vao,它实际上并没有做任何事情。vao这个猜测正确吗?

另外,我前段时间看到一个教程,它曾经glBindVertexArray(0)render(). 当有许多形状时,这不是潜在的性能损失吗?

4

1 回答 1

4

但我的猜测是,如果 vao 目前已经绑定,它实际上并没有做任何事情。这个猜测正确吗?

是的。就正确性而言,重新绑定已经绑定的东西不是问题。

不过,它可能会增加一点性能损失。在这种情况下,一个合理的 GL 实现可能不会做太多事情,但是您仍然可以调用 GL 库,并且它必须在它有机会什么都不做之前找到线程的当前上下文。因此,如果您将当前的 VAO 缓存在您身边,并且仅在它实际更改时才调用 GL,您可能会更好。但这是只有分析/基准测试才能告诉你的事情。如果您有数千甚至数百万个实例,那可能会成为一个真正的问题 - OTOH,如果您对每个实例都有单独的绘制调用,那么无论如何您都搞砸了 - 在这种情况下,您应该研究实例化渲染。

另外,我前段时间看到一个教程,它曾经在render()的末尾调用glBindVertexArray(0)。当有许多形状时,这不是潜在的性能损失吗?

是的。大多数教程这样做是为了“清洁”,但在大多数情况下这确实是浪费时间。如果您可以(并且实际上打算)在“未绑定”状态下执行某些操作,则取消绑定某些 GL 对象只是一个有用的操作 - 例如 FBO 0,它只是默认的帧缓冲区。对于 VAO,在核心配置文件中,VAO 0 完全没用,在任何情况下您都必须绑定一个才能绘制 - 因此,通过解除任何其他之间的绑定,您将一无所获。

于 2014-08-03T01:10:10.800 回答