glBindVertexBuffer与glBindBuffer的区别

11
我发现我可以使用 glBindBuffer(GL_ARRAY_BUFFER, vbo); 绑定一个顶点缓冲区。这样做是有效的,我也可以使用 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); 绑定元素数组。当使用这些时,所有内容都按预期绘制出来。
在阅读OpenGL 4.4规范第10.3.1节时,我发现提到了 glBindVertexBuffer。它看起来允许绑定多个顶点缓冲区,然后同时渲染它们。这是正确的吗?此外,它与使用 glBindBuffer 有什么不同?在绑定顶点缓冲区时,能否使用元素数组缓冲区?
2个回答

20

glBindVertexBuffer (...)函数的目标完全不同。

当它在GL_ARB_vertex_attrib_binding中引入时,其想法是分离始终存在的顶点缓冲区与指针之间的固定映射,并用更灵活的系统替换它,该系统允许您为顶点属性设置格式,为顶点缓冲区/属性设置绑定位置,然后只需交换绑定到该位置的缓冲区即可。

您不能仅使用此新功能替换对glBindBuffer (...)的调用,您至少需要调用两个其他函数来设置通用顶点属性以利用glBindVertexBuffer (...):

  1. glVertexAttribFormat (...) - 这与glVertexAttribPointer (...)实际上相同,只是它不设置指针,而是仅建立将与此属性配对的缓冲区如何被解释。

  2. glVertexAttribBinding (...) - 这将通用属性位置与类型的绑定位置(顶点缓冲区绑定)关联起来,以便您可以使用glBindVertexBuffer (...)将您的VBO绑定到此属性将使用的位置。

  3. glVertexBindingDivisor (...) - 这是glVertexAttribDivisor()的替代品。此替换品尊重由glVertexAttribBinding(...)制定的顶点属性索引与绑定槽索引之间的绑定关系。这值得指出,因为它的名称与上面列出的其他两个函数有些不符,而旧的glVertexAttribDivisor()则更加一致,但不能使用。


为了让您了解情况,我在扩展规范中包含了一些伪代码,显示了glVertexAttribPointer (...)如何与此新API添加相关。

命令:

void glVertexAttribPointer (GLuint index, GLint size, GLenum type,
                            GLboolean normalized, GLsizei stride, 
                            const GLvoid *pointer);
void glVertexAttribIPointer (GLuint index, GLint size, GLenum type,
                             GLsizei stride, const GLvoid *pointer);
void glVertexAttribLPointer (GLuint index, GLint size, GLenum type,
                             GLsizei stride, const GLvoid *pointer);

控制顶点属性状态、顶点缓冲区绑定以及顶点属性与顶点缓冲区绑定之间的映射。

假设没有生成错误,则它们是等效的:

if (no buffer is bound to GL_ARRAY_BUFFER and pointer != NULL) 
{
    generate GL_INVALID_OPERATION;
}
glVertexAttrib*Format (index, size, type, {normalized, }, 0);
glVertexAttribBinding (index, index);
if (stride != 0) {
    effectiveStride = stride;
} else {
    compute effectiveStride based on size/type;
}
GL_VERTEX_ATTRIB_ARRAY_STRIDE[index] = stride;
// GL_VERTEX_BINDING_STRIDE will be set to effectiveStride
// by glBindVertexBuffer.
glBindVertexBuffer (index, <buffer bound to GL_ARRAY_BUFFER>, 
                 (GLchar *)pointer - (GLchar *)NULL, effectiveStride);

一开始可能有点难以理解,但其实它的核心思想与当 Sampler Objects 在 GL 3.3 中被引入时将采样状态从纹理对象中分离出来非常相似。你仍然可以继续使用旧的 API,但这种替代方案会为您提供更多的灵活性。

关于元素数组缓冲区,不是的。这个新的 API 部分与此无关,因为顶点数组对象实际上管理唯一的元素数组缓冲区绑定。


-2
不完全是。`glBindVertexBuffers` 用于绑定多个顶点缓冲区。至于 `glBindVertexBuffer`,它用于将缓冲区绑定到一个顶点缓冲区。你可能需要多次调用它来绑定多个顶点缓冲区。
你可以在这里查看它们的文档: http://www.opengl.org/sdk/docs/man/xhtml/glBindVertexBuffers.xml

3
这段话的意思是:“它用于将缓冲区绑定到顶点缓冲区,这个说法非常不清晰,也没有任何规范语言支持。BindVertexBuffer() 用于将缓冲对象绑定到所谓的绑定点(在 [0,MAX_VERTEX_ATTRIB_BINDINGS - 1] 范围内),然后可以通过调用 VertexAttribBinding() 将其与特定的属性绑定集关联起来,从而将顶点数组与缓冲区分离。” - thokra

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