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
Nehe ha un buon tutorial su come fare questo, e il suo sito è generalmente una buona risorsa per le domande di OpenGL.
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.
// 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);
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.
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/
Non vale una spiegazione? –
@TinyGiant Grazie per il feedback. Quale parte non è chiara? Dal codice è facile vedere che 'glViewport' è chiamato più volte. –
In GL 4 si possono rendere a molti finestre in un passaggio di rendering. Vedi ARB_viewport_array e concetti correlati.
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
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