当glBindVertexArray时,VAO没有更新

时间:2016-10-09 17:22:21

标签: c++ opengl

我正在学习openGL,并试图理解VBO和VAO之间的关系。

据我所知,VBO是数据的缓冲区,就是这样。为了将该数据传递到OpenGL管道,我需要将VBO数据绑定到VAO。

这可以通过过多的glVertexAttrib*函数来实现。 或者,您可以将VAO设置为通过一组glVertexArray*函数自动从VBO上传数据,最后调用glEnableVertexArrayAttrib。 现在,每当我更改一些VBO中的数据时,我所要做的就是在我的VAO上调用glBindVertexArray以将数据从VBO上传到VAO。

右?

至少,这就是我理解会发生什么的方式。但是,当我尝试在代码中使用它时,我看不到预期的结果(屏幕周围出现三角形变形)。

以下是我创建VAO和VBO的代码:

void startup()
{
    static const GLfloat positions[] =
    {
         1.00f, -0.25f, 0.0f, 1.0f,
         1.00f, -0.25f, 0.0f, 1.0f ,
         1.00f, -0.25f, 0.0f, 1.0f 
    };


    m_renderingProgram = compile_shaders();

    //Create VAO and VBO
    glCreateVertexArrays(1, &m_VAO);
    glCreateBuffers(1, &m_VBO);


    //Set the VAO to automatically update it's data with VBO when it is bound
    glNamedBufferStorage(m_VBO, sizeof(positions), positions, 0);
    glVertexArrayVertexBuffer(m_VAO, 0, m_VBO, 0, 4);
    glVertexArrayAttribFormat(m_VAO, 0, 3, GL_FLOAT, GL_FALSE, 0);
    glVertexArrayAttribBinding(m_VAO, 0, 0);
    glEnableVertexArrayAttrib(m_VAO, 0);


    //Create a named buffer, so we can change the data within easily
    glNamedBufferData(m_VBO, sizeof(positions), positions, GL_MAP_WRITE_BIT);

    //Upload the data to the VAO
    glBindVertexArray(m_VAO);
}

这是我的Update()函数代码:

void render(double currentTime)
{
    const GLfloat red[] = { (float)sin(currentTime) * 0.5f + 0.5f,
                                   (float)cos(currentTime) * 0.5f + 0.5f,
                                    (float)sin(currentTime) * 0.5f + 0.5f,
                            1.0f };


    const GLfloat newPosition[] = 
    { 
        sin(currentTime) * 1.00, sin(currentTime) * -0.25, 0.0, 1.0,
        tan(currentTime) * 1.00, tan(currentTime) * -0.25, 0.0, 1.0 ,
        cos(currentTime) * 1.00, cos(currentTime) * -0.25, 0.0, 1.0
    };


    const GLfloat black[] = { 0.0f, 0.0f, 0.0f, 1.0f };
    glViewport(sin(currentTime) * 0.4f, cos(currentTime) * 0.5f, 800, 600);

    glClearBufferfv(GL_COLOR, 0, black);
    //Copy the new position to the buffer
    glNamedBufferSubData(m_VBO, 0, sizeof(newPosition), newPosition);


    //Use the shader program program
    glUseProgram(m_renderingProgram);


    glVertexAttrib4fv(1, red);
    //Update the VAO with the updated VBO
    glBindVertexArray(m_VAO);


    glDrawArrays(GL_TRIANGLES, 0, 3);
}

我希望看到的是一个三角形在屏幕周围变形并改变颜色,但我看到的是一个静态三角形改变颜色。

1 个答案:

答案 0 :(得分:2)

  

据我所知,VBO是数据的缓冲区,而且全部都是。

buffer object是数据的缓冲区。术语" VBO"指的是(当前)用作顶点属性的源的缓冲区对象。 Buffer objects can be used for many other things,您可以通过多种不同的方式使用相同的缓冲区。

  

为了将该数据传递到OpenGL管道,我需要将VBO数据绑定到VAO。

技术术语是"附加"缓冲区对象为VAO。你"附上"一个对象到另一个;你"绑定" context 的对象。

现在我们已经制定了我们的术语,让我们谈谈代码出错的地方。

//Create a named buffer, so we can change the data within easily
glNamedBufferData(m_VBO, sizeof(positions), positions, GL_MAP_WRITE_BIT);

你不能这样做。您已使用glNamedBufferStorage为该缓冲区对象创建了存储空间。更重要的是,您为它创建了不可变存储。这意味着一旦为缓冲区对象创建了不可变存储,就无法返回并创建新存储。

哪个好;实际上,这条线是完全多余的,因为您已经创建了存储并上传到它。只需删除此冗余行。

//Copy the new position to the buffer
glNamedBufferSubData(m_VBO, 0, sizeof(newPosition), newPosition);

这是我们开始遇到更严重问题的地方。

请参阅,您创建了缓冲区的存储空间,如下所示:

glNamedBufferStorage(m_VBO, sizeof(positions), positions, 0);

那个0有标志字段;它指定the ways in which you can modify the contents of the storage from the CPU(除其他外)。也就是说,不可变存储并不意味着您无法再将内容复制到其中。它只是意味着您无法重新分配存储空间。

但是你通过了0.这意味着你创建的缓冲区是完全静态的。您告诉OpenGL您不希望通过CPU进程更改缓冲区的内容。这对静态缓冲区来说很好,但这显然不是你想要的。

因此,您应该传递适当的标志而不是0。允许glNamedBufferSubData工作的标记称为GL_DYNAMIC_STORAGE_BIT