6

私は、opengl と android を理解するために単純な pong タイプのゲームに取り組んでおり、パフォーマンスの点でレンガの壁にぶつかったようです。

ゲーム ロジックは別のスレッドにあり、ドロー コマンドはブロッキング キューを介して gl スレッドに送信されます。問題は、私が約 40 fps で立ち往生していることです。私が試したことは何もフレームレートを改善していないようです.

簡単にするために、次のようにopenglをセットアップしました。

GLES20.glDisable(GLES20.GL_CULL_FACE);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glDisable(GLES20.GL_BLEND);

opengl プログラムと描画のセットアップは、次のクラスによって処理されます。

class GLRectangle {
private final String vertexShaderCode =
        "precision lowp float;" +
        // This matrix member variable provides a hook to manipulate
        // the coordinates of the objects that use this vertex shader
        "uniform lowp mat4 uMVPMatrix;" +

        "attribute lowp vec4 vPosition;" +
        "void main() {" +
        // the matrix must be included as a modifier of gl_Position
        "  gl_Position = vPosition * uMVPMatrix;" +
        "}";

private final String fragmentShaderCode =
        "precision lowp float;" +
        "uniform lowp vec4 vColor;" +
        "void main() {" +
        "  gl_FragColor = vColor;" +
        "}";

protected static int mProgram = 0;

private static ShortBuffer drawListBuffer;
private static short drawOrder[] = { 0, 1, 2, 0, 2, 3};//, 4, 5, 6, 4, 6, 7 }; // order to draw vertices

// number of coordinates per vertex in this array
private static final int COORDS_PER_VERTEX = 3;
private static final int vertexStride = COORDS_PER_VERTEX * 4; // bytes per vertex



GLRectangle(){

    int vertexShader = GameRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
    int fragmentShader = GameRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

    mProgram = GLES20.glCreateProgram();             // create empty OpenGL ES Program
    GLES20.glAttachShader(mProgram, vertexShader);   // add the vertex shader to program
    GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
    GLES20.glLinkProgram(mProgram);                  // creates OpenGL ES program executables

    // initialize byte buffer for the index list
    ByteBuffer dlb = ByteBuffer.allocateDirect(
    // (# of coordinate values * 2 bytes per short)
            drawOrder.length * 2);
    dlb.order(ByteOrder.nativeOrder());
    drawListBuffer = dlb.asShortBuffer();
    drawListBuffer.put(drawOrder);
    drawListBuffer.position(0);  
}

protected static void Draw(Drawable dObj, float mvpMatrix[])
{   
    FloatBuffer vertexBuffer = dObj.vertexBuffer;

    GLES20.glUseProgram(mProgram);
    //GameRenderer.checkGlError("glUseProgram");

    // get handle to fragment shader's vColor member
    int mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
    //GameRenderer.checkGlError("glGetUniformLocation");

    // get handle to shape's transformation matrix
    int mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
    //GameRenderer.checkGlError("glGetUniformLocation");

    // get handle to vertex shader's vPosition member
    int mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
    //GameRenderer.checkGlError("glGetAttribLocation");

    // Apply the projection and view transformation
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
    //GameRenderer.checkGlError("glUniformMatrix4fv");

    // Set color for drawing the quad
    GLES20.glUniform4fv(mColorHandle, 1, dObj.color, 0);
    //GameRenderer.checkGlError("glUniform4fv");

    // Enable a handle to the square vertices
    GLES20.glEnableVertexAttribArray(mPositionHandle);
    //GameRenderer.checkGlError("glEnableVertexAttribArray");

     // Prepare the square coordinate data
    GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                                    GLES20.GL_FLOAT, false,
                                    vertexStride, vertexBuffer);
    //GameRenderer.checkGlError("glVertexAttribPointer");

    // Draw the square
    GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
                              GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
    //GameRenderer.checkGlError("glDrawElements");

    // Disable vertex array
    GLES20.glDisableVertexAttribArray(mPositionHandle);
    //GameRenderer.checkGlError("glDisableVertexAttribArray");
}
}

私は多くのプロファイリングとグーグルを行いましたが、この作業を高速化するものを見つけることができません... DDMS 出力のスクリーンショットを含めました。

DDMS出力

私には、glClear が GLThread を 23 ミリ秒スリープさせているように見えますが、実際にはそうではないかと思います。

これをより効率的にする方法がまったくわかりません。空想的なことは何もありません。より良いレンダリング パフォーマンスを求めて、説明したマルチスレッド アプローチに切り替え、アルファ ブレンディングと深度テストをオフにし、バッチ描画アプローチに変更し (この単純な例には適用されません)、シェーダーですべてを lowp に切り替えました。 .

これを 60fps にするための支援をいただければ幸いです。

ブルース

問題を考えすぎることについてよく話してください。この 1 週間、省電力モードをオンにしていたことがわかりました...レンダリングが 40fps にロックされているようです。

4

2 に答える 2

5

この動作は、Galaxy S3 を使用して省電力モードがオンになっている場合に発生します。

省電力モードではフレームレートが 40fps に固定されているようです。スイッチをオフにすると、目的の 60fps が簡単に達成されました。

于 2012-11-12T11:44:39.017 に答える