我需要建议如何改进图形

Posted

技术标签:

【中文标题】我需要建议如何改进图形【英文标题】:I need advice how to improve graphics 【发布时间】:2013-10-24 03:29:47 【问题描述】:

我的文件包含 2300 万条记录,格式如下 atomName, x, y, z, transparence。对于解决方案,我决定使用 OpenGL。

我的任务是渲染它。在第一次迭代中,我使用块“glBegin/glEnd”并将每个原子绘制为点某种颜色。这个解决方案奏效了。但我得到了 0.002 fps。

然后我尝试使用 VBO。我形成了三个缓冲区:顶点、颜色和索引。这个解决方案奏效了。我得到了 60 fps,但我没有舒适的绑定缓冲区,我正在绘制点,而不是球体。

然后我读到了 VAO,它可以简化绑定缓冲区。好的,它成功了。我觉得装订很舒服。

现在我想绘制球体,而不是点。我想,相对于顶点集的每个点形成一个球体,可以在其上构建一个球体(具有一定的准确性)。但是如果我有 2300 万个顶点,我必须计算每个点之间的 12 个或更多顶点相关。 23 000 000 * 4 (float) = 1 Gb 数据,可能不是很好的解决方案。

下一步我应该怎么做?我无法完全理解此任务中适用的着色器或存在其他方式。

【问题讨论】:

我认为纹理点精灵可能会起作用,因为您的球体从每个角度来看都是相同的。 你的意思是我应该在每个点(x,y,z)输出球体精灵? 带纹理的点精灵基本上是具有纹理的点。所以它(可能)是你已经做过的,但是你在它上面加上了纹理。这将为您的原子提供更球形的外观。看这里informit.com/articles/article.aspx?p=770639&seqNum=7。或者只是谷歌Textured point sprites 明白我的意思。 看这里,您可能会发现它对理解该技术很有用:fullonsoftware.co.uk/snippets/content/OpenGL_-Particle_System_Tutorial-Blending-_PointSprites.pdf跨度> 【参考方案1】:

关于您的绘图过程

我的任务是渲染它。在第一次迭代中,我使用块“glBegin/glEnd”并将每个原子绘制为点某种颜色。这个解决方案奏效了。但我得到了 0.002 fps。

想一想:对于 2300 万条记录中的每一条,您至少直接调用了一个函数 (glVertex),并且可能由此隐式调用了几个函数。更糟糕的是,glVertex 可能会导致上下文切换。这意味着,您的 CPU 对于它必须处理的每个顶点都会遇到几个减速带。如今,一流的 CPU 的时钟频率约为 3 GHz,流水线长度约为 10 条指令。当您进行上下文切换时,流水线会停止,在最坏的情况下,它需要一个流水线长度来实际处理一条指令。假设您必须执行至少 1000 条指令来处理单个 glVertex 调用(这实际上是一个相当乐观的估计)。仅此一项就意味着,您每秒最多只能处理 300 万个顶点。因此,在 2300 万个顶点上,这已经小于 1 FPS。

但是你也有上下文切换,这增加了进一步的惩罚。并且可能有很多分支会导致进一步的管道刷新。

这只是 glVertex 调用。你那里也有颜色。

你想知道立即模式很慢吗?

当然很慢。 15 年来一直不鼓励使用立即模式。顶点数组从 OpenGL-1.1 开始可用。

此解决方案有效。我得到了 60 fps,

是的,因为现在所有数据都驻留在 GPU 自己的内存中。 GPU 是大规模并行和优化的,可以处理此类数据并执行它们所做的操作。

但我不习惯绑定缓冲区

好吧,OpenGL 不是一个高级场景图库。这是一个中低级绘图 API。您可以像使用精密铅笔一样在数字画布上绘画。

然后我读到了 VAO

嗯,VAO 旨在合并属于一起的缓冲区对象,因此使用它们是有意义的。

现在我想画球体,而不是点。

你有两个选择:

使用点精灵纹理。这意味着您的点在绘制时将获得区域,并且该区域将应用​​纹理。我认为这是最适合你的方法。给定正确的着色器,您甚至可以为您的点精灵提供正确的深度值,这样您的“球体”实际上会像深度​​缓冲区中的球体一样相交。

另一个选项是使用单个球体几何体的实例化,使用您的原子记录作为实例化过程的控制数据。然后,这将处理真实的球体几何。但是,我担心目前实现实例化绘图过程对于您的技能水平来说可能有点太高级了。

关于抽取2300万点

说真的,你有什么样的显示器,你可以画出 2300 万个可区分的点?您的典型计算机屏幕大约有 2000×1500 点。你现在可以买到的最高分辨率显示器大约有 4k×2.5k 像素,即 1000 万个单独的像素。假设您的原子均匀分布在一个平面上:在 2300 万个原子上绘制每个像素将被透支数倍。你根本无法以这种方式显示 2300 万个单独的原子。另一种看待这一点的方式是,显示器的像素网格意味着空间采样,您无法重现小于平均采样距离两倍的任何东西(采样定理)。

因此,仅绘制数据的子集(即实际可见的子集)绝对是有意义的。此外,如果您被放大得很远(即您可以看到完整的数据集),那么在附近合并原子是有意义的。

将数据分类为空间细分结构绝对有意义。在您的情况下,我认为八叉树将是一个不错的选择。

【讨论】:

以上是关于我需要建议如何改进图形的主要内容,如果未能解决你的问题,请参考以下文章

改进 Python NetworkX 图形布局

下面发布的图形代码的 DFS 遍历是不是有任何改进? [关闭]

如何在 MIMChart 库中为图形使用固定的颜色集?建议是可观的

Unity 关于图形渲染优化的建议摘录

如何使用一些图形在 xcode 中显示车辆的 RPM

Unity 关于图形渲染优化的建议摘录