29

我需要在 OpenGL 中在两个不同的视口中显示相同的对象,例如,一个使用正交投影,另一个使用透视。为此,是否需要在每次调用 glViewport() 后再次绘制对象?

4

6 回答 6

13

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

于 2009-04-07T15:39:57.303 回答
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);
于 2009-08-25T09:21:27.930 回答
7

最小可运行示例

类似于这个答案,但更直接和可编译。输出:

主程序

#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 -o main.out main.c -lGL -lGLU -lglut
./main.out

我认为在现代 OpenGL 4 中,您应该只渲染纹理,然后将这些纹理正交放置在屏幕上,将此视为起点:http ://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14 -渲染到纹理/

在 OpenGL 4.5.0 NVIDIA 352.63、Ubuntu 15.10 上测试。

于 2016-03-16T22:35:13.620 回答
3

是的,

如果它们在同一个窗口中,您还应该更改剪刀设置以在两个视图之间有一个干净的分隔。

于 2009-04-07T15:54:29.047 回答
1

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

于 2017-09-07T22:46:50.500 回答
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 并重绘。否则,请完全跳过该部分。

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

于 2015-06-23T19:53:56.040 回答