Dalam browser, apakah lebih baik menggunakan satu spritesheet besar atau banyak (10000) PNG berbeda?

33

Saya membuat game di jQuery, tempat saya menggunakan sekitar 10.000 32x32 ubin. Sampai sekarang, saya telah menggunakan semuanya secara terpisah (tanpa sprite sheet). Peta rata-rata menggunakan sekitar 2000 ubin (kadang-kadang digunakan kembali PNG tetapi semua div terpisah) dan kinerjanya berkisar dari stabil (Chrome) hingga agak lambat (Firefox). Masing-masing divs diposisikan benar-benar menggunakan CSS. Mereka tidak perlu diperbarui setiap centang, hanya ketika peta baru dimuat.

Apakah lebih baik bagi kinerja untuk menggunakan metode spritesheet untuk divs menggunakan penentuan posisi latar CSS, seperti yang dilakukan gameQuery?

Terima kasih sebelumnya!

Nick
sumber
3
Di mana Anda membutuhkan 10.000 ubin untuk peta? Saya menyarankan agar Anda tidak mengunggah / menggambar semua peta di sisi pengguna. Tunjukkan hanya sebagian, itu terlihat. Saat pengguna bergerak, muat bagian berikutnya. Cara setiap grafik 3D bekerja.
Deele
Peta rata-rata menggunakan 2000 ubin berbeda, atau hanya 2.000 ubin total? Seberapa besar peta yang Anda buat?
Nick Larsen
Sudahkah Anda mempertimbangkan untuk menggunakan satu atau beberapa gambar yang lebih besar sebagai latar belakang dan melakukan deteksi tabrakan poligon untuk batas?
SAHornickel

Jawaban:

50

Saran saya

Terlalu banyak PNG kecil akan menambah banyak overhead jaringan (karena ukuran permintaan HTTP, tetapi juga header PNG, dan, bahkan mungkin lebih penting lagi, ketidakmampuan untuk kompres secara efisien). Di sisi lain, satu PNG yang sangat besar memiliki kekurangan yang perlu waktu untuk memuat, dan perlu tetap secara permanen di memori (40 megabyte untuk 10.000 ubin) dalam potongan memori yang terus menerus.

Saya merekomendasikan jalan tengah: beberapa PNG berukuran cukup, misalnya 1024 ubin ukuran 32 × 32 . Mungkin dikelompokkan berdasarkan tema (misalnya, PNG dengan ubin hutan, satu dengan ubin gunung, yang lain dengan ubin kota - Saya tidak tahu tema permainan Anda, tetapi Anda mengerti).

Catatan tentang efisiensi cache

Karena efisiensi akses memori, Anda tidak boleh membuat spritesheets Anda terlalu lebar. Blitting tile dari gambar 128 × 8192 akan selalu lebih cepat daripada blitting dari gambar 8192 × 128.

Bayangkan Anda ingin membuka ubin pertama dalam gambar 8192 × 128. Demi kesederhanaan, anggap 1 pixel adalah 1 byte. Dua baris piksel pertama ditata dengan cara ini (sel berisi nomor byte mereka di memori):

┌────┬────┬───┬────┬──────────┬─────┐
  0   1 │...│ 31    ....    8191 1st line of pixels: bytes 0 to 8191
├────┼────┼───┼────┼──────────┼─────┤
81928193│...│8223   ....   16383 2nd line of pixels: bytes 8192 to 16383
├────┼────┼───┼────┼──────────┼─────┤
 ..  .. │...│ ..    ....    ... 

Jadi untuk blit dengan baris pertama dari judul pertama, mesin browser akan mengambil byte 0ke31 . Untuk blit yang baris kedua , itu akan mengambil byte 8192untuk8223 , dan seterusnya sampai garis ke-32 di mana byte 253952untuk253983 diambil.

Jumlah total byte yang diproses adalah 32 × 32. Namun, rentang memori total lebih dari 253984 byte. Pada CPU modern, ini berarti 32 atau 33 cache cache . Sebaliknya, jika gambar itu 128 × 8192, rentang memori hanya akan 4000 byte, yang berarti tidak lebih dari dua kios cache.

Karena CPU saat ini sangat cepat, cache cache sangat mahal dan menggantung perhitungan. Jadi menggunakan gambar 128 × 8192 dan bukannya gambar 8192 × 128 berpotensi 8 kali lebih cepat, setidaknya secara teori. Dalam praktiknya ini akan tergantung pada bagaimana blitting diimplementasikan: ada kemungkinan bahwa mesin yang mendasarinya sendiri membagi gambar menjadi ubin untuk mengurangi masalah.

Ini tidak mudah untuk dijelaskan dengan benar dan saya tidak berharap banyak menguraikan. Saya harap ini masuk akal!

sam hocevar
sumber
4
"Perhatikan juga bahwa karena efisiensi akses memori, Anda seharusnya tidak pernah membuat spritesheets Anda terlalu lebar. Memukul ubin dari gambar 128 × 8192 akan selalu lebih cepat daripada memoles dari gambar 8192 × 128." - Keingintahuan yang bagus, tolong jelaskan? :)
Grimshaw
@DevilWithin: Saya telah mencoba menjelaskan masalahnya; beri tahu saya jika saya cukup jelas!
sam hocevar
Hal-hal efisiensi cache sangat menarik. Apakah Anda memiliki angka tentang perbedaan ini sehubungan dengan framerate?
Gregory Avery-Weir
Apakah itu masalah, sepertinya implementasi khusus, tetapi jika API seperti OpenGL bertindak pada tekstur seperti itu, tentu penting untuk mempertimbangkannya, terima kasih :)
Grimshaw
2
@DevilWithin: apa yang saya tulis hanya berlaku untuk CPU - GPU, yang paralel secara masif, memiliki pengaturan cache yang sangat berbeda dan akan menyimpan tekstur menggunakan format internal sendiri, dioptimalkan untuk akses acak. Ini adalah alasan mengapa tekstur persegi, kekuatan dua direkomendasikan dalam OpenGL, dan saya akan mengikuti aturan itu untuk tileset juga.
sam hocevar
5

Satu spritesheet besar (kemungkinan) akan memberi Anda kinerja yang lebih baik, hanya karena salah satu penyebab lag terbesar adalah perjalanan pulang pergi dari permintaan browser ke server ke browser. 10.000 panggilan HTTP akan memakan waktu lebih lama, lebih lama dari 1 panggilan HTTP yang mengembalikan file yang 10.000 lebih besar.

Mungkin ada hal-hal lain yang dapat Anda gunakan untuk mengurangi jeda, tergantung pada struktur gim dan HTML yang Anda buat.

thedaian
sumber