是否应该取消绑定缓冲区?


12

我正在使用OpenGL ES 2进行一些测试,但遇到了一些问题,我目前的程序是这样的:

Init
-------
-> create index buffer
-> fill index buffer glBufferData 
-> create vertex buffer
-> fill vertex buffer glBufferData 

Draw
-------
 1. Apply vertex buffer

    -> Bind VAO
       -> bind vertex buffer
          - enable attributs (glVertexPointer, …)
       -> unbind vertex buffer
    -> Unbind VAO
    -> Bind VAO

 3. Apply index buffer
 4. Draw

问题

给定的代码崩溃,经过一些研究,我明白了为什么:我需要在初始部分中取消索引缓冲区的绑定(在“填充索引缓冲区glBufferData”之后),或者在第一个“绑定VAO”之前将其取消绑定

我的问题是:

  • 我可以将指标缓冲区放入VAO(VAO股票指标缓冲区吗?)?
  • 每次更新(glBufferData)之后是否都必须取消绑定缓冲区吗?

在我的应用程序中,我有一些在每一帧都更新的缓冲区(例如:粒子),所以我有一个像这样的OpenGL堆栈:

-> bind buffer 1
-> update buffer 1
-> close buffer 1
-> bind buffer 1
-> draw

前三行将更新顶点缓冲区,最后两行是绘制对象,它应类似于以下内容:

-> bind buffer 1
-> update buffer 1
-> draw

谢谢

Answers:


12

您似乎在不必要的绑定/取消绑定上做了很多事情。如果使用VAO,则仅应在设置VAO和绘制几何图形时绑定VAO。您仅在需要更新VBO / IBO时才再次绑定它们。

在绘制或更新缓冲区之后,不必取消绑定绑定,尽管这样做可能是个好主意,这样可以避免意外写入保留的缓冲区。

现在,按照您的第一手操作顺序,这就是我希望看到的总体顺序:

在初始化时:

  1. 创建并绑定VAO。您在序列中绑定的任何VBO和IBO都将与当前的VAO(此VAO)关联。

  2. 创建并绑定索引缓冲区。

    • 用填充索引缓冲区glBufferData/glMapBuffer
  3. 创建并绑定顶点缓冲区。

    • 填充顶点缓冲区glBufferData/glMapBuffer
  4. 使用glEnableVertexAttribArray/glVertexAttribPointer等设置顶点属性。

  5. (可选)取消所有绑定,以避免意外修改缓冲区和VAO。请记住先解除绑定VAO。例如:glBindVertexArray(0);

在抽奖中:

  1. 如果仅绘制缓冲区

    • 绑定VAO;
    • 执行抽奖。
  2. 如果更新和绘图

    • 绑定VAO,VBO,IBO;
    • 更新缓冲区(仅当顶点格式已更改时才需要更新顶点属性);
    • 执行抽奖。
  3. (可选)取消绑定以避免意外修改缓冲区和VAO。

就这么简单。此操作顺序应该可以正常工作。


2
我想补充一点,在我的实验中(2014年),使用了真实案例(但是使用简单的着色器避免了GPU的瓶颈),我发现在正确订购后,使用VAO的性能提升微不足道(节省了2%的CPU)当在连续的渲染调用中使用相同的VBO时,渲染调用的实现完全跳过了VBO设置(节省10%到33%的CPU),而且我遇到了一些驱动程序错误,并使用了VAO,因此我最终默认将其关闭。当使用复杂的着色器,MSAA等时,它的意义甚至不那么重要了,这是GPU的瓶颈,即使在移动设备上,CPU也会闲置等待。
Stephane Hockenhull 2014年

2
请注意,以硬件不支持的方式错位顶点数据将迫使GPU驱动程序在每个设置上对 VBO数据重新排序,而驱动程序可以使用VAO重新排序一次,只要不进行任何更改即可,因此YMMV。无论如何,最好对齐并填充顶点数据。
Stephane Hockenhull 2014年

1
为什么必须先取消VAO绑定?
Daniel Safari

@DanielSafari,您的意思是设置后?如果要先取消绑定缓冲区(绑定缓冲区0 / null),它将清除当前VAO中的绑定点。这就是为什么应先设置空VAO的原因。
glampert

@glampert-不,绑定不是这样工作的;当调用glVertexAttribPointer时使用缓冲区绑定,否则不使用(例外:GL_ELEMENT_ARRAY_BUFFER)。在glVertexAttribPointer调用之后更改缓冲区绑定无效。
Maximus Minimus
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.