二维粒子系统 - 性能

时间:2011-09-22 23:06:00

标签: c++ performance particle-system

我已根据"Bulding an Advanced Particle System" (John van der Burg, Game Developer Magazine, March 2000)中列出的想法和概念实施了二维粒子系统。

现在我想知道我应该从这个系统中获得什么样的表现。我目前正在我的简单(未完成)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,但是没有真正看到那里的性能差异?

2 个答案:

答案 0 :(得分:4)

我不能说你对这个解决方案有多大的期望,但有一些方法可以改进它。

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

对于OpenGL 2.1

Point Sprites:

您可能想要使用点精灵。我实现了一个使用它们的粒子系统,并提出了一个很好的性能(至少我的知识)。使用点精灵,您每帧执行的OpenGL调用较少,并且您向图形卡发送的数据较少(甚至将数据存储在图形卡中,不确定)。一个简短的谷歌搜索甚至应该给你一些实现,以便查看。

顶点阵列:

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

对于OpenGL 3.3及以上版本

<强>实例化

如果您正在使用OpenGL 3.3或更高版本进行编程,您甚至可以考虑使用实例来绘制粒子,这样可以进一步提高速度。再次,一个简短的谷歌搜索将让你看一些关于它的代码。

一般情况下:

使用SSE:

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

数据布局:

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

答案 1 :(得分:1)

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

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