2012-09-27 32 views
11

El problema

Acabo de empezar a trabajar con OpenGL usando GLUT. El siguiente código compila y muestra dos cubos de alambre y una esfera. El problema es que cuando intento arrastrar o cambiar el tamaño de la ventana, induce un retraso notable antes de seguir con el mouse.OpenGL GLUT ventana muy lenta, ¿por qué?

Este problema no se produce en la computadora de mi colega, el mismo código.

Estoy trabajando con Visual Studio 2012 C++ express en una computadora con Windows 7. No soy un programador experimentado.

El código

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

simplemente supongo, pero tal vez intente agregar 'Sueño (1)' en su función 'dibujar' –

+1

¡Eso realmente funcionó! ¿Conoces la razón técnica de este trabajo y por qué lo necesito, mientras que mis compañeros no? – aPerfectMisterMan

Respuesta

10

Solución:

Parece que la solución simple usando Sleep(1) en la función de hacer que trabajaba. También ha preguntado por qué - No estoy seguro de poder resolver esto correctamente, pero esta es mi mejor estimación:

¿Por qué funciona?

Sus compañeros pueden tener encendido VSync por defecto en sus controladores. Esto hace que su código se ejecute tan rápido como la pantalla puede actualizar, muy probablemente 60 fps. Le da alrededor de 16 milisegundos para renderizar el fotograma, y ​​si el código es eficiente (tomando, digamos, 2 ms para renderizar) deja mucho tiempo para que la CPU haga otras cosas relacionadas con el sistema operativo, como mover su ventana.

Ahora, si deshabilita la sincronización vertical, el programa intentará renderizar tantos cuadros como sea posible, obstruyendo de manera efectiva todos los demás procesos. Te sugerí que uses Sleep porque revela este problema en particular. Realmente no importa si es 1 o 3 ms, lo que realmente hace es decir "oye, CPU, no estoy haciendo nada en particular en este momento, por lo que puedes hacer otras cosas".

¿Pero no está ralentizando mi programa?

Usar Sleep es una técnica común. Si le preocupa perder 1 ms en cada fotograma, también puede intentar poner Sleep(0), ya que debería actuar exactamente igual, dando el tiempo libre a la CPU. También puedes intentar habilitar la sincronización vertical y verificar si mi conjetura fue correcta.

Como nota al margen, también puede ver los gráficos de uso de CPU con y sin suspensión. Debería ser 100% (o 50% en una CPU de doble núcleo) sin (correr lo más rápido posible), y mucho más bajo, dependiendo de los requisitos de tu programa y la velocidad de tu CPU.

Observaciones adicionales sobre Sleep (0)

Después de que el intervalo de reposo ha pasado, el hilo está listo para funcionar. Si especifica 0 milisegundos, el subproceso abandonará el resto de su intervalo de tiempo, pero permanecerá listo. Tenga en cuenta que no está garantizado que un hilo listo se ejecute inmediatamente. En consecuencia, es posible que el subproceso no se ejecute hasta un tiempo después de que transcurra el intervalo de inactividad. - es de here.

También tenga en cuenta que en los sistemas Linux el comportamiento puede ser ligeramente diferente; pero no soy un experto en Linux; quizás un transeúnte podría aclarar.

+1

+1 Buena explicación. Sleep (0) _yields_ la ejecución del hilo, lo que hace que la programación del hilo sea parcialmente "cooperativa" (a.o.t. _preemptive_ thread scheduling). – sehe

+2

En cuanto a Linux. La función para renunciar al tiempo de CPU en POSIX es 'sched_yield'. No requiere parámetros y tiene el mismo efecto que llamar 'Sleep (0)' en Windows. – datenwolf