To completely answer this question, I have to mention the OpenGL buffer update first.
The OpenGL instruction glBufferData
creates and initializes a buffer object's data store. An existing data store of an buffer object is completely destroyed and a new data store (possibly with a different size) is created. If a data pointer is passed to the function, then the data store is completely initialized by the data. The size of the buffer and the size of the provided data is assumed to be equal.
glBufferSubData
updates the entire data or a subset of the data of an existing data store. The data store is assumed to be created before, by glBufferData
. No data store is destroyed or created.
Of course, technically glBufferData
can always be use instead of glBufferSubData
, but glBufferSubData
will perform much better, because the expensive buffer creation (allocation) is eliminated.
Using
self.vbo.set_array(self.verts)
is a bad idea, because as seen in the implementation (PyOpenGL/OpenGL/arrays/vbo.py), this method creates a completely new buffer, with a possibly new size and will force the recreation of the buffer object's data store (because of self.copied = False
).
If the buffer was created before, then self.vbo.copy_data()
will update the data by glBufferSubData
(see if self.copied:
in copy_data
). To make this work the buffer has to be the currently bound buffer (self.vbo.bind()
). Further a copy information has to be set (VBO.copy_segments
). The copy information is stated by the item setter (VBO.__setitem__
).
This means, in "Approach 1" you would have to do something like the following:
self.vbo[:] = self.verts
self.vbo.bind()
self.vbo.copy_data()
Since OpenGL.arrays.vbo
is nothing more than a wrapper for the OpenGL buffer instructions, I would prefer to use glBufferSubData
directly, which will perform best in cases like this:
# Approach 3:
# Direct buffer update by `glBufferSubData`
self.vbo.bind()
self.vbo.implementation.glBufferSubData(self.vbo.target, 0, self.vbo.data)
With this approach even subsets of the data store can be updated. Note the 2nd parameter of glBufferSubData
is a byte offset to the buffer objects data store. Further there is an overloaded implementation, which can process a buffer size and a direct data pointer.