2010-12-28 10 views
5

Programuję w języku C# przy użyciu platformy .NET Framework 4 i staram się utworzyć grę opartą na kafelkach z XNA. Mam jedną dużą teksturę (256 pikseli na 4096 pikseli). Pamiętaj, że jest to gra oparta na kaflach, więc ta tekstura jest tak masywna tylko dlatego, że zawiera wiele kafli, z których każda ma rozmiar 32 x 32 piksele. Myślę, że eksperci na pewno wiedzą, jak wygląda gra oparta na kaflach. Orientacja jest ortogonalna (jak szachownica), a nie izometryczna.Rysuj() 20 000 32 na 32 Tekstury lub 1 duża tekstura 20 000 razy

W metodzie Game.Draw() mam dwie możliwości, z których jedna będzie niewiarygodnie wydajniejsza od drugiej.

Wybór/Sposób nr 1:

Semi-Pseudokod:

public void Draw() 
    { 
     // map tiles are drawn left-to-right, top-to-bottom 
     for (int x = 0; x < mapWidth; x++) 
     { 
      for (int y = 0; y < mapHeight; y++) 
      { 
       SpriteBatch.Draw(
        MyLargeTexture, // One large 256 x 4096 texture 
        new Rectangle(x, y, 32, 32), // Destination rectangle - ignore this, its ok 
        new Rectangle(x, y, 32, 32), // Notice the source rectangle 'cuts out' 32 by 32 squares from the texture corresponding to the loop 
        Color.White); // No tint - ignore this, its ok 
      } 
     } 
    } 

Tytuł: Tak, faktycznie, pierwsza metoda jest przedstawieniu jedna duża tekstura wiele razy, za każdym razem za pomocą małego prostokąta o tak dużej teksturze narysuj odpowiedni obraz płytki.

Wybór/Sposób nr 2:

Semi-Pseudokod:

public void Draw() 
    { 
     // map tiles are drawn left-to-right, top-to-bottom 
     for (int x = 0; x < mapWidth; x++) 
     { 
      for (int y = 0; y < mapHeight; y++) 
      { 
       Texture2D tileTexture = map.GetTileTexture(x, y); // Getting a small 32 by 32 texture (different each iteration of the loop) 

       SpriteBatch.Draw(
        tileTexture, 
        new Rectangle(x, y, 32, 32), // Destination rectangle - ignore this, its ok 
        new Rectangle(0, 0, tileTexture.Width, tileTexture.Height), // Notice the source rectangle uses the entire texture, because the entire texture IS 32 by 32 
        Color.White); // No tint - ignore this, its ok 
      } 
     } 
    } 

Tytuł: Tak, faktycznie, druga metoda jest rysunek wiele małych tekstur wiele razy.

Pytanie: Która metoda i dlaczego? Osobiście uważam, że byłoby niezwykle wydajne korzystanie z pierwszej metody. Jeśli myślisz o tym, co to oznacza dla tablicy kafelków na mapie (pomyśl o dużej mapie z 2000 na 2000 płytek, powiedzmy), każdy obiekt Tile musiałby zawierać tylko 2 liczby całkowite, dla pozycji X i Y źródła prostokąt w jednej dużej teksturze - 8 bajtów. Jeśli użyjesz metody # 2, każdy obiekt Tile w tablicy kafelków mapy będzie musiał przechowywać teksturę 32by32 - obraz - który musi 32 razy przypisać pamięć dla pikseli RGBA 32 - to 4096 bajtów na płytkę następnie? A więc, która metoda i dlaczego? Pierwszym priorytetem jest szybkość, a następnie obciążenie pamięci, a następnie wydajność lub to, w co wierzą eksperci.

Odpowiedz

9

Pierwsza metoda będzie szybsza dużo! Tak naprawdę nie ma to nic wspólnego ze strukturami danych po stronie procesora. Prawdopodobnie w obu przypadkach można by uzyskać nawet kilka bajtów - więc nie miało to znaczenia.

Powodem, że pierwsza metoda będzie szybsza, jest sposób działania GPU. Mówiąc prosto, wysyłasz komendy rysowania GPU z listami wierzchołków/trójkątów. Te wierzchołki mają różne dane (położenie, kolor, współrzędne tekstury, itp.). Zasadniczo nie można określić tekstury - teksturę do narysowania trójkątów należy określić na urządzeniu graficznym przed rysowaniem, dla całej listy trójkątów.

To, co robi SpriteBatch, to automatyczne grupowanie twoich duszków, tam gdzie to możliwe, aby zminimalizować zamiany tekstur, a co za tym idzie wysłanie poleceń. Dlatego ma opcję sortowania według faktur. Właśnie dlatego istnieje parametr źródło-prostokąt - aby umożliwić korzystanie z arkuszy sprite - dzięki czemu więcej duszków można narysować bez konieczności zmiany tekstur.

(W rzeczywistości komendy rysowania wysyłane do procesora graficznego - nawet jeśli nie używasz SpritBatch - są znane jako "partie", a kiedy wysyłasz za dużo, stajesz się "partiami limitowanymi". partia ograniczona - kilkaset partii to bardzo przybliżona ocena limitu.)

+0

Naprawdę doceniam kompleksową odpowiedź. Wielkie dzięki! – Jason

2

Zgadzam się. Im mniej tekstur, które pobierasz, tym szybciej, ponieważ minimalizuje zmiany stanu na GPU.

Aby było jeszcze szybciej, należy pamiętać, że większość płytek nie zmienia się między klatkami. Tak więc, wciągnij je wszystkie do jednego celu renderowania z jednym ekranem, a następnie na kolejne ramki, przerysuj tylko tę pojedynczą teksturę za pomocą jednego połączenia typu draw. Dodaj płytki, które zmieniają się na górze.

+0

Dzięki za twój wgląd! – Jason

Powiązane problemy