如何在OpenGL中使用多个视口?

时间:2009-04-07 15:37:30

标签: opengl viewport

我需要在两个不同的视口中在OpenGL中显示相同的对象,例如,一个使用ortographic投影,另一个使用透视。为了做到这一点,我需要在每次调用glViewport()之后再次绘制对象吗?

6 个答案:

答案 0 :(得分:13)

Nehe有一个很好的教程如何做到这一点,他的网站通常是OpenGL问题的好资源。

答案 1 :(得分: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);

答案 2 :(得分:3)

是,

并且您还应该更改剪刀设置,以便在两个视图位于同一窗口中时保持清晰的分离。

答案 3 :(得分:3)

最小可运行示例

this answer类似,但更直接且可编辑。输出:

代码:

#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/

答案 4 :(得分:1)

在GL 4中,您可以在一个渲染过程中渲染到许多视口。请参阅ARB_viewport_array及相关概念。

答案 5 :(得分:0)

将OpenGL视为准备输出到您当前正在使用的窗口的命令。

使用OpenGL有两个命令,即使是NEHE的教程也没有告诉你重要性:

wglCreateContext - 它采用窗口设备上下文DC,可以从任何窗口获取 - 无论是用户控件,窗口窗体,GL窗口还是其他应用程序窗口(如记事本)。这将创建一个OpenGL设备上下文 - 它们称为资源上下文 - 您稍后将使用它...

wglMakeCurrent - 它接受两个参数,即您正在处理的设备上下文(wglCreateContext中为Windows设备上下文传入的参数) - 以及返回的资源上下文。

仅仅利用这两件事 - 这是我的建议:

NEHE的教程提供的解决方案仅利用现有窗口并将屏幕分段以进行绘制。这是教程:http://nehe.gamedev.net/tutorial/multiple_viewports/20002/

利用glViewport,您需要在每次更新时重新绘制。

这是一种方法。

但还有另一种 - 图形和处理器强度较低的方法:

通过利用用户控件为每个视图创建一个窗口。

每个窗口都拥有它自己的hWnd。

获取DC,处理wglcreatecontext,然后在计时器上(我的每秒30帧),如果检测到状态更改,则为该视图选择wglMakeCurrent并重绘。否则,只需完全跳过该部分。

这节省了宝贵的处理能力,并且还减少了必须手动管理窗口和视口计算的代码。