Haruskah saya menggunakan matriks dunia?

8

Referensi gambar untuk pertanyaan:

objek ruang vs ruang dunia

(gambar dari tutorial CG )

API D3D9 membuat kami terbiasa dengan matriks dunia .

Namun, jika Anda menggunakan matriks dunia, maka Anda harus melakukan perkalian matriks tambahan dalam shader (yang akhirnya sama untuk banyak simpul).

Karenanya OpenGL konvensi menggabungkan pemodelan dan melihat matriks menjadi satu matriks (GL_MODELVIEWMATRIX = View * World).

Apa yang lebih baik, dan mengapa?

bobobobo
sumber

Jawaban:

7

Tidak. Kapan pun Anda memiliki matriks dunia eksplisit di shader Anda.

Penjelasan terperinci untuk alasannya dapat ditemukan di sini , tetapi versi singkatnya benar-benar sangat sederhana: Anda tidak pernah membutuhkannya dan dapat membunuh ketepatan floating-point Anda.

Jika ruang dunia Anda terlalu besar, maka kamera yang jauh dari asalnya dapat menyebabkan masalah presisi titik mengambang.

Semua ruang dunia tidak lebih dari perantara antara ruang model dan ruang kamera. Ini adalah tempat di mana Anda dapat mengekspresikan kamera dan semua objek lain di ruang yang sama. Tetapi yang Anda gunakan hanyalah menghasilkan matriks dunia-ke-kamera, yang kemudian Anda terapkan ke semua matriks model-ke-dunia untuk membuat matriks model-ke-kamera.

Anda dapat menangani masalah presisi di C ++ dengan menggunakan doubl alih-alih mengapung untuk perhitungan matriks. Anda dapat mengonversi ini kembali menjadi float sebelum mengunggahnya ke shader.

Jadi mengapa Anda membutuhkan transformasi ruang-dunia eksplisit di shader Anda? Di kode sumber Anda, ya. Tetapi di shader Anda? Apa yang akan Anda lakukan dengan itu yang tidak dapat Anda lakukan dengan ruang kamera?

Pencahayaan dapat dilakukan di ruang kamera semudah ruang dunia; yang harus Anda lakukan adalah mengubah posisi / arah cahaya Anda menjadi ruang kamera. Bagaimanapun, ruang kamera memiliki skala yang sama dengan ruang dunia. Anda melakukan transformasi ini sekali per frame per cahaya; bukan beban kinerja bahkan pada CPU.

Jadi sama sekali tidak ada gunanya mengekspos shader Anda ke transformasi ruang dunia eksplisit . Ini hanya langkah menengah yang Anda lipat ke dalam matriks Anda.

Nicol Bolas
sumber
1

Anda tidak akan melakukan penggandaan matriks tambahan di shader Anda. Caranya adalah Anda melakukan perkalian matriks satu kali per frame pada CPU, lalu unggah hasil akhir ke vertex shader Anda. Itu memberi Anda satu posisi dengan perkalian matriks per-verteks, terlepas dari apakah Anda memiliki dunia dan tampilan yang terpisah atau digabungkan.

Maximus Minimus
sumber
0

Dalam banyak kasus, Anda ingin memiliki pos dunia di vertex shader, untuk keperluan lain. Misalnya, Anda perlu menghitung vektor tampilan, untuk meneruskannya ke pixel shader untuk mengevaluasi specular.

Matriks lokal-ke-dunia juga diperlukan untuk mengubah vektor garis singgung dan vektor normal [1] menjadi ruang dunia untuk peneduh, dengan asumsi bahwa Anda melakukan peneduhan di ruang dunia (Anda mungkin melakukannya dalam ruang singgung, dalam hal ini Anda perlu set matriks yang berbeda).

Jadi IMO, masuk akal untuk memiliki dua matriks: local-to-world dan world-to-clip. Yang terakhir adalah produk dari view matrix dan projection matrix. Lewati keduanya ke vertex shader, dan lakukan multiplikasi seperti:

posWorld = mul(posLocal, matLocalToWorld)
posClip = mul(posWorld, matWorldToClip)

[1] (Selama Anda tidak memiliki penskalaan tidak seragam. Dalam hal ini normals harus diubah oleh transpos terbalik dari matriks lokal-ke-dunia.)

Nathan Reed
sumber
@NicolBolas: Poin bagus; ada masalah presisi dengan naungan di ruang dunia. Bukan berarti Anda harus menggunakan ruang kamera. Di pekerjaan saya, kami benar-benar menggunakan "ruang dunia yang berpusat pada kamera" - sumbu selaras dengan dunia, yang berasal dari kamera. Memiliki kapak yang sejajar dunia membuatnya lebih mudah untuk menerapkan cubemaps yang disimpan di ruang dunia.
Nathan Reed