2

OpenGLES1.1を使用してiPhone用のゲームを開発しています。このゲームでは、キャラクターが撃たれたときにキャラクターから放出される血液粒子があるため、画面には一度に1000以上の血液粒子が表示される可能性があります。問題は、レンダリングするパーティクルが500を超えると、ゲームのフレームレートが大幅に低下することです。

現在、各パーティクルはglDrawArrays(..)を使用してレンダリングされますが、これが速度低下の原因であることがわかります。すべてのパーティクルは同じテクスチャアトラスを共有します。

では、多くのパーティクルを描画することによる速度低下を減らすための最良のオプションは何ですか?私が見つけたオプションは次のとおりです。

  1. すべての血液粒子をグループ化し、単一のglDrawArrays(..)呼び出しを使用してレンダリングします。このメソッドを使用する場合、各粒子に独自の回転とアルファを持たせる方法はありますか?または、この方法を使用する場合、それらすべてが同じ回転を持つ必要がありますか?独自の回転でパーティクルをレンダリングできない場合、このオプションを使用できません。
  2. 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以上のパーティクルをレンダリングし、各パーティクルが固有の回転、アルファ、およびスケールを持つことができるようにするにはどうすればよいですか?

建設的なアドバイスは本当に役に立ち、大いに感謝されます!

ありがとう!

4

2 に答える 2

3

約 1 ~ 10 のテクスチャを使用します。それぞれが透明な背景に約 200 個の赤い血の点で構成されており、それぞれを約 3 ~ 10 回描画します。次に、何千ものドットがあります。すべての画像を球状のパターンなどで描画します-レイヤーで爆発します。

ゲーム中は常に現実と 1 対 1 で対応できるとは限りません。古い Xbox や iPad などで実行されるいくつかのゲームをよく見てみましょう - 実行する必要があるショートカットがあり、実行すると見栄えがよくなります。

于 2011-09-15T19:47:44.767 に答える
1

各OpenGLESAPI呼び出しにはかなりのオーバーヘッドがあるため、ここで描画ループを何百回も通過する速度が低下しているのは当然のことです。ここに到達するのはglDrawArrays()だけではなく、個々のglTranslatef()、glRotatef()、glScalef()、およびglColorf()の呼び出しも同様です。glDrawArrays()は、これらのGPUでの遅延レンダリングの動作方法により、ホットスポットのように見える場合がありますが、他の呼び出しも問題になります。

これらのパーティクルの頂点を1つの配列にグループ化する必要があります(更新されたデータをGPUに効率的にストリーミングできるように、VBOが望ましい)。結合された頂点配列で個々の回転、スケールなどの効果を確実に複製できますが、回転、スケーリングなどの際に頂点がどこにあるべきかについて計算を実行する必要があります。これにより、フレームごとにCPUにいくらかの負担がかかりますが、Accelerateフレームワークを使用してこれをベクトル処理することで、少し相殺することができます。

カラーとアルファは、配列内の頂点ごとに提供することもできるため、パーティクルごとにそれを制御できます。

ただし、OpenGL ES 2.0は、カスタムシェーダープログラムを作成できるようにすることで、これに対してさらに優れたソリューションを提供できるという点で、あなたは正しいと思います。すべてのポイントのVBOで静的頂点を送信し、マトリックスを更新するだけで、各パーティクルと各パーティクル頂点のアルファ値を操作できます。私は、球の代役として手続き型の詐欺師を生成するのと同じようなことをします。このプロセスについてはここで説明します。ソースコードをアプリケーションにダウンロードできます

于 2011-09-15T23:19:12.970 に答える