每次BindBuffer后是否需要使用VertexAttribPointer?

10
我注意到在绑定缓冲区后,除非重新调用VertexAttribPointer,否则着色器中没有输入。这是必须的吗?着色器代码可能不会改变,只会使用不同的缓冲区。
2个回答

24

tibur已经回答了实际问题,但我想补充一些背景。

glBindBuffer(GL_ARRAY_BUFFER, ...)本身并没有做任何事情。将其视为glVertexAttribPointer的额外参数。

请记住,您可以将多个缓冲区绑定到不同的属性(例如属性0使用vbo 1,而属性1和2使用vbo 2)。 对于这种设置,您会看到什么API顺序?

使用实际的API,类似于:

glBindBuffer(GL_ARRAY_BUFFER, 1);
glVertexAttribPointer(0, ...)
glBindBuffer(GL_ARRAY_BUFFER, 2);
glVertexAttribPointer(1, ...)
glVertexAttribPointer(2, ...)

glDraw*(...)

规范为什么会这样工作呢?嗯,这是向后兼容性出现的问题。当VBO被引入时,glVertexPointer等函数没有任何参数可以传递要使用哪个缓冲区对象。要么就是为每个语义(VertexPointer/NormalPointer/TexCoordPointer等)添加许多新的入口点,要么就是添加一个额外的入口点,它只是作为*Pointer调用的一个额外参数。他们选择了后者(顺便说一句,这也是为什么您必须将缓冲区内的偏移量作为指针传递的原因)。


13
根据OpenGLOpenGL规范第51页(缓冲对象状态)所述,与数组指针相关的状态存储缓冲区ID。这意味着如果您想更改用于绘制的缓冲对象,则必须重新调用glVertexAttribPointer函数。
glBindBuffer(1);
glVertexPointer(...);
glDrawArrays(...); /// Drawing will use buffer 1

glBindBuffer(2);
glDrawArrays(...); /// Drawing will still use buffer 1

glVertexPointer(...);
glDrawArrays(...); /// Drawing will now use buffer 2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接