我刚刚开始在我的小游戏中使用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段都是我的代码所以我没有发布它,除非要求)
答案 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或其他互联网应该揭示以前的讨论。