Część terminologii Nieco:
Vertex Array
znajduje się szereg (zwykle float[]
), który zawiera dane wierzchołek. Nie musi być związany z niczym. Nie należy mylić z Vertex Array Object
lub vào, który pójdę na później
Buffer Object
, powszechnie określany jako Vertex Buffer Object
podczas przechowywania wierzchołków lub VBO w skrócie, jest to, co dzwonisz tylko Buffer
.
- Nic nie zostanie zapisane z powrotem do tablicy wierzchołków,
glVertexAttribPointer
działa dokładnie tak samo jak glVertexPointer
lub glTexCoordPointer
działa, zamiast zamiast nazwanych atrybutów, podajesz liczbę określającą własny atrybut. Przekazujesz tę wartość jako index
. Wszystkie twoje połączenia glVertexAttribPointer
zostaną umieszczone w kolejce do następnego połączenia z numerem glDrawArrays
lub glDrawElements
. Jeśli masz powiązanie VAO, VAO przechowa ustawienia dla wszystkich twoich atrybutów.
Głównym problemem jest to, że wprowadzasz mylące atrybuty wierzchołków za pomocą VAO. Atrybuty vertex to tylko nowy sposób definiowania wierzchołków, texcoordów, normaliów itp. Do rysowania. Stan sklepu VAO. Ja pierwszy zamiar wyjaśnić, jak rysunek współpracuje z atrybutów wierzchołków, a następnie wyjaśnić, w jaki sposób można zmniejszyć liczbę od metoda nazywa się VAOs:
- należy włączyć atrybut, zanim będzie można go używać w cieniującego.Na przykład, jeśli chcesz wysłać wierzchołki do modułu cieniującego, najprawdopodobniej prześlesz go jako pierwszy atrybut, 0. Zanim więc wyrenderujesz, musisz włączyć go przy pomocy
glEnableVertexAttribArray(0);
.
- Teraz, gdy atrybut jest włączony, musisz zdefiniować dane, których zamierzasz użyć. W tym celu musisz powiązać swój VBO -
glBindBuffer(GL_ARRAY_BUFFER, myBuffer);
.
- A teraz możemy zdefiniować atrybut -
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
. W kolejności parametru: 0 jest definiowanym atrybutem, 3 jest rozmiarem każdego wierzchołka, GL_FLOAT
jest typem, GL_FALSE
oznacza, że nie znormalizuje każdego wierzchołka, ostatnie 2 zera oznaczają, że nie ma żadnego kroku ani przesunięcia na wierzchołkach.
- narysować coś z nim -
glDrawArrays(GL_TRIANGLES, 0, 6);
- Następną rzeczą, którą wyciągnąć nie mogą wykorzystywać atrybut 0 (realnie to będzie, ale jest to przykład), więc możemy go wyłączyć -
glDisableVertexAttribArray(0);
Wrap, że w glUseProgram()
połączenia i masz system renderowania, który działa poprawnie z shaderów. Ale załóżmy, że masz 5 różnych atrybutów, wierzchołków, texcoordów, normalnych, kolorowych i współrzędnych lightmap. Po pierwsze, będziesz wykonywał pojedyncze wywołanie glVertexAttribPointer
dla każdego z tych atrybutów, a wcześniej musisz włączyć wszystkie atrybuty. Powiedzmy, że definiujesz atrybuty 0-4, tak jak je mam na liście. Można by umożliwić wszystkie z nich tak:
for (int i = 0; i < 5; i++)
glEnableVertexAttribArray(i);
I wtedy trzeba by powiązać różne VBOs dla każdego atrybutu (chyba, że je wszystkie przechowywać w jednym VBO i wykorzystania przesunięć/krok), a następnie trzeba wykonać 5 różne połączenia glVertexAttribPointer
, od glVertexAttribPointer(0,...);
do glVertexAttribPointer(4,...);
dla współrzędnych wierzchołków do lightmap.
Mam nadzieję, że sam system ma sens. Teraz przejdę do VAO, aby wyjaśnić, jak z nich korzystać, aby ograniczyć liczbę wywołań metod podczas wykonywania tego typu renderowania. Należy pamiętać, że korzystanie z VAO nie jest konieczne.
Vertex Array Object
lub VAO służy do przechowywania stan wszystkich połączeń glVertexAttribPointer
i VBOs które były kierowane gdy każde z połączeń glVertexAttribPointer
zostały wykonane.
Generujesz jeden z połączenia z numerem glGenVertexArrays
. Aby przechowywać wszystko, czego potrzebujesz w VAO, powiązaj je z glBindVertexArray
, a następnie wykonaj pełne połączenie remisowe
. Wszystkie wywołania bindowania są przechwytywane i przechowywane przez VAO. Można rozwiązać ten vào z glBindVertexArray(0);
Teraz kiedy chcesz narysować obiekt, nie trzeba ponownie wywołać wszystkie VBO wiąże lub połączenia glVertexAttribPointer
, wystarczy powiązać vào z glBindVertexArray
następnie wywołać glDrawArrays
lub glDrawElements
i będziesz rysował dokładnie to samo, jakbyś wykonywał wszystkie te wywołania metod. Prawdopodobnie również chcesz później rozwiązać VAO.
Po odzwiązaniu VAO, cały stan powraca do stanu sprzed zawiązania VAO. Nie jestem pewien, czy jakiekolwiek zmiany, które wprowadzisz podczas wiązania VAO, są zachowane, ale można je łatwo ustalić za pomocą programu testowego. Myślę, że można myśleć o glBindVertexArray(0);
jako wiążące do „default” vào ...
Aktualizacja: Ktoś zwrócił moją uwagę na potrzebę rzeczywistej rozmowy rysować.Jak się okazuje, nie musisz wykonywać PEŁNEGO wywołania losowania podczas konfigurowania VAO, tylko wszystkie wiążące rzeczy. Nie wiem, dlaczego uważałem, że było to konieczne wcześniej, ale teraz jest naprawione.
"Obiekt bufora wierzchołków lub VBO (czasami nazywany tylko obiektem buforowym)" To "czasami" jest nazywane, ponieważ tak właśnie się nazywa. Jest to po prostu obiekt buforowy, nie różni się od jakiegokolwiek innego obiektu bufora, którego można użyć do tworzenia jednolitych bloków, przesyłania pikseli, przekształcania informacji zwrotnych lub jakiegokolwiek innego użycia. Specyfikacja OpenGL * never * odnosi się do niczego jako "obiekt bufora wierzchołków"; nawet [oryginalna specyfikacja rozszerzenia] (http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt) nigdy tego tak nie nazywa. –
Edytowane w celu dopasowania właściwego nazewnictwa, dziękuję. –
Doskonała odpowiedź. Dziękujemy za poświęcenie czasu na napisanie tego! Kilka pytań uzupełniających jednak: (1) Powiedziałeś "zanim wyrenderujesz, a zanim zdefiniujesz atrybut, musisz go włączyć za pomocą glEnableVertexAttribArray (0)" - czy na pewno trzeba go włączyć przed wywołaniem? glVertexAttribPointer'? W moich testach kolejność nie ma znaczenia. (2) Jeśli rozumiem cię poprawnie, Atrybuty wierzchołków są globalne i tylko ich stan włączony/wyłączony jest zapisany w aktualnie powiązanym VAO? – mpen