2012-09-27 22 views
11

Problem

Właśnie zacząłem pracować z OpenGL przy użyciu GLUT. Poniższy kod kompiluje i wyświetla dwie kostki szkieletu i kulę. Problem polega na tym, że podczas próby przeciągnięcia lub zmiany rozmiaru okna wywołuje zauważalne opóźnienie przed podążeniem za myszą.Okno OpenGL GLUT bardzo wolno, dlaczego?

Ten problem nie występuje na komputerze mojego kolegi, ten sam kod.

Pracuję z Visual Studio 2012 C++ express na komputerze z systemem Windows 7. Nie jestem doświadczonym programistą.

Kod

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

tylko zgadnij, ale może spróbuj dodać "Sleep (1)" w funkcji "draw" –

+1

To faktycznie zadziałało! Czy znasz techniczny powód tego działania i dlaczego go potrzebuję, podczas gdy moi koledzy nie? – aPerfectMisterMan

Odpowiedz

10

Rozwiązanie:

Wydaje się, że proste rozwiązanie za pomocą Sleep(1) w funkcji renderowania pracował. Pytasz też, dlaczego - nie jestem pewien, czy będę w stanie rozwiązać to poprawnie, ale oto moje najlepsze przypuszczenie:

Dlaczego to działa?

Twoi studenci mogą domyślnie włączyć VSync w swoich sterownikach. Powoduje to, że ich kod działa tak szybko, jak można odświeżyć ekran, najprawdopodobniej 60 fps. Daje to około 16 milisekund, aby renderować ramkę, a jeśli kod jest wydajny (biorąc, powiedzmy, 2 ms dla renderowania), pozostawia dużo czasu procesorowi na wykonywanie innych czynności związanych z systemem operacyjnym, takich jak przenoszenie okna.

Teraz, jeśli wyłączysz synchronizację pionową, program spróbuje renderować jak najwięcej klatek, skutecznie blokując wszystkie inne procesy. Zasugerowałem ci użycie Sleep, ponieważ ujawnia to jeden konkretny problem. Nie ma znaczenia, czy to 1, czy 3 ms, to, co naprawdę robi, to "hej, procesor, nie robię teraz niczego szczególnego, więc możesz robić inne rzeczy".

Ale czy to nie spowalnia mojego programu?

Korzystanie ze snu jest powszechną techniką. Jeśli martwisz się tym, że straciłeś 1 ms na każdą klatkę, możesz również spróbować wstawić Sleep(0), ponieważ powinno to działać dokładnie tak samo - dając wolny czas procesorowi. Możesz też spróbować włączyć synchronizację pionową i sprawdzić, czy moje przypuszczenia są poprawne.

Na marginesie można również spojrzeć na wykresy wykorzystania procesora zi bez uśpienia. Powinien wynosić 100% (lub 50% na dwurdzeniowym procesorze) bez (działa tak szybko, jak to możliwe) i znacznie mniej, w zależności od wymagań programu i szybkości procesora.

Dodatkowe uwagi o śnie (0)

Po interwał snu minęło, wątek jest gotowy do uruchomienia. Jeśli podasz 0 milisekund, wątek zrezygnuje z pozostałej części wycinka czasu, ale pozostanie gotowy. Zauważ, że gotowy wątek nie może zostać uruchomiony natychmiast. W konsekwencji wątek może nie działać do pewnego czasu po upływie okresu snu. - pochodzi z here.

Należy również zauważyć, że zachowanie systemu Linux może się nieznacznie różnić; ale nie jestem ekspertem od Linuksa; być może przechodzień mógłby wyjaśnić.

+1

+1 Ładne wyjaśnienie. Sleep (0) _yields_ wykonanie wątku, co powoduje częściowe "wspólne" planowanie wątków (a.o.t. _preemptive_ thread scheduling). – sehe

+2

Dotyczące systemu Linux. Funkcja rezygnacji z czasu procesora w POSIX to 'sched_yield'. Nie przyjmuje parametrów i ma mniej więcej taki sam efekt, jak wywołanie funkcji "Uśpienie (0)" w systemie Windows. – datenwolf