使用OpenGL绘制实时数据

时间:2013-09-10 14:00:06

标签: android opengl-es opengl-es-2.0 real-time

我是第一次使用GLSurfaceView玩OpenGL。我的第一个项目是使用GL_LINE_STRIP将一些实时数据绘制成折线图。然而,在我深入研究代码之前,我正在寻找一些关于如何最好地解决使用OpenGL和Android绘制实时数据的问题的建议。

我想最简单的方法是实例化一个固定长度的ByteBuffer来存储前端的顶点数据(x& y值),然后提供你的数据流是固定的速率,应该是使用ByteBuffer方法仅更新put中的y值的简单情况。但是,这将依赖于Android以准确的速率将数据传递到本机环境的假设,例如如果数据在50毫秒内流式传输,我可以确定Android会以50毫秒的间隔通过并更新ByteBuffer吗?这是采用实时绘图的典型方法吗?

如果没有,我想最好使用“实时数据”并使用每个y值计算x的值,并将两个值都传递给ByteBuffer

2 个答案:

答案 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是否更合适)。但我仍在寻找更多优化,我想尝试一些提示:

  1. Vertex Specification Best Practices > Dynamic VBO

      

    如果要更新小部分,请使用glBufferSubData。如果你   将更新整个VBO,使用glBufferData(此信息   据报道来自nVidia文件)。但是,另一种方法   在更新整个缓冲区时要声称能够正常工作   glBufferData用NULL指针,然后用glBufferSubData跟   新内容。指向glBufferData的NULL指针让驱动程序知道   你不关心以前的内容,所以可以自由替换   一个完全不同的缓冲区,这有助于驱动程序管道上传   更有效率。

  2. OpenGL ES Programming Guide for iOS > Best Practices for Working with Vertex Data

      

    您可以使用glBufferSubData函数更新缓冲区内容,   但这样做会导致性能下降,因为它冲刷了   命令缓冲区并等待所有命令完成。双倍或   三重缓冲可以在一定程度上降低性能成本。 (参见“使用   双缓冲以避免资源冲突。“)

  3. iPhone 3D Programming > Boosting Performance with Vertex Buffer Objects

      

    要修改现有VBO的内容,您可以使用   glBufferSubData:   [...]

         

    这与glBufferData的唯一区别是offset参数,   它指定从VBO开始的字节数。注意   glBufferSubData应仅用于更新具有的VBO   以前用glBufferData初始化。

         

    我们不会在本书的任何示例中使用glBufferSubData。   应该避免频繁更新glBufferSubData以获得最佳效果   性能,但在许多情况下它可能非常有用。