OpenGL GLUT 窗口非常缓慢,为什么?

11

问题

我刚开始使用GLUT来编写OpenGL代码。下面的代码可以编译并显示两个线框立方体和一个球体。然而,当我尝试拖动或调整窗口大小时,会有明显的延迟才跟随我的鼠标。

同样的代码在我的同事电脑上没有这个问题。

我正在Windows 7电脑上使用Visual Studio 2012 C++ Express,我不是一名经验丰富的程序员。

代码

    // OpenGLHandin1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <GL/glut.h>

void initView(int argc, char * argv[]){
    //init here
    glutInit(&argc, argv);
    //Simple buffer
    glutInitDisplayMode( GLUT_SINGLE | GLUT_RGBA );
    glutInitWindowPosition(100,100);
    glutInitWindowSize(800,400);
    glutCreateWindow("Handin 2");
}
void draw(){

    glClearColor(0,0,0,1);
    glClear(GL_COLOR_BUFFER_BIT);
    //Background color

    glPushMatrix();
    glLoadIdentity();
    glTranslatef(0.6, 0, 0);

    glColor3f(0.8,0,0);
    glutWireCube(1.1); //Draw the cube
    glPopMatrix();

    glPushMatrix();
    glLoadIdentity();
    glTranslatef(-0.5, 0, -0.2);

    glColor3f(0,0.8,0);
    glutWireCube(1.1); //Draw the cube
    glPopMatrix();

    glPushMatrix();
    glLoadIdentity();
    glTranslatef(0, 1.2, 0);
    glRotatef(90, 1, 0, 0);

    glColor3f(1,1,1);
    glutWireSphere(0.6, 20, 20); //Draw the sphere
    glPopMatrix();

    //draw here
    //glutSwapBuffers();
    glutPostRedisplay();
    glFlush();

}
void reshape (int w, int h){
    glViewport(0,0,w ,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45, (float)w/(float)h, 1.5, 10);
    gluLookAt(1.5, 2.5, 4, 
              0, 0.6, 0, 
              0, 1, 0); //Orient the camera
    glRotatef(5, 0, 0, 1);
    glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char * argv[])
{
    initView(argc,argv);
    glutDisplayFunc(draw);
    glutReshapeFunc(reshape);
    glutMainLoop();
}

1
只是猜测,也许尝试在你的“draw”函数中添加“Sleep(1)”会有帮助。 - Bartek Banachewicz
1
真的成功了!你知道这能正常工作的技术原因以及为什么我需要它而我的同学们不需要吗? - aPerfectMisterMan
1个回答

12

解决方案:

在渲染函数中使用Sleep(1)这个简单的解决方案似乎起作用了。你也问了为什么 - 我不确定我能够正确地解决这个问题,但这是我的最佳猜测:

为什么它会起作用呢?

你的同学可能默认在他们的驱动程序中开启了垂直同步。这会导致他们的代码只以屏幕可以刷新的速度运行,很可能是60帧每秒。它给你大约16毫秒来渲染帧,如果代码效率高(比如说需要2毫秒渲染),那么就留下了充足的时间让CPU做其他与操作系统相关的事情,比如移动你的窗口。

现在,如果你禁用垂直同步,程序将尝试尽可能多地渲染帧,有效地阻塞所有其他进程。我建议你使用Sleep,因为它揭示了这个特定的问题。无论它是1毫秒还是3毫秒,它实际上的作用是告诉“嘿,CPU,我现在没有做任何特别的事情,所以你可以做其他的事情”。

但这不会减缓我的程序吗?

使用Sleep是一种常见的技术。如果你担心每帧丢失的1毫秒,你也可以尝试放置Sleep(0),因为它应该完全相同 - 给CPU留下时间。

你还可以尝试启用垂直同步并验证我的猜测是否正确。

另外,你还可以查看有和没有Sleep时的CPU使用率图表。它应该是100%(或者在双核CPU上是50%)没有(尽可能快地运行),而有Sleep时则明显低得多,具体取决于你的程序要求和CPU的速度。

关于Sleep(0)的其他说明

经过休眠时间后,线程已准备好运行。如果您指定0毫秒,则线程将放弃其剩余的时间片但仍处于就绪状态。请注意,就绪状态的线程不能保证立即运行。因此,该线程可能要在休眠间隔过后一段时间才能运行。 - 来自这里

另外请注意,在Linux系统上的行为可能会稍有不同;但我不是Linux专家;也许路过的人可以澄清这一点。


1
+1 很好的解释。Sleep(0) yields 线程执行,部分地实现了“合作式”线程调度(而不是 抢占式 线程调度)。 - sehe
2
关于Linux。在POSIX上放弃CPU时间的函数是sched_yield。它不需要参数,并且与在Windows上调用Sleep(0)具有大致相同的效果。 - datenwolf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接