无法实现在Android Opengl ES 2.0中以60fps渲染简单四边形

6
我正在制作一个类似于乒乓球的简单游戏,以熟悉OpenGL和Android技术,并且在性能方面似乎遇到了瓶颈。
我将游戏逻辑放在一个单独的线程中,通过阻塞队列向GL线程发送绘图命令。问题是我卡在了大约40fps,而我尝试过的所有方法似乎都无法提高帧率。
为了保持简单,我使用了以下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 Output 在我看来,似乎是glClear导致GLThread休眠23ms... 但我怀疑这并不是真正的原因。
我完全不知道如何使这个更加有效率,没有任何花哨的东西。为了获得更好的呈现性能,我已经转换到了我描述的多线程方法,关闭了alpha混合和深度测试,改用批处理绘图方法(对于这个简单的例子不适用),并将所有东西都切换到着色器中的lowp。
非常感谢任何帮助使其达到60fps的方法!
Bruce 编辑:这个问题实际上非常简单,只是我过于考虑了。事实证明,过去一周我一直开着节电模式... 它似乎将渲染锁定在40fps。

这听起来只是您设备的限制,一些制造商会限制设备帧率以节省电力(我的Atrix被限制在30fps)。我认为40fps应该足够快了,不用担心。 - Tim
抱歉,不确定最好的地方在哪里...我的设备是Galaxy S3,所以我希望它可以做得比40fps更好。 - BruceJones
当四边形以所需速度移动时,您可以看到差异。 - BruceJones
它运行在安卓4.1.1版本上,使用的是三星原厂固件。 - BruceJones
2
我们来谈谈过度思考问题。事实证明,我在过去的一周里一直开启了省电模式...它似乎将渲染锁定在40fps。 - BruceJones
显示剩余3条评论
2个回答

4

当使用Galaxy S3并开启省电模式时,会出现此行为。

似乎省电模式将帧率锁定在40fps。关闭省电模式可以轻松实现所需的60fps。


0

不确定您是否可以控制EGL设置到设备表面,但如果可以,有一种方法可以将更新设置为“非同步”模式。

egl.eglSwapInterval( dpy, 0 )

这并非所有设备都可用,但允许对渲染进行一些控制。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接