Nhiều khung nhìn với OpenGL hiện đại?


9

Tôi sử dụng SDL2 .

Hiện tại shader duy nhất của tôi có ma trận MVP và biến đổi các điểm với nó.

Tôi tính toán ma trận Chế độ xem và Chiếu của mình cho máy ảnh có GLM:

glm::lookAt(pos, pos + forward, up);
glm::perspective(fov, aspectRatio, zNear, zFar);

Tôi đã tìm kiếm nó, nhưng tôi chỉ có thể tìm thấy triển khai di sản của nhiều chế độ xem.

Nếu tôi tạo ví dụ cho 4 camera và giả sử rằng tất cả chúng đều giống nhau , ngoại trừ mỗi camera có một phần tư màn hình khác nhau để hiển thị. (Vì vậy, tôi muốn 4 khung nhìn có cùng nội dung)

Tôi có thể làm cái này như thế nào? Xin lỗi nếu tôi không cung cấp đủ thông tin, vui lòng hỏi.


Bạn có đặc biệt tìm cách thực hiện kết xuất 4 lần hay chỉ để kết xuất một lần và hiển thị kết quả ở 4 vị trí khác nhau?
trichoplax

Thực hiện kết xuất 4 lần. Những gì tôi viết chỉ là một ví dụ đơn giản, ví dụ tôi muốn camera chính kết xuất một chiếc ô tô ở cửa sổ đầy đủ, và một camera khác khiến chiếc xe từ một bên trong một hình vuông nhỏ ở một trong các góc.
Tudvari

Nếu tôi hiểu điều này một cách chính xác, do đó bạn cần phải chia cửa sổ của mình thành 4 phần và trong mỗi phần sẽ hiển thị các phần khác của cảnh như vậy ?
narthex

Có, nhưng không đúng 4 phần. Tôi muốn nó phải linh hoạt. Kích thước linh hoạt và vị trí của hình chữ nhật khung nhìn.
Tudvari

Câu trả lời:


8

Kết xuất với các khung nhìn khác nhau (các bộ phận) của cùng một màn hình có thể được thực hiện như sau:

Ví dụ: chia màn hình thành bốn phần và hiển thị cùng một cảnh bốn lần cho mỗi góc với các đồng phục khác nhau và chế độ xem khác nhau:

bindFramebuffer();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
scene->setConstPerFrameUniforms();

//left bottom
glViewport(0, 0, WindowWidth*0.5, WindowHeight*0.5);
scene->setVarPerFrameUniforms(1);
scene->draw();

//right bottom
glViewport(WindowWidth*0.5, 0, WindowWidth*0.5, WindowHeight*0.5);
scene->setVarPerFrameUniforms(2);
scene->draw();

//left top
glViewport(0, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene->setVarPerFrameUniforms(3);
scene->draw();

//right top
glViewport(WindowWidth*0.5, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene->setVarPerFrameUniforms(4);
scene->draw();

glViewport(0, 0, WindowWidth, WindowHeight); //restore default

Vì vậy, với glViewPort () tôi có thể xác định nơi tôi muốn vẽ tiếp theo và với glBlendFunc tôi có thể xác định cách GPU sẽ pha trộn các khu vực chồng chéo (bộ đệm khung) với nhau. Tôi có đúng không?
Tudvari

1
Vâng, bạn có thể tự do tham gia điều đó. Theo tham số viewportlà x, y của góc dưới bên trái của khối và chiều rộng, chiều cao của khối. Với sự pha trộn bạn có thể thử nghiệm.
narthex

1
Tại sao phải pha trộn? Làm thế nào nó liên quan đến câu hỏi?
Raxvan

3
Bạn không cần pha trộn hoặc nhiều bộ đệm khung. Kết xuất sẽ không ghi vào bất kỳ pixel nào bên ngoài hình chữ nhật glViewport hiện tại, do đó bạn chỉ cần thiết lập và vẽ lần lượt từng khung nhìn. BTW, bạn cũng có thể sử dụng kiểm tra cắt kéo để hạn chế xóa đối với một hình chữ nhật nhất định, trong trường hợp bạn muốn chế độ xem chồng chéo.
Nathan Reed

2
Pha trộn không có gì để làm với điều này và làm cho câu trả lời khó hiểu hơn. Việc thiết lập các khung nhìn là tất cả những gì cần thiết
mặc định

10

Nếu bạn đang viết Vertex / Fragment Shader của riêng bạn, có một khả năng bổ sung khác để làm điều này. Nó phức tạp hơn nhiều nhưng có thể hữu ích cho bạn và / hoặc người khác. Ngoài ra, nó tăng tốc toàn bộ quá trình vẽ vì nó chỉ sử dụng một lệnh gọi đến lệnh vẽ. Số lượng Viewports tối đa được xác định bởi GL_MAX_VIEWPORTS và thường là 16.

Kể từ OpenGL 4.1, phương thức glViewportArrayv tồn tại. Nó có thể định nghĩa một loạt các Viewports. Các Viewports được tạo bằng phương pháp này có một chỉ mục được gán.

Chỉ mục này có thể được sử dụng trong Vertex Shader để đặt Viewport mà cảnh được hiển thị. (Bạn phải bao gồm tiện ích mở rộng " ARB_shader_viewport_layer_array " trong mã shader)

Trong trường hợp của bạn, tôi sẽ đề nghị làm như sau:


" Chỉ mục này có thể được sử dụng trong Vertex Shader để đặt Viewport mà cảnh được hiển thị. " Không, không thể. Chà, không phải không có phần mở rộng ARB_shader_viewport_layer_array hoặc tương đương AMD. Không ai trong số đó là tiêu chuẩn trong GL 4.5. Có lẽ bạn đang nghĩ về Geometry Shader.
Nicol Bolas

@Nicol, Cảm ơn vì gợi ý này! Tôi quên đề cập rằng bạn phải bao gồm phần mở rộng. Tôi sẽ chỉnh sửa câu trả lời của tôi.
Christian_B

5

Đây là bản sao câu trả lời của @ narthex, ngoại trừ chỉ có các khung nhìn vì đó là tất cả những gì bạn cần. Tôi không chắc tại sao bộ đệm / bộ trộn khung được đưa vào câu trả lời của anh ấy.

//left bottom
glViewport(0, 0, WindowWidth*0.5, WindowHeight*0.5);
scene->draw();

//right bottom
glViewport(WindowWidth*0.5, 0, WindowWidth*0.5, WindowHeight*0.5);
scene->draw();

//left top
glViewport(0, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene->draw();

//right top
glViewport(WindowWidth*0.5, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene->draw();

glViewport(0, 0, WindowWidth, WindowHeight); //restore default

0

Đây đều là những câu trả lời hay, nhưng vẫn có một cách khác: (Không phải lúc nào cũng vậy sao?)

Do sự phổ biến ngày càng tăng của thực tế ảo, những người ở OculusVR đã phát triển một bộ ba phần mở rộng "Multiview" được gọi là:

  1. OVR_multiview ,
  2. OVR_multiview2 , &
  3. OVR_multiview_multisampling_Vnder_to lòng

Các tiện ích mở rộng này cho phép nhiều chế độ xem của cùng một cảnh được hiển thị trong một lệnh gọi rút thăm duy nhất, loại bỏ sự dư thừa của việc hiển thị cùng một cảnh trong cùng một trạng thái khỏi quan điểm của mỗi mắt. Mặc dù được tạo ra cho mục đích VR, nhà phát triển không nhất thiết chỉ giới hạn ở hai chế độ xem. Thay vào đó, tiện ích mở rộng này cho phép có nhiều lượt xem như MAX_VIEWS_OVR chỉ định.

Trước khi sử dụng các tiện ích mở rộng này, nhà phát triển nên kiểm tra sự hỗ trợ của chúng trong trình điều khiển đồ họa của người dùng bằng cách thêm mã sau đây:

const GLubyte* extensions = GL_CHECK( glGetString( GL_EXTENSIONS ) );
char * found_extension = strstr( (const char*)extensions, "GL_OVR_multiview" );
if (NULL == found_extension)
{
     exit( EXIT_FAILURE );
}

Từ đó, vấn đề thiết lập bộ đệm khung của bạn để sử dụng tính năng này:

glFramebufferTextureMultisampledMultiviewOVR = PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEDMULTIVIEWOVR(eglGetProcAddress("glFramebufferTextureMultisampleMultiviewOVR"));
glFramebufferTextureMultisampledMultiviewOVR (GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureID, 0, 0, 2);

và tương tự như vậy trong shader:

#version 300 es
#extension GL_OVR_multiview : enable

layout(num_views = 2) in;
in vec3 vertexPosition;
uniform mat4 MVP[2];

void main(){
    gl_Position = MVP[gl_ViewID_OVR] * vec4(vertexPosition, 1.0f);
}

Trong một ứng dụng giới hạn CPU, tiện ích mở rộng này có thể giảm đáng kể thời gian kết xuất, đặc biệt là với các cảnh phức tạp hơn :

Thời gian CPU tương đối giữa multiview và âm thanh nổi thông thường.  Càng nhỏ càng tốt, với số lượng hình khối trên trục x và thời gian tương đối trên trục y.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.