1

Android Java で Canvas と Bitmap の代わりに RenderBuffer と OpenGL を使用しています。ただし、テクスチャへの描画には時間がかかります。こちらの質問を参考に速度改善(glEnableVertexAttribArray、glClearColor、glBindFramebufferの呼び出しを減らす)を試みたのですが効果がありません。これは GPU と Android OS の制限ですか?

※プログラムの抜粋です。

GLES20.glAttachShader(program, vertex);
GLES20.glAttachShader(program, fragment);
GLES20.glLinkProgram(program);
GLES20.glUseProgram(program);

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[i]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, s, s,
0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);

GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbs[i]);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER,
GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, textures[i], 0);

GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, renders[i]);
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, s, s);
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER,
GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, renders[i]);


GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbs[i]);
GLES20.glClearColor(fr, fg, fb, fa);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

GLES20.glGetIntegerv(GLES20.GL_FRAMEBUFFER_BINDING, old, 0);

GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbs[pos]);
GLES20.glViewport(0, 0, ww, hh);

:
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
:

GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, old[0]);
GLES20.glViewport(0, 0, scw, sch);
4

1 に答える 1

2

私が理解しているように、何かを描画する必要があるたびに貼り付けたすべてのコードを使用すると、プログラムの実行が遅くなっても不思議ではありません。

OpenGL (ES であるかどうかに関係なく) は「ステート マシン」モデルに基づいています。OpenGL コンテキストは、(さまざまな glXXX コマンドを使用して) それに加えた変更を保持し、OpenGL が将来のコマンドに反応する方法を変更します (特に、描画に使用するもの)。

これは、コマンドを発行すると、次のことを意味します。

GLES20.glClearColor(fr, fg, fb, fa);

あなたが実際にやっていることは、

GL_COLOR_CLEAR_VALUE

ステートマシン内の変数を[fr、fg、fb、fa]に。その瞬間から、GL_COLOR_CLEAR_VALUE は既に [fr, fg, fb, fa] に設定されており、同じ引数で glClearColor をさらに呼び出すたびに、マシン内で何も変更されません。

OpenGL ES 2.0 glClearColor リファレンス ページ

なぜ私はこれに入るのですか?OpenGL の状態の変更はパフォーマンスが重要であるため(いくつかは他のものよりも重要です): コンテキストの状態を変更すると、多くの場合、OpenGL が GPU と「対話」し、キャッシュを破棄する必要があるため、単純な変数の割り当てを超えるパフォーマンス ヒットがあります。などなど。セットアップ段階で行う場合は必要悪ですが、頻繁に変更すると、フレームごとに行うとパフォーマンスが大幅に低下する可能性があります。

したがって、最初にすべきことは、初期化メソッドと描画フレーム メソッドを作成して、プログラム内の1 秒あたりの glXXX コマンドの数を最小限に抑えることです。

標準的なアプローチは、GLSurfaceView.Renderer クラスを使用することです。

Android GLSurfaceView.Renderer クラス リファレンス

すべての初期化コマンドを

public abstract void onSurfaceCreated (GL10 gl, EGLConfig config)

public abstract void onSurfaceChanged (GL10 gl, int width, int height)

そしてメソッドに入れます:

public abstract void onDrawFrame (GL10 gl)

最小限の OpenGL コマンド (実際に描画するのに必要なものだけ)

理論はさておき、具体的な話に入ると、ここに検討することをお勧めする最適化のリストがあります。

  • 単一のプログラムを使用している場合は、全体を残してください。
    GLES20.glAttachShader(プログラム、頂点);
    GLES20.glAttachShader(プログラム、フラグメント);
    GLES20.glLinkProgram(プログラム);
    GLES20.glUseProgram(プログラム);

セットアップ セクションでブロックします (そうしない場合でも、glUseProgram を使用してプログラムを切り替えるだけです。何度も何度もリンクする必要はありません!)。glLinkProgram のパフォーマンスが大幅に向上する可能性があります。

  • テクスチャの初期化はセットアップで行われます (「状態変更」に加えて、実際には同じデータを CPU メモリから GPU メモリに何度も何度も移動しています)。

  • フレームバッファの初期化 (すべてのレンダバッファの作成とバインドを含む) もセットアップに含まれます。さらに、なぜ複数のフレームバッファが必要なのですか? :)

  • glViewport は onSurfaceChanged メソッドに入ります

  • 異なるオブジェクトを描画するために異なるフレームバッファを使用しているように思えます: 何を達成しようとしているのかはわかりませんが、戦略を変更することをお勧めします: 画面全体と同じバッファに描画します.それ以外のことを行う十分な理由があります。

最後になりましたが、このトピックに関する優れた本を次に示します。

OpenGL ES 2.0 プログラミング ガイド

これは、OpenGL ES 2.0 の優れた入門書であると同時に、OpenGL 全般の優れた入門書でもあります (私は彼らの売上を削減していません ;-) )

それが役に立てば幸い

于 2013-04-04T09:46:15.100 に答える