【问题标题】:How do I update the contents of a VertexArrayBuffer如何更新 VertexArrayBuffer 的内容
【发布时间】:2020-09-23 22:49:56
【问题描述】:

我创建了一个带有 2 个顶点数组缓冲区的 VAO。第一个缓冲区包含顶点的坐标,而第二个缓冲区包含每个顶点的 4 个数据值(GLbyte 类型)。

/*
** Create a VAO and bind it
*/
    glCreateVertexArrays(1, &vertex_array_object);
    glBindVertexArray(vertex_array_object);
/*
** Create a buffer and initilise it
*/
    glCreateBuffers(1, &vertex_buffer);
    glNamedBufferStorage(vertex_buffer, sizeof(verticies), verticies, 0);
/*
** Bind the buffer to the VAO
*/
    glVertexArrayVertexBuffer(vertex_array_object, 0, vertex_buffer, 0, sizeof(float)*3);
/*
** Specify the data format,  
*/
    glVertexArrayAttribFormat(vertex_array_object,0, 3, GL_FLOAT, GL_FALSE, 0);
/*
** Specify the vertex buffer binding for this attribute
*/
    glVertexArrayAttribBinding(vertex_array_object,0,0);
/*
** Enable the attribute
*/
    glEnableVertexArrayAttrib(vertex_array_object,0);

/*
** Now repeat for another buffer to hold per vertex data
**
** Create  and initilise it
*/
    glCreateBuffers(1, &nvd_buffer);
    glNamedBufferStorage(nvd_buffer, sizeof(vectors), vectors, 0);
/*
** Bind the buffer to the VAO
*/
    glVertexArrayVertexBuffer(vertex_array_object, 1, nvd_buffer, 0, sizeof(GLbyte)*4);
/*
** Specify the data format,  
*/
    glVertexArrayAttribFormat(vertex_array_object, 1, 4, GL_BYTE, GL_FALSE, 0);
/*
** Specify the vertex buffer binding for this attribute
*/
    glVertexArrayAttribBinding(vertex_array_object,1,1);
/*
** Enable the attribute
*/
    glEnableVertexArrayAttrib(vertex_array_object,1);

这一切正常,我的顶点着色器可以访问第二个缓冲区中的数据并将其传递给几何着色器,用于创建额外的点。

稍后我想更新第二个缓冲区中的数据,但我不知道该怎么做。我想我应该使用

  glNamedBufferSubData(....)

但我不知道如何从 VAO 获取需要输入此函数的缓冲区。我知道我可以存储分配给“nvd_buffer”的原始值,但是有没有办法直接从 VAO 获取此信息,因为我知道我用来将缓冲区绑定到 VAO 的绑定索引

glVertexArrayVertexBuffer(vertex_array_object, 1, nvd_buffer, 0, sizeof(GLbyte)*4);

【问题讨论】:

    标签: opengl vao


    【解决方案1】:

    您不应该询问 VAO 中存储了哪些缓冲区对象。造成这种情况的原因有很多。

    1. 在为 VAO 查询指定 DSA 函数时,出现了……打嗝。 The enumerators weren't actually specified to work for the DSA query functions correctly. 该问题已在规范中得到解决,但这并不意味着任何此类修复都被过滤到实现损坏的规范语言的实现中。因此,关于任何此类查询是否会成功存在一些问题。

    2. 您告诉 OpenGL 使用哪个缓冲区。因此,您已经知道答案了。没有理由问一个你已经知道答案的问题。如果你选择忘记答案,你可以很容易地选择不忘记它。所以这是一个你已经有工具可以解决的问题,你不应该让 OpenGL 为你解决它。

    3. 您不应将缓冲区对象视为由使用它们的 VAO 拥有。它们是它们自己的资源,应与使用它们的任何 VAO 区分开来进行管理。实际上,大多数 VAO 使用(特别是使用单独的属性格式)将在整个渲染循环中将不同的缓冲区附加到 VAO。所以在这些情况下,缓冲区和使用它的 VAO 之间的联系是完全短暂的。

    4. 生命周期问题。如果在 VAO 未绑定到上下文时删除缓冲区对象名称,则缓冲区对象将继续存在,直到它不再附加到任何 VAO。如果您从 VAO 查询缓冲区对象,那么您将有效地使名称恢复“生命”,但仍然会在此类缓冲区不再使用时消失。这可能会导致很难检测到的错误。所以如果不从OpenGL中查询名字,就不可能出现这种错误。

    综上所述,您正在寻找的功能是glGetVertexArrayIndexediv。由于在撰写本文时文档尚未根据我在第 1 项中提到的错误修复进行更新,因此它不会告诉您要使用的正确枚举数。所以查询看起来像这样:

    GLuint buffer;
    glGetVertexArrayIndexediv(vao, binding_index, GL_VERTEX_BINDING_BUFFER, reinterpret_cast<GLint*>(&buffer));
    

    其中binding_index 是您传递给glVertexArrayVertexBuffer 的索引。


    但是,这实际上不会使您的上传代码正常工作。哦,是的,它会给你一个有效的缓冲区对象名称,但你不能上传到它。为什么?

    因为你告诉 OpenGL 你不会。就在这里:

    glNamedBufferStorage(vertex_buffer, sizeof(verticies), verticies, 0);
    

    0 是您为刚刚创建的不可变存储缓冲区提供的使用标志。对于可变缓冲区,使用提示只是一个提示;它不会限制您使用它的能力。

    不是不可变存储缓冲区的情况。如果您没有指定您将以某种方式从 CPU 操作数据存储,那么您不能以这种方式操作它。所以如果你想在一个不可变的存储缓冲区上使用glNamedBufferSubData,你必须告诉 OpenGL 你打算通过providing the appropriate flag 这样做。具体来说,GL_DYNAMIC_STORAGE_BIT

    【讨论】:

      猜你喜欢
      • 2012-08-20
      • 1970-01-01
      • 2015-04-13
      • 2023-03-29
      • 2021-03-11
      • 1970-01-01
      • 1970-01-01
      • 2021-04-29
      • 1970-01-01
      相关资源
      最近更新 更多