¿Cómo usar múltiples viewports en OpenGL?


Necesito mostrar el mismo objeto en OpenGL en dos viewports diferentes, por ejemplo, uno usando proyección ortográfica y el otro usando perspectiva. Para hacer esto, ¿necesito dibujar de nuevo el objeto después de cada llamada a glViewport()?

6 answers

Nehe tiene un buen tutorial sobre cómo hacer esto, y su sitio es generalmente un buen recurso para preguntas OpenGL.

 12
Author: Ed James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-07 15:39:57
 // 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
Author: Markus Unterwaditzer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-05 15:25:05

Y también debe cambiar la configuración de tijera para tener una separación limpia entre las dos vistas si están en la misma ventana.

 3
Author: fa.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-07 15:54:29

Ejemplo ejecutable mínimo

Similar a esta respuesta, pero más directa y compilable. Salida:

Código:

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

Compilar con:

gcc -lGL -lGLU -lglut main.c

Probado en OpenGL 4.5.0 NVIDIA 352.63, Ubuntu 15.10.

TODO: Creo que en OpenGL 4 moderno solo debes renderizar a texturas, y luego colocar esas texturas ortogonalmente en la pantalla, ve esto como un punto de partida: http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture /

 3
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-21 22:52:51

En GL 4 puede renderizar a muchas vistas en un solo pase de renderizado. Véase ARB_viewport_array y conceptos relacionados.

 1
Author: Nicolas Louis Guillemot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-07 22:46:50

Piense en OpenGL como nada más que comandos que lo preparan para la salida a la ventana con la que está trabajando actualmente.

Hay dos comandos con OpenGL que ni siquiera los tutoriales de NEHE te dicen la importancia de:

WglCreateContext - que toma un DC context de window device, se puede obtener desde CUALQUIER ventana, ya sea un control de usuario, un formulario de windows, una ventana GL u otra ventana de aplicación (como el bloc de notas). Esto crea un contexto de dispositivo OpenGL-se refieren a como un contexto de recursos - que más tarde se utiliza con ...

WglMakeCurrent - que toma dos parámetros, el Contexto del Dispositivo con el que está tratando (el parámetro pasado para el Contexto del Dispositivo de Windows en wglCreateContext) - y el Contexto del Recurso que devuelve.

Aprovechando SOLO estas dos cosas-aquí está mi consejo:

El tutorial de NEHE proporciona una solución que aprovecha SOLO la ventana existente y segmenta la pantalla para dibujar. Aquí está el tutorial: http://nehe.gamedev.net/tutorial/multiple_viewports/20002 /

Aprovechando glViewport tendrá que volver a dibujar en cada actualización.

Ese es un método.

Pero hay otro método menos gráfico e intenso del procesador:

Cree una ventana para cada vista aprovechando un control de usuario.

Cada ventana tiene su propio hWnd.

Obtenga el DC, procese el wglcreatecontext, y luego, en un temporizador (el mío es de 30 fotogramas por segundo), si detecta el estado cambie, luego seleccione wglMakeCurrent para esa vista y vuelva a dibujar. De lo contrario, simplemente omita la sección por completo.

Esto conserva una valiosa potencia de procesamiento, y también reduce el código de tener que administrar los cálculos de ventana y vista manualmente.

 0
Author: Q The First Timelord,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-23 19:53:56