【问题标题】:glDrawElements throws divide by zero error when using multiple VAO使用多个 VAO 时 glDrawElements 抛出除以零错误
【发布时间】:2020-01-05 08:29:15
【问题描述】:

我正在使用 opengl 构建游戏。当我调用 glDrawElements 时,会引发来自 ig9icd32.dll 的除以零错误。经过一些研究,我发现它是一个英特尔库

由于 ig9icd32.dll 是 Intel 驱动,我尝试用专用 GPU 运行游戏,但出现同样的错误。

使用单个 VAO 并在不绘制第二个的情况下进行编译不会给出任何错误。 我检查了 VAO 生成和 VBO 绑定:它们工作得很好。

    {
        glGenVertexArrays(1, &m_HighwayVAO);
        glGenVertexArrays(1, &m_lanesVAO);

        {
            glBindVertexArray(m_HighwayVAO);

            unsigned int vbo, ebo;
            glGenBuffers(1, &vbo);
            glGenBuffers(1, &ebo);

            glBindBuffer(GL_ARRAY_BUFFER, vbo);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);

            //Vertex: x,y,z, u,v
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
            glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
            glEnableVertexAttribArray(0);
            glEnableVertexAttribArray(1);

            glBindVertexArray(0);
        }


        {

            glBindVertexArray(m_lanesVAO);

            unsigned int buffer, index;
            glGenBuffers(1, &buffer);
            glGenBuffers(1, &index);
            glBindBuffer(GL_ARRAY_BUFFER, buffer);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index);

            //Vertex: x,y,z, r,g,b,
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), 0);
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
            glEnableVertexAttribArray(0);
            glEnableVertexAttribArray(1);


            glBindVertexArray(0);

        }

    }

这是我初始化 VAO 的地方。 它们位于单独的范围内,因此我可以在编辑器上折叠。 没有范围也会发生同样的错误。

m_HighwayVAO 和 m_lanesVAO 是在 Header 中定义的变量。它们被初始化为 0。

void Rendr::highway(double time) {

    float factor = time / 3;
    //Vertex: x,y,z, u,v
    float data[] = {
            -1.0f, 0.0f, 0.0f, 0.0f, 1.0f + factor,
             1.0f, 0.0f, 0.0f, 1.0f, 1.0f + factor,
            -1.0f, 0.0f, 6.0f, 0.0f, 0.0f + factor,
             1.0f, 0.0f, 6.0f, 1.0f, 0.0f + factor
    };

    unsigned int indices[] = {
            0,2,3,
            3,1,0
    };

    glBindVertexArray(m_HighwayVAO);

    glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_DYNAMIC_DRAW);

    glUseProgram(m_TextureProgram);
    glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(int), GL_UNSIGNED_INT, (void*)0);
    //error thrown here

    glBindVertexArray(0);

}

如果您需要更多代码,我很乐意添加到帖子中。

提前感谢您的帮助。

【问题讨论】:

  • 请发布您收到的确切错误消息。在调用 glDrawElements 之前,您是否检查过您的程序是否存在 GL 错误?

标签: c++ opengl opengl-3


【解决方案1】:

要创建和初始化缓冲区对象的数据存储,您必须绑定正确的ARRAY_BUFFER 缓冲区对象:

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);

glBindVertexArray 确实将任何缓冲区对象绑定到 ARRAY_BUFFER 缓冲区目标。


注意,绑定到目标ARRAY_BUFFER的最后一个缓冲区是buffer

glBindBuffer(GL_ARRAY_BUFFER, buffer);

这个状态被保留并且永远不会再改变。因此,vbo 的缓冲区对象的数据存储永远不会被创建和初始化。

这与index buffer (ELEMENT_ARRAY_BUFFER) 的行为不同。索引缓冲区绑定存储在 Vertex Array Object.
请注意,VAO 状态向量中陈述的每个属性可能引用不同的ARRAY_BUFFER。此引用在调用glVertexAttribPointer 时存储。然后将当前绑定到目标ARRAY_BUFFER的缓冲区与属性相关联,并将对象的名称(值)存储在VAO的状态向量中。

【讨论】:

  • 谢谢,我认为 VAO 还存储了缓冲区绑定,因为我尝试使用第二个 VAO 并且它有效。所以每次我想更改顶点数据时,我都必须绑定 GL_ARRAY_BUFFER 和 VAO,不是吗?
  • 是的,现在一切都解决了。我将对原始问题添加编辑。再次感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-23
  • 1970-01-01
  • 2013-07-28
  • 2021-12-10
相关资源
最近更新 更多