2

我已经基于“构建高级粒子系统”(John van der Burg,Game Developer Magazine,2000 年 3 月)中概述的想法和概念实现了 2D 粒子系统。

现在我想知道我应该从这个系统中获得什么性能。我目前正在我的简单(未完成)SDL/OpenGL 平台游戏的上下文中对其进行测试,其中所有粒子每帧都会更新。绘制如下

// Bind Texture
glBindTexture(GL_TEXTURE_2D, *texture);
// for all particles
    glBegin(GL_QUADS);
    glTexCoord2d(0,0);  glVertex2f(x,y);
    glTexCoord2d(1,0);  glVertex2f(x+w,y);
    glTexCoord2d(1,1);  glVertex2f(x+w,y+h);
    glTexCoord2d(0,1);  glVertex2f(x,y+h);
    glEnd();   

其中一个纹理用于​​所有粒子。

它可以平稳运行多达约 3000 个粒子。老实说,我期待更多,特别是因为这意味着要在屏幕上与多个系统一起使用。我应该希望平滑显示多少粒子?

PS:我对 C++ 和 OpenGL 也比较陌生,所以很可能是我在某个地方搞砸了!?

编辑使用POINT_SPRITE

glEnable(GL_POINT_SPRITE);
glBindTexture(GL_TEXTURE_2D, *texture);
glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE); 

// for all particles
    glBegin(GL_POINTS);
    glPointSize(size);
    glVertex2f(x,y);
    glEnd();

glDisable( GL_POINT_SPRITE );

根本看不到使用GL_QUADS的任何性能差异!?

编辑使用VERTEX_ARRAY

// Setup
glEnable (GL_POINT_SPRITE);                                         
glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);              
glPointSize(20);                                    

// A big array to hold all the points
const int NumPoints = 2000;
Vector2 ArrayOfPoints[NumPoints];
for (int i = 0; i < NumPoints; i++) {
    ArrayOfPoints[i].x = 350 + rand()%201;
    ArrayOfPoints[i].y = 350 + rand()%201;
}

// Rendering
glEnableClientState(GL_VERTEX_ARRAY);     // Enable vertex arrays
glVertexPointer(2, GL_FLOAT, 0, ArrayOfPoints);     // Specify data
glDrawArrays(GL_POINTS, 0, NumPoints);  // ddraw with points, starting from the 0'th point in my array and draw exactly NumPoints

使用 VA 对上述性能产生了影响。然后我尝试了 VBO,但真的没有看到那里的性能差异吗?

4

2 回答 2

4

我不能说您对该解决方案有多少期望,但有一些方法可以改进它。

首先,通过使用 glBegin() 和 glEnd() 您正在使用立即模式,据我所知,这是最慢的做事方式。此外,它甚至不再出现在当前的 OpenGL 标准中。

对于 OpenGL 2.1

点精灵:

您可能想要使用点精灵。我使用它们实现了一个粒子系统,并提出了一个很好的性能(至少就我当时的知识而言)。使用点精灵,您每帧执行的 OpenGL 调用更少,并且您向显卡发送的数据更少(或者甚至将数据存储在显卡上,对此不确定)。一个简短的谷歌搜索甚至应该给你一些实现来看看。

顶点数组:

如果使用点精灵没有帮助,您应该考虑将顶点数组与点精灵结合使用(以节省一点内存)。基本上,您必须将粒子的顶点数据存储在一个数组中。然后,您可以通过调用 glEnableClientState() 以 GL_VERTEX_ARRAY 作为参数来启用顶点数组支持。之后,调用 glVertexPointer()(参数在 OpenGL 文档中解释)并调用 glDrawArrays() 来绘制粒子。这会将您的 OpenGL 调用减少到只有少数,而不是每帧 3000 次调用。

适用于 OpenGL 3.3 及更高版本

实例化:

如果您正在针对 OpenGL 3.3 或更高版本进行编程,您甚至可以考虑使用实例化来绘制粒子,这应该会进一步加快速度。再次,简短的谷歌搜索将让您查看一些关于此的代码。

一般来说:

使用 SSE:

此外,更新顶点位置时可能会浪费一些时间。所以,如果你想加快速度,你可以看看使用 SSE 来更新它们。如果做得正确,您将获得很多性能(至少在大量粒子上)

数据布局:

最后,我最近找到了一个关于数组结构 (SoA) 和结构数组 (AoS)的链接( divergentcoder.com/programming/aos-soa-explorations-part-1 ,感谢 Ben)。以粒子系统为例,对它们如何影响性能进行了比较。

于 2011-09-22T23:21:58.200 回答
1

考虑使用顶点数组而不是立即模式(glBegin/End): http: //www.songho.ca/opengl/gl_vertexarray.html

如果您愿意进入着色器,您还可以搜索“顶点着色器”并考虑在您的项目中使用该方法。

于 2011-09-22T23:14:25.237 回答