6

opengl es 2.0 を使用して Android 2D ゲームをプログラミングしています。スプライトをバック バッファに描画した後、ライトを FBO に描画し、それを再びバック バッファにブレンドしようとします。FBO をフレームバッファに描画すると、色がなくても透過的であり、Samsung Galaxy w でフレームレートが 60 から 30 に低下します (GPU としてアドレノ 205 を使用)。シーンに単一のスプライトを描画し、透明な FBO テクスチャを画面にブレンドしても、フレームレートが低下します。その電話で照明効果のある他のゲームを試してみましたが、それらは問題なく動作します。その電話ではほとんどすべてのゲームが問題なく動作します。フレームバッファも使用していると思います。Galaxy SII (mali 400 gpu) では正常に動作します。私は opengl にまったく慣れていないので、どこかで間違いを犯していると思います。コードを共有します。

// Create a framebuffer and renderbuffer
GLES20.glGenFramebuffers(1, fb, offset);
GLES20.glGenRenderbuffers(1, depthRb, offset);

// Create a texture to hold the frame buffer
GLES20.glGenTextures(1, renderTex, offset);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTex[offset]);

GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA,
                    screenWidth, screenHeight, 0,
                    GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE,
                    null);


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);

//bind renderbuffer
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRb[offset]);

GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16,
                             screenWidth, screenHeight);

// bind the framebuffer
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[offset]);

// specify texture as color attachment
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
                              GLES20.GL_TEXTURE_2D, renderTex[offset], 0);

// specify depth_renderbufer as depth attachment
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT,
                                 GLES20.GL_RENDERBUFFER, depthRb[0]);

// Check FBO status.
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);

if ( status == GLES20.GL_FRAMEBUFFER_COMPLETE )
{
    Log.d("GLGame framebuffer creation", "Framebuffer complete");
}


// set default framebuffer
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);

サーフェスの作成時にこれを 1 回行います。正しいかどうかはわかりません。必要なときに切り替えるために、テクスチャとフレームバッファの ID を保持しています。私の描画コード:

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
ShaderProgram program = glgame.getProgram();

//put vertices in the floatbuffer
mTriangleVertices.put(vertices, 0, len);
mTriangleVertices.flip();

GLES20.glVertexAttribPointer(program.POSITION_LOCATION, 2, GLES20.GL_FLOAT, false,
                             TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);

//preparing parameter for texture position
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
GLES20.glEnableVertexAttribArray(program.POSITION_LOCATION);

//preparing parameter for texture coords
GLES20.glVertexAttribPointer(program.TEXTURECOORD_LOCATION, 2, GLES20.GL_FLOAT,
                             false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES,
                             mTriangleVertices);

//set projection matrix
GLES20.glEnableVertexAttribArray(program.TEXTURECOORD_LOCATION);
GLES20.glUniformMatrix4fv(program.MATRIX_LOCATION, 1, false, matrix, 0);

//draw triangle with indices to form a rectangle
GLES20.glDrawElements(GLES20.GL_TRIANGLES, numSprites * 6, GLES20.GL_UNSIGNED_SHORT,
                      indicesbuf);

//clear buffers
mTriangleVertices.clear();
mVertexColors.clear();

すべてが画面に正しくレンダリングされますが、FBO テクスチャを描画するとパフォーマンスが低下します。ご助力ありがとうございます。私はこれに一生懸命取り組みましたが、解決策が見つかりませんでした。

4

1 に答える 1

13

qualcommのドキュメントによると、すべてのglbindframebufferの後にglclearする必要があります。これは、タイルアーキテクチャに関連する問題です。フレームバッファを切り替える場合、データをfastmemから通常のメモリにコピーして現在のフレームバッファを保存し、slowmemからfastmemにコピーして取得する必要があります。新しくバインドされたフレームのコンテンツ。glbindの直後にクリアする場合、slowmemからfastmemにデータがコピーされず、時間を節約できますが、レンダリングパイプラインを頻繁に再設計する必要があるため、slowとslowの間でデータをやり取りする必要がなくなります。メモリが速いので、バインドするたびにglclearを実行してみてください。これは役立つはずです。また、adrenoプロファイラーを使用して、問題のある呼び出しに関する追加情報を取得することもできますが、adreno200で役立つとは思えません。ぼかし用に2つのバッファーを取得しようとしています。 10fpsで終わる、bindframebuffer呼び出しは、クリアされていない場合は最大20ミリ秒かかる可能性があり、クリアされていない場合は2ミリ秒で終了する必要があります。

于 2012-06-15T14:13:41.783 に答える