Apa itu algoritma pengemasan tekstur yang baik? Secara teknis, pengemasan bin adalah NP-hard , jadi heuristik adalah apa yang saya cari.
52
Apa itu algoritma pengemasan tekstur yang baik? Secara teknis, pengemasan bin adalah NP-hard , jadi heuristik adalah apa yang saya cari.
Jawaban:
Saya menghabiskan beberapa bulan di satu pekerjaan dengan algoritma pengemasan tekstur yang lebih baik.
Algoritma yang kami mulai dengan sederhana. Kumpulkan semua item input. Urutkan berdasarkan jumlah piksel yang dikonsumsi, besar ke kecil. Letakkan di tekstur Anda dalam urutan scanline, hanya menguji hal-hal dari pixel topleft ke pixel topright, bergerak ke bawah garis, dan ulangi, ulang ke pixel topleft setelah setiap penempatan berhasil.
Anda perlu meng-hardcode lebar atau mencari heuristik lain untuk ini. Dalam upaya untuk melestarikan kuadrat, algoritme kami akan mulai pada 128, lalu meningkat sebesar 128-an sampai muncul dengan hasil yang tidak lebih dalam daripada lebarnya.
Jadi, kami memiliki algoritma itu, dan saya memutuskan untuk memperbaikinya. Saya mencoba banyak heuristik aneh - mencoba menemukan objek yang cocok bersama, melakukan beberapa pembobotan atas sekelompok sifat ruang pengepakan yang diinginkan, berputar dan membalik. Setelah semua pekerjaan saya, secara harfiah tiga bulan kerja, saya akhirnya menghemat ruang 3%.
Ya. 3%.
Dan setelah kami menjalankan rutin kompresi kami di atasnya, itu benar-benar berakhir lebih besar (yang saya masih tidak bisa menjelaskan) jadi kami membuang semuanya dan kembali ke algoritma lama.
Mengurutkan item, selai menjadi tekstur dalam urutan scanline. Itu algoritma Anda. Mudah untuk dikodekan, cepat dijalankan, dan Anda tidak akan menjadi lebih baik tanpa kerja yang luar biasa. Pekerjaan itu tidak bermanfaat kecuali perusahaan Anda setidaknya memiliki 50 orang, dan mungkin lebih.
Dan sebagai catatan, saya baru saja mengimplementasikan algoritma ini (lebar tetap 512 piksel) untuk aplikasi yang persis sama persis seperti yang Anda lakukan (tidak ada kelemahan, tetapi mesin terbang freetype yang dibuat khusus.) Inilah hasilnya. Itu terlihat buram karena tambang saya menggunakan algoritma rendering teks berbasis jarak-bidang Valve , yang juga menyumbang ruang ekstra antara mesin terbang. Jelas, tidak ada banyak ruang kosong yang tersisa, dan itu melakukan pekerjaan yang baik untuk menjejalkan semuanya ke tempat-tempat terbuka.
Semua kode untuk ini berlisensi BSD dan tersedia di github .
sumber
Tesis PhD dari Andrea Lodi berjudul Algoritma untuk Pengemasan dan Penugasan Bin Dua Dimensi .
Tesis ini membahas beberapa bentuk yang lebih sulit dari masalah ini. Untungnya, pengemasan tekstur adalah versi yang paling mudah. Algoritma terbaik yang ia temukan disebut Touching Perimeter .
Mengutip dari halaman 52:
Yang juga menarik, makalah ini menjelaskan algoritma untuk menentukan ukuran peta tekstur yang dikemas secara optimal. Itu akan berguna untuk menentukan apakah mungkin untuk mencocokkan semua tekstur dalam satu atlas 1024x1024.
sumber
Jika ada yang masih tertarik, saya telah sepenuhnya menulis ulang pustaka rectpack2D sehingga jauh lebih efisien.
Ini bekerja dengan menjaga
std::vector
ruang kosong di atlas, dimulai dengan beberapa ukuran maksimum awal (biasanya, ukuran tekstur maksimum yang diperbolehkan pada GPU tertentu), membelah ruang kosong pertama yang layak dan menyimpan pemisahan kembali ke vektor.Terobosan kinerja datang dengan hanya menggunakan vektor, bukannya menjaga seluruh pohon, seperti yang telah dilakukan sebelumnya.
Prosedur ini dijelaskan secara rinci dalam README .
Perpustakaan berada di bawah MIT, jadi saya senang untuk Anda jika Anda merasa berguna!
Contoh hasil:
Pengujian dilakukan pada Intel (R) Core (TM) i7-4770K CPU @ 3.50GHz. Biner dibangun dengan clang 6.0.0, menggunakan -03 switch.
Sprite permainan sewenang-wenang + Mesin terbang Jepang: total 3264 subjek.
Runtime: 4 milidetik
Pixel Terbuang: 15538 (0,31% - setara dengan 125 x 125 persegi)
Output (2116 x 2382):
Dalam warna:
(hitam adalah ruang yang terbuang)
Mesin terbang Jepang + beberapa sprite GUI: 3122 subjek.
Runtime: 3,5 - 7 ms
Piksel Terbuang: 9288 (1,23% - setara dengan 96 x 96 persegi)
Output (866 x 871):
Dalam warna:
(hitam adalah ruang yang terbuang)
sumber
Algoritma heuristik yang baik dapat ditemukan di sini . Ketika saya mencoba sesuatu yang serupa baru-baru ini, saya menemukan ini dirujuk sebagai titik awal dasar untuk sebagian besar implementasi yang saya lihat.
Bekerja sangat baik dengan banyak item berbentuk biasa, berukuran serupa, atau dengan perpaduan yang baik dari gambar kecil dan lebih sedikit. Saran terbaik untuk mencapai hasil yang baik adalah jangan lupa untuk menyortir input Anda dalam hal ukuran gambar, lalu kemas dari yang terbesar ke yang terkecil karena gambar yang lebih kecil akan dimasukkan ke dalam ruang di sekitar gambar yang lebih besar. Bagaimana Anda melakukan ini menyortir Anda dan mungkin tergantung pada tujuan Anda. Saya menggunakan perimeter daripada area sebagai perkiraan urutan pertama karena saya mengambil pandangan bahwa gambar tinggi + tipis / pendek + lebar (yang akan memiliki area rendah) sebenarnya sangat sulit untuk ditempatkan nanti dalam sebuah paket, jadi dengan menggunakan perimeter Anda mendorong bentuk-bentuk aneh menuju bagian depan ordo.
Berikut ini adalah contoh sampel output untuk paket saya pada set acak gambar dari direktori dump gambar situs web saya :).
Angka-angka dalam kotak adalah id dari blok yang mengandung di pohon jadi beri Anda gagasan tentang urutan sisipan. Yang pertama adalah ID "3" karena itu adalah simpul daun pertama (hanya daun yang mengandung gambar) dan akibatnya memiliki 2 orang tua).
sumber
Secara pribadi, saya hanya menggunakan sistem pertama-blok-yang-cocok serakah terbesar. Ini tidak optimal, tetapi triknya OK.
Perhatikan bahwa, jika Anda memiliki jumlah blok tekstur yang masuk akal, Anda dapat mencari urutan pemesanan yang lengkap bahkan jika masalahnya adalah NP.
sumber
Sesuatu yang saya gunakan, yang bekerja dengan baik bahkan untuk peta UV yang tidak beraturan, adalah mengubah patch UV menjadi bitmap mask, dan memelihara mask untuk tekstur itu sendiri, mencari posisi pertama patch UV akan cocok. Saya memesan blok sesuai dengan beberapa heuristik sederhana (tinggi, lebar, ukuran, apa pun), dan saya memungkinkan rotasi blok untuk meminimalkan atau memaksimalkan heuristik yang dipilih. Itu memberi ruang pencarian yang bisa dikelola untuk brute force.
Jika Anda kemudian dapat mengulangi bahwa mencoba beberapa heuristik, dan / atau menerapkan faktor acak dalam memilih pemesanan dan mengulangi sampai batas waktu habis.
Dengan skema ini Anda akan mendapatkan pulau-pulau UV kecil yang dikemas ke dalam celah-celah yang dibuat oleh pulau-pulau besar, dan bahkan di dalam lubang yang tersisa di dalam satu tambalan UV sendiri.
sumber
Kami baru-baru ini merilis skrip python yang akan mengemas tekstur menjadi beberapa file gambar dengan ukuran tertentu.
Dikutip dari blog kami:
"Walaupun ada banyak paket yang dapat ditemukan online, kesulitan kami adalah menemukan apa pun yang dapat menangani gambar dalam jumlah besar di banyak direktori. Dengan demikian, pengemas atlas kami sendiri telah lahir!
Seperti ini, skrip kecil kami akan mulai di direktori dasar dan memuat semua .PNGs ke dalam atlas. Jika atlas itu terisi, itu menciptakan yang baru. Kemudian, ia akan mencoba menyesuaikan sisa gambar di semua atlas sebelumnya sebelum menemukan tempat di yang baru. Dengan begitu, setiap atlas dikemas sekencang mungkin. Atlase dinamai berdasarkan folder tempat gambar mereka berasal.
Anda dapat mengubah ukuran atlas (baris 65), format gambar yang ingin Anda kemas (baris 67), direktori muat (baris 10) dan direktori simpan (baris 13) cukup mudah tanpa pengalaman di Python. Sebagai penafian kecil, ini dikocok bersama dalam beberapa hari untuk bekerja secara khusus dengan mesin kami. Saya mendorong Anda untuk meminta fitur, berkomentar dengan variasi Anda sendiri, dan melaporkan kesalahan apa pun, tetapi setiap perubahan pada skrip akan terjadi di waktu luang saya. "
Jangan ragu untuk memeriksa kode sumber lengkap di sini: http://www.retroaffect.com/blog/159/Image_Atlas_Packer/#b
sumber
Sangat mudah untuk mengemas font karena semua (atau sebagian besar) dari tekstur mesin terbang hampir ukuran yang sama. Lakukan hal paling sederhana yang terjadi pada Anda dan itu akan sangat dekat dengan optimal.
Kepintaran menjadi lebih penting saat Anda mengemas gambar dengan ukuran yang sangat berbeda. Maka Anda ingin dapat memasukkan ke dalam celah, dll. Meskipun begitu, meskipun demikian, algoritma sederhana seperti pencarian urutan pemindaian yang dibahas sebelumnya akan menghasilkan hasil yang sangat wajar.
Tidak ada algo canggih yang ajaib. Mereka tidak akan 50% lebih efisien daripada algo sederhana, dan Anda tidak akan mendapatkan manfaat yang konsisten dari mereka kecuali Anda memiliki jumlah lembar tekstur yang mengejutkan. itu karena peningkatan kecil yang dibuat oleh algoritma yang lebih baik hanya akan dilihat secara agregat.
Lakukan yang sederhana, dan beralihlah ke sesuatu di mana upaya Anda akan dihargai lebih baik
sumber
Jika khusus untuk tekstur font, maka Anda mungkin melakukan sesuatu yang tidak optimal tetapi bagus dan sederhana:
Urutkan karakter berdasarkan tinggi, tertinggi terlebih dahulu
Mulai dari 0,0 Tempatkan karakter pertama pada koordinat saat ini, lanjutkan X, tempatkan berikutnya, ulangi sampai kami tidak dapat memasukkan yang lain
Atur ulang X ke 0, naikkan Y ke bawah dengan ketinggian karakter tertinggi di baris, dan isi baris lain
Ulangi sampai kita kehabisan karakter, atau tidak dapat masuk ke baris lain.
sumber