2012-09-27 5 views
11

Il problema

Ho appena iniziato a lavorare con OpenGL utilizzando GLUT. Il codice sottostante compila e visualizza due cubi wireframe e una sfera. Il problema è che quando tento di trascinare o ridimensionare la finestra induce un ritardo notevole prima di seguire il mio mouse.La finestra OpenGL GLUT è molto lenta, perché?

Questo problema non si verifica sul computer del mio collega, stesso codice.

Sto lavorando con Visual Studio 2012 C++ express su un computer Windows 7. Sono un programmatore non esperto.

Il codice

// 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

solo una supposizione, ma forse prova ad aggiungere 'Sonno (1)' nella tua funzione 'draw' –

+1

Che ha funzionato davvero! Conoscete la ragione tecnica di questo lavoro e perché ne ho bisogno mentre i miei compagni non lo fanno? – aPerfectMisterMan

risposta

10

Soluzione:

Sembra che la soluzione semplice mediante Sleep(1) nella funzione rendering lavorato. Hai anche chiesto il motivo: non sono sicuro che riuscirò a risolverlo correttamente, ma ecco la mia ipotesi migliore:

Perché funziona anche?

tuoi compagni possono avere VSync attivata per impostazione predefinita nei loro driver. Questo fa sì che il loro codice venga eseguito solo velocemente come lo schermo può aggiornare, molto probabilmente 60 fps. Ti dà circa 16 millisecondi per rendere il frame, e se il codice è efficiente (prendendo, diciamo, 2 ms per il rendering) lascia molto tempo alla CPU di fare altre cose relative al sistema operativo, come lo spostamento della finestra.

Ora, se si disattiva la sincronizzazione verticale, il programma cercherà di rendere il maggior numero di fotogrammi possibile, intasamento efficacemente tutti gli altri processi. Ti ho suggerito di usare Sleep, perché rivela questo particolare problema. Non importa se è 1 o 3 ms, quello che fa è dire "hey, CPU, non sto facendo nulla in particolare in questo momento, quindi puoi fare altre cose".

Ma non è vero rallentando il mio programma?

Utilizzando il sonno è una tecnica comune. Se ti preoccupi di quella perdita di 1 ms ogni fotogramma, puoi anche provare a inserire Sleep(0), poiché dovrebbe funzionare esattamente allo stesso modo, dando il tempo libero alla CPU. Potresti anche provare a abilitare la sincronizzazione verticale e verificare se effettivamente la mia ipotesi fosse corretta.

Come nota a margine, è anche possibile esaminare i grafici di utilizzo della CPU con e senza sleep. Dovrebbe essere 100% (o 50% su una CPU dual-core) senza (funzionante il più velocemente possibile), e molto più basso con, a seconda dei requisiti del programma e della velocità della CPU.

Ulteriori osservazioni in merito a Sleep (0)

Dopo l'intervallo di sonno è passato, il filo è pronto per essere eseguito. Se si specifica 0 millisecondi, il thread rinuncerà al resto del suo intervallo temporale ma resterà pronto. Si noti che non è garantito che un thread pronto venga eseguito immediatamente. Di conseguenza, il thread potrebbe non funzionare fino a qualche tempo dopo l'intervallo di sospensione. - è da here.

Si noti inoltre che il comportamento dei sistemi Linux potrebbe essere leggermente diverso; ma non sono un esperto di linux; forse un passante potrebbe chiarire.

+1

+1 Bella spiegazione. Sleep (0) _stampa_ l'esecuzione del thread, rendendo la pianificazione del thread parzialmente "cooperativa" (a.o.t. _preemptive_ scheduling del thread). – sehe

+2

Per quanto riguarda Linux. La funzione per abbandonare il tempo della CPU su POSIX è 'sched_yield'. Non richiede parametri e ha lo stesso effetto di chiamare 'Sleep (0)' su Windows. – datenwolf