OpenGL: Thay đổi kích thước màn hình và glOrtho / glViewport


16

Tôi đã nghiên cứu câu hỏi này từ một số nguồn và vẫn chưa tìm thấy câu trả lời chắc chắn rằng "vâng đó là suy nghĩ đúng" hoặc "không, đây là cách nó được thực hiện."

Tôi đang cố gắng đảm bảo tính độc lập của độ phân giải với kết xuất OpenGL. Cách tôi nghĩ rằng tôi nên đi về nó, là tạo ra một phép chiếu bằng glOrthobất cứ thứ gì tôi muốn thế giới tọa độ. Ví dụ , glOrtho(-50.0, 50.0, -50.0, 50.0, 1.0, -1.0). Tiếp theo, đặt chế độ xem thành độ phân giải màn hình , tức là - glViewport(0, 0, 800, 600). Cuối cùng, bất cứ khi nào cửa sổ được định cỡ lại, hãy thực hiện cuộc gọi glViewportvới độ phân giải màn hình được cập nhật. Điều này sẽ mở rộng số liệu của bạn.

Đây có phải là cách chính xác để đảm bảo rằng các mô hình có cùng tỷ lệ không gian màn hình trên các độ phân giải khác nhau? Tôi có nên sử dụng phép chiếu bằng độ phân giải không? Tôi tìm thấy một số câu trả lời cho biết glOrthonên sử dụng độ phân giải của cửa sổ của bạn trong khi những người khác nói rằng nó nên / có thể khác.

Suy nghĩ?

Câu trả lời:


20

Những gì bạn đã mô tả là hoàn toàn đầy đủ và phù hợp để cung cấp tính độc lập giải quyết. Bất cứ điều gì bạn vẽ thực sự sẽ luôn chiếm tỷ lệ tương tự của cửa sổ của bạn.

Tuy nhiên, nếu bạn không làm gì hơn thế, bạn sẽ gặp vấn đề về tỷ lệ khung hình . Ví dụ: với các số bạn đã viết, nếu bạn vẽ một vòng tròn, nó sẽ bị đè bẹp - rộng hơn chiều cao, vì tỷ lệ ngang của bạn là 800 / (50 + 50) = 8 và tỷ lệ dọc của bạn là 600 / (50+ 50) = 6.

Không thể có bất kỳ giải pháp tự động cho vấn đề này ; bạn sẽ phải chọn kết quả đồ họa nào bạn muốn và xem xét ảnh hưởng của nó đến lối chơi. Một số ví dụ phổ biến:

  • Trong trò chơi 3D chiếu phối cảnh không có HUD, giải pháp đơn giản thông thường (có sẵn trong OpenGL như một phần của gluPerspective) là sửa trường nhìn của phép chiếu so với kích thước dọc . Điều này có nghĩa là trong một trò chơi như vậy, nếu bạn thay đổi kích thước cửa sổ theo chiều ngang, bạn sẽ thấy ít nhiều cảnh và phần giữa của hình ảnh sẽ không thay đổi gì cả.

    Ý tưởng tương tự cũng có thể được áp dụng cho chế độ xem 2D / 2.5D.

    (Lưu ý rằng điều này cho phép người chơi mở rộng trường nhìn của họ theo chiều ngang bằng cách tạo một cửa sổ rộng nhưng không cao. Điều này có thể không mong muốn trong một trò chơi nhiều người chơi cạnh tranh.)

  • Nếu bạn có đồ họa lấp đầy khung nhìn với tỷ lệ khung hình cố định (ví dụ: bản đồ 2D không cuộn hoặc viền trang trí) hoặc nếu bạn không thể thay đổi bố cục, thì bạn phải làm gì đó như có hai thanh màu đen trên hai các bên để lấp đầy không gian chưa sử dụng.

    Hoặc bạn có thể tạo đồ họa có vật liệu phụ phù hợp theo chủ đề xung quanh các cạnh mà chúng có thể được cắt để phù hợp với màn hình mà không làm hại trò chơi.

  • Nếu bạn có HUD ở trên cùng của đồ họa khác, bạn có thể quyết định rằng mỗi phần tử HUD được cố định vào một phần của cửa sổ (trên cùng bên trái, dưới cùng ở giữa, v.v.) và tính tọa độ của nó; 'độ giãn' của việc thay đổi tỷ lệ khung hình được hấp thụ bởi 'khoảng trắng' giữa các yếu tố HUD.

Đối với toán học cụ thể của vấn đề, cho rằng bạn đang thực hiện độc lập độ phân giải, tất cả những gì bạn cần bắt đầu là tỷ lệ khung hình, một con số duy nhất : width / height. Ví dụ, nếu cửa sổ là hình vuông thì nó sẽ là 1; nếu là 800 x 600 thì sẽ là 800/600 = 4/3 = 1.333̅.

Ví dụ: giả sử bạn muốn chiếu hình chính tả mà bạn đã viết để có thêm không gian ở bên trái và bên phải nếu cửa sổ được mở rộng. Bạn có thể làm điều đó như thế này:

float aspect = width / height;
glViewport(0, 0, width, height);
glOrtho(-50.0 * aspect, 50.0 * aspect, -50.0, 50.0, 1.0, -1.0);

Điều này đảm bảo rằng, đối với các cửa sổ ít nhất là rộng bằng chiều cao, mọi thứ bạn vẽ với tọa độ x và y trong khoảng -50 đến 50 sẽ hiển thị.

Mặt khác, nếu cửa sổ hẹp hơn chiều cao, phạm vi -50 đến 50 sẽ bị cắt. Giả sử bạn muốn đảm bảo rằng nó luôn hiển thị (để nội dung của bạn ở kích thước tối đa nếu cửa sổ là hình vuông, nhưng nhỏ hơn); trong trường hợp đó, bạn chỉ cần làm điều tương tự với chiều cao thay vì chiều rộng.

float aspect = width / height;
glViewport(0, 0, width, height);
if (aspect >= 1.0)
  glOrtho(-50.0 * aspect, 50.0 * aspect, -50.0, 50.0, 1.0, -1.0);
else
  glOrtho(-50.0, 50.0, -50.0 / aspect, 50.0 / aspect, 1.0, -1.0);

Lưu ý rằng trong trường hợp thứ hai, chúng tôi chia thay vì nhân. Điều này chỉ đơn giản là vì chúng tôi đã tính tỷ lệ khung hình width / heightthay vì height / width; hãy đối ứng nếu bạn thấy dễ hiểu hơn theo cách đó.

Một lần nữa, đây không phải là cách duy nhất để quản lý tỷ lệ khung hình; đây chỉ là một điều rất đơn giản để đảm bảo rằng nội dung của bạn không bị cắt xén cũng không bị cắt. Chỉ ra những gì bạn muốn xảy ra khi cửa sổ của bạn rộng, cao hoặc bất cứ điều gì; sau đó làm việc ra toán học của nó


Cảm ơn bạn đã phản hồi sâu sắc RẤT. Trả lời câu hỏi của tôi quá đủ.
Chris Henderson
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.