使用 OpenGL 在 C++ 中绘制具有大量数据点的散点图的最佳方法
Posted
技术标签:
【中文标题】使用 OpenGL 在 C++ 中绘制具有大量数据点的散点图的最佳方法【英文标题】:Best way to draw scatter plot with lots of data points in C++ using OpenGL 【发布时间】:2011-10-19 06:50:36 【问题描述】:我正在用 C++ 编写一个程序,该程序通过 UDP 套接字获取 4 维点数据,然后在 6 个单独的 2D 散点图中绘制数据。例如,如果我们将维度命名为:A、B、C、D,则六个二维图将是 AxB、AxC、AxD、BxC、BxD 和 CxD。在几个小时的过程中,该程序累积了约 50K 点。
目前我使用立即模式绘制每个点一次。我不会在绘图调用之间清除缓冲区,因此之前绘制的点会一直存在,直到缓冲区被清除。我对这种方法不满意,因为即时模式很慢且已弃用。当我必须清除缓冲区时,例如当窗口重新调整大小时,我会丢失所有以前绘制的数据。我想提出一个解决方案,在缓冲区被清除后允许数据持久化。此外,如果绘图也可以通过调整窗口大小轻松缩放,那就太好了。
我曾考虑为每个坐标系维护一个顶点数组(2 维),但这需要 6 个单独的数组,并且需要 3 倍于维护所有 4 维数组的内存。
我是否以正确的方式思考这个问题?这个问题的正确解决方案是什么?
最终目标是让应用程序尽可能接近实时地显示数据。
编辑 是否可以在点进入时继续逐个绘制点,当我需要调整屏幕大小时,抓取屏幕的图像,然后显示调整大小的版本图片?
【问题讨论】:
【参考方案1】:使用顶点缓冲区对象可以提高渲染速度,因为要绘制的几何图形可以直接存储在显卡内存中。但是,在您的情况下,如果数据总是更改,我无法告诉您此方法是否比立即模式更快,因为您可能必须在每次数据更改时重建顶点数组对象。如果你只添加点,也许你可以制作多个 VBO 来对点进行分组,并使用立即模式渲染最后收到的点,直到你可以创建一个新的组。例如,如果您收到 100054 个点,也许您可以制作 10 组 10000 个点,并以即时模式渲染最后 54 个点。
关于内存问题,我认为可以在显卡中存储 4 个元素的顶点 - 然后您可以使用不同的顶点着色器来选择要使用的顶点的哪些组件作为渲染坐标。使用这种技术,内存使用量只会是您收到的两倍:一个用于您收到的数据,另一个用于顶点缓冲区对象。
【讨论】:
VBO 至少应该不比客户端阵列慢,并且绝对比即时模式快。 VBO(以及一般的顶点数组)不仅用于内存副本,还用于驱动程序调用开销。 我们可以通过将stride
和 pointer
参数更改为 glVertexPointer
而不必为不同的视图使用不同的顶点着色器而侥幸。
@user786653 不确定,在他使用坐标A和D的情况下,我不知道他如何跳过B和C坐标。也许使用统一属性将有助于使用一个着色器(选择将由着色器使用给定属性完成),但这可能不如使用多个着色器快)。
可以映射缓冲区。如果附加了点,则仅发送差异。应尽可能避免立即模式。
@neodelphi 您可以使用glBufferSubData
或map_buffer_range
扩展名,因此驱动程序可以对此进行优化并仅复制必要的内容。以上是关于使用 OpenGL 在 C++ 中绘制具有大量数据点的散点图的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章