为什么必须在 glBindVertexArray 之外调用元素缓冲区的 glBufferSubData?
Why glBufferSubData for element buffer must be called outside of glBindVertexArray?
我正在尝试替换这个 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
之后执行此操作,我只会变黑 window。奇怪的是,GL_ARRAY_BUFFER
可以在glBindVertexArray
之后更新。这个观察背后的顶点缓冲区和元素缓冲区有什么区别?
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:
The name space for vertex array objects is the unsigned integers, with zero
reserved by the GL to represent the default vertex array object.
The command
void GenVertexArrays( sizei n, uint *arrays );
returns n previous unused vertex array object names in arrays.
...
A vertex array object is created by binding a name returned by GenVertexArray
with the command
void BindVertexArray( uint array );
array
is the vertex array object name. The resulting vertex array object is a new state vector, comprising all the state and with the same initial values listed in tables 23.3 and 23.4.
BindVertexArray
may also be used to bind an existing vertex array object. If the bind is successful no change is made to the state of the bound vertex array object, and any previous binding is broken.
Table 23.4, Vertex Array Object State
ELEMENT_ARRAY_BUFFER_BINDING
, VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
, VERTEX_ATTRIB_BINDING
, VERTEX_ATTRIB_RELATIVE_OFFSET
, VERTEX_BINDING_OFFSET
, VERTEX_BINDING_STRIDE
, VERTEX_BINDING_DIVISOR
, VERTEX_BINDING_BUFFER
.
我正在尝试替换这个 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
之后执行此操作,我只会变黑 window。奇怪的是,GL_ARRAY_BUFFER
可以在glBindVertexArray
之后更新。这个观察背后的顶点缓冲区和元素缓冲区有什么区别?
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:
The name space for vertex array objects is the unsigned integers, with zero reserved by the GL to represent the default vertex array object. The command
void GenVertexArrays( sizei n, uint *arrays );
returns n previous unused vertex array object names in arrays.
...
A vertex array object is created by binding a name returned by
GenVertexArray
with the commandvoid BindVertexArray( uint array );
array
is the vertex array object name. The resulting vertex array object is a new state vector, comprising all the state and with the same initial values listed in tables 23.3 and 23.4.
BindVertexArray
may also be used to bind an existing vertex array object. If the bind is successful no change is made to the state of the bound vertex array object, and any previous binding is broken.Table 23.4, Vertex Array Object State
ELEMENT_ARRAY_BUFFER_BINDING
,VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
,VERTEX_ATTRIB_BINDING
,VERTEX_ATTRIB_RELATIVE_OFFSET
,VERTEX_BINDING_OFFSET
,VERTEX_BINDING_STRIDE
,VERTEX_BINDING_DIVISOR
,VERTEX_BINDING_BUFFER
.