Bagaimana saya harus menangani kliping simpul yang lebih dekat ke mata daripada bidang klip dekat?


13

Saya memutar mesin 3D saya sendiri, dalam JavaScript, dan hanya menggunakan gambar kanvas, tanpa WebGL. Ini adalah klon Minecraft lainnya; Saya suka kotak, jangan menilai saya.

Sejauh ini, semuanya bekerja dengan luar biasa, kecuali satu hal: dalam 3D, ketika beberapa simpul berada di belakang pesawat kliping dekat, proyeksi mereka di layar menjadi aneh (dengan asumsi simpul lain yang digunakan untuk melacak pesawat ada di depan).

Saya mencoba memotong titik-titik ini tetapi kemudian saya bisa melihat melalui permukaan yang menggunakan simpul ini. Di WebGL / OpenGL kartu grafis menangani titik-titik ini dan pesawat diberikan dengan benar, tetapi saya tidak memiliki akses ke perangkat keras jadi saya harus kode ini sendiri.

Saya tidak begitu yakin apa yang harus saya lakukan, saat ini hal terakhir yang terlintas dalam pikiran saya adalah membalikkan proyeksi poin di belakang pesawat dekat kliping pemain, yang tampaknya logis karena saya harus memproyeksikan titik ke layar yang ada di depan. dari simpul.

Inilah pikiran saya:

masukkan deskripsi gambar di sini

Berikut adalah beberapa gambar untuk menggambarkan apa yang terjadi:

masukkan deskripsi gambar di sini

Dari kejauhan kotak biru tampak sempurna.

masukkan deskripsi gambar di sini

Ketika beberapa simpul berada di belakang bidang kliping dekat pemain, saya melakukan proyeksi terbalik, tetapi tidak terlihat benar:

focalLength *= -1;
2d.x = x*focalLength/z;
2d.y = y*focalLength/z;

Perhatikan bahwa kotak abu-abu di belakang sepenuhnya dihapus karena semua simpul yang digunakan untuk menggambar wajahnya ada di belakang pemain.

masukkan deskripsi gambar di sini

Inilah yang terjadi ketika melihat ke atas atau ke bawah.

Saya tidak tahu bagaimana membuat matematika di balik ini, saya berharap seseorang telah mengalami masalah yang sama dan dapat membantu saya.


1
Jika titik-titik lebih dekat ke mata daripada bidang klip dekat, mereka harus dipotong - dan ini memang memungkinkan Anda melihat "melalui" suatu objek. Ini adalah perilaku yang khas; tabrakan biasanya mencegah artefak visual tertentu. Apakah itu satu-satunya yang salah dengan solusi kliping Anda?

@JoshPetrie: Saya mengerti bahwa poin harus terpotong, tetapi jika saya melakukan itu seluruh kotak akan menghilang sebagai satu atau dua dari simpul dimana rutin menggambar harus dilewati hilang (dalam 2d) dan pemain akan dapat melihat melalui alun-alun itu. Saya ingin mereka "di luar" kanvas (pada proyeksi) sehingga alun-alun masih bisa digambar. Saya tidak yakin apakah saya cukup jelas.
Solenoid

Anda - Saya mengatakan bahwa adalah perilaku normal dan Anda ingin mencegah hal ini terjadi dengan mencegah pemain dari mendapatkan yang dekat dengan salah satu kubus. Jika Anda benar-benar ingin melakukan ini, Anda harus memotong tetapi merekonstruksi segitiga (mungkin). Ini akan tetap terlihat tidak biasa, terutama jika Anda memiliki tekstur. Jika apa yang saya katakan tidak masuk akal, Anda dapat bergabung dengan kami di obrolan sehingga kami tidak membuat utas komentar yang benar-benar cerewet.

Apa yang Anda katakan masuk akal, merekonstruksi membutuhkan terlalu banyak waktu sehingga itu bukan solusi. Saya berharap ada cara untuk tetap menggambar titik di pesawat 2d yang ada di belakang pemain sehingga lineTo(x,y)fungsinya masih bisa dipanggil, hanya saja saya tidak tahu bagaimana perilakunya ... itu dimensi yang aneh, saya setuju.
Solenoid

Jawaban:


1

Tujuan dari pesawat kliping dekat adalah bahwa itu adalah pesawat kliping . Segitiga yang berada di luar bidang kliping terpotong : dipotong-potong sehingga setiap bagian yang tersisa berada di dalam wilayah kliping.

Anda dapat mencoba untuk mengabaikan klip dekat jika Anda mau. Memang OpenGL dan D3D memiliki cara mematikan dekat kliping pesawat sama sekali (meskipun buffer kedalaman masih memiliki nilai dekat minimum). Masalahnya bukan klip dekat.

Masalahnya adalah dengan simpul yang ada di belakang kamera.

Anda tidak dapat membuat segitiga yang ada di belakang kamera. Bukan dengan proyeksi perspektif. Segitiga semacam itu tidak masuk akal di bawah matematika di balik proyeksi perspektif. Selain itu, mereka juga berada di luar frustrasi.

Mematikan kliping dekat mengubah frustum menjadi piramida. Alasan piramida berhenti pada titik tersebut adalah karena titik di atas piramida berada di belakang keempat sisi piramida. Jadi setiap titik di belakang kamera (ujung piramida) berada di atas, di bawah, ke kiri, dan ke kanan wilayah layar yang terlihat. Semua di waktu yang sama.

Seperti yang saya katakan: simpul di bawah proyeksi perspektif yang ada di belakang kamera tidak masuk akal.

Anda harus menerapkan kliping. Anda harus mendeteksi ketika ada simpul segitiga, di ruang klip ( sebelum pembagian perspektif) di belakang kamera. Jika ya, maka Anda harus memotong segitiga itu, hanya menghasilkan segitiga yang ada di depan kamera.

Ini bukan proses yang sederhana. Ini akan melibatkan matematika yang hanya masuk akal jika Anda memiliki pemahaman penuh tentang sistem koordinat yang homogen. Atau, Anda bisa langsung menyisihkan segitiga jika ada simpul di belakang kamera.


Sampai sekarang saya menyisihkan seluruh segitiga, tetapi kemudian saya melihat melalui pesawat (lihat gambar di atas). Saya benar-benar membutuhkan gambar untuk memahami mengapa itu tidak masuk akal secara geometris. Satu-satunya solusi adalah menghitung persimpangan garis-pesawat ketika salah satu simpul berada di belakang bidang kliping dan menggunakan persimpangan itu untuk melacak garis dari titik yang ada di depan, sayangnya ini mahal.
Solenoid

0

Jika bagian dari segitiga di belakang bidang dekat dapatkah Anda melakukan pemeriksaan per-pixel untuk melihat apakah posisi piksel berada di belakang bidang kliping?

Anda mungkin memperlakukan pesawat dekat seperti pesawat kliping lainnya. Misalnya pesawat kliping digunakan untuk hal-hal seperti pesawat air (untuk refleksi dan refraksi). Saya akan berpikir bahwa pesawat kliping ini akan bekerja seperti pesawat kliping dekat, dan klip pada basis per-pixel.

Saya tahu bagaimana menangani pesawat kliping di HLSL dengan DirectX, tetapi implementasinya bisa menjadi hak milik. Jika Anda bisa mendapatkan info untuk itu mungkin akan membantu.

Selain itu, berikut ini tautan yang mungkin membantu Anda: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter42.html


Pengujian per piksel sangat mahal dalam bahasa yang ditafsirkan seperti Javascript, sekarang saya hampir tidak dapat menerima fps.
Solenoid
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.