Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 二维粒子系统-性能_C++_Performance_Particle System - Fatal编程技术网

C++ 二维粒子系统-性能

C++ 二维粒子系统-性能,c++,performance,particle-system,C++,Performance,Particle System,我根据中概述的想法和概念实现了一个二维粒子系统 现在我想知道我应该期望这个系统有什么样的性能。我目前正在我的简单(未完成)SDL/OpenGL平台的上下文中测试它,其中所有粒子每帧都会更新。绘图过程如下所示 // Bind Texture glBindTexture(GL_TEXTURE_2D, *texture); // for all particles glBegin(GL_QUADS); glTexCoord2d(0,0); glVertex2f(x,y); g

我根据中概述的想法和概念实现了一个二维粒子系统

现在我想知道我应该期望这个系统有什么样的性能。我目前正在我的简单(未完成)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比较陌生,所以我可能在某个地方搞砸了!?p> 使用

点精灵编辑

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
根本看不到任何性能差异

使用
顶点数组编辑

// 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
//设置
glEnable(GL_POINT_SPRITE);
glTexEnvi(GL_POINT_SPRITE,GL_COORD_REPLACE,GL_TRUE);
gl点大小(20);
//容纳所有点的大阵列
常量int NumPoints=2000;
向量2数组点[NumPoints];
对于(int i=0;i

使用VAs使上述性能有所不同。然后我尝试了VBOs,但没有发现性能上的差异?

考虑使用顶点数组而不是立即模式(glBegin/End):


如果你愿意进入着色器,你也可以搜索“顶点着色器”,并考虑为你的项目使用这种方法。

我不能说你能从这个解决方案中得到多少期望,但是有一些改进的方法。 首先,通过使用glBegin()和glEnd(),您使用的是即时模式,据我所知,这是最慢的做事方式。此外,它甚至不再出现在当前的OpenGL标准中

对于OpenGL 2.1 点精灵:

您可能需要使用点精灵。我用它们实现了一个粒子系统,并获得了很好的性能(至少就我当时所知)。使用点精灵,您每帧执行的OpenGL调用更少,向图形卡发送的数据也更少(甚至将数据存储在图形卡中,对此不确定)。一个简短的谷歌搜索甚至可以让你看到它的一些实现

顶点数组:

如果使用点精灵不起作用,你应该考虑使用顶点数组和点精灵(保存一点内存)。基本上,必须将粒子的顶点数据存储在阵列中。然后,通过调用glEnableClientState()并将GL_vertex_数组作为参数来启用顶点数组支持。然后,调用glVertexPointer()(参数在OpenGL文档中解释)并调用glDrawArrays()来绘制粒子。这将使您的OpenGL调用减少到仅处理一次,而不是每帧3000次调用

适用于OpenGL 3.3及以上版本 实例化:

如果你是针对OpenGL 3.3或以上编程,你甚至可以考虑使用实例来绘制你的粒子,这应该进一步加快速度。同样,一个简短的谷歌搜索会让你看到一些关于这方面的代码

一般来说: 使用SSE:

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

数据布局:


最后,我最近发现了一个关于阵列结构(SoA)和结构阵列(AoS)的链接(,谢谢Ben)。以粒子系统为例,比较了它们对性能的影响。

我使用了
glGetString(GL\u版本)
来确定我当前使用的是版本2.1.2。你能给我指一个初学者教程,解释如何使用点精灵吗?我读过一些关于它的文章,听起来不错,但是我还没有找到合适的代码?关于SoA与Aos,您指的是什么?(有人在回答我之前的另一个问题时发布了它:)哈,是的,这正是我的意思:D好的,我又找到了这个网站:,我上次基本上使用了那个代码。它不需要对您进行太多更改,因为它仍然使用即时模式。因此,在那之后,如果你想,你仍然可以研究如何将其与先进的OpenGL技术(如VBOs etcI)相结合。我已经尝试了一些点精灵代码(见我原始问题中的编辑),但我在屏幕上什么都看不到?使用即时模式渲染是一个巨大的速度杀手,但一开始并不总是可见的。如果你的应用程序特别受GPU限制,那么在你开始受CPU限制之前,它不会被激活;在你的例子中,这可能是3000粒子标记。消除这一点可能很困难,因为您每帧都要重新创建缓冲区(除非您可以使用单个四元粒子并玩变换),但是使用单个绘制调用将为您的应用程序和驱动程序节省大量CPU时间。@Ben glGetError()是否返回任何错误状态?是否正确设置了glPointSize()和glPointParameterf()?