Zajmuję się tworzeniem gier 2D i mam wiele duszków. Użyłem animacji i modeli 3D do renderowania w 2D, aby nadać im wygląd „Fallout” lub „Diablo”. Jest to również łatwiejsze niż ręczne rysowanie, lol.
Musiałem już zmniejszyć liczbę klatek na sekundę do 15 klatek na sekundę, co było najniższym wynikiem, jaki mogłem obniżyć, nie powodując, że wyglądają na nierówne. Było to jednak smutne z powodu niewiarygodnie gładkich 24 klatek.
Są dwa powody, dla których to zrobiłem:
1) Ogranicz miejsce na dysku twardym. Im mniej obrazów, tym mniejsza będzie moja całkowita gra.
2) Ogranicz zużycie pamięci RAM. Im mniej obrazów do załadowania, tym bardziej prawdopodobne jest, że uniknę problemów z powiększaniem mojego ograniczenia pamięci RAM.
Gdyby jednak istniał sposób na kompresowanie obrazów w przestrzeni HDD i pamięci RAM, zrobiłbym to. Testowałem to już wcześniej i większość nie otrzymuje żadnej zmiany jakości przy nadawaniu z RGBA8888 na RGBA5555 i tylko niewielki hit przy konwersji na RGBA4444 w moim programie TexturePacker. Obecnie nie robię tego, ponieważ SFML wydaje się używać tej samej ilości pamięci, niezależnie od tego, jaki to jest typ obrazu .PNG. Zastanawiałem się, jak inaczej to załadować, ale nie znalazłem nic na ten temat.
Dużo czytałem o tym, jak radzić sobie z grami 2D. Konsensus jest przytłaczający: spakuj swoje duszki w większą teksturę, aby uzyskać doskonałą wydajność! Więc pakuję moje małe duszki do znacznie większego arkusza za pomocą TexturePacker.
Jednak planuję mieć 10-15 animacji na postać, 5 kierunków ruchu i 15-40 klatek na animację (prawdopodobnie średnio 24). Z 15 animacjami, 5 kierunkami i średnio 24 klatkami na animację; To 1800 pojedynczych klatek na znak. Jeśli zapakowane w arkusz sprite, to tylko 75 obrazów zamiast tego. (Jeden arkusz duszka na animację, na kierunek. 15 * 5)
W przypadku jednej ogromnej postaci bossa w grze nie mogę użyć arkusza sprite i muszę zaprogramować sposób, aby po prostu załadować jedno zdjęcie na raz. Nie wiem jeszcze, czy mogę to zrobić dla wydajności.
Dla postaci już spakowałem je do arkusza sprite. W przypadku pojedynczej postaci, która chodzi, wydaje się, że działa to przez większość czasu, chociaż czasami zwleka. Jednak przypisuję to mojemu źle opracowanemu kodowi, który zamienia tekstury zamiast wstępnie ładować wszystkie tekstury dla tego znaku.
Gdybym miał wstępnie załadować tekstury, ma to sens dla arkuszy sprite. Wyobrażam sobie tylko, że to zły pomysł, aby wstępnie załadować 1800 małych obrazów dla każdej postaci.
Jednak wyobrażam sobie, że przesyłanie ich do pamięci i do pamięci pojedynczo byłoby niezwykle szybkie, więc musiałbym mieć tylko jeden obraz w pamięci na raz. Czy to nie znaczy, że w danym momencie każda postać zużyłaby tylko kilka KB zamiast 45 + MB?
Wyobrażam sobie, że zabiłoby to moją wydajność, ponieważ przesyłanie strumieniowe musiałoby być niezwykle szybkie (15 obrazów wchodzących i wychodzących z pamięci i renderowanych na sekundę) i chociaż obrazy byłyby bardzo małe - lepszym pomysłem może być ładowanie arkuszy postaci zamiast tego do pamięci. Ale i tak będę musiał kodować system renderowania podobny do strumienia pojedynczego obrazu dla mojej większej postaci bossa.
Eksperymentowałem, ale nie jest to prosty proces. Zwłaszcza, że pracuję nad innymi częściami silnika gry, które obecnie nie zajmują się grafiką.
Odpowiedzi:
Mamy podobny przypadek z naszym remake'em RTS. Wszystkie jednostki i domy są duszkami. Mamy 18 000 duszków dla jednostek i domów oraz terenu, a także kolejne ~ 6 000 dla kolorów drużynowych (stosowanych jako maski). Długotrwale mamy również około 30 000 znaków używanych w czcionkach.
Zatem głównym powodem atlasów są:
Co nam nie zadziałało:
Teraz mamy wszystko zapakowane w kilkadziesiąt 1024x1024 atlasów (nowoczesne procesory graficzne obsługują nawet większe wymiary) i to działa dobrze, jedząc tylko ~ 300 MB pamięci, co jest całkiem dobre dla gry na PC. Niektóre optymalizacje, które mieliśmy:
Kiedy poważnie zastanawiasz się nad przeniesieniem na urządzenia mobilne, będziesz martwić się ograniczeniami. Na razie wystarczy uruchomić grę i przyciągnąć graczy! ;)
źródło
Mam stycznie powiązanego odpowiedź w tutaj , ale ogólna idea jest taka, że jeśli jesteś załadunku i tekstur rysunku w różnych momentach (nie masz ładowania dodatkowych tekstur gdy jesteś rendering), to nie są dwa miejsca, gdzie co ci wpłynie na twoją wydajność:
Czas ładowania:
To jest moment, w którym umieścisz swoje tekstury w pamięci. Cała ilość danych, które wysyłasz do VRAM, co będzie przede wszystkim określić, jak długo czas ładowania będzie. Uczynienie tekstur mniejszymi formatami, takimi jak RGBA4444, przyspieszy to. Jednak jeśli nie przesyłasz tekstów w wysokich setkach megabajtów do VRAM, prawdopodobnie nie będziesz mieć tutaj wąskiego gardła. Jeśli to zrobisz, ładny ekran ładowania może ułatwić oczekiwanie.
Łączenie tekstur w atlasy będzie miało niewielki efekt, ponieważ cała ilość informacji wysyłanych do VRAM będzie taka sama. W rzeczywistości, jeśli atlujesz swoje tekstury i musisz zostawić puste miejsca w swoich atlasach, wtedy faktycznie wyślesz więcej danych do VRAM, a zatem ta część będzie wolniejsza!
Wydajność renderowania:
Gdy wszystkie tekstury znajdą się w pamięci VRAM, ich liczba nie wpłynie na wydajność renderowania. Istnieją cztery elementy, które wpływają na wydajność renderowania:
Zmiany stanu renderowania : Za każdym razem, gdy zmienisz obraz, z którego chcesz renderować, poważnie wydłuży czas potrzebny do jego renderowania. Ogólnie rzecz biorąc, chcesz zminimalizować liczbę zmian stanu i możesz zmniejszyć liczbę zmian stanu, grupując kilka obrazów, które będziesz kolejno rysować, w atlasie tekstur.
Sam atlasing nie wystarczy. Musisz atlasować w taki sposób, aby zmiany stanu były redukowane, aby uzyskać wzrost wydajności. Na przykład może się wydawać, że umieszczenie głównego bohatera w arkuszu ikonek da ci wzrost wydajności, ale jeśli rysujesz tylko jednego ikonkę z tego arkusza na ramkę, nie uzyskasz żadnego wzrostu wydajności w porównaniu do posiadania każdy duszek w osobnym pliku.
Właściwe atlasing nie jest trywialny, ale ogólnie można bezpiecznie grupować duszki z tej samej warstwy. Na przykład posiadanie wszystkich elementów GUI w jednym arkuszu sprite jest bardzo obiecującym pomysłem, podczas gdy grupowanie potworów alfabetycznie może nie.
Rysuj połączenia: Ogólnie rzecz biorąc, możesz chcieć ograniczyć liczbę swoich połączeń do minimum. Dobrą zasadą jest to, że jeśli nie ma żadnych zmian stanu renderowania między dwoma wywołaniami losowania, możesz połączyć je w jedno wywołanie losowania. Aby uzyskać bardziej zaawansowany wzrost wydajności, możesz użyć, powiedzmy, 8 próbników tekstur i grupowych wywołań rysunkowych dla każdych 8 tekstur, więc musisz zmieniać tekstury tylko co 8 tekstur.
Liczba trójkątów: im więcej narysujesz trójkątów, tym dłużej będzie trzeba je narysować. Jednak we współczesnych komputerach i w większości gier 2D będziesz bardzo daleko od maksymalizacji tego. Możesz bezpiecznie narysować setki tysięcy duszków na ramkę i nadal uzyskać niesamowicie dobre liczby klatek na sekundę. Prawdopodobnie będziesz bardziej związany z procesorem, jeśli rysujesz ogromne ilości duszków, zanim pojawią się problemy z GPU.
Ustawienia interfejsu API: jeśli wszystko robisz dobrze, a wciąż dziwnie mało klatek na sekundę, sprawdź ustawienia, za pomocą których rysujesz swoje duszki. Nie znam SFML, ale na przykład w Direct3D 9, tworzenie bufora wierzchołków za pomocą
D3DUSAGE_DYNAMIC
lub wD3DPOOL_MANAGED
może z łatwością zwiększyć dziesięciokrotnie czas renderowania. Oczywiście użycie vSync ograniczy liczbę klatek na sekundę przy częstotliwości odświeżania monitora. Ponadto użycie niezrównanych FVF może obniżyć wydajność niektórych GPU. To samo dotyczy Direct3D 9.W twoim przypadku sprawdź dokumentację interfejsu API, którego używasz.
Jeśli masz tylko niewielką do umiarkowanej liczbę tekstur (mniej niż 1 GB) i rysujesz małe ilości ikonek (mniej niż milion na ramkę), to pierwszą rzeczą, na którą bym spojrzał, była zmiana ustawień API i następnie zmniejszając liczbę stanów renderowania i rysując połączenia.
źródło