OpenGL 4.5 直接状态访问渲染一个三角形 - GL_INVALID_VALUE [重复]

Posted

技术标签:

【中文标题】OpenGL 4.5 直接状态访问渲染一个三角形 - GL_INVALID_VALUE [重复]【英文标题】:OpenGL 4.5 Direct State Access Render a Triangle - GL_INVALID_VALUE [duplicate] 【发布时间】:2020-05-15 19:45:16 【问题描述】:

说明

我目前正在学习 OpenGL,并想尝试 OpenGL 4.5 的直接状态访问扩展。因此,我设置了一个简单的三角形渲染示例(3D),它应该渲染我的三角形。下面的代码每帧执行一次,并在 3D 空间中绘制一个三角形。

    void Geometry::draw(glm::vec3 pos, glm::vec3 pos1, glm::vec3 pos2) 
        float vertices[9] = 
            pos.x, pos.y, pos.z,
            pos1.x, pos1.y, pos1.z,
            pos2.x, pos2.y, pos2.z
        ;

        unsigned int m_VaoID;
        glGenVertexArrays(1, &m_VaoID);
        glBindVertexArray(m_VaoID);

        unsigned int m_VboID;
        glGenBuffers(1, &m_VboID);
        glBindBuffer(GL_ARRAY_BUFFER, m_VboID);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, 0);

        Shader shader = Shader("../../shader.glsl");
        shader.compileShader();
        shader.useShader();

        glDrawArrays(GL_TRIANGLES, 0, 3);

        glBindVertexArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glDeleteVertexArrays(1, &m_VaoID);
        glDeleteBuffers(1, &m_VboID);
    

但是,一旦我更改代码以使用直接状态访问扩展,它就不再呈现三角形而是产生错误消息。

    void Geometry::drawDSA(glm::vec3 pos, glm::vec3 pos1, glm::vec3 pos2) 
        float vertices[9] = 
            pos.x, pos.y, pos.z,
            pos1.x, pos1.y, pos1.z,
            pos2.x, pos2.y, pos2.z
        ;

        unsigned int m_VaoID;
        glCreateVertexArrays(1, &m_VaoID);
        glVertexArrayAttribFormat(m_VaoID, 0, 3, GL_FLOAT, GL_FALSE, 0);

        unsigned int m_VboID;
        glCreateBuffers(1, &m_VboID);
        glNamedBufferData(m_VboID, sizeof(vertices), vertices, GL_STATIC_DRAW);

        glVertexArrayAttribBinding(m_VaoID, 0, m_VboID);

        Shader shader = Shader("../../shader.glsl");
        shader.compileShader();
        shader.useShader();

        glBindVertexArray(m_VaoID);
        glBindBuffer(GL_ARRAY_BUFFER, m_VboID);

        glDrawArrays(GL_TRIANGLES, 0, 3);

        glBindVertexArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glDeleteVertexArrays(1, &m_VaoID);
        glDeleteBuffers(1, &m_VboID);
    

在我的 更新循环 中调用这两种方法,并使用相同的值(介于 -1.f 和 0.f 之间)。

错误输出:

这是我得到的错误的控制台输出:

[OpenGL Debug HIGH] GL_INVALID_VALUE in glVertexArrayAttribBinding(bindingindex=16 >= GL_MAX_VERTEX_ATTRIB_BINDINGS)
[OpenGL Debug HIGH] GL_INVALID_VALUE in glVertexArrayAttribBinding(bindingindex=17 >= GL_MAX_VERTEX_ATTRIB_BINDINGS)
[OpenGL Debug HIGH] GL_INVALID_VALUE in glVertexArrayAttribBinding(bindingindex=18 >= GL_MAX_VERTEX_ATTRIB_BINDINGS)
[OpenGL Debug HIGH] GL_INVALID_VALUE in glVertexArrayAttribBinding(bindingindex=19 >= GL_MAX_VERTEX_ATTRIB_BINDINGS)

到目前为止我尝试了什么

我查看了 Khronos Wiki 和 docs.gl 文档,但我找不到为什么我的代码会产生上述错误而不是渲染我的三角形。

【问题讨论】:

glVertexArrayAttribBinding的第三个参数不应该是VBO。您也错过了对glVertexArrayAttribFormatglVertexArrayVertexBuffer 的呼叫。我猜你完全混淆了 DSA 的工作原理。查看Direct State access with vertex buffers,了解如何将旧代码转换为 DSA 的分步说明。另请注意,绘图时不应调用glBindBuffer 【参考方案1】:

glVertexArrayAttribBinding的3d参数不是顶点缓冲对象,是绑定索引。这是您必须选择的任意 ID。 以下指令将绑定索引与指定 VAO 的属性索引 (0) 相关联。

glVertexArrayAttribBinding(m_VaoID, 0, m_VboID);

glVertexArrayAttribBinding(m_VaoID, 0, binding_index);

此外,您必须使用glVertexArrayVertexBuffer 将缓冲区对象关联到指定 VAO 的绑定索引:

glVertexArrayVertexBuffer(m_VaoID, binding_index, m_VboID, 0, sizeof(float) * 3);

【讨论】:

谢谢你的答案。您能否指定绑定索引的用途?我可以选择任何随机数吗?有趣的是,尽管使用了 DSA,我仍然必须致电 glBindVertexBuffer。我认为这不再是必要的了。 @ShadowDragon 1. 是随机的。 2. 我改了答案。 @ShadowDragon:你不应该使用 glBindVertexBuffer 而是 glVertexArrayVertexBuffer。

以上是关于OpenGL 4.5 直接状态访问渲染一个三角形 - GL_INVALID_VALUE [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如果当前处于活动状态,则 OpenGL 纹理不会渲染

OpenGL

OpenGL

初识OpenGL (-)编程思想

GLSL 编程思想

Modern OpenGL - 顶点数组、属性与绑定点(OpenGL 4.5+)