9

OpenGL ES 2.0 を使用して Android で大量の線をバッチ描画しようとしていますが、これを行う最善の方法を知る必要があります。

現在、描画するすべての頂点の FloatBuffer を構築し、すべての線を一度に描画する LineEngine というクラスを作成しました。問題は明らかに FloatBuffer.put() が非常に遅く、狂ったように CPU 時間を食い尽くしていることです。

これが私のクラスです

public class LineEngine {
    private static final float[] IDENTIY = new float[16];
    private FloatBuffer mLinePoints;
    private FloatBuffer mLineColors;
    private int mCount;

    public LineEngine(int maxLines) {
        Matrix.setIdentityM(IDENTIY, 0);

        ByteBuffer byteBuf = ByteBuffer.allocateDirect(maxLines * 2 * 4 * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        mLinePoints = byteBuf.asFloatBuffer();

        byteBuf = ByteBuffer.allocateDirect(maxLines * 2 * 4 * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        mLineColors = byteBuf.asFloatBuffer();

        reset();
    }

    public void addLine(float[] position, float[] color){
        mLinePoints.put(position, 0, 8); //These lines
        mLineColors.put(color, 0, 4); // are taking
        mLineColors.put(color, 0, 4); // the longest!
        mCount++;
    }

    public void reset(){
        mLinePoints.position(0);
        mLineColors.position(0);
        mCount = 0;
    }

    public void draw(){
        mLinePoints.position(0);
        mLineColors.position(0);
        GraphicsEngine.setMMatrix(IDENTIY);
        GraphicsEngine.setColors(mLineColors);
        GraphicsEngine.setVertices4d(mLinePoints);
        GraphicsEngine.disableTexture();
        GLES20.glDrawArrays(GLES20.GL_LINES, 0, mCount * 2);
        GraphicsEngine.disableColors();
        reset();
    }
}

これらすべての行をまとめてバッチ処理するより良い方法はありますか?

4

3 に答える 3

1

あなたがやろうとしていることは、SpriteBatching と呼ばれます。プログラムを openGL で堅牢にしたい場合は、次のことを確認する必要があります (プログラムが遅くなる原因のリスト)。

-フレームごとに多くの opengl ES 状態に変更します。

-有効//無効(テクスチャなど)を何度も繰り返します。何かを有効にすると、再度行う必要はなく、フレームに自動的に適用されます。

-スプライトシートの代わりに多くのアセットを使用。はい、それはパフォーマンスに大きな影響を与えます。たとえば、10 個の画像がある場合、画像ごとに異なるテクスチャをロードする必要があり、それは遅いです。これを行うためのより良い方法は、スプライト シートを作成することです (Google で無料のスプライト シート作成者を確認できます)。

-あなたの画像は高品質です。はい!解像度とファイル拡張子を確認してください。.png ファイルを優先します。

- api 8 の float バッファーのバグに注意してください (バグを修正するには、代わりに int バッファーを使用する必要があります)。

-Java コンテナーの使用。これは最大の落とし穴です。文字列連結 (コンテナーではありませんが、毎回新しい文字列を返します) を使用したり、新しいクラスのインスタンスを返すリストやその他のコンテナーを使用したりすると、ガベージ コレクションが原因でプログラムが遅くなる可能性があります。入力処理については、プール クラスと呼ばれる手法を検索することをお勧めします。その使用は、新しいオブジェクトを作成する代わりに、オブジェクトをリサイクルすることです。ガベージ コレクターは大きな敵です。彼を喜ばせ、彼を呼び出す可能性のあるプログラミング手法は避けてください。

- その場でロードするのではなく、代わりにローダー クラスを作成し、アプリの開始時に必要なすべてのアセットをロードします。

このリストを実装すると、プログラムが堅牢になる可能性があります。

最後の補足です。スプライトバッチャーとは?spriteBatcher は、単一のテクスチャを使用して複数のオブジェクトをレンダリングするクラスです。頂点、インデックス、色、u - v 座標を自動的に作成し、それらをバッチとしてレンダリングします。このパターンは、CPU パワーだけでなく GPU パワーも節約します。投稿されたコードからは、CPU の速度が低下する原因はわかりませんが、私の経験からすると、以前に言及したリストの 1 つ (または複数) が原因です。リストを確認してフォローし、google で spriteBatching を検索してください。あなたのプログラムが高速に動作することを確信しています。私が助けてくれることを願っています!

編集:プログラムが遅くなる原因を見つけたと思います。バッファを反転しないでください!位置をリセットするだけです。オブジェクトを追加するだけで、バッファの過負荷が発生します。reset メソッドでは、バッファを反転するだけです。mLineColors.flip mLinePaints.flip は仕事をします。フレームごとに新しい Verice を送信する場合は、フレームごとに呼び出すようにしてください。

于 2014-12-12T22:04:02.107 に答える
0

クラスから呼び出される非常に単純なネイティブ関数を使用するだけです。float[]ばかげたバッファ インターフェイスで CPU 時間を殺す必要はありません。

于 2014-05-27T22:06:01.247 に答える
0

比較的大きな float 配列を持つ FloatBuffer.put(float[]) は、かなり高速になるはずです。単一の put(float) 呼び出しには多くのオーバーヘッドがあります。

于 2012-12-04T21:05:31.657 に答える