Saya berharap seseorang dapat membantu saya memahami GLViewport dan apa yang terjadi ketika kami mengubah ukurannya
Ini akan menggambarkan kebingungan saya ....
Jadi, di sini saya punya quad yang macet di tengah layar. Jika saya memiliki GLViewport saya cocok dengan lebar dan tinggi perangkat, saya mendapatkan apa yang ada di gambar pertama (kiri). Persis seperti yang saya harapkan.
- Resolusi perangkat, 2560 x 1600
- Resolusi viewport 2560 x 1600
- Ukuran quad 200 x 200 (Catatan, gambar di atas bukan untuk skala !!! :-))
- Bentuk quad, muncul sebagai kotak
Sekarang, untuk gambar ke-2 (kanan) ...
- Resolusi perangkat, 2560 x 1600
- Resolusi viewport 2560 x 1200 (dan berpusat vertikal)
- Ukuran quad (200, 200)
- Bentuk quad, muncul sebagai persegi panjang
Pertanyaan saya adalah, mengapa quad ditampilkan sebagai persegi panjang sekarang dan bukan persegi? Saya telah mengkonfirmasi dengan mencatat bahwa quad saya berukuran 200 x 200 piksel - tentunya ukuran piksel fisiknya tetap sama? Mereka tidak bisa berubah. Jadi apa yang terjadi di sini?
Saya pikir (jelas salah) bahwa ketika saya memperbesar viewport, itu benar-benar memotong piksel.
Akan sangat menghargai jika seseorang dapat menjelaskan cara kerjanya.
Edit
Saat ini, saya mengatur viewport saya seperti ini:
width = (int) Math.min(deviceWidth, deviceHeight * 1.702127659574468);
height = (int) Math.min(deviceHeight, deviceWidth / 1.702127659574468);
ratio = width / height;
GLES20.glViewport(offsetX, offsetY, width, height);
Matrix.orthoM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
offsetX dan offsetY hanya agar ketika ada kotak surat, viewport terpusat.
sumber
glScissor
bukanglViewport
, itu hanya akan memotong piksel tanpa mengubah apa pun yang diberikan.glViewport
berperilaku lebih seperti mengubah ukuran gambar asli, daripada memotongnya; itu sebabnya itu meremas kotak Anda.Jawaban:
Untuk memahami apa yang terjadi, Anda harus memahami jalur render:
Geometri Anda (quad) awalnya didefinisikan dalam ruang dunia, anggap ini sebagai beberapa sistem koordinat global. Di dalam vertex shader yang ditransformasikan menjadi koordinat perangkat dinormalisasi (NDC), sistem koordinat virtual didefinisikan demikian, sehingga semuanya mulai -1 hingga 1 akan tertarik ke layar. Perhatikan, NDC berkisar dari -1 hingga 1 di X dan Y, dan itu benar-benar independen dari rasio aspek perangkat dan resolusi. Transformasi dari ruang dunia ke NDC dilakukan oleh model, view, dan matrix proyeksi (dalam bentuk sederhana, hanya satu matriks untuk semuanya atau geometri bahkan didefinisikan dalam NDC untuk memulainya!).
Unit rasterisasi perlu mengetahui di mana dan seberapa besar raster seharusnya dan ini adalah apa yang Anda definisikan dengan panggilan glViewport: di mana memulainya adalah dua parameter pertama, ukurannya adalah dua yang kedua. Perangkat keras kemudian akan mengkonversi dari koordinat NDC ke piksel dengan skala dan pergeseran sederhana - dan inilah yang Anda lihat dalam contoh Anda: skala pada sumbu Y.
Jadi untuk memastikan quad Anda dirender dalam rasio aspek yang benar, Anda juga perlu menyesuaikan matriks proyeksi untuk memasukkan rasio aspek yang diharapkan dari panggilan glViewport.
sumber
glFrustum
, yang tidak mencantumkan matriks persis yang dibangun oleh fungsi-fungsi ini. Matriks proyeksi umum lainnya yang Anda inginkan dibuat olehglOrtho
. Sementara semua perintah ini sudah usang, dokumen pada mereka adalah sumber yang bagus untuk beberapa matematika yang diturunkan.Dalam panggilan Anda ke glViewport Anda menentukan lebih sedikit piksel dalam lebar dan tinggi. Matriks proyeksi Anda didefinisikan dalam bentuk piksel. Itu sebabnya Anda harus menghitung matriks proyeksi baru setelah panggilan glViewport.
sumber
Untuk gambar pertama:
Kami membuat matriks proyeksi. Sebagai contoh, parameter yang digunakan adalah: Left1, Right1, Bottom1, Top1, Near1, Far1. Di sini, Aspect_Ratio_1A = (Kanan1 - Kiri1) / (Top1 - Bottom1);
Kemudian kami melakukan transformasi view port. Sebagai contoh, parameter yang digunakan adalah: Width1, Height1. (Saya tidak menyebutkan parameter shift untuk kesederhanaan). Di sini, Aspect_Ratio_1B = Width1 / Height1;
Untuk gambar kedua:
Kami membuat matriks proyeksi yang sama dengan parameter yang sama seperti sebelumnya. Jadi: Aspect_Ratio_2A = Aspect_Ratio_1A;
Kali ini transformasi port tampilan memiliki parameter yang berbeda: Width2 dan Height2. Di sini, Aspect_Ratio_2B = Width2 / Height2.
Kami perhatikan bahwa Aspect_Ratio_1B dan Aspect_Ratio_2B berbeda. Secara khusus mereka adalah:
Aspect_Ratio_1B = 2560/1600 = 1,6 Aspect_Ratio_2B = 2560/1200 = 2.13
Jadi, jika kita meringkas apa yang kita lakukan untuk kasus kedua adalah:
Kami memproyeksikan gambar ke pesawat dengan Aspect_Ratio_2A dan sebelum menunjukkannya kepada pengguna, kami menskalakannya ke Aspect_Ratio_2B. Pengguna lain meminta kami untuk mengoreksi matriks proyeksi kami sedemikian rupa sehingga Aspect_Ratio_2A = Aspect_Ratio_2B.
Kita juga dapat membaca komentar Robert beberapa kali untuk memiliki pemahaman yang lebih baik.
Juga, saya tidak bisa setuju bahwa kuad merah di gambar kedua memiliki ukuran 200 x 200 piksel ketika digambar di layar. Karena kita tahu, sebuah pixel adalah bujur sangkar, jika quad memiliki salah satu sisi lebih panjang dari yang lain, sisi yang lebih panjang membutuhkan lebih banyak pixel untuk digambar pasti. Saya, secara pribadi, tidak tahu apa itu logging, tetapi mungkin itu tidak mengembalikan ukuran piksel layar.
sumber