2013-01-10 18 views
19

Piszę trochę silnika graficznego za pomocą OpenGL (przez OpenTK z C#).OpenGL, VAO i wiele buforów

Aby zdefiniować atrybuty wierzchołków, posiadam klasę VertexDeclaration z tablicą struktur VertexElement odwzorowanych na wywołania glEnableVertexAttribArray/glVertexAttribPointer.

Ponadto, w celu obsługi wielu strumieni wierzchołków, mam specjalną strukturę przechowującą bufor wierzchołków, deklarację wierzchołków, przesunięcie wierzchołków i częstotliwość wystąpienia (jak struktura XNA VertexBufferBinding).

Obecnie za każdym razem, gdy wywoływane jest wywołanie rysunku, wykonuję iteracje po wszystkich ustawionych strumieniach wierzchołków i wiążę ich bufory wierzchołków, stosuję deklaracje wierzchołków, wyłączam nieużywane atrybuty wierzchołków i rysuję prymitywy.

Chciałbym użyć VAO do buforowania wywołań glEnableVertexAttribArray do nich, i zawsze, gdy stosowany jest strumień wierzchołków, należy powiązać VAO i zmienić powiązanie bufora tablicowego.

Czy to właściwe użycie VAO?

Odpowiedz

34

Czy to właściwe użycie VAO?

Nie .

glVertexAttribPointeruses the buffer object that was bound to GL_ARRAY_BUFFERat the moment the function was called. Więc nie można tego zrobić:

glVertexAttribPointer(...); 
glBindBuffer(GL_ARRAY_BUFFER, bufferObject); 
glDrawArrays(...); 

Będzie to nie użycie bufferObject; użyje tego, co było związane z GL_ARRAY_BUFFER, gdy pierwotnie wywołano nazwę glVertexAttribPointer.

VAO przechwytują ten stan. VAO będzie więc, dla każdego atrybutu vertex, zapisywać obiekt buforowy, który był związany z GL_ARRAY_BUFFER, gdy został wywołany. W ten sposób można robić rzeczy tak:

glBindVertexArray(VAO); 
glBindBuffer(GL_ARRAY_BUFFER, buffer1); 
glVertexAttribPointer(0, ...); 
glVertexAttribPointer(1, ...); 
glBindBuffer(GL_ARRAY_BUFFER, buffer2); 
glVertexAttribPointer(2, ...); 

Atrybuty 0 i 1 będzie pochodzić z buffer1 i Atrybut 2 będzie pochodzić z buffer2. VAO przechwytuje teraz cały ten stan. Aby uczynić, po prostu to zrobić:

glBindVertexArray(VAO); 
glDraw*(); 

W skrócie, jeśli chcesz zmienić miejsce przechowywania atrybut pochodzi z OpenGL, należy również zmienić to Format. Nawet jeśli jest to ten sam format, musisz ponownie zadzwonić pod numer glVertexAttribPointer.

: Ta dyskusja zakłada jesteś nie użyciu nowego ARB_vertex_attrib_binding. Lub, jak wiadomo, "Exactly how Direct3D does vertex attribute binding." Jeśli używasz implementacji oferującej to rozszerzenie, możesz efektywnie robić to, o czym mówisz, ponieważ format atrybutu nie jest powiązany z pamięcią obiektu bufora. Nie ma też torturowanej logiki glVertexAttribPointer.

Ogólnie rzecz ujmując, sposobem rozwiązania tego problemu w świecie OpenGL jest umieszczenie jak największej liczby rzeczy w tym samym obiekcie bufora. W przeciwnym razie wystarczy użyć jednego VAO dla każdego obiektu.

+0

Dzięki za tę wspaniałą odpowiedź.W takim razie krok 'glBufferData' wchodzi w życie? Czy nie musisz najpierw buforować danych przed użyciem "glVertexAttribPointer"? Przepraszamy, jestem bardzo nowy w OpenGL –