Dozajlama performansı nasıl artırılır


9

Mobil platformlar için hareketli grafik tabanlı bir 2D oyun geliştiriyorum ve grafikleri oluşturmak için OpenGL (aslında Irrlicht) kullanıyorum. İlk olarak hareketli grafik oluşturmayı basit bir şekilde uyguladım: her oyun nesnesi kendi GPU çizim çağrısı ile dörtlü olarak işlenir, yani 200 oyun nesnesim olsaydı, çerçeve başına 200 çizim çağrısı yaptım. Tabii ki bu kötü bir seçimdi ve oyunum tamamen CPU'ya bağlıydı çünkü her GPU çizim çağrısında küçük bir CPU ek yükü var. GPU çoğu zaman boşta kaldı.

Şimdi, nesneleri büyük gruplar halinde toplayarak ve bu grupları yalnızca birkaç çizim çağrısı ile oluşturarak performansı artırabileceğimi düşündüm. Toplu işlemi uyguladım (böylece aynı dokuyu paylaşan her oyun nesnesi aynı toplu işte işlenir) ve sorunlarımın gittiğini düşündüm ... sadece kare hızımın öncekinden daha düşük olduğunu bulmak için.

Neden? 200 (veya daha fazla) oyun nesnesim var ve saniyede 60 kez güncelleniyor. CPU'daki köşeler için yeni konumu (çeviri ve döndürme) yeniden hesaplamak zorunda olduğum her kare (mobil platformlarda GPU örneklemeyi desteklemediğinden bunu yapamam) ve bu hesaplamayı saniyede 48000 (200 * 60 * 4) her hareketli grafiğin 4 köşesi vardır) çok yavaş görünüyor.

Performansı artırmak için ne yapabilirim? Tüm oyun nesneleri her kareyi hareket ettiriyor / döndürüyor (neredeyse) bu yüzden köşe konumlarını yeniden hesaplamam gerekiyor. Sadece düşünebildiğim optimizasyon rotasyonlar için bir arama tablosu, böylece onları hesaplamak zorunda kalmayacağım. Nokta sprite yardımcı olur mu? Kötü hackler var mı? Başka herhangi bir şey?

Teşekkürler.

Yanıtlar:


5

Android için irrlicht portumu kullandınız mı? Android ve iphone'da 2d sprite için, sizinle aynı hileleri kullanıyorum: OpenGL ES 1.x ve 2.x'te birçok çözüm deniyorum:

  • z (paralaks) ve dokuya göre sıralayın, CPU'daki dönüşümleri yapın ve glDrawArrays veya glDrawElements (en hızlı yol) deyin. Mümkünse büyük bir doku kullanın.
  • VBO ile aynı hile, daha hızlı değil çünkü her çerçeve için tüm bilgileri yeniliyorsunuz. Statik sprite'lar için yararlı olabilir.
  • OpenGL ES 2.x kullanın ve konumları hesaplamak için Vertex gölgelendiricisini kullanın (daha yavaş)
  • PointSprites'i kullanın (kare değilse ve çok fazla saydam piksel dolgu hızını öldürürse çözüm yoktur)
  • gldrawtexoes uzantısını kullan ...
  • her hareketli grafik için bir drawcall kullanın (en yavaş yöntem)

Böylece sizin gibi, tüm dönüşümler CPU tarafından OGLES 1.x veya OGLES 2.x için yapılır. Neon talimatlarınız varsa, hesaplamalarınızı hızlandırmak için bunları kullanabilirsiniz.

Ps: iphone veya android cihazlarda, CPU sınırlı değilim ancak doluluk oranı sınırlı. Bu yüzden fazla çekmeyi sınırlamak çok önemlidir.


Mükemmel, bu aradığım bir şey. Irrlicht bağlantı noktanızın farkında değildim ancak Irrlicht üzerinde sürümüm zaten iOS'ta çalışıyor. CPU sınırlı olmadığınızı söylüyorsunuz - kaç tane sprite çekiyorsunuz? İPhone'daki 100 sprite için kare hızınız nedir? 200 nesnem varsa, saniyede 48000 hesaplama yapıyorum. Doldurma hızı hakkındaki görüşünüz iyi.
user4241

Statik sprite (arkaplan) VBO'dadır. Paralaks başına bir VBO kullanıyorum. Aksi takdirde, Moblox üzerinde 100 ila 200 sprite var. 3G dahil tüm iPhone'larda, 30fps'den fazla (hatırladığım gibi) var. Ama büyük spritelar çok pahalıdır (doldurma sorunu) ....
Ellis

Ben CPU üzerinde yapılan tüm pozisyonlar bilgi işlem ile 20 000 parçacıklar kadar kullanabilirsiniz bir parçacık motoru üzerinde çalışıyorum ve ben aşırı ayarları (3GS ve iPhone4) ile 10fps var. Bu yüzden 3GS veya iPhone4'te iyi kare hızına sahip 1000 sprite mümkün olmalıdır.
Ellis

Teşekkür ederim, çok yardım etmek! Parçacık motorunuzu nasıl uyguluyorsunuz? Sanırım gölgelendiricilerle oynuyorsun?
user4241

Her parçacık boyutunu ayarlamak için gl_PointSize gerektiğinden gölgelendiriciler kullanın. Eski telefonlar hedefim olmadığı için artık OGLES 1.x ile çalışmıyorum. İlk olarak, tüm kodum OGLES 1.x, sonra OGLES 1.x ve OGLES 2.x (performans iyileştirme yok) ve şimdi OGLES 2.x (oluşturma iyileştirme) idi.
Ellis

1

Ben her render nesnenin pozisyon / rotasyon içeren ve yaptığınız gibi doku dayalı toplu VBO sahip tavsiye ederim. Ogl ES'ye çok aşina değilim, bu yüzden hangi glsl sürümünü desteklediğinden emin değilim, ancak bir dizi dokuya dayalı olarak toplu iş yapabilir ve 4 veya daha fazla dokuyu geçtiğinizi depolayabilirsiniz. tepe noktasının içinde kullanırsınız. Nokta spriteları kesinlikle performansınızı artıracaktır, çünkü gönderdiğiniz veri miktarını büyük ölçüde azaltacaktır ve doğru bir şekilde yaparsanız toplu işlem performansı asla düşürmemelidir. Ayrıca, gölgelendiricideki dönüşü hesaplayarak ve yalnızca bir int / float değerini parametrelere veya tepe noktasının içinden geçirerek performansı biraz artırabilirsiniz. (parametreler daha hızlı olurdu,


Cevabınız için teşekkür ederim. Gölgelendiricide döndürme hesaplaması yapma konusundaki öneriniz excellet ama maalesef gölgelendiricileri desteklemeyen OpenGL ES 1 kullanıyorum, bu yüzden sabit boru hattına yapıştım. Nokta spriteları deneyeceğim ama her durumda kullanamıyorum çünkü boyutları için üst sınır var. VBO hakkında hala biraz kötümserim, her bir çerçevenin her çerçevenin konumunu yeniden hesaplarsam, VBO nasıl yardımcı olur?
user4241

tepe noktası verilerinizin gpu üzerinde kalmasına izin verir, bu da her karede gpu'ya göndermek zorunda olduğunuz veri miktarını azaltır. Bu tho'dan yararlanmak için gölgelendiricilere ihtiyacınız yoktur, köşe verilerini hiç değiştirmeniz gerekmez, her bir hareketli grafik için temel bir konumunuz (başlangıç ​​noktası gibi) varsa, dünya matrisini şu şekilde değiştirebilirsiniz: beraberlik çağrılmadan önce dönüşüm. ancak, harmanlama sırasında bu zor olabilir. sabit fonksiyonu kullanarak, muhtemelen VBO'lara geçmek ve en azından şimdilik partiyi bırakmak daha faydalı olacaktır, bu kesinlikle size bir destek verecektir.
sringer

Senin değinmek istediğin noktayı anlıyorum. Sonuçta, yığınlama hakkında konuşmuyorsunuz, sadece bir oyun nesnesini çizmek için bir çizim çağrısı kullanıyorsunuz. Kesinlikle VBO'nun oyunumdaki FPS'yi nasıl etkilediğini test edeceğim, ancak yine de çerçeve başına 200 çizim çağrısı çok büyük geliyor ... ama sanırım onunla yaşamak zorundayım. Başka cevap görünmezse cevabınızı kabul edeceğim.
user4241

1

Örneklemesiz mobil platformlardan bahsediyorsunuz. Ama hala köşe gölgelendiricilerin var, değil mi?

Bu durumda, yine de çok hızlı olan sahte örnekleme yapabilirsiniz. Köşe noktaları (hareketli grafiğin merkez noktasına göre, örneğin -1 / -1, 1 / -1, 1/1, -1/1) ve ihtiyacınız olan doku koordinatlarını içeren bir VBO (GL_STATIC_DRAW) yapın .
Ardından, her çizim çağrısının genel köşe özelliklerinden birini hareketli grafiğin merkez noktasına ayarlayın ve arabellek bağlı olarak iki üçgeni çizin. Köşe gölgelendiricisinin içinde, genel köşe özniteliğini okuyun ve tepe noktasının koordinatlarını ekleyin.

Bu, her hareketli grafik için bir veri aktarımını engellemenizi sağlar ve çok daha hızlı olmalıdır. Gerçek çekiliş çağrıları çok önemli değil, aradaki engelleme / durma.


Bu, OpenGL ES 2.0 için iyi bir çözüm gibi görünüyor. Ne yazık ki hiç gölgelendirici olmayan ES 1 kullanıyorum.
user4241

0

Sorun, her karede GPU'ya gönderdiğiniz veri miktarında bulunur. Her toplu iş için bir VBO oluşturun ve bir kez doldurun, ardından toplu iş çizerken ilgili dönüşüm matrislerini (glMultMatrix veya ES 2.0 kullanıyorsanız bir gölgelendirici) uygulayın.


Benzersiz dönüşümleri olan 200 ayrı oyun nesnesine sahip olduğumda bunun nasıl yardımcı olduğunu anlamıyorum? GlMultMatrix kullanmak istediğim gibi olmayan tüm nesnelere aynı dönüşümü uygular. Ayrıca, GPU'ya veri göndermek darboğaz değildir; CPU tarafı dönüşümlerini kaldırırsam performans çok iyidir.
user4241

Evet, ancak bir VBO doğru şekilde uygulanırsa performansı artırabilir. Şu anda 200 nesnenizi nasıl oluşturuyorsunuz? GlBegin / glEnd kullanıyor musunuz?
TheBuzzSaw

1
Özel sahne düğümü ile Irrlicht 3D motoru kullanıyorum, bu yüzden doğrudan OpenGL kullanmıyorum (ancak bu durumda basit glBegin / glEnd kullanıyor). Tüm çerçeveyi her karede değiştirmek zorunda kaldığım için VBO gerçekten yardımcı olur mu? Ayrıca, bu, tepe dönüşümü hesaplamaları nedeniyle CPU'ya bağlı olma ile ilgili temel sorunu çözmez. Ama yine de cevaplarınız için teşekkürler!
user4241
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.