Как использовать несколько видовых экранов в OpenGL?
Мне нужно показать один и тот же объект в OpenGL в двух разных иллюминаторах, например, один с использованием ортографической проекции, а другой с помощью перспективы. Для этого мне нужно снова нарисовать объект после каждого вызова glViewport ()?
6 ответов
Nehe имеет хороший учебник о том, как это сделать, и его сайт, как правило, хороший ресурс для вопросов OpenGL.
// 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);
да
и вы также должны изменить настройки ножниц, чтобы иметь чистое разделение между двумя видами, если они находятся в одном окне.
минимальный runnable пример
аналогично ответ, но более прямой и компилируемые. Вывод:
код:
#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;
}
компиляция с помощью:
gcc -lGL -lGLU -lglut main.c
протестировано на OpenGL 4.5.0 NVIDIA 352.63, Ubuntu 15.10.
TODO: я думаю, что в современном OpenGL 4 Вы должны просто визуализировать текстуры, а затем разместить эти текстуры ортогонально на экране, см. Это как отправную точку: http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/
в GL 4 Вы можете визуализировать многие видовые экраны за один проход рендеринга. См.ARB_viewport_array и связанные с ними понятия.
подумайте о OpenGL как не что иное, как команды, которые готовят вас к выходу в окно, с которым вы сейчас работаете.
есть две команды с OpenGL, которые даже учебники NEHE не говорят вам о важности:
wglCreateContext-который принимает контекст оконного устройства DC, может быть получен из любого окна - будь то пользовательский элемент управления, форма windows, окно GL или другое окно приложения (например, блокнот). Это создает контекст устройства OpenGL - они относятся к контексту ресурса, который вы позже используете ...
wglMakeCurrent-который принимает два параметра, контекст устройства, с которым вы имеете дело (параметр, переданный для контекста устройства Windows в wglCreateContext) - и контекст ресурса, который возвращает.
используя только эти две вещи - вот мой совет:
учебник NEHE предоставляет решение, которое использует только существующее окно и сегментирует экран для рисования. Это место учебник: http://nehe.gamedev.net/tutorial/multiple_viewports/20002/
используя glViewport, вам нужно будет повторно использовать каждое обновление.
Это один из методов.
но есть еще один-менее графически и процессор интенсивный метод:
создайте окно для каждого представления, используя пользовательский элемент управления.
каждое окно имеет свой собственный hWnd.
получить DC, обработать wglcreatecontext, а затем на таймер (мой-30 кадров в секунду), если вы обнаружите изменение состояния, выберите wglMakeCurrent для этого представления и перерисуйте. В противном случае, просто пропустите раздел полностью.
это сохраняет ценную вычислительную мощность, а также уменьшает код от необходимости управлять вычислениями окна и окна просмотра вручную.