【问题标题】:Why glBufferSubData for element buffer must be called outside of glBindVertexArray?为什么元素缓冲区的 glBufferSubData 必须在 glBindVertexArray 之外调用?
【发布时间】:2018-11-18 02:02:04
【问题描述】:

我试图在这个 hello world 示例 https://github.com/jvm-graphics-labs/hello-triangle/blob/master/src/main/java/gl4/HelloTriangleSimple.java 中替换元素缓冲区的内容,并且我设法通过使用 glBufferSubData 进行了一些小的更改,但我对一个特殊性感到好奇 - 在我的显示方法中在我打电话给glBindVertexArray之前,我必须先打电话给glBufferSubData

gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferName.get(Buffer.ELEMENT));
elementBuffer.rewind();
elementBuffer.put(elementData).rewind();
gl.glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, elementBuffer.capacity() * Short.BYTES, elementBuffer);
gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
gl.glBindVertexArray(vertexArrayName.get(0));

如果我在glBindVertexArray 之后执行此操作,我只会得到黑色窗口。奇怪的是GL_ARRAY_BUFFER可以glBindVertexArray之后更新。这个观察背后的顶点缓冲区和元素缓冲区有什么区别?

【问题讨论】:

  • 元素数组缓冲区对象的名称存储在顶点数组对象状态向量中。如果绑定了 VAO,并且您执行gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0),则元素缓冲区对象的名称将替换为 0,并且对元素的引用被破坏。这会导致 gl.drawElements 不再适用于 VAO。
  • @Rabbid76 这就是答案。如果您将其复制为真实答案,我会将其标记为真实答案。没有的话我自己复制。我已经尝试过了,你说的现在也很明显,但作为一个初学者,我看不到这种联系。但是,我仍然对缓冲区之间的区别感到有些困惑。如果我可以将 0 绑定为 GL_ARRAY_BUFFER 并且绘图仍然有效,这是否意味着它没有从 VAO 中引用?
  • VAO 存储GL_ELEMENT_ARRAY_BUFFER 类型的缓冲区绑定。但它不适用于GL_ARRAY_BUFFER 类型,它们由glVertexAttribPointer 存储

标签: opengl jogl


【解决方案1】:

GL_ELEMENT_ARRAY_BUFFER 对象存储在顶点数组对象状态向量中。

如果绑定了Vertex Array Object 元素缓冲区可以通过

gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferName.get(Buffer.ELEMENT));

如果你这样做了

gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)

然后元素缓冲区对象的名称被替换为 0 并且对元素的引用被破坏。这导致 gl.drawElements 不再适用于这个 VAO,因为它不引用任何索引列表。


进一步说明,总是有一个顶点数组对象。顶点数组对象 0 是默认的顶点数组对象,仅当您使用兼容性配置文件上下文(非核心)时才有效。

这意味着

gl.glBindVertexArray(0);
gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferName.get(Buffer.ELEMENT));

将元素缓冲区关联到默认顶点数组对象 (0)。这在兼容性配置文件上下文中完全有效。


OpenGL 4.6 API Compatibility Profile Specification; 10.3.1 Vertex Array Objects; page 393

顶点数组对象的命名空间是无符号整数,为零 由 GL 保留,用于表示默认的顶点数组对象。 命令

void GenVertexArrays( sizei n, uint *arrays );

在数组中返回 n 个以前未使用的顶点数组对象名称。

...

通过将GenVertexArray返回的名称与命令绑定来创建顶点数组对象

void BindVertexArray( uint array );

array 是顶点数组对象名称。生成的顶点数组对象是一个新的状态向量,包含所有状态并具有表 23.3 和 23.4 中列出的相同初始值。
BindVertexArray 也可用于绑定现有的顶点数组对象。如果绑定成功,则绑定的顶点数组对象的状态不会发生任何变化,并且之前的任何绑定都会被破坏。

表 23.4,顶点数组对象状态
ELEMENT_ARRAY_BUFFER_BINDINGVERTEX_ATTRIB_ARRAY_BUFFER_BINDINGVERTEX_ATTRIB_BINDINGVERTEX_ATTRIB_RELATIVE_OFFSETVERTEX_BINDING_OFFSETVERTEX_BINDING_STRIDEVERTEX_BINDING_DIVISOR,@987654340 @。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-10
    • 2015-01-19
    • 1970-01-01
    • 2013-10-28
    • 1970-01-01
    • 2020-07-06
    相关资源
    最近更新 更多