views:

479

answers:

1

I'm using OpenGL ES to make a game on the iPhone. Unfortunately, I see small (and irregular) hiccups.

I use a timer with a sleep, calling the draw function every 60th of a second, in order to garantee a solid frame rate. I've tried to change the moment in time my timer awakens from its sleep, giving the draw function more time to execute. The hiccups do get less once the draw function's been given more time. With 8 milliseconds, the animations are almost fluid. My findings are:

  1. Apparently giving the GPU more time to execute the actual drawing, results in an (almost) perfect fluid animation.
  2. Drawing at the exact end of my frame results in stutter, hiccups and what not.

Now that I know that, I'm not sure how to proceed. I have two contradicting ideas about the cause of this behaviour:

  1. First, could it be that the OpenGL commands interfere with the drawing of the previous frame? As far as I understand this can't be the case since the commands are stored and will only execute when the draw command is given.
  2. Second, could the fluctuating time of the draw commands cause the timer to skip a tick?

So which explanation is more likely? Or is neither? Of course I could just try to put the draw function in a seperate thread and see if that solves my problem. But I hope to understand more of OpenGL.

This is the function being called and explains what I'm taking about:

- (void) drawView
{
    // measure time with mach_absolute_time

    // gameEngine update    
    // OpenGL commands (translate, rotate, drawArrays etc.) 

    // end measure time with mach_absolute_time
    // usleep(animationInterval - duration  - constant) 
    // constant is the time to start executing

    // draw
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];    
}
+1  A: 

You might want to read this article about game loops, which explains a lot. Generally the best solution is to call the draw routine in an infinite loop inside a separate thread (see this question) and update the underlying game model according to how much time elapsed since the last update. This will give you smooth motion.

Edit: As for the source of the “hiccups”, they probably have nothing to do with OpenGL. At 60 fps we are talking 1/60 sec ≈ 17 ms per frame. This is a tight schedule that’s easy to miss, because there are other processes running on the device. Safari or Mail.app wake up in the background, the device thinks for a while and now your frame takes 30 ms or even much more. This is very easy to spot if your model expects perfectly steady framerate. The solution is to update the model according to the real time elapsed, as I have written above. The linked article explains this all thoroughly.

zoul
Thanks! This helped a lot. :)
Kriem
You’re welcome. There are also good ideas in the Cocos2D engine for iPhone (http://tinyurl.com/5hpjba), especially if you are doing 2D.
zoul
I am. Will check that out. Thanks again!
Kriem