在OpenGL ES中打嗝。什么是正确的实施? [英] Hiccups in OpenGL ES. What is the correct implementation?

查看:128
本文介绍了在OpenGL ES中打嗝。什么是正确的实施?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用OpenGL ES在iPhone上制作游戏。 不幸的是,我看到小的(和不规则的)打嗝。

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

我使用带睡眠的计时器,每隔60秒调用一次绘图功能,以保证稳固的帧率。我试图改变我的计时器从睡眠状态唤醒的时刻,给予绘制功能更多的时间来执行。一旦绘制函数被赋予更多时间,打嗝就会减少。在8毫秒的时间内,动画几乎是流畅的。我的发现是:

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. 显然让GPU有更多时间来执行实际绘图,从而产生(几乎)完美的流体动画。

  2. 在我的框架的确切结束处绘制导致口吃,打嗝和什么不是。

现在我知道了,我不确定如何继续。关于这种行为的原因我有两个矛盾的想法:

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


  1. 首先,可能是OpenGL命令干扰了绘图上一帧的情况?据我所知,由于存储了命令,因此不会出现这种情况,只有在给出draw命令时才会执行。

  2. 其次,绘制命令的波动时间是否会导致计时器跳过勾号?

  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?

那么哪种解释更有可能?或者既不是?当然我可以尝试将绘图功能放在一个单独的线程中,看看是否能解决我的问题。但我希望能够更多地了解OpenGL。

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];    
}


推荐答案

你可能想读这个有关游戏循环的文章,这解释了很多。通常,最好的解决方案是在单独的线程内的无限循环中调用draw例程(参见这个问题)并根据自上次更新以来经过的时间更新基础游戏模型。这将为您提供平稳的动作。

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.

编辑:至于打嗝的来源,它们可能与OpenGL无关。在60帧/秒时,我们说的是每帧1/60秒≈17毫秒。这是一个很容易错过的紧凑计划,因为设备上还有其他进程在运行。 Safari或Mail.app在后台唤醒,设备会考虑一段时间,现在你的帧需要30毫秒甚至更多。如果您的模型期望完全稳定的帧速率,则很容易发现。解决方案是根据实际经过的时间更新模型,如上所述。链接的文章彻底解释了这一点。

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.

这篇关于在OpenGL ES中打嗝。什么是正确的实施?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆