gpt4 book ai didi

Android:了解 OnDrawFrame、FPS 和 VSync (OpenGL ES 2.0)

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:43:40 27 4
gpt4 key购买 nike

一段时间以来,我的 Android 游戏中运动的 Sprite 间歇性“卡顿”。这是一款非常简单的 2D OpenGL ES 2.0 游戏。 (这是一个持续存在的问题,我已经多次重新访问过)。

在我的游戏循环中,我有 2 个“计时器”——一个记录前一秒的帧数,另一个计算从当前 onDrawFrame 迭代结束到开始的时间(以毫秒为单位)下一个。

这是我发现的:

当不渲染任何东西时,我得到 60fps(大多数情况下),并且每次调用 onDrawFrame 时,它​​都会报告自己花费的时间超过 16.667 毫秒。现在,如果我渲染某些东西(无论是 1 个四边形还是 100 个四边形,结果都是一样的),我得到 60fps(大部分)但是现在,只有大约 20% 的 onDrawFrame 调用报告自己花费了更长的时间距离上次调用的时间少于 16.667 毫秒。

我真的不明白为什么会发生这种情况,首先,为什么当 onDrawFrame 没有做任何事情时,它被调用得如此“缓慢” - 更重要的是,为什么任何 GL 调用(一个简单的四边形)仍然使onDrawFrame 调用之间的时间超过 16.667 毫秒(尽管频率要低得多)。

我应该说,当 onDrawFrame 报告从上一次迭代开始花费的时间超过 16.667 毫秒时,它几乎总是伴随着 FPS 下降(降至 58 或 59),但并非所有时间,有时,FPS 保持不变.相反,有时当 FPS 下降时,会在最后一次迭代完成后的 16.667 毫秒内调用 onDrawFrame。

所以......

我正在尝试修复我的游戏循环并消除这些“卡顿”——其他一些需要注意的事项:

  • 当我进行方法分析时,它显示 glSwapBuffers,有时需要很长时间
  • 当我执行 GL Trace 时,它​​说的大多数场景渲染时间不到 1 毫秒,但有时奇数帧需要 3.5-4 毫秒 - 相同的场景。除了花费的时间,没有什么改变
  • 几乎每次丢帧或 onDrawFrame 报告长时间延迟(或两者)时,都会出现视觉故障,但并非每次都如此。大的视觉故障似乎与多个“延迟的”onDrawFrame 调用和/或丢帧同时发生。
  • 我不认为这是一个场景复杂性问题,原因有两个:1) 即使我渲染我的场景两次,也不会使问题变得更糟,我仍然在大多数情况下偶尔获得 60FPS下降,就像之前和 2) 一样,即使我剥离场景,我仍然遇到问题。

我显然误解了一些东西,所以向正确的方向插入将不胜感激。

OnDrawFrame

@Override
public void onDrawFrame(GL10 gl) {

startTime = System.nanoTime();
fps++;
totalTime = System.nanoTime() - timeSinceLastCalled;

if (totalTime > 16667000) {
Log.v("Logging","Time between onDrawFrame calls: " + (totalTime /(double)1000000));
}

//Grab time
newTime = System.currentTimeMillis() * 0.001;
frameTime = newTime - currentTime; //Time the last frame took

if (frameTime > 0.25)
frameTime = 0.25;

currentTime = newTime;
accumulator += frameTime;

while (accumulator >= dt){
saveGameState();
updateLogic();
accumulator -= dt;
}

interpolation = (float) (accumulator / dt);

Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);

render(interpolation);

if (startTime > lastSecond + 1000000000) {
lastSecond = startTime;
Log.v("Logging","fps: "+fps);
fps=0;
}

endTime = startTime;
timeSinceLastCalled = System.nanoTime();
}

上面的这个游戏循环是这个优秀 article 中的特色游戏循环.

最佳答案

一些想法:

  • 不要使用 System.currentTimeMillis() 来计时。它基于挂钟,可以通过网络更新。使用基于单调时钟的 System.nanoTime()
  • 参见 this appendix有关游戏循环的一些注释。队列填充对很多事情都很好,但要明白你并没有完全脱离 VSYNC,所以计时往往不准确。
  • 某些设备(特别是那些基于 qcom SOC 的设备)在认为自己空闲时会降低 CPU 速度。始终在触摸屏上积极移动手指的同时记下时间。
  • 如果您想调试帧速率问题,您需要使用 systrace . traceview 分析在这里没那么有用。

参见 Grafika's “记录 GL 应用程序”Activity 是一个简单的 GLES 应用程序示例,该应用程序会丢帧,但会调整动画以使其很少被注意到。

关于Android:了解 OnDrawFrame、FPS 和 VSync (OpenGL ES 2.0),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38512936/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com