为什么必须在glBindVertexArray之外调用元素缓冲区的glBufferSubData?

时间:2018-11-17 11:29:14

标签: opengl jogl

在这个您好世界的示例https://github.com/jvm-graphics-labs/hello-triangle/blob/master/src/main/java/gl4/HelloTriangleSimple.java中,我试图替换元素缓冲区的内容,并通过使用glBufferSubData进行了一些小的更改,但我对此感到好奇-在我的显示方法中,我必须先致电glBufferSubData,然后再致电glBindVertexArray

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之后进行更新。此观察结果背后的顶点缓冲区和元素缓冲区有什么区别?

1 个答案:

答案 0 :(得分:3)

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_BINDING VERTEX_ATTRIB_ARRAY_BUFFER_BINDINGVERTEX_ATTRIB_BINDINGVERTEX_ATTRIB_RELATIVE_OFFSETVERTEX_BINDING_OFFSETVERTEX_BINDING_STRIDEVERTEX_BINDING_DIVISOR,{ {1}}。