【发布时间】:2011-09-15 17:36:29
【问题描述】:
我正在使用 OpenGL ES 1.1 为 iPhone 开发游戏。在这个游戏中,我有角色在被射击时会发出的血颗粒,因此屏幕上随时可以有1000多个血颗粒。问题是当我要渲染超过 500 个粒子时,游戏的帧率会大幅下降。
目前,每个粒子都使用 glDrawArrays(..) 进行渲染,我知道这是导致速度变慢的原因。所有粒子共享同一个纹理图集。
那么,减少绘制许多粒子的速度的最佳选择是什么?以下是我找到的选项:
- 将所有血液颗粒组合在一起并使用单个 glDrawArrays(..) 调用来渲染它们 --如果我使用这种方法,是否有办法让每个颗粒都有自己的自己的旋转和阿尔法?或者当使用这种方法时,它们是否都必须具有相同的旋转?如果我无法渲染具有唯一旋转的粒子,则无法使用此选项。
- 在 OpenGL ES 2.0 中使用点精灵。我还没有使用 OpenGL ES 2.0,因为我需要在我设定的截止日期之前在 App Store 上发布我的游戏。要使用 OpenGL ES 需要进行初步研究,遗憾的是我没有时间进行。我将在以后的版本中升级到 OpenGL ES 2.0,但首先我只想使用 1.1。
这是每个粒子自己渲染的。这是我最初的粒子渲染方法,它导致游戏在渲染 500 多个粒子后帧速率显着下降。
// original method: each particle renders itself.
// slow when many particles must be rendered
[[AtlasLibrary sharedAtlasLibrary] ensureContainingTextureAtlasIsBoundInOpenGLES:self.containingAtlasKey];
glPushMatrix();
// translate
glTranslatef(translation.x, translation.y, translation.z);
// rotate
glRotatef(rotation.x, 1, 0, 0);
glRotatef(rotation.y, 0, 1, 0);
glRotatef(rotation.z, 0, 0, 1);
// scale
glScalef(scale.x, scale.y, scale.z);
// alpha
glColor4f(1.0, 1.0, 1.0, alpha);
// load vertices
glVertexPointer(2, GL_FLOAT, 0, texturedQuad.vertices);
glEnableClientState(GL_VERTEX_ARRAY);
// load uv coordinates for texture
glTexCoordPointer(2, GL_FLOAT, 0, texturedQuad.textureCoords);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// render
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glPopMatrix();
然后我使用了方法 1,但是使用这种方法(我知道),粒子不能具有唯一的旋转、缩放或 alpha。
// this is method 1: group all particles and call glDrawArrays(..) once
// declare vertex and uv-coordinate arrays
int numParticles = 2000;
CGFloat *vertices = (CGFloat *) malloc(2 * 6 * numParticles * sizeof(CGFloat));
CGFloat *uvCoordinates = (CGFloat *) malloc (2 * 6 * numParticles * sizeof(CGFloat));
...build vertex arrays based on particle vertices and uv-coordinates.
...this part works fine.
// get ready to render the particles
glPushMatrix();
glLoadIdentity();
// if the particles' texture atlas is not already bound in OpenGL ES, then bind it
[[AtlasLibrary sharedAtlasLibrary] ensureContainingTextureAtlasIsBoundInOpenGLES:((Particle *)[particles objectAtIndex:0]).containingAtlasKey];
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, uvCoordinates);
// render
glDrawArrays(GL_TRIANGLES, 0, vertexIndex);
glPopMatrix();
我会重申我的问题:
如何渲染 1000 多个粒子而不会大幅降低帧速率,并且每个粒子仍然可以具有唯一的旋转、alpha 和缩放?
任何建设性的建议都会非常有帮助,我们将不胜感激!
谢谢!
【问题讨论】:
-
FWIW,你也可以在 ES 1.1 上使用点精灵。该功能不限于 2.0。
标签: objective-c ios opengl-es particle-system