如果 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