【问题标题】:OpenGL, VAOs and multiple buffersOpenGL、VAO 和多个缓冲区
【发布时间】:2012-12-24 08:25:41
【问题描述】:

我正在使用 OpenGL 编写一个小图形引擎(通过 OpenTK 和 C#)。

为了定义顶点属性,我有一个 VertexDeclaration 类,其中包含一组 VertexElement 结构,这些结构映射到 glEnableVertexAttribArray/glVertexAttribPointer 调用。

另外,为了支持多个顶点流,我有一个特殊的结构来保存顶点缓冲区、顶点声明、顶点偏移和实例频率(如 XNA 的 VertexBufferBinding 结构)。

目前,每当调用绘图调用时,我都会遍历所有设置的顶点流并 绑定它们的顶点缓冲区,应用顶点声明,禁用未使用的顶点属性并绘制图元。

我想使用 VAO 将 glEnableVertexAttribArray 调用缓存到其中, 并且每当应用顶点流时,绑定 VAO 并更改其数组缓冲区绑定。

这是对 VAO 的正确用法吗?

【问题讨论】:

  • 看来this question 是一个有用的链接。不知道为什么答案对“缓存”glEnableVertexAttribArray 调用说“不”。链接问题“何时致电glVertexAttribPointer?”的答案说这正是 VAO 的用途,也是当今推荐的方法。

标签: opengl


【解决方案1】:

这是对 VAO 的正确用法吗?

没有1

glVertexAttribPointeruses the buffer object that was bound to GL_ARRAY_BUFFER at the moment the function was called。所以你不能这样做:

glVertexAttribPointer(...);
glBindBuffer(GL_ARRAY_BUFFER, bufferObject);
glDrawArrays(...);

这将使用bufferObject;它将使用最初调用 glVertexAttribPointer 时绑定到 GL_ARRAY_BUFFER 的任何内容。

VAO 捕获此状态。因此,对于每个顶点属性,VAO 将存储调用时绑定到GL_ARRAY_BUFFER 的任何缓冲区对象。这允许您执行以下操作:

glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, buffer1);
glVertexAttribPointer(0, ...);
glVertexAttribPointer(1, ...);
glBindBuffer(GL_ARRAY_BUFFER, buffer2);
glVertexAttribPointer(2, ...);

属性 0 和 1 将来自 buffer1,而属性 2 将来自 buffer2。 VAO 现在捕获了所有这些状态。要渲染,您只需这样做:

glBindVertexArray(VAO);
glDraw*();

简而言之,如果你想改变一个属性在 OpenGL 中的存储来源,你也必须改变它的格式。即使是同样的格式,也必须再次调用glVertexAttribPointer

1:本次讨论假设您使用新的ARB_vertex_attrib_binding。或者,众所周知,“Exactly how Direct3D does vertex attribute binding.”如果您碰巧使用提供此扩展的实现,则可以有效地执行您所说的操作,因为属性格式与缓冲区对象的存储无关。而且glVertexAttribPointer的折磨逻辑也没有了。

一般来说,我们在 OpenGL 世界中解决这个问题的方法是将尽可能多的东西放在同一个缓冲区对象中。如果做不到这一点,只需为每个对象使用一个 VAO。

【讨论】:

  • 感谢您的出色回答。那么glBufferData 步骤在哪里起作用?使用glVertexAttribPointer之前不需要先缓存数据吗?抱歉,我对 OpenGL 很陌生
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-11
  • 2012-02-16
  • 1970-01-01
相关资源
最近更新 更多