OpenGL在多个地方多次绘制同一个多边形

Posted

技术标签:

【中文标题】OpenGL在多个地方多次绘制同一个多边形【英文标题】:OpenGL drawing the same polygon many times in multiple places 【发布时间】:2011-10-25 19:28:58 【问题描述】:

在我的 opengl 应用程序中,我在屏幕上的不同点绘制了大约 50k 次相同的多边形。在我目前的方法中,我执行以下操作:

将多边形一次绘制到显示列表中 对于多边形的每个实例,推动矩阵,平移到该点,适当缩放和旋转(每个点的缩放将相同,平移和旋转不会)。

但是,对于 50k 多边形,这是 50k 推送和弹出以及正确矩阵平移的计算以移动到正确的点。

我的一位同事还建议将整个场景绘制到缓冲区中,然后仅通过一次平移绘制整个缓冲区。这里的权衡是我们需要将所有多边形顶点保存在内存中,而不仅仅是显示列表,但我们不需要为每个顶点执行 push/translate/scale/rotate/pop。

第一种方法是我们目前已经实施的方法,我希望看看我们是否可以改进它,因为第二种方法需要进行重大更改(但是,如果第二种方法更快,我们可以总是重写)。

所有这些推送/弹出都是必要的吗?有没有更快的方法来做到这一点?我应该担心这么多推送/弹出会降低性能吗?

【问题讨论】:

【参考方案1】:

这取决于你的最终目标。最新的 OpenGL 规范启用了“几何实例化”的功能。您可以将所有矩阵加载到缓冲区中,然后使用单个“绘制实例”调用(OpenGL 3+)绘制所有 50k。如果您正在寻找临时修复,至少将多边形加载到顶点缓冲区对象中。显示列表非常陈旧且已被弃用。

这 50k 多边形会独立移动吗?您将不得不忍受 一些 形式的“推送/弹出”(即使现代场景图不一定使用显式矩阵堆栈)。如果 50k 多边形是静态的,您可以将整个场景预编译成 一个 VBO。这会让它的渲染速度非常快。

【讨论】:

多边形不会独立移动,所以希望这可以简化事情。但是,对象的属性可能会独立改变,例如颜色。将整个场景编译成单个 vbo 是否仍然有意义? 可能。这仍然取决于变化的性质。我会说是的。您可以将顶点 VBO 标记为 GL_STATIC_DRAW(向 GPU 表明您不会对其进行太多更改)。将你的颜色 VBO 标记为 GL_DYNAMIC_DRAW(告诉 GPU 你会改变很多)。然后,您必须知道在编辑该 VBO 时如何计算偏移量,但这是可以做到的。 另外,颜色变化的本质是什么?如果更改有数学模式,也可以在着色器中处理! 颜色变化可能是,例如,如果用户点击一个对象,它会变成“选定”颜色。或者用户实际上可以选择“将这些项目涂成蓝色”。可能还有其他变化,不仅仅是颜色,例如形状或大小。【参考方案2】:

如果您可以使用最新版本的 OpenGL(>=3.1,IIRC),您可能需要查看glDrawArraysInstanced 和/或glDrawElementsInstanced。对于旧版本,您可能可以使用glDrawArraysInstancedEXT/`glDrawElementsInstancedEXT,但它们是扩展,因此您必须这样访问它们。

无论哪种方式,总体思路都相当简单:您有一个网格和多个指定在何处绘制网格的变换,然后您逐步使用不同的变换绘制网格。但是请注意,这一定不会带来重大改进——它取决于实现(甚至比大多数事情所做的更多)。

【讨论】:

不幸的是,我只能依靠 openGL 2.1。用户可能有更高的要求,但这是我们的最低要求。但听起来你同意它应该被绘制为单个场景并将所有多边形存储在场景中各自的位置,然后一次绘制整个场景?正确吗(类似于我同事提出的第二个想法)? 杰瑞,请看我对@TheBuzzSaw 的评论。单个对象的颜色会独立于其他对象发生变化是否重要?每次这些属性发生变化时,我是否需要重新绘制整个网格?

以上是关于OpenGL在多个地方多次绘制同一个多边形的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL第二节:绘制多个颜色四边形

OpenGL - 在鼠标点击时绘制多边形,多边形总是在右边

用鼠标在 OpenGL GLUT 中绘制多边形

如何在OpenGL中将像素作为纹理绘制到多边形?

OpenGL:绘制多边形时,如果第一个顶点在屏幕空间之外怎么办(三角扇)

在 OpenGL 3+ 中有效地绘制多边形(每个多边形一种颜色)