如果过快地调用glutPostRedisplay()会发生什么?

时间:2016-02-24 19:18:43

标签: opengl graphics glut

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

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

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

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

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

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

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

1 个答案:

答案 0 :(得分: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()。

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