gpt4 book ai didi

opengl - Vertex Array Objects - 关于保存当前绑定(bind)的顶点缓冲区的确切状态信息的混淆

转载 作者:行者123 更新时间:2023-12-04 03:44:33 25 4
gpt4 key购买 nike

我正在学习 arcsynthesis 上的优秀教程在构建图形引擎时发现我并不像我想象的那样了解 VAO。

来自教程Chapter 5. Objects In Depth

Buffer Binding and Attribute Association

You may notice that glBindBuffer(GL_ARRAY_BUFFER) is not on that list, even though it is part of the attribute setup for rendering. The binding to GL_ARRAY_BUFFER is not part of a VAO because the association between a buffer object and a vertex attribute does not happen when you call glBindBuffer(GL_ARRAY_BUFFER). This association happens when you call glVertexAttribPointer.

When you call glVertexAttribPointer, OpenGL takes whatever buffer is at the moment of this call bound to GL_ARRAY_BUFFER and associates it with the given vertex attribute. Think of the GL_ARRAY_BUFFER binding as a global pointer that glVertexAttribPointer reads. So you are free to bind whatever you want or nothing at all to GL_ARRAY_BUFFER after making a glVertexAttribPointer call; it will affect nothing in the final rendering. So VAOs do store which buffer objects are associated with which attributes; but they do not store the GL_ARRAY_BUFFER binding itself.



我最初错过了最后一行“......但他们不存储 GL_ARRAY_BUFFER 绑定(bind)本身”。在我注意到这一行之前,我认为一旦调用 glVertexAttribPointer 就保存了当前绑定(bind)的缓冲区。由于缺少这些知识,我构建了一个网格类,并且能够获得一个具有多个网格正确渲染的场景。

下面列出了该代码的一部分。请注意,我没有在绘图函数中调用 glBindBuffer。
// MESH RENDERING

/* ... */
/* SETUP FUNCTION */
/* ... */

// Setup vertex array object
glGenVertexArrays(1, &_vertex_array_object_id);
glBindVertexArray(_vertex_array_object_id);

// Setup vertex buffers
glGenBuffers(1, &_vertex_buffer_object_id);
glBindBuffer(GL_ARRAY_BUFFER, _vertex_buffer_object_id);
glBufferData(GL_ARRAY_BUFFER, _vertices.size() * sizeof(vertex), &_vertices[0], GL_STATIC_DRAW);

// Setup vertex attributes
glEnableVertexAttribArray(e_aid_position);
glEnableVertexAttribArray(e_aid_normal);
glEnableVertexAttribArray(e_aid_color);
glEnableVertexAttribArray(e_aid_tex);

glVertexAttribPointer(e_aid_position, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), (GLvoid*)offsetof(vertex, pos));
glVertexAttribPointer(e_aid_normal, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), (GLvoid*)offsetof(vertex, norm));
glVertexAttribPointer(e_aid_color, 4, GL_FLOAT, GL_FALSE, sizeof(vertex), (GLvoid*)offsetof(vertex, col));
glVertexAttribPointer(e_aid_tex, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), (GLvoid*)offsetof(vertex, tex));

/* ... */
/* DRAW FUNCTION */
/* ... */

glBindVertexArray(_vertex_array_object_id);
glDrawArrays(GL_TRIANGLES, 0, _vertices.size());

现在我要开始照明了,我想绘制一些调试图,这样我就可以验证我所有的法线是否正确。目前,我只是将要为一个帧渲染的所有行存储在一个向量中。由于这些数据可能会在每一帧都发生变化,因此我使用 GL_DYNAMIC_DRAW 并在渲染之前指定数据。

最初,当我这样做时,我会得到指向无穷远的垃圾线。违规代码如下:
// DEBUG DRAW LINE RENDERING 

/* ... */
/* SETUP FUNCTION */
/* ... */

// Setup vertex array object
glGenVertexArrays(1, &_vertex_array_object_id);
glBindVertexArray(_vertex_array_object_id);

// Setup vertex buffers
glGenBuffers(1, &_vertex_buffer_object_id);
glBindBuffer(GL_ARRAY_BUFFER, _vertex_buffer_object_id);
// Note: no buffer data supplied here!!!

// Setup vertex attributes
glEnableVertexAttribArray(e_aid_position);
glEnableVertexAttribArray(e_aid_color);

glVertexAttribPointer(e_aid_position, 3, GL_FLOAT, GL_FALSE, sizeof(line_vertex), (GLvoid*)offsetof(line_vertex, pos));
glVertexAttribPointer(e_aid_color, 4, GL_FLOAT, GL_FALSE, sizeof(line_vertex), (GLvoid*)offsetof(line_vertex, col));

/* ... */
/* DRAW FUNCTION */
/* ... */

glBindVertexArray(_vertex_array_object_id);
// Specifying buffer data here instead!!!
glBufferData(GL_ARRAY_BUFFER, _line_vertices.size() * sizeof(line_vertex), &_line_vertices[0], GL_DYNAMIC_DRAW);
glDrawArrays(GL_LINES, 0, _line_vertices.size());

经过一番寻找,以及找到我上面遗漏的细节,我发现如果我在绘制函数中调用 glBufferData 之前调用 glBindBuffer,一切正常。

考虑到这一点,我对为什么我的网格渲染首先起作用感到困惑。如果我更改缓冲区中的数据,是否只需要再次调用 glBindBuffer ?或者如果您不绑定(bind)缓冲区并且我只是不走运并且让它工作,那么行为是否未定义?

请注意,我的目标是 OpenGL 3.0 版。

最佳答案

Do I only need to call glBindBuffer again if I change the data in the buffer?



是的,每次调用 glVertexAttribPointer 时,VAO 对象都会记住绑定(bind)了哪些缓冲区。虽然该 VAO 已绑定(bind),所以您通常不需要调用 glBindBuffer再次。但是,如果您想更改缓冲区中的数据,OpenGL 需要知道您正在更改哪个缓冲区,因此您需要调用 glBindBuffer在调用 glBufferData 之前.此时绑定(bind)哪个 VAO 对象无关紧要。

关于opengl - Vertex Array Objects - 关于保存当前绑定(bind)的顶点缓冲区的确切状态信息的混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17227031/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com