Apakah sistem koordinat OpenGL kidal atau tidak?

88

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.

341008
sumber
3
Bukankah ini sepenuhnya bergantung pada bagaimana Anda menulis transformasi Anda di shader dan karena itu sepenuhnya terserah Anda?
jcoder
Hanya dua sen saya evl.uic.edu/ralph/508S98/coordinates.html , ia memiliki beberapa gambar yang cukup jelas.
rraallvv
Saya kira Anda tidak akan mempertimbangkan untuk memperbarui jawaban yang Anda terima?
Jonathan Mee

Jawaban:

133

Ada kebingungan di sini.

masukkan deskripsi gambar 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 glOrthoatau glFrustum. Penskalaan z sebesar -1 (dengan membiarkan x dan y sebagaimana adanya) memiliki efek mengubah penggunaan tangan sistem koordinat.

Untuk glFrustum,

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

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:

masukkan deskripsi gambar di sini

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

  • Dekat: Jarak ke bidang kliping kedalaman yang lebih dekat. Jarak ini negatif jika pesawat berada di belakang pemirsa.

dan jauh:

  • zFar Jarak ke bidang pemotongan yang lebih dalam. Jarak ini negatif jika pesawat berada di belakang pemirsa.

Di sini kami memiliki volume tampilan kanonik biasa

resmi

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

glOrthof(-1, 1, -1, 1, 10, -10) ; // near=10, FAR=-10,

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 .

bobobobo
sumber
1
"vektor maju dinegasikan di gluLookAt" - dapatkah Anda mengonfirmasi bahwa memang demikian? Bukan gluPerspective atau glFrustum atau glOrtho?
Kos
1
Kami tiba-tiba kidal dari ruang klip dan seterusnya bukan hanya ruang jendela.
legends2k
3
+1 untuk keseluruhan jawaban, -1 (tunggu, bukan -2) untuk "Cara kita beralih dari tangan kanan ke kidal adalah karena vektor maju dinegasikan dalam implementasi standar gluLookAt (), yang merupakan fungsinya semua orang menggunakan untuk membuat matriks tampilan. Jika Anda meniadakan vektor maju, ini memiliki efek mengubah penggunaan sistem koordinat. " , Yang hanya sampah ...
Christian Rau
2
... Meniadakan vektor maju dalam gluLookAtkomputasi tidak ada hubungannya dengan mengubah penggunaan ruang koordinat, begitulah cara matriks ini dihitung (dan pada kenyataannya + z memang "mundur" di ruang tangan kanan). gluLookAttidak 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.
Christian Rau
2
@bobobo Pepatah Anda jika Anda menghitung matriks tampilan hanya menggunakan fungsi rotasi dan terjemahan (yang saya rasa Anda tidak akan menuduh mengubah penggunaan tangan), alih-alih gluLookAt, tidak akan ada perubahan basis, sementara gluLookAtitu? Jelas tidak (karena Anda mungkin tahu bahwa tidak "semua orang" menggunakan gluLookAtuntuk penghitungan matriks tampilan), karena seperti yang seharusnya Anda ketahui gluLookAttidak melakukan apa pun selain sekumpulan panggilan rotasi dan terjemahan (bahkan mereka menyamar sebagai perubahan istilah "tingkat tinggi " dari dasar " ) tanpa refleksi sama sekali.
Christian Rau
26

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 terkejut tidak ada yang menyebutkan sesuatu: OpenGL bekerja dalam sistem koordinat kidal juga. Setidaknya, itu terjadi saat Anda bekerja dengan shader dan menggunakan rentang kedalaman default.

Setelah Anda membuang pipeline fungsi tetap, Anda berurusan langsung dengan "ruang klip". Spesifikasi OpenGL mendefinisikan ruang klip sebagai sistem koordinat homogen 4D. Saat Anda mengikuti transformasi melalui koordinat perangkat yang dinormalisasi, dan turun ke ruang jendela, Anda akan menemukan ini.

Ruang jendela adalah ruang piksel jendela. Titik asal berada di pojok kiri bawah, dengan + Y naik dan + X di kanan. Kedengarannya sangat mirip dengan sistem koordinat tangan kanan. Tapi bagaimana dengan Z?

Rentang kedalaman default (glDepthRange) menetapkan nilai Z dekat ke 0 dan nilai Z jauh ke satu . Jadi, + Z menjauh dari penampil.

Itu sistem koordinat kidal. Ya kamu bisaubah uji kedalaman dari GL_LESS menjadi GL_GREATER danubah glDepthRange dari [0, 1] menjadi [1, 0]. Tetapi status default OpenGL adalah bekerja dalam sistem koordinat kidal . Dan tidak ada transformasi yang diperlukan untuk mendapatkan ruang jendela dari clip-space meniadakan Z. Jadi clip-space, output dari vertex (atau geometri) shader adalah ruang kidal (semacam. Ini adalah ruang homogen 4D, jadi sulit untuk menjabarkan sifat kidal).

Dalam pipeline fungsi tetap, matriks proyeksi standar (diproduksi oleh glOrtho, glFrustum, dan sejenisnya) semuanya berubah dari ruang bertangan kanan menjadi ruang bertangan kiri . Mereka membalik arti Z; cukup periksa matriks yang mereka hasilkan. Di ruang mata, + Z bergerak ke arah penampil; di ruang pasca-proyeksi, ia menjauh.

Saya menduga Microsoft (dan GLide) sama sekali tidak repot-repot melakukan negasi dalam matriks proyeksi mereka.

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.

hultqvist
sumber
Rentang kedalaman tidak boleh [1, -1]. Saya pikir yang Anda maksud [1, 0]. Juga, ini telah disebutkan sebelumnya .
Nicol Bolas
Jawaban Anda bagus, sayang sekali untuk pertanyaan DirectX, Anda harus memposting ulang di sini!
hultqvist
3
@SigTerm mengapa menurut Anda mengoreksi pernyataan yang salah tidak sepadan? Saya telah menghabiskan beberapa jam memecahkan masalah koordinat simpul dan pembuatan rotasi matriks hanya untuk mengetahui bahwa sistem koordinat default sebenarnya tidak kidal.
hultqvist
1
Pertanyaannya adalah apakah itu sistem tangan kiri atau kanan. Jawaban ini memiliki lebih banyak detail dari itu, menjelaskan dua cara lain untuk melakukannya dengan tangan kanan, menambahkan -1 dalam transformasi matriks adalah cara lain untuk melakukannya. Tetapi tidak ada yang penting jika Anda yakin sistemnya kidal secara default, Anda hanya dapat mengubah sesuatu jika Anda tahu apa yang Anda ubah. Masih
hultqvist
1
Saya menemukan jawabannya sangat mencerahkan, dan itu muncul dalam pencarian sehingga itu sangat berharga bagi saya.
Pelajari OpenGL ES
13

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.

ZK_
sumber
3
Saya pikir ini tidak cukup diulang. Semua diagram yang menunjukkan "transformasi pemodelan", "transformasi tampilan", "transformasi perspektif" gagal menunjukkan bahwa mereka bukan bagian intrinsik dari OpenGL. Anda bahkan dapat melakukan semua transformasi Anda secara manual, dengan atau tanpa shader, dengan atau tanpa matriks.
Tom
3
Mungkin akan lebih baik jika mengulanginya untuk memasukkan kata-kata "koordinat perangkat yang dinormalisasi".
Tommy
6
OpenGL mendahului DirectX beberapa tahun, jadi OpenGL jelas tidak mencoba membedakan dirinya dari DirectX. Pengembang utama DirectX, Alex St. John, mengatakan bahwa keputusan Microsoft untuk menggunakan sistem koordinat kidal adalah "sebagian karena preferensi pribadi" dan "pilihan yang sewenang-wenang."
Chris Nolet
Ini tidak sepenuhnya benar. OpenGL juga mengetahui sistem koordinat kliping, karena kliping terjadi di dalamnya. Sistem koordinat klip memiliki kemampuan yang sama dengan sistem koordinat NDC.
plasmacel
7

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.

Heinzlmaen
sumber
7
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.
chrisvarnz
3

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.

AsingDevil
sumber
0

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.

weatx
sumber