我是第一次使用GLSurfaceView
玩OpenGL。我的第一个项目是使用GL_LINE_STRIP
将一些实时数据绘制成折线图。然而,在我深入研究代码之前,我正在寻找一些关于如何最好地解决使用OpenGL和Android绘制实时数据的问题的建议。
我想最简单的方法是实例化一个固定长度的ByteBuffer
来存储前端的顶点数据(x& y值),然后提供你的数据流是固定的速率,应该是使用ByteBuffer
方法仅更新put
中的y值的简单情况。但是,这将依赖于Android以准确的速率将数据传递到本机环境的假设,例如如果数据在50毫秒内流式传输,我可以确定Android会以50毫秒的间隔通过并更新ByteBuffer
吗?这是采用实时绘图的典型方法吗?
如果没有,我想最好使用“实时数据”并使用每个y值计算x的值,并将两个值都传递给ByteBuffer
。
答案 0 :(得分:3)
第一:你确定你真的需要OpenGL吗?这听起来像是您应该可以使用自定义Android视图和Android Canvas绘图API执行的操作。
也就是说,如果你想要一个简单的OpenGL解决方案,请在内存中更新你的ByteBuffer。每次有新数据点到达时:从前面删除最旧的条目,将最新的条目附加到后面。更新缓冲区后,使用glBufferData()
再次将其上传到GPU。
当需要使用glDrawElement(GL_LINE_STRIP, ...)
重绘时,请务必更新视图矩阵,以便“滚动”新数据点。
请注意,此技术效率不高。首先更新CPU上的所有顶点数据,然后每隔50ms将所有顶点数据传输到GPU。但是,如果屏幕上只有几百个顶点,则无关紧要。
更有效的解决方案是在GPU内存上保持Circular Buffer。每次新数据到达时,您都可以使用glBufferSubData()
替换最旧的数据点。这样更有效,但它需要您跟踪最旧数据点的存储位置。
答案 1 :(得分:1)
我目前正在开展一项类似的任务,每个200毫秒更新数据,缓冲区包含高达100k的值,并且到目前为止运行得非常流畅(不知道Canvas是否更合适)。但我仍在寻找更多优化,我想尝试一些提示:
Vertex Specification Best Practices > Dynamic VBO
如果要更新小部分,请使用glBufferSubData。如果你 将更新整个VBO,使用glBufferData(此信息 据报道来自nVidia文件)。但是,另一种方法 在更新整个缓冲区时要声称能够正常工作 glBufferData用NULL指针,然后用glBufferSubData跟 新内容。指向glBufferData的NULL指针让驱动程序知道 你不关心以前的内容,所以可以自由替换 一个完全不同的缓冲区,这有助于驱动程序管道上传 更有效率。
OpenGL ES Programming Guide for iOS > Best Practices for Working with Vertex Data
您可以使用glBufferSubData函数更新缓冲区内容, 但这样做会导致性能下降,因为它冲刷了 命令缓冲区并等待所有命令完成。双倍或 三重缓冲可以在一定程度上降低性能成本。 (参见“使用 双缓冲以避免资源冲突。“)
iPhone 3D Programming > Boosting Performance with Vertex Buffer Objects
要修改现有VBO的内容,您可以使用 glBufferSubData: [...]
这与glBufferData的唯一区别是offset参数, 它指定从VBO开始的字节数。注意 glBufferSubData应仅用于更新具有的VBO 以前用glBufferData初始化。
我们不会在本书的任何示例中使用glBufferSubData。 应该避免频繁更新glBufferSubData以获得最佳效果 性能,但在许多情况下它可能非常有用。