web-dev-qa-db-fra.com

Comment utiliser plusieurs vues dans OpenGL?

Je dois montrer le même objet dans OpenGL dans deux vues différentes, l'une utilisant une projection ortographique, l'autre une perspective. Pour ce faire, dois-je dessiner à nouveau l'objet après chaque appel à glViewport ()?

27
Victor Araújo

Nehe a un bon tutoriel sur la façon de procéder, et son site est généralement une bonne ressource pour les questions OpenGL.

13
Ed James
 // normal mode
  if(!divided_view_port)
    glViewport(0, 0, w, h);
else
{
    // right bottom
    glViewport(w/2, h/2, w, h);
    glLoadIdentity ();
    gluLookAt(5.0f, 5.0f, 5.0f,
              0.0f, 0.0f, 0.0f,
              0.0f, 1.0f, 0.0f);

    display();

    // left bottom
    glViewport(0, h/2, w/2, h);
    glLoadIdentity();
    gluLookAt (5.0f, 0.0f, 0.0f,
              0.0f, 0.0f, 0.0f,
              0.0f, 1.0f, 0.0f);

    display();

    // top right
    glViewport(w/2, 0, w, h/2);
    glLoadIdentity();
    gluLookAt(0.0f, 0.0f, 5.0f,
              0.0f, 0.0f, 0.0f,
              0.0f, 1.0f, 0.0f);

    display();

    // top left
    glViewport(0, 0, w/2, h/2);
    glLoadIdentity();
    gluLookAt(0.0f, 5.0f, 0.0f,
              0.0f, 0.0f, 0.0f,
              0.0f, 1.0f, 0.0f);

    display();
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

if (w <= h)
    glOrtho(-2.0, 2.0, 
            -2.0 * (GLfloat) h / (GLfloat) w, 2.0 * (GLfloat) h / (GLfloat) w, 
    -10.0, 100.0); 
else
    glOrtho(-2.0 * (GLfloat) w / (GLfloat) h, 2.0 * (GLfloat) w / (GLfloat) h, 
    -2.0, 2.0, 
    -10.0, 100.0);

glMatrixMode(GL_MODELVIEW);
9
p govind rao

Exemple minimal exécutable

Similaire à cette réponse , mais plus directe et compilable. Sortie:

Code: 

#include <stdlib.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

static int width;
static int height;

static void display(void) {
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0f, 0.0f, 0.0f);

    glViewport(0, 0, width/2, height/2);
    glLoadIdentity();
    gluLookAt(0.0, 0.0, -3.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    glutWireTeapot(1);

    glViewport(width/2, 0, width/2, height/2);
    glLoadIdentity();
    gluLookAt(0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    glutWireTeapot(1);

    glViewport(0, height/2, width/2, height/2);
    glLoadIdentity();
    gluLookAt(0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0);
    glutWireTeapot(1);

    glViewport(width/2, height/2, width/2, height/2);
    glLoadIdentity();
    gluLookAt(0.0, -3.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0);
    glutWireTeapot(1);

    glFlush();
}

static void reshape(int w, int h) {
    width = w;
    height = h;
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
    glMatrixMode(GL_MODELVIEW);
}

int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100, 100);
    glutCreateWindow(argv[0]);
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_FLAT);
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMainLoop();
    return EXIT_SUCCESS;
}

Compiler avec:

gcc -lGL -lGLU -lglut main.c

Testé sur OpenGL 4.5.0 NVIDIA 352.63, Ubuntu 15.10.

TODO: Je pense que dans OpenGL 4 moderne, vous devez simplement restituer les textures, puis les placer orthogonalement à l'écran, voir ceci comme point de départ: http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/

oui,

et vous devez également modifier les paramètres des ciseaux pour séparer les deux vues si elles se trouvent dans la même fenêtre.

3
fa.

Dans GL 4, vous pouvez effectuer le rendu de nombreuses fenêtres en un seul passage. Voir ARB_viewport array et les concepts associés.

Pensez qu'OpenGL n'est rien d'autre que des commandes qui vous préparent à afficher dans la fenêtre avec laquelle vous travaillez.

Il y a deux commandes avec OpenGL que même les tutoriels de NEHE ne vous disent pas l'importance de:

wglCreateContext - qui prend un contrôleur de domaine de périphérique de fenêtre, peut être obtenu dans TOUTES les fenêtres - qu’il s’agisse d’un contrôle utilisateur, d’un formulaire Windows, d’une fenêtre GL ou d’une autre fenêtre d’application (telle que le bloc-notes). Cela crée un contexte de périphérique OpenGL - ils se réfèrent à un contexte de ressource - que vous utiliserez plus tard avec ...

wglMakeCurrent - qui prend deux paramètres, le contexte de périphérique avec lequel vous traitez (paramètre transmis pour le contexte de périphérique Windows dans wglCreateContext) - et le contexte de ressource qui retourne. 

En utilisant SEULEMENT ces deux choses - voici mon conseil:

Le didacticiel de NEHE fournit une solution qui exploite SEULEMENT la fenêtre existante et segmente l’écran pour le dessin. Voici le tutoriel: http://nehe.gamedev.net/tutorial/multiple_viewports/20002/

En utilisant glViewport, vous devrez redessiner chaque mise à jour. 

C'est une méthode. 

Mais il y a une autre méthode moins graphique et plus intense en processeurs:

Créez une fenêtre pour chaque vue en utilisant un contrôle utilisateur. 

Chaque fenêtre a son propre hWnd. 

Obtenez le contrôleur de domaine, traitez le contexte de wglcreat, puis, si vous détectez un changement d'état, le temps d'une minuterie (la mienne est de 30 images par seconde), puis sélectionnez wglMakeCurrent pour cette vue et redessinez. Sinon, il suffit de sauter la section entièrement. 

Cela préserve une précieuse puissance de traitement et évite également au code de gérer manuellement les calculs de fenêtre et de fenêtre d'affichage. 

0