GLUT教程 - glutPostRedisplay函数

转载 2013年12月04日 10:04:38

http://www.cnblogs.com/live41/p/3395899.html


[译]GLUT教程 - glutPostRedisplay函数

Lighthouse3d.com >> GLUT Tutorial >> Avoiding the Idle Func >> glutPostRedisplay

 

直到所有源代码都使用显示函数作为空闲函数.这意味着当没有任何事件要处理的时候GLUT会调用显示函数,也就是说,它会尽可能频繁的调用显示函数.

这个一个建立交互程序的简单方法.当你的回调函数处理完键盘事件后,显示函数会自动被调用,屏幕会被重绘.

我们要做的只是把显示函数和空闲函数注册到同一个回调函数.

如果我们的程序打算以独占的方式运行,或者想要获取测试分数,这是可行的.然而,当我们的程序只是操作系统进程之一时,计算机的资源就会变得不充足.

问题就在于我们的GLUT程序,它过于频繁的调用显示函数,即使已经没有新对象需要渲染.你可以去看下任务管理器中进程的选项卡,你会发现即使帧与帧之间没有渲染更改,我们的GLUT程序仍然会快速消耗CPU资源.GPU资源毫无疑问的也会被消耗.

当我们需要CPU或GPU资源来做其它事的时候我们就会想节省这些资源,保持我们的GLUT程序的占用行为不生效.

要达到这个目的,我们必须选择性的告诉GLUT去调用显示函数.glutPostRedisplay函数就是为了这个用途而设计的.

glutPostRedisplay函数会标记当前窗体来重新显示,它会促使主循环尽快的调用完显示函数.注意它只影响当前窗体(获得焦点的窗体),不是所有窗体.上一个例子有子窗体,我们必须做一些扩展测量来确保工作正常.

首先我们将会为主窗体更改显示函数,改成它可以调用所有子窗体定义的渲染函数.然后我们只需要在主窗体中调用glutPostRedisplay函数,所有的窗体都会被重新渲染.

在主函数中添加:

复制代码
int main(int argc, char **argv) {

    // init GLUT and create main window
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowPosition(100,100);
    glutInitWindowSize(800,800);
    mainWindow = glutCreateWindow("Lighthouse3D - GLUT Tutorial");

    // callbacks for main window
    glutDisplayFunc(renderScene);
    glutReshapeFunc(changeSize);
        glutIdleFunc(renderSceneAll);
        ...
复制代码

 

我们打算更改主窗体的显示函数为renderSceneAll,就是上一个空闲函数,我们会先取消空闲函数的原有绑定回调.于是新的main函数如下:

复制代码
int main(int argc, char **argv) {

    // init GLUT and create main window
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowPosition(100,100);
    glutInitWindowSize(800,800);
    mainWindow = glutCreateWindow("Lighthouse3D - GLUT Tutorial");

    // callbacks for main window
    glutDisplayFunc(renderSceneAll);
    glutReshapeFunc(changeSize);

    // Removing the idle function to save CPU and GPU
    //glutIdleFunc(renderSceneAll);
        ...
复制代码

 

现在来看我们要把glutPostRedisplay函数的调用放在哪里.我们只想要在渲染图像有更改的时候调用显示函数.当所有场景处于静止状态,渲染差异化的唯一时刻就是当我们移动镜头的时候.

镜头移动一般是用鼠标键盘,所以我们必须添加glutPostRedisplay的调用到这些事件的回调函数中.

现在就先来改鼠标回调函数.鼠标移动时镜头跟着移动.所以我们会将来的下面这段代码:

复制代码
void mouseMove(int x, int y) {

    // this will only be true when the left button is down
    if (xOrigin >= 0) {

        // update deltaAngle
        deltaAngle = (x - xOrigin) * 0.001f;

        // update camera's direction
        lx = sin(angle + deltaAngle);
        lz = -cos(angle + deltaAngle);
    }
}
复制代码

改成下面这样:

复制代码
void mouseMove(int x, int y) {

    // this will only be true when the left button is down
    if (xOrigin >= 0) {

        // update deltaAngle
        deltaAngle = (x - xOrigin) * 0.001f;

        // update camera's direction
        lx = sin(angle + deltaAngle);
        lz = -cos(angle + deltaAngle);

                // setting the main window as active
                //and marking it for redraw
        glutSetWindow(mainWindow);
        glutPostRedisplay();
    }
}
复制代码

 

现在轮到键盘回调函数.处理键盘事件的函数叫pressKey.我们会将原来的下面这段代码:

复制代码
void pressKey(int key, int xx, int yy) {

    switch (key) {
        case GLUT_KEY_UP : deltaMove = 0.5f; break;
        case GLUT_KEY_DOWN : deltaMove = -0.5f; break;
    }
}
复制代码

改成下面这样:

复制代码
void pressKey(int key, int xx, int yy) {

    switch (key) {
        case GLUT_KEY_UP : deltaMove = 0.5f; break;
        case GLUT_KEY_DOWN : deltaMove = -0.5f; break;
    }

        // setting the main window as active
        //and marking it for redraw
    glutSetWindow(mainWindow);
    glutPostRedisplay();

}
复制代码

 

不幸的是,我们关闭了键盘重复输入的键盘回调函数,因此以上代码的修改是不够的.pressKey函数只会被调用一次,不是你预期中的按压多久就调用多少次.

幸运的是有一个方法可以解决这个问题.当我们按下键时设置一个非零值的状态变量.稍后我们检查该变量来确定镜头位置是否需要更新.该检查是放在renderSceneAll函数中,所以我们的测试将会放在用户初始按下键的任何地方.

下面是之前例子中renderSceneAll的代码:

复制代码
// Global render func
void renderSceneAll() {

    // check for keyboard movement
    if (deltaMove) {
        computePos(deltaMove);
    }

    renderScene();
    renderScenesw1();
    renderScenesw2();
    renderScenesw3();
}
复制代码

 

变量deltaMode在一个键最初被按下的时候会被置非零值.因此我们可以在if条件语句中调用glutPostRedisplay函数,实现如下:

复制代码
// Global render func
void renderSceneAll() {

    // check for keyboard movement
    if (deltaMove) {
        computePos(deltaMove);

                // set the main window as active and
                // ask for a redraw
        glutSetWindow(mainWindow);
        glutPostRedisplay();
    }

    renderScene();
    renderScenesw1();
    renderScenesw2();
    renderScenesw3();
}
复制代码

 

做完以上更改后,我们的显示函数会被重复调用直至deltaMove变量归零.只有当用户松开按键的时候发生,releaseKey函数实现如下:

复制代码
void releaseKey(int key, int x, int y) {

    switch (key) {
        case GLUT_KEY_UP :
        case GLUT_KEY_DOWN : deltaMove = 0;break;
    }
}
复制代码

 

下一节会给出完整代码.

glutpostredisplay,mianloop用法理解

glutpostredisplay,mianloop   glutPostRedisplay 标记当前窗口需要重新绘制。通过glutMainLoop下一次循环时,窗口显示将被回调以重新显示窗...
  • u013720169
  • u013720169
  • 2014年02月22日 10:38
  • 1795

glutSwapBuffers和glutPostRedisplay

双缓存用SwapBuffer,单缓存用glFlush() /*  * Copyright (c) 1993-2003, Silicon Graphics, Inc.  * All Right...
  • Blues1021
  • Blues1021
  • 2016年05月13日 10:11
  • 1587

读取并显示 obj (2)

这个是读取obj的另一个版本,专门读取由灰度图转换的obj。
  • lcbwlx
  • lcbwlx
  • 2014年04月28日 23:02
  • 640

关于OpenNI2和OpenCV2的那些事——获取三维点云数据并用OpenGL表示

上一节呢,我们利用openni2获得了彩色图像和深度图像,这一节我们用openni2的转换函数将深度数据转换为三维点云,然后用彩色数据作为纹理将点云用opengl画出来。 首先介绍Coordinate...
  • aptx704610875
  • aptx704610875
  • 2015年11月12日 15:45
  • 7786

OpenGL---GLUT教程(二) GLUT初始化

                                             GLUT教程                                                 ...
  • xie_zi
  • xie_zi
  • 2007年12月02日 01:51
  • 10212

GLUT 工具箱函数

GLUT工具箱提供几种图形3维图形的函数: void glutWireSphere(GLdouble radius, GLint slices, GLint stacks);  丝状球void ...
  • zcj331
  • zcj331
  • 2014年04月11日 13:29
  • 410

opengl 显示图片以及保存图片

opengl 的贴图功能是很基本的,不过也难住了我这个新手,所以特意写了一个示例程序,以便以后查阅。 程序很简单,只是在在 x, y 平面画一个框,然后贴上一张图。并且可以保存opengl窗口到图...
  • lcbwlx
  • lcbwlx
  • 2014年01月18日 16:09
  • 2456

基于opengl的RoundBox绘制

opengl RoundBox
  • dizuo
  • dizuo
  • 2010年07月08日 20:08
  • 2384

GLUT教程--基本的启动建立窗口的简单渲染图形例子

GLUT教程 在这个部分我们将在我们的程序里建立一个main函数,这个main函数将完成必须的初始化和开启事件处理循环。所有的GLUT函数都有glut前缀并且那些完成一些初始化的函数有g...
  • thanklife
  • thanklife
  • 2016年10月09日 09:39
  • 901

OpenGL---GLUT教程(一) GLUT简介,体系

                                            GLUT 教程                                            体系 GL...
  • xie_zi
  • xie_zi
  • 2007年12月02日 00:36
  • 11643
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:GLUT教程 - glutPostRedisplay函数
举报原因:
原因补充:

(最多只允许输入30个字)