什么时候应该调用glVertexAttribPointer?

Mar*_*ram 34 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)?

Chr*_*ica 52

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

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

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

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

//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
Run Code Online (Sandbox Code Playgroud)

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

//initialization
glGenBuffers
glBindBuffer
glBufferData

...

//rendering
glBindBuffer
glVertexAttribPointer
glEnableVertexAttribArray
glDrawWhatever
Run Code Online (Sandbox Code Playgroud)

  • @MarkIngram根据评论的结论,您可以删除VBO,但您需要事先取消绑定*VAO*. (2认同)