Saya mencoba memahami sistem koordinat OpenGL. Namun, beberapa tutorial mengatakan sistem koordinat default adalah kidal (lihat http://www.c-sharpcorner.com/UploadFile/jeradus/OpenGLBasics11172005014307AM/OpenGLBasics.aspx ) dan yang lainnya mengatakan itu adalah tangan kanan (lihat http: // www .falloutsoftware.com / tutorials / gl / gl0.htm ). Yang mana yang benar? Saya memahami bahwa kita dapat mengubah satu sama lain dengan pencerminan tetapi saya ingin mengetahui koordinat default.
opengl
coordinates
341008
sumber
sumber
Jawaban:
Ada kebingungan di sini.
OpenGL digunakan dengan benar di ruang objek dan ruang dunia.
Tapi di ruang jendela (alias ruang layar) kita tiba-tiba kidal .
Bagaimana ini bisa terjadi ?
Cara kita beralih dari tangan kanan ke kidal adalah entri penskalaan z negatif dalam matriks proyeksi
glOrtho
atauglFrustum
. Penskalaan z sebesar -1 (dengan membiarkan x dan y sebagaimana adanya) memiliki efek mengubah penggunaan tangan sistem koordinat.Untuk glFrustum,
jauh dan dekat seharusnya positif, dengan jauh > dekat . Katakanlah jauh = 1000 dan dekat = 1. Maka C = - (1001) / (999) = -1.002.
Lihat di sini untuk detail dan diagram lebih lanjut.
Dari perspektif ortografik , glOrtho menghasilkan matriks seperti ini:
Di sini, kiri , kanan , bawah dan atas hanyalah koordinat untuk vertikal kiri , vertikal kanan , horizontal bawah , bidang kliping horizontal atas (resp) .
Pesawat dekat dan jauh , bagaimanapun, dispesifikasikan secara berbeda . The dekat parameter didefinisikan sebagai
dan jauh:
Di sini kami memiliki volume tampilan kanonik biasa
Karena pengali z adalah (-2 / (jauh-dekat)), tanda minus secara efektif menskalakan z dengan -1 . Ini berarti bahwa "z" diputar ke kiri selama transformasi tampilan, tanpa sepengetahuan kebanyakan orang karena mereka hanya bekerja di OpenGL sebagai sistem koordinat "tangan kanan".
Jadi, jika Anda menelepon
Maka NEAR PLANE berada 10 unit di depan Anda . Kamu dimana Mengapa, di asalnya, dengan sumbu x di kanan Anda, sumbu y di atas kepala Anda, dan hidung Anda mengarah ke bawah sumbu z negatif (itu defaultnya "Secara default, kamera terletak di titik asal , menunjuk ke bawah sumbu z negatif, dan memiliki vektor atas (0, 1, 0). " ). Jadi bidang terdekat berada pada z = -10. Bidang jauh berada 10 unit di belakang Anda, pada z = + 10 .
sumber
gluLookAt
komputasi tidak ada hubungannya dengan mengubah penggunaan ruang koordinat, begitulah cara matriks ini dihitung (dan pada kenyataannya + z memang "mundur" di ruang tangan kanan).gluLookAt
tidak lain adalah menghitung transformasi benda kaku biasa (rotasi + terjemahan) di ruang tangan kanan. Ini adalah matriks proyeksi yang digunakan oleh pipa fungsi tetap (dan biasanya oleh shader juga) yang melakukan perubahan kidal aktual dalam negasinya terhadap komponen-z, seperti yang telah Anda catat dalam jawaban Anda.gluLookAt
, tidak akan ada perubahan basis, sementaragluLookAt
itu? Jelas tidak (karena Anda mungkin tahu bahwa tidak "semua orang" menggunakangluLookAt
untuk penghitungan matriks tampilan), karena seperti yang seharusnya Anda ketahuigluLookAt
tidak melakukan apa pun selain sekumpulan panggilan rotasi dan terjemahan (bahkan mereka menyamar sebagai perubahan istilah "tingkat tinggi " dari dasar " ) tanpa refleksi sama sekali.Secara default, Koordinat Perangkat yang Dinormalisasi adalah kidal.
GlDepthRange secara default [0, 1] (dekat, jauh) membuat titik sumbu + z ke layar dan dengan + x ke kanan dan + y ke atas adalah sistem tangan kiri.
Mengubah rentang kedalaman menjadi [1, 0] akan membuat sistem tidak bekerja dengan baik.
Mengutip jawaban sebelumnya dari Nicol : (pemogokan adalah pekerjaan saya, dijelaskan di bawah)
Saya memang menyerang satu bagian karena menyimpang dari temuan saya.
Baik mengubah DepthRange atau DepthFunc dan menggunakan ClearDepth (0) berfungsi tetapi saat menggunakan keduanya, keduanya membatalkan satu sama lain kembali ke sistem kidal.
sumber
HANYA NDC
Anda seharusnya hanya memperhatikan bahwa OpenGL hanya mengetahui NDC! dan itu adalah sistem koordinat kidal.
Apa pun sistem koordinat yang Anda gunakan - sistem koordinat sumbu tangan kiri atau kanan - semua perlu dicerminkan ke NDC. Jika Anda suka, Anda benar-benar dapat menangani ruang dunia sebagai sistem koordinat kidal.
Mengapa kita biasanya menggunakan sistem koordinat tangan kanan di dunia-ruang?
Saya pikir itu konvensional. Itu terjadi begitu saja. Mungkin hanya ingin membedakan dengan DirectX.
sumber
Buku "Panduan Pemrograman WebGl" oleh Kouichi Matsuda menghabiskan hampir sepuluh halaman tentang "WebGl / OpenGl: Left or Right Handed?"
Menurut buku itu:
Dalam praktiknya, kebanyakan orang menggunakan sistem tangan kanan
OpenGl sebenarnya adalah sistem kidal secara internal
Secara internal, sebenarnya bukan keduanya. Di bagian paling bawah OpenGl tidak peduli dengan nilai z. Urutan Anda menggambar sesuatu menentukan apa yang digambar di atas (gambar segitiga dulu, lalu segi empat, segi empat menimpa segitiga).
Saya tidak sepenuhnya setuju dengan "bukan keduanya", tetapi itu mungkin pertanyaan filosofis.
sumber
The order in which you draw things determines what is drawn on top (draw a triangle first, then a quad, the quad overrides the triangle).
Ini benar, jika tidak ada pengujian mendalam. Dengan adanya pengujian kedalaman, nilai z dari sebuah fragmen dibandingkan dengan nilai dalam buffer kedalaman, dan fragmen tersebut akan dibuang jika gagal dalam pengujian kedalaman, sehingga quad mungkin atau mungkin tidak menimpa segitiga tergantung pada kedalamannya dan fungsi kedalaman digunakan.Opengl jelas kidal. Anda melihat banyak tutorial yang menyatakan sebaliknya karena mereka meniadakan nilai z dalam matriks proyeksi. Ketika simpul terakhir dihitung di dalam shader simpul, itu mengubah simpul yang Anda lewati dari sisi-klien (coord kanan) ke tangan kiri, dan simpul kemudian akan diteruskan ke shader geometri dan shader fragmen. Jika Anda menggunakan sistem koordinat kanan di sisi klien, Opengl tidak peduli. Ia hanya mengetahui sistem koordinat yang dinormalisasi, yang kidal.
Sunting: Jika Anda tidak mempercayai saya, cukup bereksperimen di shader vertex Anda dengan menambahkan matriks terjemahan, dan Anda dapat dengan mudah melihat apakah Opengl kidal atau tidak.
sumber
Dengan menggunakan fungsi proyeksi dan transformasi bawaan OpenGL, mengamati gerakan di layar mengikuti aturan sistem koordinat tangan kanan . Misalnya, jika sebuah benda di depan pandangan Anda diterjemahkan ke arah z positif, benda tersebut akan bergerak ke arah Anda.
Penyangga kedalaman justru sebaliknya, dan di sinilah NDC (Koordinat Perangkat Normalisasi) berperan. Jika meneruskan GL_LESS ke glDepthFunc berarti piksel akan digambar ketika lebih dekat dengan Anda daripada yang sudah ada di buffer kedalaman, piksel dianggap hidup dalam sistem koordinat kidal .
Ada satu sistem koordinat lagi, dan itu adalah viewport! Sistem koordinat viewport sedemikian rupa sehingga + x mengarah ke kanan, dan + y mengarah ke bawah. Saya pikir pada titik ini sifat kidal diperdebatkan karena kita hanya berurusan dengan x, y pada saat ini.
Terakhir, gluLookAt di bawah kap harus meniadakan vektor tampilan. Karena matematika mengasumsikan sebuah vektor menunjuk ke arah positif ke arah objek yang dilihatnya, dan kamera melihat ke bawah -z, vektor pandang harus dinegasikan sehingga sejajar dengan kamera.
Sesuatu untuk dikunyah. Tidaklah masuk akal untuk menyebut arah z dari sistem koordinat tangan kanan sebagai vektor maju :). Saya pikir Microsoft menyadari hal ini ketika mereka merancang Direct3D.
sumber