0

ユーザーが画面に触れることでピックアップしてドラッグできるテクスチャ付きの 90 以上の 2D 形状を描画するプログラムがあります。かなりの途切れがあり、DDMS によると、最も多くの CPU 時間を消費する (~85%) メソッドは draw() メソッドです。実際に動いているのは 1 つの形状だけで、他の 89 の形状は動いていないため、FrameBuffer オブジェクトを使用して 89 の形状をテクスチャにレンダリングし、そのテクスチャを画面全体を占める形状に描画することは可能/高速でしょうか? そうでない場合、物事をスピードアップする他の潜在的な方法はありますか?

private void draw() {
    // Pass in the position information
    mCubePositions.position(0);
    GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false, 0, mCubePositions);
    GLES20.glEnableVertexAttribArray(mPositionHandle);

    // Pass in the color information
    mCubeColors.position(0);
    GLES20.glVertexAttribPointer(mColorHandle, mColorDataSize, GLES20.GL_FLOAT, false, 0, mCubeColors);
    GLES20.glEnableVertexAttribArray(mColorHandle);

    // Pass in the texture coordinate information
    mCubeTextureCoordinates.position(0);
    GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, mCubeTextureCoordinates);
    GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);

    // This multiplies the view matrix by the model matrix, and stores the
    // result in the MVP matrix
    // (which currently contains model * view).
    Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);

    // Pass in the modelview matrix.
    GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0);

    // This multiplies the modelview matrix by the projection matrix, and
    // stores the result in the MVP matrix
    // (which now contains model * view * projection).
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);

    // Pass in the combined matrix.
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);

    // Draw the cube.
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
}

前もって感謝します。

4

1 に答える 1

3

クワッドを意味するときに「キューブ」に言及する質問に混乱したので、この回答は 3D ケースを扱います。とにかく、おそらくより有益です。

ビュー行列と射影行列を組み合わせて ViewProj 行列にします。次に、頂点シェーダーで VertexPos * Model * ViewProj を実行します。

また、本当にバッチする必要があります。すべてのキューブを含む 1 つの大きな配列と、各キューブの変換を含む別の配列が必要です。次に、すべてのキューブに対して 1 回の描画呼び出しを行います。頂点バッファ オブジェクトを使用するように変換することを検討してください。描画呼び出しは、舞台裏の API で大量のロジックやメモリ コピーなどを呼び出すため、CPU を集中的に使用します。ゲームエンジンは、それらを最小限に抑えるために多大な努力を払っています。

1回のドローコールで多くのものを描画する方法

すべての異なるテクスチャを 1 つのテクスチャ (「アトラス」) に入れ、各キューブの UV を調整してテクスチャの適切な部分を検索することで補正します。すべてのモデル マトリックスを連続した配列に配置し、頂点シェーダーでこの配列にインデックスを付けます。

attribute vec3 a_position;
attribute vec2 a_texCoord;
attribute int  a_modelIndex;
attribute int  a_UVlIndex;

uniform   mat4   u_model[90];
uniform   vec2   u_UVOffset[16];   // Support 16 different textures in our atlas.

varying   vec2   v_texCoord;
...

void main()
{
    gl_Position = u_viewProj * u_model[a_modelIndex] * vec4(a_position, 1);
    v_texCoord  = a_texCoord + u_UVOffset[a_UVlIndex];
    ...
}    

すべての頂点データを 1 つの大きな配列にパックすることができるので、最終的には次のようGLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6 * 90);になります。モデル マトリックスが残りの部分 (スケール、回転、移動) を処理します。これを行うには、glDrawArrays の代わりに使用し、 --- 簡単にするために 3 つのリストを想定して --- 立方体を作成する頂点配列内の 36 個の頂点を参照する 36 個のインデックスを指定し、それらの 36 個のインデックスを 90 回繰り返してインデックスを作成します。配列。頂点は、(0, 0, 0) を中心とする単位立方体である必要があります。この同じ「キューブ テンプレート」は、頂点シェーダーのモデル マトリックスによって変更され、それぞれの可視「キューブ インスタンス」が作成されます。各フレームを変更する必要があるのは、モデル マトリックスとテクスチャ UV だけです。glDrawElements

glVertexAttribPointer()を使用すると、好きなものを頂点シェーダーに吐き出すことができます。glVertexAttribPointer をクリエイティブに使用して、モデル マトリックスをユニフォームではなく属性として持つ方が効率的です。

モバイル デバイスは、ピクセル バウンドに非常に敏感になる傾向があります。画面上で立方体が非常に大きい場合は、オーバードローが多くなっている可能性があります。高い CPU % (結局のところ、これはパーセンテージにすぎません) は赤いニシンである可能性があり、GPU でピクセルにバインドされている可能性があります。これを簡単にテストするには、すべてのキューブを非常に小さくして、フレームレートが向上するかどうかを確認します。

参考までに、S5570にはAdreno 200 GPUが搭載されています。

于 2012-10-26T07:34:25.960 に答える