如何有效地管理 OpenGL 中的常量几何和颜色变化?
How to manage constant geometry and changing color in OpenGL efficiently?
我必须绘制多个立方体(取决于数据,范围从 6k 到,在极端情况下,11k 对象)。
立方体有固定的位置,在动画过程中不会改变,但颜色会在每一帧发生变化。我认为可以绘制一次几何图形,然后重新绘制颜色,但如何才能有效地实现呢?
另外,我是一个初学者,所以我对OpenGL只有一个基本的了解。
最佳实践是什么(假设使用 PyOpenGL)?
我没有任何专门使用 pyOpenGL 的经验,但我有丰富的 webGL 经验和一些 openGL 经验,所以希望这会有所帮助。
我不完全确定你所说的一次绘制几何然后只绘制颜色是什么意思,你的意思是就像有一个缓冲区用于位置和一个用于颜色然后只改变颜色?如果是这样我认为这是不可能的,因为我认为 openGL 一次只能处理一个顶点属性缓冲区。
我想说最好的方法是将所有立方体放在同一个缓冲区中以减少绘制调用,并将缓冲区的使用设置为 GL_DYNAMIC_DRAW 正如 BeyelerStudios 评论的那样,因为动态缓冲区是旨在经常访问。然后在更改颜色时将位置和颜色数据都更新到此缓冲区中。
希望对您有所帮助!
已经有一段时间了,但与此同时我已经解决了这个问题,并认为发布答案可能会有帮助。
一般来说,因为BeyelerStudios suggested, glBufferData
可以通过设置GL_DYNAMIC_DRAW
或GL_STATIC_DRAW
作为usage
参数来判断是否要动态改变一个缓冲区的内容。
然而,还有更多内容,因为我们可以走得更远。
我将使用 PyOpenGl 来解释这一点,但 C++ 可能也是如此 api.
让我们看一下可能负责创建 VBO 的一组函数:
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
基本上,create_vbo
函数声明了两个缓冲区:顶点缓冲区为静态缓冲区,颜色缓冲区为动态缓冲区。我们可以采取的额外步骤是使用 glBufferSubdata
而不是 glBufferData
作为 vbo_cubic_draw
中的动态缓冲区。然后只需要重新绘制颜色缓冲区,然后我们就可以在draw_vbo
中调用一些绘图函数(例如glDrawArrays
)。显然,这种方法需要两个单独的缓冲区,一个用于颜色,一个用于顶点,这有时是不希望的。但是看看 glBufferSubdata
文档,我认为不可能将它用于单个交错缓冲区,因为我们确实只有 offset 参数。也许有人对此有不同的看法?
编辑。实际上,如果数组紧凑且结构合理,则很有可能 - 我怀疑您可以只使用一个大缓冲区而不是多个缓冲区。
我必须绘制多个立方体(取决于数据,范围从 6k 到,在极端情况下,11k 对象)。
立方体有固定的位置,在动画过程中不会改变,但颜色会在每一帧发生变化。我认为可以绘制一次几何图形,然后重新绘制颜色,但如何才能有效地实现呢?
另外,我是一个初学者,所以我对OpenGL只有一个基本的了解。 最佳实践是什么(假设使用 PyOpenGL)?
我没有任何专门使用 pyOpenGL 的经验,但我有丰富的 webGL 经验和一些 openGL 经验,所以希望这会有所帮助。
我不完全确定你所说的一次绘制几何然后只绘制颜色是什么意思,你的意思是就像有一个缓冲区用于位置和一个用于颜色然后只改变颜色?如果是这样我认为这是不可能的,因为我认为 openGL 一次只能处理一个顶点属性缓冲区。
我想说最好的方法是将所有立方体放在同一个缓冲区中以减少绘制调用,并将缓冲区的使用设置为 GL_DYNAMIC_DRAW 正如 BeyelerStudios 评论的那样,因为动态缓冲区是旨在经常访问。然后在更改颜色时将位置和颜色数据都更新到此缓冲区中。
希望对您有所帮助!
已经有一段时间了,但与此同时我已经解决了这个问题,并认为发布答案可能会有帮助。
一般来说,因为BeyelerStudios suggested, glBufferData
可以通过设置GL_DYNAMIC_DRAW
或GL_STATIC_DRAW
作为usage
参数来判断是否要动态改变一个缓冲区的内容。
然而,还有更多内容,因为我们可以走得更远。
我将使用 PyOpenGl 来解释这一点,但 C++ 可能也是如此 api.
让我们看一下可能负责创建 VBO 的一组函数:
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
基本上,create_vbo
函数声明了两个缓冲区:顶点缓冲区为静态缓冲区,颜色缓冲区为动态缓冲区。我们可以采取的额外步骤是使用 glBufferSubdata
而不是 glBufferData
作为 vbo_cubic_draw
中的动态缓冲区。然后只需要重新绘制颜色缓冲区,然后我们就可以在draw_vbo
中调用一些绘图函数(例如glDrawArrays
)。显然,这种方法需要两个单独的缓冲区,一个用于颜色,一个用于顶点,这有时是不希望的。但是看看 glBufferSubdata
文档,我认为不可能将它用于单个交错缓冲区,因为我们确实只有 offset 参数。也许有人对此有不同的看法?
编辑。实际上,如果数组紧凑且结构合理,则很有可能 - 我怀疑您可以只使用一个大缓冲区而不是多个缓冲区。