我的程序接收到一些数据点(每秒0-400)。
// simplified example of point's data structure
struct Point {
QPoint p;
QTime t;
quint32 value;
}
我需要渲染一些过滤点(例如
point.time > currentTime-5
和point.value>5
)。我需要存储数据历史记录(直到〜50'000点)。
数据也可以在CPU上使用。
我将使用对象拾取。
点以3d呈现。
相机位置可以更改,但点数据是恒定的。
问题
实现此效果的最佳架构是什么?有什么问题?这类数据的最佳做法是什么,应避免的做法是什么?
可能的解决方案
存储和过滤数据。
>
将数据存储在CPU(世界坐标)上,在CPU上过滤数据并将已过滤的数据发送到VBO,使用着色器计算屏幕空间坐标。
将数据存储在CPU和GPU上(
在CPU上过滤点并计算偏移量并使用
glMultiDrawArrays
。仅将数据存储在GPU上(在点到达时更新VBO)。
过滤它使用着色器,可以在需要时将数据从VBO获取到CPU。
解决方案1.相当简单,但我认为这是一个不好的做法。
解决方案2解决方案3.具有读取GPU-> CPU的数据。
我尝试了这些解决方案,而解决方案2出现在我的身上最好,但是有一些问题:
数据的乘法必须轻柔地处理。 >这不是最容易读取和修改的解决方案。
当数据发生更改时,有很多事情需要更改。
我在VBO上使用了循环缓冲区之类的东西并发送偏移量可以在其上渲染。
环境
OpenGL 3.3
Qt 5+绑定
Linux
PS
我对计算机图形学和openGL相当陌生,所以也许这种问题甚至都有它的名字。我改变了几次实现,花了很多时间,但由于它的复杂性,我对此并不满意。任何材料,指南和想法都可以接受。
#1 楼
我的建议实际上是坚持解决方案1,除非并且直到需要更多解决方案为止。这是最简单,最容易理解的,并且使其表现良好应该是很可行的。一方面,重新筛选点并重新上传一堆图像似乎很浪费。每帧向VBO发送数据。我想这就是为什么您说这是“不良做法”的原因。但是请考虑涉及的数据总量。数量级估计表明,对于现代计算机,每帧处理此数据量并不是一件很容易的事。
您引用的
Point
结构看起来大约是20个字节(假设p
为3浮点数,而t
是一个浮点数或整数)。使用50,000点,数据的总大小约为1 MB。即使您的实际数据结构稍大,数据的总大小仍然只有几MB,按今天的标准来说很小。在CPU上处理此数据量并将其传输到GPU所需的时间约为0.1毫秒。 (假设CPU带宽为〜20 GB /秒,PCIe传输带宽为〜8 GB /秒。)因此,这是完全合理的数据量,可以重新处理每个帧,实际上,您可以处理更多次而不会给您带来压力因此,只需使事情简单而有效地进行内存访问即可:
将点存储在大型平面数组中(可能使用环形缓冲区)以允许新的输入点覆盖旧的输入点。)
每帧,使用CPU上的紧密循环扫描这些点,然后将通过过滤器的点复制到VBO中。
为了获得最佳效率,创建VBO时可能应该使用
GL_DYNAMIC_DRAW
用法,然后每帧使用glMapBufferRange
,然后将过滤后的点直接复制到映射的缓冲区中。将
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT
用于access
的glMapBufferRange
参数;这将允许GL驱动程序执行引擎盖下的双重缓冲,以将数据有效地流式传输到GPU。有关此处发生的情况的更多信息,请参见“缓冲区对象流”。然后取消映射缓冲区并发出绘制命令,使用顶点着色器照常将点转换为屏幕空间。