Różnica w glDrawArrays i glDrawElements


12

Odświeżając swój umysł w OpenGL ES, natknąłem się na glDrawArraysi glDrawElements.

Rozumiem, w jaki sposób są używane i rozumiem, dlaczego się różnią.

Wydaje mi się, że nie rozumiem tego, że nie rozumiem, w jaki sposób glDrawElementsmożna zapisywać wezwania do losowania ( zapisywanie wezwań do losowania to opis, o którym wspomina większość książek, które przeczytałem, stąd moja wzmianka o tym tutaj).

Wyobraź sobie prosty scenariusz, w którym próbowałem narysować kwadrat za pomocą 2 trójkątów.

Potrzebowałbym mieć zestaw 6 wierzchołków używających glDrawArrayspodczas używania glDrawElements, potrzebowałbym tylko 4 oprócz tablicy indeksów, która ma 6 elementów.

Biorąc pod uwagę powyższe, oto, czego nie rozumiem:

  1. w jaki sposób można glDrawElementszapisać wywołania losowania, jeśli nadal musi korzystać z tablicy indeksów (6 indeksów, w przypadku kwadratu), aby indeksować do mojej tablicy wierzchołków, która zawierała 4 elementy (6 razy)? Innymi słowy, czy to oznacza, glDrawElementsże nadal musiałoby mieć w sumie 6 takich samych losowań glDrawArrays?
  2. w jaki sposób glDrawElementsoszczędzać miejsce, gdyby nadal trzeba było mieć 2 tablice, a mianowicie jedną dla wierzchołków i jedną dla indeksów?
  3. W przypadku rysowania kwadratu z 2 trójkątów, dla uproszczenia, ilu wywołań rysunkowych potrzebuje glDrawElements(4 elementy w tablicy wierzchołków i 6 elementów w tablicy indeksów) i glDrawArrays(6 elementów tylko w tablicy wierzchołków) indywidualnie?

Dzięki.

Odpowiedzi:


16

Każdy glDraw * jest sprawdzeniem losowania.

1 glDrawArrays to 1 call draw.
1 glDrawElements to 1 call draw.

Nie ma znaczenia (jeśli chodzi o liczbę wywołań remisowych), ile wierzchołków lub indeksów używasz, 1 glDraw * to 1 call draw.

Proste przypadki rysowania quadów (zakładając, że używana wersja GL nie usunęła quadów) lub trójkątów, nie są dobrym przykładem na ich porównanie, ponieważ listę quadów lub listę trójkątów można narysować za pomocą jednego wywołania i glDrawArrays będą wydawać się bardziej wydajne, ponieważ nie mają dodatkowego obciążenia związanego z indeksowaniem.

Weźmy nieco bardziej złożony przypadek, ale taki, który reprezentuje bardziej realistyczny scenariusz. Wyobraź sobie, że masz model złożony z wielu trójkątnych pasków i wentylatorów:

glDrawArrays (GL_TRIANGLE_FAN, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_FAN, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_FAN, .....);

W tym przykładzie użycie glDrawArrays daje w sumie 6 wywołań rysowania dla modelu. Jednak zarówno paski, jak i wentylatory można łatwo przekonwertować na indeksowane trójkąty, więc dodaj indeksy i będzie to:

glDrawElements (GL_TRIANGLES, .....);

To jedno losowanie dla całego modelu.


Zalety glDrawElements w porównaniu z glDrawArrays to coś więcej niż tylko oszczędność pamięci, co jest naiwnym sposobem pomiaru. Istnieje możliwość zaoszczędzenia pamięci, gdy wierzchołki mogą być ponownie użyte, ponieważ indeks jest zwykle mniejszy niż wierzchołek (więc nawet jeśli masz wiele wskaźników w równowadze, będą one mniejsze), ale inne zalety to:

  • Zmniejszona liczba połączeń losujących. Każde wywołanie losowania wiąże się z pewnym obciążeniem związanym z weryfikowaniem stanu, konfigurowaniem itp., A znaczna część tego obciążenia występuje po stronie procesora. Zmniejszając liczbę sprawdzanych połączeń, unikamy dużej części tego narzutu.

  • Ponowne użycie wierzchołków. To znacznie więcej niż tylko oszczędzanie pamięci. Twój procesor graficzny prawdopodobnie ma sprzętową pamięć podręczną wierzchołków, w której można przechowywać ostatnio przekształcone wierzchołki; jeśli ten sam wierzchołek pojawi się ponownie, a jeśli jest w pamięci podręcznej, można go ponownie użyć z pamięci podręcznej zamiast konieczności ponownej transformacji. Twój sprzęt sprawdzi pamięć podręczną, porównując indeksy, więc w kategoriach OpenGL jedynym sposobem korzystania z pamięci podręcznej jest użycie glDrawElements.


Aby odpowiedzieć na konkretne pytania:

  1. w jaki sposób glDrawElements może zapisać połączenia losowania ...? W użytym przykładzie tak nie jest. Każdy ma jedno losowanie. Jak dyskutuję powyżej, ten przykład jest bardzo zły do ​​porównania tych dwóch.

  2. jak użycie glDrawElements oszczędza miejsce ...? Ponieważ indeksy są mniejsze niż wierzchołki. Indeks 16-bitowy to dwa bajty, a wierzchołek pozycji / koloru / texcoorda ma 24 bajty. 6 wierzchołków to 144 bajty, 4 wierzchołki plus 6 wskaźników to 108 bajtów.

  3. W przypadku rysowania kwadratu z 2 trójkątów ...? Sam na sam. Wywołanie glDraw * to jedno wywołanie losowania, liczba użytych wierzchołków lub indeksów nie ma znaczenia dla tego pomiaru. Ale muszę ponownie podkreślić, to bardzo zły przykład na porównanie tych dwóch.


Wreszcie, aby nieco skomplikować sprawę, podczas gdy glDrawElements z trójkątami jest optymalną ścieżką na komputerowych procesorach graficznych, na urządzeniach mobilnych może być zupełnie inaczej. Niektóre mobilne układy GPU mogą preferować glDrawArrays z GL_TRIANGLE_STRIP (w tym przypadku dodamy zdegenerowane trójkąty do konkatenacji prymitywów), a nawet nie poruszyłem bardziej zaawansowanych tematów, takich jak prymitywne restartowanie lub wielokrotne losowanie.


Dziękuję bardzo za opinie; Poświęcam trochę czasu na przeczytanie tego, co udostępniłeś. Chciałem tylko poinformować, że potwierdziłem twoją odpowiedź. Dzięki jeszcze raz.
Unheilig,

W przykładzie konwersji 6 wywołań DrawTriangleFans i DrawTriangleStrips na 1 pojedyncze wywołanie DrawTriangles. Czy to naprawdę poprawia wydajność? Mojego rozeznania rysunek pasek trójkąt składający się z 100 trójkątów jest dużo bardziej wydajny niż rysunek 100 trójkątów indywidualnie, a korzyści byłyby łatwo zrównoważyć kary nastąpiło z użyciem 6 wywołań funkcji, zamiast 1.
Samuel Li

@SamuelLi 6-to-1 nie będzie ogromną poprawą, ma jedynie na celu zilustrowanie zasady. Ponadto, jak już wskazałem, paski zwykle nie stanowią wygranej wydajności w stosunku do indeksowanych list na sprzęcie komputerowym po 1998 roku. Sprawdź datę na dowolnym dokumencie zalecającym użycie pasków.
Maximus Minimus

Masz rację, dzięki za wyjaśnienia! @MaximusMinimus
Samuel Li
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.