Ini adalah jawaban yang panjang, tetapi sebenarnya premis dasar divide-by-camera-z sangat sederhana: Semakin jauh sesuatu menjauh dari Anda, semakin kecil tampilannya. Juga, jarak yang lebih kecil antara dua hal muncul.
Positions (Tidak wajib dibaca jika Anda menggunakan Unity!)
Pertama, Anda perlu merender posisi / poin yang menggunakan perspektif yang benar.
Posisi berbaring di pesawat datar. Anda menginginkan sesuatu seperti gambar di sebelah kanan ... pertimbangkan sudut-sudut ubin sebagai titik / posisi sampel.
Inilah cara Anda mendekati transformasi poin:
- Sistem koordinat Anda adalah sebagai berikut:
z
berjalan positif ke layar, sementara x
berjalan dari kiri ke kanan dan y
berjalan ke bawah. Kamera z adalah dunia z. Itulah jalan pintas yang membuat ini jauh lebih mudah daripada menulis mesin 3D penuh. Kelemahan? Kamera tidak dapat mengubah orientasi (meskipun dapat mengubah posisi).
- Simpan posisi 3D awal kamera Anda. Masukkan kembali (minus
z
) dari asal dunia.
- Simpan koleksi poin 3D di bidang xz (berikan
y=0
). Cobalah untuk pusat mereka di seluruh dunia asal di x
, (0,0,0)
, yaitu dari negatifn
ke positifn
. Ini untuk memusatkan mereka di viewport, saat rendering dimulai.
- Pertimbangkan titik awal / titik piksel yang merencanakan menjadi pusat layar.
- Tentukan jarak dari kamera di mana 1 unit ruang dunia = 1 piksel. Ini berarti jika Anda memindahkan kamera hanya 1 unit ruang dunia, objek apa pun yang berjarak 10 unit akan bergeser hanya 1 piksel - cukup jauh! Simpan jarak ini sebagai konstanta
K
.
Sekarang, untuk setiap titik, render pada posisi menggunakan rumus berikut: screenPosition(x,y) = screenOrigin + (worldPosition(x,y) - cameraPosition(x,y)) / ((worldPosition(z) - cameraPosition(z)) * K)
... seperti yang Anda lihat, kami mendasarkan posisi render pada z
-jarak antara titik saat ini dan kamera.
Mainkan dengan posisi z kamera sampai Anda melihat poin yang diberikan. Tapi yang akan Anda lihat adalah bahwa semua poin akan ditampilkan di garis tengah layar. Jadi kita perlu memperbaikinya. Coba K=1
vs. K=10
untuk melihat perbedaannya.
Anda sekarang dapat memindahkan kamera y
untuk melihat bagaimana kamera Anda bergerak di atas dan di bawah bidang titik (yaitu titik-titik akan membuat, perspektif-benar, di bawah atau di atas garis tengah layar, masing-masing, saat Anda menggerakkan kamera ke atas dan ke bawah ).
Ini adalah pedoman yang sangat kasar. Ada beberapa detail implementasi yang akan Anda lakukan. Langkah pertama adalah hanya untuk menampilkan sesuatu, kemudian mengubah dari sana. Satu detail yang terlintas dalam pikiran adalah bahwa jika Anda ingin kamera terlihat lebih seperti melihat ke bawah, maka Anda perlu menggeser asal perenderan Anda ke atas, lebih dekat ke bagian atas viewport. Detail lain adalah bahwa jarak Anda antara kamera dan titik mungkin perlu memasukkan rasio trigonometri ... Saya pikir menggunakantan
menawarkan perspektif yang lebih realistis. Tidak ingat dengan jelas tentang ini, tetapi Anda akan segera melihat apakah perspektifnya terlihat aneh dan dapat beradaptasi sesuai itu. Saya tidak bisa lebih spesifik tanpa menulis ulang sampel.
Per-billboard bengkok dan scaling (diperlukan)
Sekarang Anda dapat melihat perspektif di antara set posisi titik Anda, dan dapat menambahkan, menghapus, atau memindahkan posisi (seperti dengan karakter) sesuka Anda, Anda juga perlu menerapkan perspektif pada masing-masing sprite yang akan di-root pada posisi tersebut.
Di D2, selalu tampak bagi saya sebagai fungsi lungsin lateral sederhana yang diterapkan lebih pada papan reklame yang berada di bawah layar, daripada pada yang di atas, dan juga lebih saat Anda menjauh dari garis tengah yang mengalir ke bawah. layar.
Mungkin ada beberapa penskalaan vertikal yang diterapkan pada papan iklan juga, misalnya. pohon semakin pendek dibandingkan dengan skala yang diharapkan, lebih dekat bagian bawah layar (untuk membuatnya tampak seolah-olah kamera melihat ke bawah pada pohon - saya menemukan pohon Tristram menjadi cara terbaik untuk menjelajahi ini dengan aman, kembali ke hari ;) ).
Apa yang akan saya lakukan adalah:
- Atasi fungsi penskalaan dasar berdasarkan jarak dari kamera ke ground di berbagai titik. Jadi, Anda akan memiliki penskalaan yang serupa untuk setiap garis pemindaian.
- Hanya setelah saya melakukan itu, barulah saya akan melihat lungsin lateral - pertama berdasarkan jarak dari garis tengah berlari di layar.
- Terakhir saya akan menyelidiki bagaimana lungsin lateral dipengaruhi oleh jarak ke bawah layar (dan saya merasa bahwa rasio trigonometri sederhana akan menjadi inti dari hal ini).
Perspektif-memperbaiki ubin (Tidak wajib dibaca jika Anda menggunakan Unity!)
Mudah-mudahan di atas akan memberi Anda diposisikan dengan benar, melengkung "berdiri" sprite (yaitu objek yang duduk tegak lurus dengan bidang tanah, seperti karakter, pohon, rumah).
Namun, Anda juga perlu mempertimbangkan cara membuat ubin lantai berubah bentuk dengan benar dan mulus. Dan saya pikir Anda akan menemukan itulah bagian yang, khususnya, membutuhkan GPU pada D2. Saya ingat bahwa pada sistem tanpa GPU, opsi perspektif dinonaktifkan. Alasan untuk ini hampir pasti adalah bahwa GPU dapat mengambil permukaan tekstur dan menerapkan koreksi perspektif dengan sangat cepat, tanpa ada gangguan antara ubin, dan tanpa khawatir melakukan transformasi non-affine dalam kode aplikasi, yang melibatkan beberapa matrik matematika dan bisa sedikit mahal:
Saya punya beberapa saran bagi Anda untuk berurusan dengan ini:
- (Unity) Gunakan Unity Camera untuk memasok render bidang datar, permukaan bertekstur, lalu tangani distorsi papan reklame secara terpisah berdasarkan posisi layar.
- Lakukan logika ini (atau bahkan semua logika render) dalam GPU shaders.
- Jangan gunakan ubin tanah sama sekali. Sebagai gantinya, cukup gunakan sprite titik - seperti karakter itu sendiri - pada bidang yang berwarna seragam (misalnya hijau untuk rumput) untuk memberikan detail agar bidang tersebut tidak terlihat kusam. Ini akan meningkatkan biaya rendering Anda, tetapi ini tentunya cara termudah untuk mengatasi masalah ini.