2017-06-10 3 views
1

J'apprends OpenGL avec X11 sous Linux, et j'ai un problème que je ne réalise pas ce qui ne va pas.Mises à jour lentes OpenGL lorsque les objets sont petits dans l'espace écran

Lorsque je dessine un objet qui couvre un grand espace sur l'écran, il rend rapidement et met à jour X11 avec un taux de framerate élevé. Mais quand je déplace la caméra loin de l'objet, ou dessine un petit objet, de manière à ce qu'il couvre un petit espace sur l'écran (disons, en pixels), les mises à jour sont vraiment lentes. Comme il dessine petit, plus lent il met à jour le cadre.

Lorsque je suis à 100 unités loin d'un plan 1x1, il atteint environ 1 image par seconde.

Voici le code:

XGetWindowAttributes(dpy, win, &gwa); 
glViewport(0, 0, Width, Height); 
SetupViewMatrix(); 

Camera * cam = mainCamera.GetComponent<Camera>(); 
if(cam != NULL){ 
    CamPose(cam->eyePose, cam->pivotPoint, cam->upDirection); 
} else { 
    CamPose(Vector3::back(), Vector3::forward(), Vector3::up()); 
} 
//glViewport(0, 0, gwa.width, gwa.height); 

ClearScreen(); 

GLfloat cube[] = { 
     -0.05f, -0.05f, -0.05f, 
     -0.05f, 0.05f, -0.05f, 
     0.05f, 0.05f, -0.05f, 
     -0.05f, -0.05f, -0.05f, 
     0.05f, 0.05f, -0.05f, 
     0.05f, -0.05f, -0.05f, 
};//*/ 
GLfloat colors[] = { 
     0.5f, 0.5f, 0.5f, 1.0f, 
     0.5f, 0.5f, 0.5f, 1.0f, 
     0.5f, 0.5f, 0.5f, 1.0f, 

     0.5f, 0.5f, 0.5f, 1.0f, 
     0.5f, 0.5f, 0.5f, 1.0f, 
     0.5f, 0.5f, 0.5f, 1.0f, 
};//*/ 

glVertexPointer(3, GL_FLOAT, 0, cube); 
glColorPointer(4, GL_FLOAT, 0, colors); 

glEnableClientState(GL_VERTEX_ARRAY); 
glEnableClientState(GL_COLOR_ARRAY); 
glDrawArrays(GL_TRIANGLES, 0, 6); 
glDisableClientState(GL_COLOR_ARRAY); 
glDisableClientState(GL_VERTEX_ARRAY); 

glXSwapBuffers(dpy, win); 
glFlush(); 

et la fonction SetupViewMatrix:

void WindowDrawer::SetupViewMatrix(){ 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluPerspective(65, (float)Width/Height, 0.1, 1000); 
}; 

et la fonction ClearScreen:

void WindowDrawer::ClearScreen(){ 
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
} 

EDIT: J'ajoute un peu plus de code aider. Celui-ci est la fonction Init j'utilise pour créer une fenêtre:

void WindowDrawer::InitX11OpenGL(){ 
    dpy = XOpenDisplay(NULL); 
    if(dpy == NULL){ 
     printf("\n\tCannot Connect to X server\n\n"); 
     exit(0); 
    } 
    root = DefaultRootWindow(dpy); 

    vi = glXChooseVisual(dpy, 0, att); 
    if(vi == NULL){ 
     printf("\n\tno appropriate visual found\n\n"); 
     exit(0); 
    } else { 
     printf("\nvisual %p selected\n", (void *)vi->visualid); 
    } 
    cmap = XCreateColormap(dpy, root, vi->visual, AllocNone); 
    swa.colormap = cmap; 
    swa.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask; 

    win = XCreateWindow(dpy, root, 0, 0, 720, 480, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa); 
    XMapWindow(dpy, win); 
    glc = glXCreateContext(dpy, vi, NULL, GL_TRUE); 
    glXMakeCurrent(dpy, win, glc); 
    glEnable(GL_DEPTH_TEST); 
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 
} 

Et celui-ci j'utilise pour créer une boucle d'événement:

void WindowObject::DealWithEvents(){ 
    if(XEventsQueued(windowDrawer.dpy, QueuedAlready)){ 
     XNextEvent(windowDrawer.dpy, &xev); 
     eventHandler.RouteXEvents(&xev, windowDrawer.dpy); 
    } else { 
     memset(&redrawEvent, 0, sizeof(redrawEvent)); 
     redrawEvent.type = Expose; 
     redrawEvent.xexpose.window = windowDrawer.win; 
     XSendEvent(windowDrawer.dpy, windowDrawer.win, False, ExposureMask, &redrawEvent); 
     XFlush(windowDrawer.dpy); 
     eventHandler.RouteXEvents((XEvent *)&redrawEvent, windowDrawer.dpy); 
    } 
}; 

Eh bien, comme je peux voir, Ce problème n'est pas un problème de performance, mais une mise à jour de la file d'attente (ou quelque chose comme). Parce que lorsque l'objet est proche de la caméra, disons, il utilise un grand écran, il dessine plus rapidement comme il le devrait, mais quand il devient plus petit dans l'espace écran, il ralentit linéairement les mises à jour de l'écran. J'imprime les événements pour exposer, keypress et keyrelease, tous ces événements s'exécutent rapidement, comme il se doit, seules les mises à jour de la zone d'écran ne suivent pas la vitesse du système.

+0

Quelle version d'OpenGL ciblez-vous? Pour OpenGL moderne, 'glEnableClientState' a été supprimé dans OpenGL 4.5., Et le rendu sans shader n'est pas non plus supporté. –

+0

Je suis sûr que ce n'est pas le problème dans la question. –

+1

Comment mesurez-vous la fréquence d'images?(J'espère que non seulement en le regardant, les petits objets ne changent souvent pas) Comment générez-vous l'événement X Expose pour forcer un redessin, XClear après chaque image, un minuteur? Avez-vous activé la compression d'événement? –

Répondre

-2

Il y a des choses ici qui ne ressemblent pas à son "optimisé" correctement. Par exemple, vous utilisez gluPerspective. C'est déprécié depuis 10 ans !! Nous ne voulons pas ça! Pourquoi ne pas simplement créer votre propre viewmatrix dans votre classe de caméra? :)

Aussi, je ne suis pas sûr si c'est le problème. Mais il semble que vous appeliez glClearColor dans la boucle RENDER. Ce qui est bien sûr, pas bon. Mettez cela dans votre fonction init. C'est possible c'est le problème.

+0

Merci pour votre réponse. Je suis juste en suivant des tutoriels, c'est pourquoi j'utilise d'anciennes fonctions :). J'ai essayé de déplacer glClearColor à la fonction d'initialisation, mais cela n'a pas résolu le problème. –

+0

Aussi, plus tard, je vais essayer de mettre en œuvre de nouvelles meilleures méthodes, mais pour l'instant, je suis en train d'apprendre :) –

+0

Aucun ami de problème, bonne chance pour trouver votre erreur! :) – Verideth

0

Oh, j'ai trouvé l'erreur, et je réponds à ma propre question à ce sujet. J'ai honte de le dire, car il était si stupide comme prévu par un débutant en graphisme:/

Le problème est que je travaille avec un petit écran, sur un moniteur faible ppi. De plus, la forme sur l'écran est un carré parfait (il ne peint pas les bords diagonaux sur les pixels), donc quand l'objet est petit, il faut beaucoup de temps pour repeindre les pixels de la bordure. L'infographie utilise un effet anti-crénelage pour adoucir cet effet, et opengl brut ne le fait pas, donc cela provoque un effet vraiment différent de ce que j'ai l'habitude de voir. J'ai pris longtemps pour réaliser que c'était seulement un problème de détail de pixel ...

Merci à tous pour toute aide.

+0

Ceci n'explique pas l'illogique 1 fps. – Ripi2

+0

Eh bien, il n'y avait pas 1 fps, mais juste les pixels ont pris environ 1 seconde pour être repeints en raison de la petite forme étant tiré, disons, l'interpolation entre pixels ne change que les pixels à dessiner à 1 seconde ... –