如果 glutPostRedisplay() 被调用太快会发生啥?

Posted

技术标签:

【中文标题】如果 glutPostRedisplay() 被调用太快会发生啥?【英文标题】:What happens if glutPostRedisplay() is called too quickly?如果 glutPostRedisplay() 被调用太快会发生什么? 【发布时间】:2016-02-24 19:18:42 【问题描述】:

我正在用 GLUT 编写一个 OpenGL 程序,它显示场景中的一些移动对象。使用我的函数Render() 完成渲染。但是,我还想在每个循环中移动这些对象的位置,这是在我的函数 Step() 中完成的。

现在,我尝试运行一个循环,在每个循环上调用Render(),然后是Step(),然后是glutPostRedisplay()。但是,这不起作用;显示的窗口没有响应。

我认为这是因为我还需要运行 glutMainLoop() 以便 GLUT 不断使窗口响应。因此,我需要一个在每一帧上调用的计时器函数,并更新对象位置并渲染它们。所以,我现在为此使用glutTimerFunc(...),如下:

glutDisplayFunc(Render);
glutTimerFunc(3, Step, 0);
glutMainLoop();

我对此的理解是每3ms,它就会调用我的Step()函数。如果我现在在Step() 的末尾添加对glutPostRedisplay() 的调用,我的程序运行良好并且对象按预期移动。

但是,我想知道的是,当对我的对象位置进行所有更改所需的时间超过 3 毫秒时会发生什么。在这种情况下,当下次调用Step() 时,我的程序仍将处理对Step() 的最后一次调用。这将导致积压的Step() 呼叫等待处理。

我应该如何处理这个问题?是从 3ms 增加到更大数字的唯一方法吗?还是有其他解决方案?

【问题讨论】:

【参考方案1】:

glutPostRedisplay() 只是设置一个标志。它的工作原理是这样的:

int do_display = 0;

void glutPostRedisplay(void) 
    do_display = 1;


void glutMainLoop(void) 
    for(;;) 
        event ev = get_OS_event();
        switch(ev.type) 
        case keyboard_event: call_keyboard_function(ev); return;
        case mouse_event:    call_mouse_function(ev); return;
        /* ... */
        
        if( do_display ) 
            call_display_function();
            do_display = 0;
         else 
            call_idle_function();
        
    

因此,您可以随意调用glutPostRedisplay,只要您不让主循环有机会处理所有未决事件,它实际上不会调用您的显示函数。

因此,我需要一个在每一帧上调用的计时器函数,并更新对象位置并渲染它们。

不,你想要的是一个让动画前进并调用glutPostRedisplay的空闲函数。

但是,我想知道的是,当对我的对象位置进行所有更改所需的时间超过 3 毫秒时会发生什么。在这种情况下,当对 Step() 进行下一次调用时,我的程序仍将处理对 Step() 的最后一次调用。

不,因为计时器不会引入并发性。发生的事情是,计时器事件正在堆积。然而,使用定时器来控制动画是个坏主意。相反,您应该测量步进函数调用之间的时间,并根据时间差异推进动画。此外,为了最大限度地减少延迟,您不应在显示功能中直接实现动画步骤,以便使用最新的动画步骤进行绘制。

【讨论】:

以上是关于如果 glutPostRedisplay() 被调用太快会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 GlutPostRedisplay 和 sleep 功能在此代码中不起作用?

GLUT Tutorials 19:glutPostRedisplay vs. Idle Func

autobahn JS,如果 RPC 的被调用者是异步的怎么办?

Button Click 事件被调用以保持事件

rdi 和 rsi 调用者保存还是被调用者保存的寄存器?

被调用者分配被调用者释放