Masalah dengan menggunakan atlas tekstur dan kebocoran texels yang berdekatan berkaitan dengan cara kerja penyaringan tekstur linier.
Untuk setiap titik dalam tekstur yang tidak disampel secara tepat di tengah texel, pengambilan sampel linier akan mengambil sampel 4 texel yang berdekatan dan menghitung nilai di lokasi yang Anda tanyakan sebagai bobot (berdasarkan jarak dari titik sampel) rata-rata semua 4 sampel.
Berikut visualisasi masalah yang bagus:
Karena Anda tidak dapat menggunakan sesuatu seperti GL_CLAMP_TO_EDGE
pada atlas tekstur, Anda perlu membuat texels tepi di sekitar tepi setiap tekstur. Teks perbatasan ini akan mencegah sampel tetangga dari tekstur yang sangat berbeda di atlas mengubah gambar melalui interpolasi tertimbang yang dijelaskan di atas.
Perhatikan bahwa ketika Anda menggunakan penyaringan anisotropik, Anda mungkin perlu menambah lebar perbatasan. Ini karena penyaringan anisotropik akan meningkatkan ukuran lingkungan sampel pada sudut ekstrem.
Untuk mengilustrasikan apa yang saya maksud dengan menggunakan batas di sekitar tepi setiap tekstur, pertimbangkan berbagai mode bungkus yang tersedia di OpenGL. Berikan perhatian khusus CLAMP TO EDGE
.
Meskipun ada mode yang disebut "Clamp to Border", itu sebenarnya bukan yang kami minati. Mode itu memungkinkan Anda menentukan satu warna untuk digunakan sebagai batas di sekitar tekstur Anda untuk setiap koordinat tekstur yang berada di luar batas normal [0,0] -1.0] jangkauan.
Yang kami inginkan adalah mereplikasi perilaku CLAMP_TO_EDGE
, di mana setiap tekstur berkoordinasi di luar kisaran yang tepat untuk (sub-) tekstur menerima nilai dari pusat texel terakhir ke arah di luar batas. Karena Anda memiliki kontrol penuh atas koordinat tekstur dalam sistem atlas, satu-satunya skenario di mana koordinat tekstur (efektif) mungkin merujuk ke lokasi di luar tekstur Anda adalah selama langkah rata-rata tertimbang penyaringan tekstur.
Kita tahu bahwa GL_LINEAR
akan mengambil sampel 4 tetangga terdekat seperti yang terlihat pada diagram di atas, jadi kita hanya perlu perbatasan 1-texel. Anda mungkin memerlukan batas texel yang lebih luas jika Anda menggunakan pemfilteran anisotropik, karena ini meningkatkan ukuran lingkungan sampel dalam kondisi tertentu.
Berikut adalah contoh tekstur yang menggambarkan batas lebih jelas, meskipun untuk tujuan Anda, Anda dapat membuat lebar 1 texel atau 2 texel lebar.
(CATATAN: Batas yang saya maksudkan bukan hitam di sekitar keempat tepi gambar, tetapi area tempat pola kotak-kotak berhenti berulang secara teratur)
Jika Anda bertanya-tanya, inilah mengapa saya terus memunculkan penyaringan anisotropik. Ini mengubah bentuk lingkungan sampel berdasarkan sudut dan dapat menyebabkan lebih dari 4 texels digunakan untuk memfilter:
http://www.arcsynthesis.org/gltut/Texturing/ParallelogramDiag.svg
Semakin besar tingkat anisotropi yang Anda gunakan, semakin besar kemungkinan Anda harus berurusan dengan lingkungan sampel yang mengandung lebih dari 4 texels. Batas 2 texel harus memadai untuk sebagian besar situasi penyaringan anisotropik.
Last but not least, di sini adalah bagaimana atlas tekstur dikemas akan dibangun yang akan mereplikasi GL_CLAMP_TO_EDGE
perilaku di hadapan GL_LINEAR
filter tekstur:
( Kurangi 1 dari X dan Y dalam koordinat hitam, saya tidak membuktikan membaca gambar sebelum memposting. )
Karena penyimpanan tepi, menyimpan 4 tekstur 256x256 di atlas ini membutuhkan tekstur dengan dimensi 516x516. Perbatasan diberi kode warna berdasarkan bagaimana Anda akan mengisinya dengan data texel selama pembuatan atlas:
- Merah = Ganti dengan texel langsung di bawah
- Kuning = Ganti dengan texel tepat di atas
- Hijau = Ganti dengan texel langsung ke kiri
- Biru = Ganti dengan texel langsung ke kanan
Secara efektif dalam contoh yang dikemas ini, setiap tekstur di atlas menggunakan wilayah atlas 258x258, tetapi Anda akan menghasilkan koordinat tekstur yang memetakan ke wilayah 256x256 yang terlihat. Teks pembatas hanya pernah digunakan ketika penyaringan tekstur dilakukan di tepi tekstur di atlas, dan cara mereka dirancang meniru GL_CLAMP_TO_EDGE
perilaku.
Jika Anda bertanya-tanya, Anda dapat menerapkan jenis mode bungkus lainnya menggunakan pendekatan serupa - GL_REPEAT
dapat diimplementasikan dengan menukar texels perbatasan kiri / kanan dan atas / bawah di atlas tekstur dan sedikit koordinat matematika dengan koordinat tekstur pandai dalam sebuah shader. Itu sedikit lebih rumit, jadi jangan khawatir tentang itu untuk saat ini. Karena Anda hanya berurusan dengan sprite sheet, batasi diri Anda GL_CLAMP_TO_EDGE
:)
GL_NEAREST
atauGL_LINEAR
untuk rendering tekstur?