OpenGLES1.1を使用してiPhone用のゲームを開発しています。このゲームでは、キャラクターが撃たれたときにキャラクターから放出される血液粒子があるため、画面には一度に1000以上の血液粒子が表示される可能性があります。問題は、レンダリングするパーティクルが500を超えると、ゲームのフレームレートが大幅に低下することです。
現在、各パーティクルはglDrawArrays(..)を使用してレンダリングされますが、これが速度低下の原因であることがわかります。すべてのパーティクルは同じテクスチャアトラスを共有します。
では、多くのパーティクルを描画することによる速度低下を減らすための最良のオプションは何ですか?私が見つけたオプションは次のとおりです。
- すべての血液粒子をグループ化し、単一のglDrawArrays(..)呼び出しを使用してレンダリングします。このメソッドを使用する場合、各粒子に独自の回転とアルファを持たせる方法はありますか?または、この方法を使用する場合、それらすべてが同じ回転を持つ必要がありますか?独自の回転でパーティクルをレンダリングできない場合、このオプションを使用できません。
- OpenGLES2.0でポイントスプライトを使用します。 私はまだOpenGLES2.0を使用していませんが、AppStoreでゲームをリリースするために設定した期限に間に合わせる必要があります。OpenGL ESを使用するには、予備調査が必要になりますが、残念ながら実行する時間がありません。後のリリースでOpenGLES2.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を使用しましたが、この方法(私が知っている)を使用して、パーティクルに一意の回転、スケール、またはアルファを設定することはできません。
// 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以上のパーティクルをレンダリングし、各パーティクルが固有の回転、アルファ、およびスケールを持つことができるようにするにはどうすればよいですか?
建設的なアドバイスは本当に役に立ち、大いに感謝されます!
ありがとう!