c++ - 使用 IBO/EBO 时,程序仅在创建 VAO 后调用 glBindBuffer 绑定(bind) IBO/EBO 时才有效

标签 c++ c opengl vbo vao

出于某种原因,该程序仅在我创建 VAO 后再次绑定(bind) IBO/EBO 时才有效。我在网上读到,和多篇 SO 帖子,glBindBuffer 仅绑定(bind)当前缓冲区,并且它将其附加到 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,程序就会崩溃。我想知道的是为什么在创建VAO之后我必须再次调用glBindBuffer,当调用glBindBuffer时只会使缓冲区成为其他函数的事件缓冲区。

Pastebin (FULL CODE)

最佳答案

问题出在您的初始调用的顺序上。 GL_ELEMENT_ARRAY_BUFFER 绑定(bind)是 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 绑定(bind)是 VAO 状态的一部分,因此序列末尾的 glBindVertexArray() 调用将建立 GL_ELEMENT_ARRAY_BUFFER缓冲区绑定(bind)是您要绑定(bind)的 VAO vao 的一部分。由于您刚刚创建了 vao,因此它是 0。因此,在此序列的末尾,您没有元素数组缓冲区绑定(bind)。

或者,从不同的方向来看,当您在开始时调用 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo) 时,VAO 0 被绑定(bind)。因此,此绑定(bind)成为 VAO 0 状态的一部分。然后,当您绑定(bind)不同的 VAO vao 时,您将丢失该绑定(bind),并替换为属于 VAO vao 状态一部分的绑定(bind)。

要使其按预期工作,您需要在绑定(bind) VAO 之后进行初始 GL_ELEMENT_ARRAY_BUFFER 绑定(bind)。然后它就成为VAO状态的一部分,并且以后每次绑定(bind)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);

关于c++ - 使用 IBO/EBO 时,程序仅在创建 VAO 后调用 glBindBuffer 绑定(bind) IBO/EBO 时才有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31176226/

相关文章:

windows - 无法在 Windows 上编译一个简单的 freeglut 测试程序

Java:绘制线条 Slick LWJGL OpenGL

c - 如何根据位的位置随机选择一个值

c - 为什么要在守护程序启动期间将 STDIN、STDOUT、STDERR 重定向到/dev/null?

c++ - 序列化和反序列化 uint64_t - 不同平台上的不同结果

android - C++计算套接字传输速度

java - OpenGL 将滤镜应用于带有 slick.util 纹理的纹理

c++ - C++关键字 "const"使用建议

c++ - 模板 :Name resolution -->can any one tell an other example for this statement. ..请

c++ - 如何在尝试为某些非类型值实例化模板子类方法时产生编译器错误?