使用 IBO/EBO 时,程序仅在创建 VAO 后调用 glBindBuffer 绑定 IBO/EBO 时才有效
When using IBO/EBO, program only works when I call glBindBuffer to bind the IBO/EBO AFTER creation of the VAO
出于某种原因,此程序仅在我创建 VAO 后再次绑定 IBO/EBO 时才有效。我在网上阅读 和多个 SO 帖子 ,glBindBuffer 仅绑定当前缓冲区,并且 不 将其附加到 VAO。我认为 glVertexAttribPointer 是将数据附加到 VAO 的函数。
float points[] = {
-0.5f, 0.5f, 0.0f, // top left = 0
0.5f, 0.5f, 0.0f, // top right = 1
0.5f, -0.5f, 0.0f, // bottom right = 2
-0.5f, -0.5f, 0.0f, // bottom left = 3
};
GLuint elements[] = {
0, 1, 2,
2, 3, 0,
};
// generate vbo (point buffer)
GLuint pb = 0;
glGenBuffers(1, &pb);
glBindBuffer(GL_ARRAY_BUFFER, pb);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
// generate element buffer object (ibo/ebo)
GLuint ebo = 0;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
// generate vao
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, pb);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); // when I bind buffer again, it works
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
如果我没有第二个glBindBuffer,程序就会崩溃。我想知道的是为什么我必须再次调用 glBindBuffer,在我创建 VAO 之后,调用 glBindBuffer 只会使缓冲区成为其他函数的活动缓冲区。
如果查看规范,顶点数组对象状态不包括元素缓冲区对象。
的确,启用VAO并没有设置元素绑定点。
问题出在您最初调用的顺序上。 GL_ELEMENT_ARRAY_BUFFER
绑定是 VAO 状态的一部分。看看这个序列:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
由于 GL_ELEMENT_ARRAY_BUFFER
绑定是 VAO 状态的一部分,序列末尾的 glBindVertexArray()
调用将建立 GL_ELEMENT_ARRAY_BUFFER
缓冲区绑定,它是 VAO vao
你有约束力。其中,由于您刚刚创建了 vao
,所以是 0
。所以在这个序列的末尾,你没有元素数组缓冲区绑定。
或者,从不同的方向来看,当你在开始时进行 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)
调用时,VAO 0
是绑定的。所以这个绑定成为VAO状态的一部分0
。然后,当您绑定不同的 VAO vao
时,您将失去绑定,并且它会被属于 VAO vao
.
状态的绑定所取代
要使这项工作如您所愿,您需要在 绑定 VAO 之后 进行初始 GL_ELEMENT_ARRAY_BUFFER
绑定。然后它成为 VAO 状态的一部分,以后每次绑定 VAO 时都会重新建立:
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
出于某种原因,此程序仅在我创建 VAO 后再次绑定 IBO/EBO 时才有效。我在网上阅读 和多个 SO 帖子 ,glBindBuffer 仅绑定当前缓冲区,并且 不 将其附加到 VAO。我认为 glVertexAttribPointer 是将数据附加到 VAO 的函数。
float points[] = {
-0.5f, 0.5f, 0.0f, // top left = 0
0.5f, 0.5f, 0.0f, // top right = 1
0.5f, -0.5f, 0.0f, // bottom right = 2
-0.5f, -0.5f, 0.0f, // bottom left = 3
};
GLuint elements[] = {
0, 1, 2,
2, 3, 0,
};
// generate vbo (point buffer)
GLuint pb = 0;
glGenBuffers(1, &pb);
glBindBuffer(GL_ARRAY_BUFFER, pb);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
// generate element buffer object (ibo/ebo)
GLuint ebo = 0;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
// generate vao
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, pb);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); // when I bind buffer again, it works
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
如果我没有第二个glBindBuffer,程序就会崩溃。我想知道的是为什么我必须再次调用 glBindBuffer,在我创建 VAO 之后,调用 glBindBuffer 只会使缓冲区成为其他函数的活动缓冲区。
如果查看规范,顶点数组对象状态不包括元素缓冲区对象。
的确,启用VAO并没有设置元素绑定点。
问题出在您最初调用的顺序上。 GL_ELEMENT_ARRAY_BUFFER
绑定是 VAO 状态的一部分。看看这个序列:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
由于 GL_ELEMENT_ARRAY_BUFFER
绑定是 VAO 状态的一部分,序列末尾的 glBindVertexArray()
调用将建立 GL_ELEMENT_ARRAY_BUFFER
缓冲区绑定,它是 VAO vao
你有约束力。其中,由于您刚刚创建了 vao
,所以是 0
。所以在这个序列的末尾,你没有元素数组缓冲区绑定。
或者,从不同的方向来看,当你在开始时进行 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)
调用时,VAO 0
是绑定的。所以这个绑定成为VAO状态的一部分0
。然后,当您绑定不同的 VAO vao
时,您将失去绑定,并且它会被属于 VAO vao
.
要使这项工作如您所愿,您需要在 绑定 VAO 之后 进行初始 GL_ELEMENT_ARRAY_BUFFER
绑定。然后它成为 VAO 状态的一部分,以后每次绑定 VAO 时都会重新建立:
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);