Apa sebenarnya yang menyebabkan permukaan saling tumpang tindih?

10

Saya benar-benar tidak tahu apa yang menyebabkan satu permukaan saling tumpang tindih. Dalam mesin 3D yang saya buat, teknik saya gagal dalam kasus tepi.

Metode saya adalah menyortir permukaan yang akan dicat dari yang terjauh ke terdekat. Untuk menentukan kedekatan, saya membandingkan nilai rata-rata z. Kadang-kadang, bagaimanapun, permukaan tumpang tindih memiliki tinggi nilai z rata-rata dari yang itu tumpang tindih. Dengan demikian, permukaan yang lebih jauh dicat lebih dekat - menghasilkan rendering aneh seperti ini:

Kotak ungu besar dengan bagian merah di samping

Apa yang dimaksudkan untuk dilihat adalah permukaan depan ungu dari kubus saja, sementara permukaan sisi merah dicat di atas permukaan ungu. Nilai rata-rata z dari permukaan ungu lebih tinggi, dan karenanya 'lebih jauh'. Jadi saya ragu apakah teknik ini benar.

Apa yang saya coba adalah mendapatkan jarak dari kamera (yaitu asal) ke permukaan, tetapi kemudian saya membutuhkan sebuah titik. Saya memilih bagian tengah dari setiap permukaan tetapi juga ini sepertinya tidak selalu berhasil karena tidak semua permukaan sama besar.

Oleh karena itu, apa cara yang dapat diandalkan untuk menentukan urutan kedekatan permukaan terhadap asal?

pimvdb
sumber

Jawaban:

11

Anda tampaknya mencoba menerapkan Algoritma Pelukis . Saya kira Anda mencoba menulis rasteriser dari awal sebagai latihan pembelajaran, karena sebagian besar perangkat keras 3D modern menggunakan apa yang disebutkan oleh Bart (buffer Z / Depth). Agar algoritme pelukis berfungsi dalam semua kasus, Anda harus siap untuk membagi permukaan saat mereka dibuat untuk menyelesaikan skenario yang mungkin (seperti masalah poligon yang tumpang tindih yang ditunjukkan pada halaman Wikipedia).

Dengan rendering dari yang terjauh ke terdekat Anda juga menghabiskan waktu rendering piksel yang nantinya mungkin akan tersumbat oleh poligon lain, yang ketika Anda mulai meletakkan tekstur dan shader kompleks pada poligon membuang siklus berharga. Inilah alasan mengapa perangkat keras modern lebih suka Anda merender dari depan ke belakang, menggunakan buffer kedalaman untuk menentukan apakah piksel yang akan dirender lebih jauh daripada yang ada di layar (dan karenanya dapat dibuang).

Bahkan dengan sebagian besar perangkat keras akselerasi modern Anda masih perlu menyortir dan membuat dari belakang ke depan setiap poligon semi-transparan, rendering ini hanya sekali semua poligon buram telah diberikan.

Roger Perkins
sumber
Anda benar dalam mengatakan bahwa saya sedang membuat perender sederhana. Intinya adalah bahwa saya tidak menggunakan perpustakaan 3D. Saya melakukan semua perhitungan proyeksi sendiri dan kemudian menggambar garis menggunakan perpustakaan gambar 2D. Ini bukan yang tercepat di luar sana dan saya tidak melakukan apa-apa berdasarkan per-pixel. Saya hanya punya 4 titik dari setiap permukaan dan mengisi bentuk persegi panjang dengan warna. Karena saya menggambar permukaan lengkap pada satu waktu, apakah saya benar mengatakan bahwa saya harus mundur ke depan?
pimvdb
Kedengarannya sangat menyenangkan dan cara yang bagus untuk belajar. Kembali ke depan adalah satu-satunya cara Anda jika Anda melakukan ini tanpa bentuk penyangga kedalaman. Saya pikir Anda harus mengerjakan semua koordinat layar dari poligon Anda dan kemudian memeriksa adanya tumpang tindih. Di mana mereka tumpang tindih secara mendalam Anda berpotensi perlu memotong poligon untuk membuat, sehingga Anda benar-benar dapat menyelesaikan penyortiran dengan benar. Anda mungkin juga ingin melihat Back Face Culling sebagai cara untuk menghilangkan poligon yang seharusnya tidak terlihat
Roger Perkins
Roger Perkins benar. Anda tidak akan dapat mencapai penyortiran z yang benar dengan cara itu (artinya Anda akan selalu memiliki beberapa kasus tepi), kecuali jika Anda memotong poligonnya. Itu bisa menjadi agak lambat.
bummzack
Saya membuatnya bekerja! Apa yang saya lakukan adalah kombinasi dari pemusnahan backface dan penyortiran: dalam kubus padat, beberapa wajah tidak terlihat sementara yang lain (maks. 3). Jadi saya melukis bagian yang tidak terlihat terlebih dahulu, dan bagian yang terlihat di atasnya. Ini berfungsi seperti mantra, jika saya menghapus satu atau lebih sisi, mereka tumpang tindih tetapi masih digambar dalam urutan yang benar. Terima kasih!
pimvdb
1
Itu hanya akan bekerja untuk bentuk cembung sederhana, seperti kubus. Saya senang saat ini berhasil untuk Anda, tetapi itu bukan solusi umum.
Richard Fabian
3

Apa yang Anda miliki adalah masalah visibilitas . Salah satu solusinya adalah menggunakan z-buffer .

Bart van Heukelom
sumber
Terima kasih, tetapi z-buffering memerlukan per-pixel rendering jika saya tidak salah. Saya tidak melakukan itu - saya menggambar garis lurus di antara titik-titik kubus yang diproyeksikan. Apakah z-buffering masih memungkinkan?
pimvdb
Bahkan jika Anda menggambar garis lurus, pada titik tertentu sebelum gambar sampai ke layar (atau file bitmap) itu akan dalam format piksel.
Bart van Heukelom
Itu benar tetapi perpustakaan gambar saya terlalu lambat untuk melakukan rendering piksel dengan 20fps. Terimakasih Meskipun.
pimvdb
2

Menyortir wajah sesuai dengan nilai rata-rata z mereka tidak berfungsi, karena nilai rata-rata z tidak memberikan informasi tentang nilai z aktual dari simpul atau bahkan piksel permukaan.

Contoh (peringatan, ASCII art depan):

          /
         /
cam     /
-->    / 
      /
     /--       <--B
    /
    ^--A

Ada dua wajah A dan B. Dari sudut pandang kamera A ada di depan B. Namun nilai rata-rata B lebih kecil. Mari kita lihat nilai-z lainnya:

  • nilai z minimum A adalah 4
  • nilai z maksimum A adalah 11
  • oleh karena itu nilai z rata-rata A adalah 7,5
  • nilai z minimum B adalah 6
  • nilai z maksimum B adalah 8
  • oleh karena itu nilai z rata-rata B adalah 7

Anda bisa mencoba mengurutkannya berdasarkan nilai z minimalnya tetapi ada kasus di mana itu tidak akan berhasil juga. Tidak ada cara untuk mengurutkan wajah sewenang-wenang dengan benar menggunakan hanya satu nilai z.

Dalam algoritma Newell, http://en.wikipedia.org/wiki/Newell 's_algorithm yang Anda lakukan adalah mengurutkan min / max-rentang dari nilai-z. Jika rentang dua wajah tidak tumpang tindih, Anda bisa tahu pasti yang mana di depan. Jika ya, terkadang Anda benar-benar harus membelah wajah. Kadang-kadang cukup untuk raytrace setiap titik untuk oklusi atau teknik lainnya.

Jonas Bötel
sumber
Diagram itu adalah tampilan overhead dari apa yang akan saya duga terjadi di screenshot-nya.
jhocking
1

Ada baiknya Anda belajar tentang rendering dengan melakukan. Pujian. Dalam contoh ini, tidak ada solusi "pelukis algoritma", alih-alih mencoba memperbaikinya dengan mengurutkan, pada PS1 kami dulu hanya mencoba untuk menjaga poligon di sekitar ukuran yang sama ketika mereka bersebelahan (yang Anda lakukan sebagai Sejauh yang saya tahu), dan backface cull (yang tidak Anda lakukan)

Culling backface adalah memeriksa permukaan normal dalam ruang layar untuk arahnya (hanya mendapatkan tanda elemen kedalaman dari ruang layar berubah normal (dalam kasus kami itu adalah z dari normal), atau produk silang dari dua vektor dari segitiga yaitu lintas (v1-v0, v2-v0))

Jika Anda menerapkan pemusnahan backface, Anda juga mengurangi jumlah rasterisasi yang Anda lakukan .. menang ganda.

Richard Fabian
sumber
Terimakasih atas tanggapan Anda. Saya memang membaca tentang backface pemusnahan tetapi intinya adalah bahwa saya ingin dapat menghapus satu sisi. Dengan kubus padat ini mungkin bekerja dengan baik, tetapi jika saya menghapus satu sisi maka ada okulasi terjadi - jadi saya masih perlu mengurutkannya, saya kira. Ngomong-ngomong, saya datang dengan ide menembakkan sinar dari asal melalui titik tengah permukaan. Jika sinar itu melintasi permukaan lain setelah itu, maka permukaan pertama tumpang tindih dengan yang kedua. Bisakah Anda memberi tahu saya apakah gagasan itu benar? Terima kasih!
pimvdb
Meskipun ide Anda akan berhasil untuk contoh kasus Anda, ada banyak kasus lain di mana itu tidak akan berfungsi. Misalnya, adegan yang sama dengan yang Anda miliki di sana, tetapi dengan kamera dimiringkan sehingga bagian tengah render yang salah tidak tumpang tindih. Saya pikir Anda harus mengesampingkan primitif Anda menjadi potongan-potongan kecil.
Richard Fabian