使用 glDrawArrays() 绘制函数需要调用两次才能显示任何内容

Draw function with glDrawArrays() needs to be called twice for anything to show

这是一个奇怪的问题。我有一个功能:

void drawLines(std::vector<GLfloat> lines) {
    glBindVertexArray(VAO2);

    //positions
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)0);
    glEnableVertexAttribArray(0);

    //colors
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER, VBO2);
    glBufferData(GL_ARRAY_BUFFER, sizeof(lines[0]) * lines.size(), &lines[0], GL_STATIC_DRAW);

    glUseProgram(pShaderProgram);
    glDrawArrays(GL_TRIANGLES, 0, lines.size() / 6);
}

它绘制指定粗细的线条(这是内置于lines数据中的,其中包含三个位置浮点数和三个颜色浮点数,每个点有超过200个点来标记线结束)。调用该函数一次不会产生任何结果,即使在使用 SwapBuffers(HDC)glFlush() 之后也是如此。但是,当我两次调用该函数时,一切都会显示出来。我怀疑在通过渲染管道推送缓冲区时我遗漏了一些细微差别,这可能会通过多次绑定缓冲区来激活。我不确定。有什么想法吗?

glVertexAttribPointer 需要一个绑定到 GL_ARRAY_BUFFER 绑定点的缓冲区,以便在通用顶点属性和缓冲区对象之间建立关联以从中获取数据。

但是,在 glVertexAttribPointer.

的调用之后 glBindBuffer(GL_ARRAY_BUFFER, VBO2) 绑定缓冲区

这就是您需要两次调用的原因,因为第一次调用不会将任何缓冲区对象关联到通用顶点属性,因为之前可能没有绑定缓冲区。

然而,您使用 VAO 的方式是可疑的,因为您在此 method/function 中所做的一切都已经保存为 VAO 状态。因此,您既不需要每次都重新建立通用顶点属性和缓冲区对象之间的关联,也不需要每次绘制时都启用通用顶点属性。

所有这些都可以在为 VAO 指定顶点时一次完成