Bagaimana saya bisa mencegah viewport dari peregangan / distorsi?

13

Pada dasarnya, saya ingin tahu bagaimana saya bisa menghapus distorsi atau peregangan gambar yang diberikan ketika ukuran viewport / jendela berubah.

Gambar-gambar berikut menunjukkan distorsi / peregangan yang saya bicarakan:

Gambar Asli (Jendela Kotak)

Tidak ada distorsi

Gambar Terdistorsi / Membentang (Jendela Persegi Panjang)

Dengan Distorsi

Idealnya, gambar kedua harus menampilkan bola tanpa peregangan horizontal, dan akan mengekspos lebih banyak adegan kepada pengguna untuk menjelaskan ukuran jendela yang lebih besar.

Bagaimana ini bisa dilakukan?

Saya bekerja dengan OpenGL untuk membuat gambar, dan saya menggunakan proyeksi perspektif melalui panggilan:

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60, window.width/window.height, 0.01f, 100.0f)

Aspek-rasio width/heightsesuai dengan semua dokumen / tutorial yang saya temui, jadi saya tidak berharap itu salah. Namun, kecurigaan saya adalah bahwa itu mempengaruhi masalah peregangan.


Setelah dipikirkan

Sejujurnya, ketika saya memikirkan masalah ini lebih jauh, saya akan percaya bahwa solusinya melibatkan hubungan proporsional langsung antara sudut fovy (bidang pandang dalam arah y) dan aspek-rasio.

Proyeksi Perspektif

Menggunakan gambar di atas sebagai referensi, jika lebar tumbuh (menyebabkan bentangan horizontal), tampaknya sangat masuk akal bahwa sudut fovy harus meningkat untuk menyebabkan bentangan vertikal yang 'memperbaiki' proporsionalitas gambar yang diberikan.

Demikian juga, penurunan lebar membutuhkan penurunan sudut fovy.

Memperbarui:

Jadi, setelah menyelidiki ini lebih lanjut, saya telah memutuskan untuk mengubah cara saya mengatur frustasi menonton seperti ini:

gluPerspective(60 * (float)window.width/window.height, (float)window.width/window.height, 0.01f, 100.0f)

Dan harapan saya benar, yang menyelesaikan masalah proporsionalitas. Namun, itu tidak mencapai hasil yang saya inginkan. Ketika lebar jendela meningkat, gambar yang diberikan menjadi lebih kecil (tetapi bola memang melingkar). Sebaliknya, bola seharusnya tidak mengubah ukuran sama sekali; hanya jumlah adegan yang ditampilkan yang harus berubah.

Nicholas Miller
sumber

Jawaban:

14

Faktanya, pertanyaan awal adalah 1 dibuang dari solusi.

Kode Asli

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60, window.width/window.height, 0.01f, 100.0f)

Kode Tetap

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60, (float)window.width/window.height, 0.01f, 100.0f)

Masalahnya adalah itu window.widthdan window.heightbilangan bulat, yang menyebabkan aspek-rasio menjadi hasil dari divisi bilangan bulat.

Casting salah satu dimensi ke float menyebabkan hasilnya menggunakan divisi floating-point sebagai gantinya.

Karena aspek-rasio sekarang benar, tidak ada lagi peregangan seperti yang terlihat di posting asli.

EDIT: Kode dalam posting asli (dan jawabannya) hanyalah kode semu untuk panggilan ke GPU; program aktual yang digunakan untuk menampilkan gambar di atas ditulis dalam Java. Bagi mereka yang tidak bekerja dengan Java, saya belum meneliti untuk melihat apakah divisi integer / floating-point diimplementasikan dengan cara yang sama. Apapun, solusinya adalah memastikan bahwa aspek-rasio memang dihitung dengan benar.

Nicholas Miller
sumber