2012-09-27 118 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