I'm trying to replace contents of element buffer in this hello world example https://github.com/jvm-graphics-labs/hello-triangle/blob/master/src/main/java/gl4/HelloTriangleSimple.java and I managed to do it with some minor changes by using glBufferSubData
, but I'm curious about one peculiarity - in my display method I have to call glBufferSubData
before I call 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));
If I do it after glBindVertexArray
, I'm getting only black window. The strange thing is that GL_ARRAY_BUFFER
can be updated after glBindVertexArray
. What is the difference between vertex buffer and element buffer behind this observation?
The GL_ELEMENT_ARRAY_BUFFER
object is stored in the vertex array objects state vector.
If a Vertex Array Object is bound the an element buffer can be attached to it by
gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferName.get(Buffer.ELEMENT));
But if you do
gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
then the name of the element buffer object is replaced by 0 and the reference to the elements is broken. This causes that gl.drawElements
won't work any more for the this VAO, because it doesn't refer to any index list.
Further note, there is always a vertex array object. The vertex array object 0 is the default vertex array object which is only valid when you use a compatibility profile context (not core).
This means that
gl.glBindVertexArray(0);
gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferName.get(Buffer.ELEMENT));
will associate a element buffer to the default vertex array object (0). This is perfectly valid in compatibility profile context.
See the 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
.