我已根据"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,但是没有真正看到那里的性能差异?
答案 0 :(得分:4)
我不能说你对这个解决方案有多大的期望,但有一些方法可以改进它。
首先,通过使用glBegin()和glEnd(),你使用立即模式,据我所知,这是最慢的做事方式。此外,它不再存在于当前的OpenGL标准中。
Point Sprites:
您可能想要使用点精灵。我实现了一个使用它们的粒子系统,并提出了一个很好的性能(至少我的知识)。使用点精灵,您每帧执行的OpenGL调用较少,并且您向图形卡发送的数据较少(甚至将数据存储在图形卡中,不确定)。一个简短的谷歌搜索甚至应该给你一些实现,以便查看。
顶点阵列:
如果使用点精灵无效,则应考虑将顶点数组与点精灵结合使用(以节省一点内存)。基本上,您必须将粒子的顶点数据存储在数组中。然后通过使用GL_VERTEX_ARRAY作为参数调用glEnableClientState()来启用顶点数组支持。之后,调用glVertexPointer()(参数在OpenGL文档中解释)并调用glDrawArrays()来绘制粒子。这会将您的OpenGL调用减少到只有少量而不是每帧3000次调用。
<强>实例化强>
如果您正在使用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
如果您愿意进入着色器,您还可以搜索“顶点着色器”并考虑将该方法用于您的项目。