2

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

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

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

4

2 回答 2

3

第一:你确定你真的需要OpenGL吗?这听起来像是您应该能够使用自定义 Android 视图和 Android Canvas绘图 API 来完成的事情。


也就是说,如果您想使用简单的 OpenGL 解决方案,请更新内存中的 ByteBuffer。每次有新数据点到达时:从前面删除最旧的条目,将最新的附加到后面。更新缓冲区后,再次将其上传到 GPU glBufferData()

当需要重绘时glDrawElement(GL_LINE_STRIP, ...),请确保更新您的视图矩阵,以便您“滚动”新数据点。

请注意,这种技术效率不高。首先更新 CPU 上的所有顶点数据,然后每 50 毫秒将所有顶点数据传输到 GPU。但是,如果屏幕上只有几百个顶点,则无关紧要。


更有效的解决方案是在 GPU 内存上维护一个循环缓冲区。每次新数据到达时,您都使用 替换最旧的数据点glBufferSubData()。这更有效,但它需要您跟踪最旧数据点的存储位置。

于 2013-09-10T16:06:12.977 回答
1

我目前正在从事一项类似的任务,每 200 毫秒在包含多达 100k 个值的缓冲区中更新数据,并且到目前为止运行得非常流畅(不知道 Canvas 是否更合适)。但是我还在寻找更多的优化,周围有几个提示我想尝试一下:

  1. 顶点规范最佳实践 > 动态 VBO

    如果您要更新一小部分,请使用 glBufferSubData。如果您要更新整个 VBO,请使用 glBufferData(据报道,此信息来自 nVidia 文档)。但是,另一种在更新整个缓冲区时效果很好的方法是使用 NULL 指针调用 glBufferData,然后使用新内容调用 glBufferSubData。指向 glBufferData 的 NULL 指针让驱动程序知道您不关心以前的内容,因此可以自由地替换完全不同的缓冲区,这有助于驱动程序管道更有效地上传。

  2. 适用于 iOS 的 OpenGL ES 编程指南 > 使用顶点数据的最佳实践

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

  3. iPhone 3D 编程 > 使用顶点缓冲区对象提高性能

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

    这和 glBufferData 之间的唯一区别是 offset 参数,它指定从 VBO 开始的字节数。请注意,glBufferSubData 应该仅用于更新先前已使用 glBufferData 初始化的 VBO。

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

于 2013-10-04T09:13:27.373 回答