2009-04-07 40 views
27

Tôi cần hiển thị cùng một đối tượng trong OpenGL trong hai chế độ xem khác nhau, ví dụ, một đối tượng sử dụng phép chiếu ortographic và một đối tượng sử dụng phối cảnh khác. Để làm điều này, tôi có cần vẽ lại đối tượng sau mỗi lần gọi tới glViewport() không?Cách sử dụng nhiều chế độ xem trong OpenGL?

Trả lời

12

Nehe có hướng dẫn tốt về cách thực hiện việc này và trang web của anh thường là tài nguyên tốt cho câu hỏi OpenGL.

+3

Đối với tôi, bài viết được liên kết đề xuất câu trả lời "có, [bạn phải]" - nhưng tác giả của nó dường như * muốn * vẽ thứ gì đó khác nhau trên mỗi chế độ xem. Do đó, tôi vẫn đánh giá cao nếu ai đó xác nhận bằng những từ đơn giản nếu có "có, bạn phải vẽ lại đối tượng trong mỗi chế độ xem" hoặc "không, bạn không phải - xem " – akavel

+0

Khi tôi hiểu được đường dẫn OpenGL , để vẽ lại một thứ gì đó từ một phép biến đổi khác, các đỉnh phải được truyền lại vào đường ống với phép biến đổi mới, vì vậy vâng bạn sẽ phải vẽ lại chắc chắn. – user1294021

3

có,

và bạn cũng nên thay đổi các thiết lập kéo để có một tách sạch giữa hai quan điểm nếu họ đang ở trong cùng một cửa sổ.

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); 
0

Hãy suy nghĩ về OpenGL như không có gì ngoài các lệnh chuẩn bị cho bạn xuất ra cửa sổ bạn hiện đang làm việc.

Có hai lệnh với OpenGL rằng hướng dẫn thậm chí Nehe của không cho bạn biết tầm quan trọng của:

wglCreateContext - mà phải mất một bối cảnh thiết bị cửa sổ DC, có thể được lấy từ bất kỳ cửa sổ - cho dù đó là một điều khiển người dùng, dạng cửa sổ, cửa sổ GL hoặc cửa sổ ứng dụng khác (như notepad). Điều này tạo ra bối cảnh thiết bị OpenGL - chúng đề cập đến bối cảnh tài nguyên - mà sau này bạn sử dụng với ...

wglMakeCurrent - có hai tham số, bối cảnh thiết bị mà bạn đang xử lý (tham số được truyền cho Windows) Ngữ cảnh thiết bị trong wglCreateContext) - và Ngữ cảnh tài nguyên trả về.

Tận CHỈ hai điều này - đây là lời khuyên của tôi:

hướng dẫn Nehe cung cấp một giải pháp đó thúc đẩy các cửa sổ hiện tại CHỈ và phân khúc màn hình để vẽ. Dưới đây là hướng dẫn: http://nehe.gamedev.net/tutorial/multiple_viewports/20002/

Tận dụng glViewport bạn sẽ cần phải vẽ lại trên mọi bản cập nhật.

Đó là một phương pháp.

Nhưng có phương pháp khác - ít đồ họa và xử lý mạnh hơn:

Tạo cửa sổ cho mỗi chế độ xem bằng cách tận dụng điều khiển người dùng.

Mỗi cửa sổ có hWnd riêng.

Lấy DC, xử lý wglcreatecontext, và sau đó, trên bộ đếm thời gian (tôi là 30 khung hình giây), nếu bạn phát hiện thay đổi trạng thái, sau đó chọn wglMakeCurrent cho chế độ xem đó và vẽ lại. Nếu không, chỉ cần bỏ qua phần hoàn toàn.

Điều này bảo tồn sức mạnh xử lý có giá trị và cũng làm giảm mã do phải quản lý các tính toán cửa sổ và chế độ xem theo cách thủ công.

3

Minimal Runnable dụ

Tương tự như this answer, nhưng trực tiếp hơn và biên dịch được.Output:

Code:

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

Compile với:

gcc -lGL -lGLU -lglut main.c 

Thử nghiệm trên OpenGL 4.5.0 NVIDIA 352,63, Ubuntu 15.10.

TODO: Tôi nghĩ rằng trong OpenGL hiện đại 4 bạn chỉ nên trả cho texture, và sau đó đặt những textures orthogonaly trên màn hình, coi đây là một điểm khởi đầu: http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/

+0

Không đáng để giải thích? –

+0

@TinyGiant Cảm ơn phản hồi. Phần nào không rõ ràng? Từ mã, rất dễ thấy rằng 'glViewport' được gọi nhiều lần. –

0

Trong GL 4 bạn có thể trả cho nhiều viewports trong một lần hiển thị. Xem ARB_viewport_array và các khái niệm liên quan.

Các vấn đề liên quan