调用更新时,Android OpenGL上一帧重新出现

时间:2014-08-27 23:00:38

标签: android opengl-es-2.0

我刚刚开始在我的小游戏中使用OpenGL ES 2 for android,并且在每个帧上重新绘制屏幕时遇到了问题。

我在渲染器的onDrawFrame上设置了一个循环,只是一个简单的[updateGameLogic() - > drawGame()]或Thread.sleep()循环基于从上一次drawGame调用中经过的时间。

目前,updateGameLogic()方法只是将摄像机转换为+ ve X方向(游戏为2d)。

在drawGame()调用中,我首先使用GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT)清除我的屏幕。然后我有3个glBindTexture和glDrawElements调用来绘制具有不同纹理图集的3类对象。

出现问题,在屏幕上绘制的每个帧之间,出现前一帧的闪烁,这是不希望的,并使游戏看起来头晕。确切地说,假设游戏即将从第2帧绘制第3帧,在第2帧消失和第3帧出现之前,存在显示第1帧的分割时刻。

我认为这可能是由于GLSurfaceView被系统缓冲的方式所以我在绘制之前尝试调用多个glClear但是一切都保持不变。如果有人可以为问题提供一些解释/解决方案,以及我做错了什么,谢天谢地。 (基本上第2到第4段都是我的代码所以我没有发布它,除非要求)

1 个答案:

答案 0 :(得分:0)

从评论中的澄清,听起来你的代码中有这样的东西:

public void onDrawFrame(GL10 gl) {
    long currentTime = SystemClock.elapsedRealtime();
    long deltaTime = currentTime - mLastFrameTime;
    if (deltaTime < 33) {
        Thread.sleep(33 - deltaTime);
        return;
    }

    mLastFrameTime = currentTime;

    updateGameLogic(deltaTime);
    drawGame();
}

这确实会引起问题。调用onDrawFrame()时,必须呈现框架。你不能在没有画任何东西的情况下返回。调用者将假设您在任何情况下都渲染了一个帧,它最终将显示在屏幕上。如果你决定不渲染任何东西,那么无论发生在你应该画的表面上的是什么。我不知道这会是什么,但它很可能是早期2-3帧的旧框架。

如果你想人为地限制帧速率,例如为了节省电力,遗憾的是在Android中没有很好的方法可以做到这一点。在onDrawFrame()中使用睡眠有点脏(并且本质上不可靠,恕我直言),但在这种情况下可能是必要的。关键是要么在睡觉之前或之后,你仍然需要渲染一个框架。作为第一次尝试,我会尝试将上述内容调整为以下内容:

public void onDrawFrame(GL10 gl) {
    long currentTime = SystemClock.elapsedRealtime();
    long deltaTime = currentTime - mLastFrameTime;
    if (deltaTime < 33) {
        Thread.sleep(33 - deltaTime);
        currentTime = SystemClock.elapsedRealtime();
        deltaTime = currentTime - mLastFrameTime;
    }

    mLastFrameTime = currentTime;

    updateGameLogic(deltaTime);
    drawGame();
}

请注意,虽然仍然存在人为延迟,但代码中不再有return

这个想法可能有更强大的变化,可以将重绘限制为30 fps。一些搜索SO或其他互联网应该揭示以前的讨论。