40

何时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

4 回答 4

60

该函数glVertexAttribPointer指定渲染某些东西(即下一次glDraw...调用)时使用的顶点属性的格式和源缓冲区(忽略客户端数组的不推荐使用)。

现在有两种情况。您要么使用顶点数组对象 (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

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

//initialization
glGenBuffers
glBindBuffer
glBufferData

...

//rendering
glBindBuffer
glVertexAttribPointer
glEnableVertexAttribArray
glDrawWhatever
于 2013-06-17T14:46:53.530 回答
4

glVertexAttribPointer不是真正属于缓冲区也不属于程序的东西 - 比方说 -它们之间的粘合剂。(此功能在 Opengl 4.3 中被拆分为不同的功能VertexAttrib*FormatVertexAttribBinding并可BindVertexBuffer通过 ARB_vertex_attrib_binding实现

但是,如果您想说它是某事的一部分,我会说它是VAO存储绑定了 Buffer 对象的状态、启用了哪些属性以及必须如何将 Buffer 数据传递给Program的一部分。

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

编辑 说明顺序的简单设置:

  1. 创建/设置Buffers 和创建程序
  2. 创建VAO定义启用哪些属性,使用时应绑定哪些缓冲区VAO以及如何将数据传递给程序(glVertexAttribPointer
于 2013-06-17T14:21:36.593 回答
2

缓冲区、通用顶点属性和着色器属性变量的关联非常微妙。glVertexAttribPointer建立这个协会。有关详细说明,请参阅OpenGL 术语

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

于 2016-04-10T05:06:11.693 回答
1

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

最后一个参数在参考手册中定义得特别好:

指定当前绑定到 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();
于 2013-06-17T14:21:41.987 回答