2012-09-27 119 views
11

问题

我刚刚开始使用GLUT使用OpenGL。下面的代码编译并显示两个线框立方体和一个球体。问题是,当我试图拖动窗口或调整窗口大小时,它会在跟随我的鼠标之前引起明显的延迟。OpenGL GLUT窗口很慢,为什么?

在我的同事的计算机,相同的代码上不会发生此问题。

我正在使用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)' –

+1

这实际上是有效的!你知道这项工作的技术原因,为什么我需要它,而我的同学不需要? – aPerfectMisterMan

回答

10

解决方案:

看来,在渲染功能使用Sleep(1)简单的解决方案工作。你也问过为什么 - 我不确定我能否正确解决这个问题,但这里是我的最佳猜测:

为什么它能工作?

你的同学可以在他们的驱动程序默认打开VSync。这导致他们的代码只能以屏幕刷新的速度运行,最可能的是60 fps。它给你大约16毫秒的渲染帧,并且如果代码是有效的(比如,渲染时间为2毫秒),CPU留出足够的时间去做其他与操作系统相关的东西,比如移动窗口。

现在,如果禁用垂直同步,程序将尝试渲染尽可能多的帧,从而有效地阻塞所有其他进程。我建议你使用睡眠,因为它揭示了这个特殊问题。不管它是1毫秒还是3毫秒,它的真正用处是“嘿,CPU,我现在没有做任何特别的事情,所以你可以做其他事情”。

但是这不是减慢我的程序吗?

使用睡眠是一种常用技术。如果您担心每帧丢失1毫秒,您也可以尝试将Sleep(0)放在一起,因为它应该完全相同 - 为CPU提供空闲时间。您也可以尝试启用垂直同步并验证我的猜测是否正确。

作为一个便笺,您还可以查看有无睡眠的CPU使用率图。根据您的程序要求和CPU的速度,它应该是100%(或双核CPU上的50%),而不是(尽可能快地运行),并且要低得多。

关于睡眠的补充说明(0)

睡眠间隔过去之后,线程准备运行。如果指定0毫秒,则线程将放弃其时间片的其余部分,但保持就绪状态。请注意,现成的线程不能保证立即运行。因此,直到睡眠间隔过去一段时间后,线程才可能运行。 - 它来自here

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

+1

+1很好的解释。 Sleep(0)_yields_执行线程,进行部分'合作'线程调度(a.o.t._preemptive_线程调度)。 – sehe

+2

关于Linux。在POSIX上放弃CPU时间的函数是'sched_yield'。它不需要任何参数,并且具有与在Windows上调用“Sleep(0)”相同的效果。 – datenwolf