【问题标题】:Improve Particle system OpenGL改进粒子系统OpenGL
【发布时间】:2011-07-25 09:40:45
【问题描述】:

我正在寻找一种方法来提高我的粒子系统性能,因为它在 FPS 方面的成本非常高。 这是因为我打电话:

glDrawElements(GL_TRIANGLE_STRIP, mNumberOfIndices,
          GL_UNSIGNED_SHORT, 0);

我为我的应用程序中的每个粒子(可能在 1000 到 5000 个粒子之间)调用此方法。请注意,当增加到超过 1000 个粒子时,我的应用程序开始在 FPS 中下降。我用的是VBO:s,但是调用这个方法的时候性能太贵了。

有什么想法可以让粒子系统更高效吗?

编辑:这是我的粒子系统绘制事物的方式:

glBindTexture(GL_TEXTURE_2D, textureObject);
glBindBuffer(GL_ARRAY_BUFFER, vboVertexBuffer[0]);
glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vboTextureBuffer[0]);
glTexCoordPointer(2, GL_FLOAT, 0, 0); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndexBuffer[0]);

Vector3f partPos;

for (int i = 0; i < m_numParticles; i++) {
    partPos = m_particleList[i].m_pos;          
    glTranslatef(partPos.x, partPos.y, partPos.z);
    glDrawElements(GL_TRIANGLE_STRIP, mNumberOfIndices, 
        GL_UNSIGNED_SHORT, 0);
    gl.glTranslatef(-partPos.x, -partPos.y, -partPos.z);
}

【问题讨论】:

  • 坐标等使用什么数据类型?如果您使用的不是 GL_FLOAT,那么您会看到(巨大的)性能下降。
  • @Rookie:我有浮点值。
  • 我知道这篇文章有点老了,但对于任何想知道的人来说,这是我发现的一个很棒的教程。 (我不是本教程的作者)。 opengl-tutorial.org/intermediate-tutorials/billboards-particles/…

标签: opengl opengl-es


【解决方案1】:

按照您的描述方式,听起来每个粒子都有自己的 VBO。这不是应该做的。将所有粒子放入单个 VBO 并使用单个 glDrawElementsglDrawArrays 调用一次将它们全部绘制出来。或者更好,如果有的话:使用实例化。

【讨论】:

  • 感谢您的回答,但我为每个粒子重复使用相同的 VBO。然后我只是使用glDrawElements() 遍历每个粒子。问题是对glDrawElements()的调用太多了,我对如何解决这个问题还不够清楚。
  • 答案很明确:通过一次绘制调用绘制整个粒子系统。
  • @kvark:这对我来说并不是什么大问题。问题是因为每个粒子都需要自己的位置,所以最好的方法是什么?在绘制期间修改 VBO?
  • 一次将它们全部放入一个 VBO。使其成为未连接面的单个(大)网格。粒子 1 和索引 0、1、2、3,粒子 2 在索引 4、5、6、7 等。
  • 朱利安·阿桑奇。重点是:粒子位置数据仍然从您的系统内存进入 VRAM 进行绘图。在您当前的实现中,它以内部制服的形式传播,通过 glTranslate 设置。如果你让粒子位置成为 VBO 的一部分,每帧改变它,它仍然是传输总线的相同数量的数据。但是绘图操作会更快。
【解决方案2】:

稍微扩展一下 datenwolf 所说的内容,只需将所有粒子索引打包到一个索引缓冲区中,然后通过一个 glDrawElements 调用绘制所有粒子。这意味着您不能再使用三角形条,只能使用三角形组,但这应该不是太大的问题。

否则,如果您的硬件支持实例化渲染(或更好的实例化数组),您只需将单个粒子渲染 n 次,并使用从每个粒子的相应数组获取的位置和 texCoord 数据来实现。然后,您仍然需要在顶点着色器中计算四个角的位置和 texCoord 数据(假设您为每个粒子绘制一个四边形),因为对于实例化数组,每个实例(粒子)只能获得一个属性。

您也可以使用几何着色器来创建粒子的四边形并仅渲染单个点集,但我认为这可能比实例化要慢,因为 SM4/GL3 硬件很可能也支持实例化。

【讨论】:

  • 感谢您的回答。好的,然后我需要将所有粒子放入单个 VBO 中,该 VBO 拥有正确的 x、y 和 z 坐标(我可以跳过翻译它们),因为它们需要在不同的位置渲染。但是,由于位置总是在变化,因此在绘制期间将新的 VBO 上传到 OpenGL 是否有效?
  • @Julian 只需创建位置缓冲区GL_DYNAMIC_DRAW(甚至GL_STREM_DRAW?)并每帧更新它(使用glMapBufferglBuffer(Sub)Data),它至少应该比你的更快当前的解决方案。
  • 谢谢,当我在我的工作计算机上时会试试这个。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-09
  • 2013-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多