什么时候应该调用glVertexAttribPointer?

时间:2013-06-17 14:14:43

标签: opengl

在应该调用glVertexAttribPointer时,文档中并不明显。看起来它是VBO初始化的一部分,但我注意到在渲染过程中调用它的示例代码。

glVertexAttribPointer(vertexAttributeId, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), reinterpret_cast<const GLvoid*>(offsetof(Vertex2D, m_x)));

glVertexAttribPointer初始化期间应该调用GL_ARRAY_BUFFER还是在渲染期间(调用glBindBuffer之后)调用它?

4 个答案:

答案 0 :(得分:47)

函数glVertexAttribPointer指定在呈现某些内容时使用的顶点属性的格式和源缓冲区(忽略客户端数组的弃用用法)(即下一个glDraw...调用)。

现在有两种情况。您可以使用顶点数组对象(VAO),也可以不使用(虽然不使用VAO,但现代OpenGL中不鼓励/禁止使用VAO)。如果您使用VAO,那么您通常会在呈现正确设置状态之前调用glVertexAttribPointer(以及相应的glEnableVertexAttribArray)。如果使用VAO,你实际上在VAO创建代码中调用它(和启用函数)(这通常是一些初始化或对象创建的一部分),因为它的设置存储在VAO中,并且在渲染时你需要做的就是绑定VAO并调用绘制函数。

但无论何时调用glVertexAttribPointer,都应该在之前绑定相应的缓冲区(无论何时实际创建和填充),因为glVertexAttribPointer函数设置当前绑定的{{1}作为此属性的源缓冲区(并存储此设置,因此之后您可以自由绑定另一个VBO)。

所以在使用VAO的现代OpenGL中(推荐),它通常与此工作流程类似:

GL_ARRAY_BUFFER

当不使用VAO时,它会是这样的:

//initialization
glGenVertexArrays
glBindVertexArray

glGenBuffers
glBindBuffer
glBufferData

glVertexAttribPointer
glEnableVertexAttribArray

glBindVertexArray(0)

glDeleteBuffers //you can already delete it after the VAO is unbound, since the
                //VAO still references it, keeping it alive (see comments below).

...

//rendering
glBindVertexArray
glDrawWhatever

答案 1 :(得分:4)

glVertexAttribPointer不属于缓冲区,也不属于程序 - 就是说 - glue 他们之间。 (其功能在Opengl 4.3中分为不同的功能VertexAttrib*FormatVertexAttribBindingBindVertexBuffer可通过ARB_vertex_attrib_binding提供

但是如果你想说它是某些东西的一部分我会说它是VAO的一部分,它存储了哪些Buffer对象被绑定的状态,哪些attribs被启用以及Buffer数据如何被被传递给程序

因此它属于您设置VAO的部分。

修改 简单的设置说明了顺序:

  1. 创建/设置Buffer并创建程序
  2. create VAO定义哪些attribs已启用,哪些缓冲区应在使用VAO时绑定,以及该数据如何传递给程序(glVertexAttribPointer

答案 2 :(得分:2)

缓冲区,通用顶点属性和着色器属性变量的关联非常微妙。 glVertexAttribPointer建立了这种关联。有关详细说明,请参阅OpenGL-Terminology

此外,链接OpenGL-VBO,shader,VAO显示了一个包含必要的API调用序列的工作示例。

答案 3 :(得分:1)

必须调用{p> glVertexAttribPointer(在大多数情况下),当适当的(即你要使用的)VBO被绑定时。然后它的最后一个参数在所述缓冲区中偏移。

最后一个参数在the reference manual中定义得特别好:

  

指定第一个通用顶点的第一个组件的偏移量   当前绑定的缓冲区的数据存储中的数组中的属性   到GL_ARRAY_BUFFER目标。初始值为0.

适当的顶点指针与VBO源的绑定存储在VAO中,如果可能,您应该使用它。

简短的例子(原谅我的伪代码):

// Setup
CreateVAO(); BindVAO();
CreateVBO(); BindVBO();
VertexAttribPointer(/*id*/ 0, 3, GL_FLOAT, /*starting at offset*/ 0);

// We have specified Vertex attribute bound to location 0,
// with size of 3 floats, starting at offset 0 of VBO we've just created.        

//Draw
BindVAO();
Draw();