2D grafikler - neden spritesheets kullanıyorsunuz?


62

Sprite'ların bir sprite sayfasından nasıl oluşturulacağına dair pek çok örnek gördüm, ancak neden 2d oyunlarda sprite ile başa çıkmanın en yaygın yolu olduğunu anlamadım.

Belirli bir sprite türü için her animasyon karesini kendi dokusu olarak ele alarak yaptığım birkaç demo uygulamasında 2d sprite rendering ile başladım - ve bu doku koleksiyonu bir sözlükte depolanıyor. Bu benim için çalışıyor gibi görünüyor ve animasyonlarımı gif / mng dosyaları olarak yapma ve sonra çerçeveleri tek tek png'lere çıkartma eğiliminde olduğum için iş akışıma oldukça uygun.

Tek tek dokulardan ziyade tek bir sayfadan oluşturmanın göze çarpan bir performans avantajı var mı? Saniyede yüzlerce kez ekrana milyonlarca çokgen çizebilen modern donanımla, birkaç düzine 50x100px dikdörtgenle uğraşan 2d oyunlar için bile önemli mi?

Bir dokuyu grafik belleğine yükleme ve onu XNA'da görüntüleme uygulama ayrıntıları oldukça soyutlanmış görünüyor. Tek bildiğim, dokular yüklendiklerinde grafik cihaza bağlı oldukları, ardından oyun döngüsü sırasında dokuların gruplar halinde işlendiği. Bu yüzden seçimimin performansı etkileyip etkilemediği net değil.

2d oyun geliştiricilerin çoğunun onları kullanıyor gibi göründüğünün çok iyi nedenleri olduğundan şüpheliyim, nedenini anlamıyorum.


Hayır, 50 garip sprite için gerçekten çok fazla önemli değil. Ama kaybedecek ne var ki?
Komünist Ördek

Yanıtlar:


69

Spritesheets kullanmak için güçlü bir argüman, grafik kartındaki mevcut doku sayısının sınırlandırılabileceğidir. Bu nedenle grafik kitaplığınızın dokusunu sürekli kaldırması ve dokuları GPU'ya yeniden tahsis etmesi gerekir. Sadece bir kez büyük bir doku tahsis etmek çok daha verimli.

Ayrıca doku boyutlarının genellikle 2 olduğunu düşünün. Dolayısıyla, bir 50x100 piksel Sprite değerine sahipseniz, 64x128 piksel boyutunda veya daha kötü durumda 128x128 piksel boyutundaki dokuları tahsis edersiniz. Bu sadece grafik hafızasını boşa harcıyor. Tüm sprite'ları 1024x1024px'lik bir dokuya daha iyi yerleştirin, bu da 20x10 sprite olur ve yatay ve dikey olarak sadece 24 piksel kaybedersiniz. Bazen, farklı boyutlardaki sprite'lar bile dokuyu mümkün olduğu kadar verimli kullanmak için büyük bir sprite sayfasına birleştirilir.

Zeyilname: Sprite-levha kullanmanın çok önemli bir nedeni, GPU’nuzdaki beraberlik aramaların miktarını azaltmaktır; bu da performans üzerinde kayda değer bir etkiye sahiptir. Bu diğer cevaplarda da belirtilmiştir ve bunu daha fazla görünürlük elde etmesi için tamlık adına ekliyorum.


1
Teşekkürler, bu noktalardan hiçbirini düşünmedim - Kabaca mevcut doku sayısının sınırının ne olduğunu biliyor musunuz? Grafik özelliklerini belirtilen bu statü hiç görmedim - limit temelde grafik RAM miktarına eşit mi?
Columbo

Genellikle sınır GPU hafızası olur, evet. Eski kartlardaki dokuların sayısında bazı kısıtlamalar olduğunu düşündüm ama bu noktayı ispatlayan bir referans bulamıyorum.
serseri

12
Miktarda bir sınır olmasa bile, çok sayıda küçük görüntüyü taşımak için veri yolu trafiği bir (veya birkaç) büyük aktarım (lar) kadar verimli değildir.
Mordachai

5
İyi noktalar, ancak en önemli husus, beraberlik çağrısını geri sayarak boru hattı duraklatmasını en aza indirgemektir. GPU'lar, küçük ölçekli büyük işlerden ziyade küçük miktarda büyük işi tercih ediyor. Tüm sprite'larınızı küçük, büyük miktarlarda bir miktara yerleştirmek, metin aşamasını bir kez ayarlayabilir ve bir kerede toplu olarak çok fazla spekür çizebilirsiniz. Spritebatch bunu sizin için yapar. Birden fazla çizelge sayfanız varsa, dokuya göre sıralamak için spritebatch'e bildirdiğinizden emin olun
Cubed2D

Ekleme doku sıkıştırma bütün bunlar üstüne, yükü çok küçük bir az miktarda herhangi gevşeklik alanı açacak
Joe Plante

36

Kullanacağım tartışmanın tek bir beraberlik çağrısında birden fazla şeyi yapabilme yeteneği olacağını söyleyebilirim. Örneğin font oluşturma, örneğin bir elektronik tablo olmadan, her karakteri ayrı bir doku takasıyla ve ardından bir beraberlik çağrısı ile yapmanız gerekecek. Bunları bir elektronik tabloya atın ve tüm cümleleri tek bir beraberlik çağrısıyla (köşeler için farklı UV'leri belirterek seçili olan fonttaki fark karakterleri) oluşturabilirsiniz. Bu, çok sayıda platformda çok fazla gerçekleme işleme yükü çok fazla API çağrısı yapmaktayken, çok daha verimli bir oluşturma yöntemidir.

Ayrıca yerden tasarruf etmenize de yardımcı olabilir, ancak ilk etapta ambalajınızın içine ne koyduğuna bağlıdır.


2
+1 Çizim çağrıları üzerine dokunur. (kabul edilen cevabında görmediğim bir şey)
Michael Coleman

11

Her beraberlik çağrısı belirli bir miktar ek yüke sahiptir. Sprite sayfalarını kullanarak, bir animasyonun aynı karesini kullanmayan şeylerin resmini (veya genellikle aynı malzemede bulunan her şeyi), performansı büyük ölçüde artırabilirsiniz. Oyununuza bağlı olarak modern PC'ler için bu çok önemli olmayabilir, ancak iPhone için kesinlikle önemlidir.


2
Kesinlikle hala önemli. Grafik donanımı, az sayıda ayrıntılı model için (örneğin karakterler) tonlarca poligonu itmeye yönelik olarak optimize edilmiştir, çünkü çoğu oyun bu yöndedir. Sonuç olarak, sadece birkaç düzine arama çağrısında mümkün olduğu kadar çokgen itmeniz gerekiyor. Şehir gibi büyük sahneler yaratan oyun motorları, çekiliş çağrılarını azaltmak için çoğu zaman birden fazla dokuyu anında bir araya getirir.
jhocking

Çok fazla 3B donanımda doku eşleştirmesi yapmanın ve bit karıştırma işlemlerinin hareketli sayfadan faydalanıp faydalanmadığını kesinlikle merak ediyorum.
Joe Plante

7

Performans değerlendirmelerine ek olarak, sprite levhalar sanat oluştururken kullanışlı olabilir; Her karakter kendi sayfasında olabilir ve tüm kareleri sadece kaydırarak görebilirsiniz. Tüm karelere tutarlı bir bakış atmamı sağlıyor.

Ek olarak, AS3'te kodluyorum ve her resim dosyası ayrı bir gömme talimatı gerektiriyor. Ayrı bir kaynak sınıfı kullanıyor olsam bile, tüm kareler için 24 gömme yerine tek bir çizelgenin tamamının tek bir gömülmesini tercih ederim.


1
+1. OP, Flash kullanmasa da, gömme veya yükleme de spritesets lehine bir nokta. Ayrıca, varlıklar bir Web sunucusundan yüklendiğinde de geçerlidir (her istek için "her istek için") birkaç yüz istek için 1 istek tercih edilir.
serseri

Kesinlikle bir çevrimiçi oyun için sunucu isteklerini azaltmak istiyorum. Her ikisinin de bu ana amacı gerçekleştirebilmesi için görüntüleri bir .swf dosyasına veya bir elektronik tabloya koymanın daha iyi olup olmadığını düşündük (nihayetinde sprite sayfalarının sanatçılarımız için daha az emek harcadığına karar verdik).
12'de 12:12

7

XNA ile spritesheets kullanmak için başka bir neden de Xbox360 geliştirme ile projenizdeki dosya sayısıyla ilgili olarak yavaş dağıtım / yükleme süreleriyle ilgili bilinen bir sorun olmasıdır. Bu nedenle, çok sayıda küçük resim dosyasının tek bir resim dosyası halinde birleştirilmesi bu sorunla mücadeleye yardımcı olacaktır.


5

Burada hafıza / GPU'dan bahsetmeyeceğim, çünkü böyle cevaplar var.

Bunun yerine, sanatınızı üzerinde çalıştıkça ve sonrasında temizleyebilir. Yürüyüş döngüsünü görmek için 10 görüntü arasında gezinmek yerine tüm kareleri tek seferde görebilirsiniz. Bunu dağıtmak istiyorsanız, 10 yerine başa çıkmak için yalnızca 1 dosyanız var.

Ve sonra (organize bir bakış açısıyla) karakter.png ve enemy.png karakterwalk01 üzerinden karakterwalk10'a, daha sonra characterattack01'den characterattack05'e sahip olmak daha temiz ve devam ediyor.


4

Grafik belleği, disklerdeki dosya sistemleri gibi şişirilmiş bir bellek yönetimine sahip değildir ; oposite budur: basit ve hızlı tutulur .

Bu kadar basit ve hızlı bir bellek yönetimi, genişliğini ve / veya yüksekliğini yarıya indirmek suretiyle birden fazla küçük sprite kesilmiş yalnızca tek bir dev 4096x4096 sprite sahip olması gibi olabilir. (Benzer bir 1 boyutlu hafıza yönetimi tekniği var, ancak adını unuttum.) Sonunda, Birleştirme gerçekleştirilmelidir.

Çalışma zamanında bu tür bellek yönetimini atlamak için , geliştiriciler derleme zamanında veya grafiklerin tasarım sürecinde otomatik olarak tek büyük sprite'ları birden fazla küçük sprite ile doldururlar .


3

Ayrıca, başlatma sırasında sizi kurtarabilecek G / Ç işlemlerini de unutmayın. Bir CD sürücüsünden yüklüyorsanız, her dosya ekstra bir G / Ç çağrısıdır ve aranması biraz zaman alabilir (modern HDD'ler dosya başına yaklaşık 15 ms, CD'ler belki 50-100 ms?). Bu, yalnızca bir dosyanın alınması gerektiğinden size çok fazla başlatma süresi kazandırır. Ayrıca, uygulamanızın başka bir şey yapması durumunda (GPU'yu beklemek gibi) işletim sisteminizin bu G / Ç işlemlerini önbelleğe almasını sağlar.


1
Diğer taraftan, dosya arama sorununu çözmek istiyorsanız, tüm sprite'larınızı özel bir format kullanarak tek bir dosyada paketleyebilirsiniz. Çoğu oyun bunu yapar.
Tigrou

0

Daha verimli performanstan başka, daha kolay buluyorum. Sanatı oluştururken resimlerinizin daima sınırlarının içinde kaldığından emin olmak için biraz fazladan çalışma yapmanız gerekir, ancak şu anda uğraştığınız tüm görüntüleri görmeniz çok daha kolaydır.

Kanıtlamak da daha kolay, bence. Sadece şöyle bir nesne dizisine sahibim:

sheet = {
    img: (the actual image),
    rects: [
        {x:0, y:0, w:32, h:32},
        {x:32, y:0, w:32, h:32},
        {x:64, y:0, w:32, h:32}
    ]
};

sheets.push(sheet);

Sonra her öğe için iki değer vereceğim: levha ve rect. Sayfa, nesneler dizisindeki dizin olur ve rect, bu sayfanın rects dizisindeki dizin olur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.