For a while now I've experienced an intermittent 'stuttering' of the sprites that are in motion within my Android Game. It's a fiarly simple 2D OpenGL ES 2.0 game. (This is an ongoing problem which I have re-visited many times).
In my game loop, I have 2 'timers' - one which will log the number of frames in the previous second, and another which counts the time (in Milliseconds) from the end of the current onDrawFrame iteration to the start of the next.
This is what I've found:
When not rendering anything, I get 60fps (for the most part), and every time onDrawFrame is called, it reports itself as taking longer that 16.667ms. Now, If I render something (doesn't matter if it's 1 quad or 100 quads, the result is the same), I get 60fps (for the most part) but now, only about 20% of onDrawFrame calls report themselves as taking longer than 16.667ms from the last call.
I don't really understand why this happens, firstly, why, when onDrawFrame isn't doing anything, is it called so 'slowly' - and more importantly, why does any GL call (one simple quad), still make the time between onDrawFrame calls longer than 16.667ms (albeit much less frequently).
I should say that when onDrawFrame reports taking longer than 16.667ms from the last iteration, it is almost always accompanied by a drop in FPS (to 58 or 59), but not all of the time, sometimes, the FPS stays constant. And conversely, sometimes when the FPS drops, onDrawFrame is called within 16.667ms of the last iteration completing.
So......
I'm trying to fix my game-loop and eradicate these 'stutters' - some other things to note:
- When I do method profiling, it shows glSwapBuffers, sometimes taking a long time
- When I do a GL Trace, most scenes its says renders in less than 1ms, but sometimes the odd frame takes 3.5-4ms - same scene. Nothing changes apart from the time it takes
- Almost every time a frame is dropped, or onDrawFrame reports a long delay (or both), there is a visual glitch, but not every time. Big visual glitches seems to coincide with multiple 'delayed' onDrawFrame calls and /or dropped frames.
- I don't think this is a scene complexity issue for 2 reasons: 1) even if I render my scene twice, it doesn't make the problem any worse, I still for the most part, get 60FPS with the occasional drop, just as before and 2), even if I strip the scene bare, I still get the problem.
I obviously am misunderstanding something, so a push in the right direction would be appreciated.
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();
}
This game loop above is the one featured in this excellent article.
if (frameTime > 0.25)
actually affects only the statementframeTime = 0.25;
however your indentation suggests otherwise. – PaveronDrawFrame()
start time, but as mentioned in the article linked from my answer, that's based on queue back-pressure rather than VSYNC, and will vary a bit. That said, I usedonDrawFrame()
times in Android Breakout (github.com/fadden/android-breakout) and it looked fine. – IntricacyonDrawFrame
calls and actually from the end of one frame to the start of the next one. For that duration to be 1/60 your code should take zero time. If your code takes non-zero time this value should always be < 1/60. The fact that you observe larger values (how large exactly?) means that the system just delays calling your code, not that your frame is slow. Some frames are expected to take longer (e.g. the first frame drawn by GL seems to be slower), but I would expect a glitch would probably have to do with wrong integration – Paver