I have to draw multiple cubes (depending on data, ranging from 6k to, in an extreme case, 11k objects).
The cubes have fixed positions that do not change during the animation, however the color does change each frame. I reckon it is possible to draw geometry once, then just redraw the color, but how one can achieve that efficiently?
Also, I am a total beginner, so I do have only a basic understanding of OpenGL. What is the best practice (assuming the use of PyOpenGL)?
It has been a while but in the meantime I've solved this issue and thought that posting an answer might be helpful.
Generally, as BeyelerStudios suggested, glBufferData
can be used to determine if contents of one buffer are to be dynamically changed by setting GL_DYNAMIC_DRAW
or GL_STATIC_DRAW
as usage
parameter.
However, there is a little more to this, as we can go even further.
I am going to use PyOpenGl to explain that but probably the same goes for C++ api.
Let's have a look at a set of functions that might be responsible for creating VBO's:
def create_vbo(self):
buffers = gl.glGenBuffers(2)
# vertices buffer is static, so GL_STATIC_DRAW
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, buffers[0])
gl.glBufferData(gl.GL_ARRAY_BUFFER,
self.vectors_list,
gl.GL_STATIC_DRAW)
# colour buffer
# note the parameter GL_DYNAMIC DRAW - this buffer will be rebound
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, buffers[1])
gl.glBufferData(gl.GL_ARRAY_BUFFER,
self.colour_vectors[self.i],
gl.GL_DYNAMIC_DRAW)
return buffers
def vbo_cubic_draw(self):
... # make sure buffers are not None i.e. were created
# actually replaces data in colour buffer
gl.glBufferSubData(gl.GL_ARRAY_BUFFER, 0, self.buffer_len,
colour_vectors[self.i])
self.draw_vbo() # call drawing
def draw_vbo(self):
... # enable client states
# bind vertex buffer - will be static
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.buffers[0])
gl.glVertexPointer(4, gl.GL_FLOAT, 0, None)
# bind color buffer which is dynamic
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.buffers[1])
gl.glColorPointer(3, gl.GL_FLOAT, 0, None)
... # do more stuff and actually draw
Basically, create_vbo
function declares two buffers: vertex buffer as static and colour buffer as dynamic. An extra step we can take is to make use of glBufferSubdata
instead of glBufferData
for dynamic buffer in vbo_cubic_draw
. Then it is only required to redraw the colour buffer and then we actually can call some drawing function (e.g. glDrawArrays
) in draw_vbo
. Obviously, such approach requires two separate buffers, one for colour and one for vertices which is sometimes undesired. But looking at glBufferSubdata
doc, I don't think it's possible to use it for single interleaved buffers since we do have only offset parameter. Perhaps someone has a different take on that?
EDIT. Actually it might be very much possible if array is tightly packed and properly structured - I suspect you can use just one large buffer instead of many.