Мне нужно показать один и тот же объект в OpenGL в двух разных видовых экранах, например, один с использованием ортографической проекции, а другой с использованием перспективы. Чтобы сделать это, нужно ли снова рисовать объект после каждого вызова glViewport()?
Несколько видовых экранов в OpenGL
Ответ 1
Nehe имеет хороший учебник о том, как это сделать, и его сайт, как правило, хороший ресурс для вопросов OpenGL.
Ответ 2
// 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);
Ответ 3
да,
и вы также должны изменить настройки scissor, чтобы иметь чистое разделение между двумя представлениями, если они находятся в одном окне.
Ответ 4
Минимальный пример
Как и этот ответ, но более прямой и компилируемый. Выход:
Код:
#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.
Ответ 5
Подумайте, что OpenGL является не чем иным, как командами, которые готовят вас к выводу в окно, в котором вы в настоящее время работаете.
Есть две команды с OpenGL, которые даже в учебниках NEHE не говорят о важности:
wglCreateContext - который принимает контекст оконного устройства DC, может быть получен из любого окна - будь то пользовательский элемент управления, форма окна, окно GL или другое окно приложения (например, блокнот). Это создает контекст устройства OpenGL - они называются контекстом ресурса, который вы позже используете с...
wglMakeCurrent - который принимает два параметра - Контекст устройства, с которым вы имеете дело (параметр, переданный для контекста устройства Windows в wglCreateContext) - и возвращаемый контекст ресурса.
Использование ТОЛЬКО этих двух вещей - вот мой совет:
Учебник NEHE предоставляет решение, которое использует ТОЛЬКО существующее окно и сегментирует экран для рисования. Здесь учебник: http://nehe.gamedev.net/tutorial/multiple_viewports/20002/
Используя glViewport, вам нужно будет повторно рисовать каждое обновление.
Этот метод.
Но есть другой - менее графический и процессорный интенсивный метод:
Создайте окно для каждого вида, используя пользовательский элемент управления.
Каждое окно имеет собственный hWnd.
Получите DC, обработайте wglcreatecontext, а затем на таймере (мой 30 кадров в секунду), если вы обнаружите изменение состояния, затем выберите wglMakeCurrent для этого представления и перерисуйте. В противном случае просто пропустите раздел целиком.
Это сохраняет значительную вычислительную мощность, а также уменьшает код от необходимости вручную управлять вычислениями окна и просмотра.
Ответ 6
В GL 4 вы можете отображать многие видовые экраны в одном проходе рендеринга. См. ARB_viewport_array и соответствующие понятия.