2009-04-07 15 views
27

Ho bisogno di mostrare lo stesso oggetto in OpenGL in due viewport differenti, ad esempio uno con proiezione ortografica e l'altro con prospettiva. Per fare ciò, devo disegnare nuovamente l'oggetto dopo ogni chiamata a glViewport()?Come utilizzare più finestre in OpenGL?

risposta

12

Nehe ha un buon tutorial su come fare questo, e il suo sito è generalmente una buona risorsa per le domande di OpenGL.

+3

Per me, l'articolo collegato suggerisce una risposta "sì, [devi]" - ma il suo autore sembra * voler * disegnare qualcosa di diverso su ogni viewport. Pertanto, sarei comunque grato se qualcuno confermasse in parole semplici se è "sì, devi ridisegnare gli oggetti in ogni finestra" o "no, non devi - vedere " – akavel

+0

Come ho capito la pipeline di OpenGL , per poter ridisegnare qualcosa da una trasformazione diversa, i vertici devono essere passati di nuovo nella pipeline con la nuova trasformazione, quindi si dovrà ridisegnare di sicuro. – user1294021

3

sì,

e si dovrebbe anche modificare le impostazioni di forbice di avere una netta separazione tra i due punti di vista, se sono nella stessa finestra.

9
// 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); 
0

Pensa a OpenGL come a nient'altro che a comandi che preparano l'output alla finestra con cui stai attualmente lavorando.

Ci sono due comandi con OpenGL che tutorial, anche di NeHe non vi dicono l'importanza di:

wglCreateContext - che prende un contesto di periferica finestra DC, possono essere ottenute da qualsiasi finestra - che si tratti di un controllo utente, un forma di finestra, una finestra GL o un'altra finestra dell'applicazione (come il blocco note). Questo crea un contesto di dispositivo OpenGL - si riferiscono a un contesto di risorse - che in seguito utilizzi ...

wglMakeCurrent - che prende due parametri, il Contesto dispositivo con cui hai a che fare (il parametro passato per Windows Device Context in wglCreateContext) - e il contesto delle risorse che ritorna.

Sfruttando solo queste due cose - Ecco il mio consiglio:

tutorial di NeHe fornisce una soluzione che sfrutta la finestra esistente SOLO e segmenti dello schermo per il disegno. Ecco il tutorial: http://nehe.gamedev.net/tutorial/multiple_viewports/20002/

Sfruttando glViewport è necessario ri-disegnare su ogni aggiornamento.

Questo è un metodo.

Ma c'è un altro - meno grafica e del processore metodo intenso:

Creare una finestra per ogni vista, sfruttando un controllo utente.

Ogni finestra ha il proprio hWnd.

Ottenere il controller di dominio, elaborare il wglcreatecontext e quindi, su un timer (il mio è di 30 fotogrammi al secondo), se si rileva il cambiamento di stato, selezionare wglMakeCurrent per quella vista e ridisegnare. Altrimenti, salta semplicemente la sezione.

Questo conserva una preziosa potenza di elaborazione e riduce anche il codice da dover gestire manualmente i calcoli della finestra e della vista.

3

Minimal esempio eseguibile

simili this answer, ma più diretto e compilabile.Uscita:

Codice:

#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; 
} 

Compilare con:

gcc -lGL -lGLU -lglut main.c 

provata su OpenGL 4.5.0 NVIDIA 352.63, Ubuntu 15.10.

TODO: Credo che in OpenGL moderno 4 si dovrebbe solo rendere a texture, e quindi posizionare le texture orthogonaly sullo schermo, vedere questo come un punto di partenza: http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/

+0

Non vale una spiegazione? –

+0

@TinyGiant Grazie per il feedback. Quale parte non è chiara? Dal codice è facile vedere che 'glViewport' è chiamato più volte. –

0

In GL 4 si possono rendere a molti finestre in un passaggio di rendering. Vedi ARB_viewport_array e concetti correlati.

Problemi correlati