2012-01-21 27 views
7

Po wyszukaniu i przeczytaniu o Modern OpenGL w celu uaktualnienia mojego istniejącego projektu, jestem nieco zdezorientowany, ponieważ moja architektura 3D oparta jest na OpenGL 2.1.Nowoczesne OpenGL: stosy VBO, GLM i Matrix

tak, o ile mi się ...

  • Musimy wygenerować nasze Vertex-buffer-obiektów z wierzchołków, normalnych, indeksów, kolorów, UVS itp

  • następnie możemy użyć GLM do transformacji macierzy, i używamy tylko VBO stworzyć lub manipulować siatki wreszcie mijamy wszystko do cieniowania wierzchołków GLSL jak ten ...

    glm::mat4 MVP = projection * view * model; 
    glUniformMatrix4fv(glGetUniformLocation(shaderProgramID, "MVP"), 1, GL_FALSE, glm::value_ptr(MVP)); //or &MVP[0][0] 
    
    // uniform mat4 MVP; 
    // in vec3 Vertex; 
    // void main(void) 
    // { 
    // gl_Position = MVP * vec4(Vertex, 1.0); //instead of ftransform(); 
    // } 
    

PYTANIE: Jak wykonujemy transformacje hierarchiczne bez technologii pushMatrix/popMatrix? (czy może dokonujemy transformacji hierarchicznej za pomocą naszych VBO, czy jest to możliwe?)

Jeśli nie jest to możliwe, to w jaki sposób osiągnąć ten sam rezultat, co w pushMatrix/popMatrix przy użyciu stosu GLM i C++ <> biblioteka?

Powiedzmy, muszę coś takiego:

> Set identity 
> Translate to X, Y, Z 
> Draw Mesh 1 
> Rotate 0.5 by X axis 
> Draw Mesh 2 
> Scale down to 0.1 
> Draw Mesh 3 
+1

@ BЈовић: [Matematyka OpenGL (GLM)] (http://glm.g-truc.net/), biblioteka C++ przeznaczona tylko do nagłówka dla matematyki/matematyki wektorowej. – genpfault

Odpowiedz

5
  • Musimy wygenerować nasze Vertex-buffer-obiektów z wierzchołków, indeksy, normalne, kolory, UVS itp

to naprawdę nie jest konieczne stosowanie VBOs, po stronie klienta działają również Vertex Arrays. Jednak zdecydowanie zaleca się korzystanie z VBO, ponieważ ułatwia życie kierowcy, a na dłuższą metę również jako użytkownika, który musi żonglować danymi. Obciążenie kodu jest pomijalne (mniej więcej tak samo, jak generowanie i przesyłanie danych tekstur), a wydajność będzie tylko większa.

  • następnie możemy wykorzystać GLM do transformacji macierzy, i używamy tylko VBO stworzyć lub manipulować siatki wreszcie mijamy wszystko w GLSL cieniowania wierzchołków, jak to ...

You nie ogranicza się tylko do GLM. Możliwa będzie każda biblioteka matematyczna. Jeśli szukasz czegoś, czego możesz użyć w C99, zajrzyj do mojego (wciąż niekompletnego) linmath.hhttps://github.com/datenwolf/linmath.h, który jest po prostu plikiem nagłówkowym z funkcjami static inline.Muszę jeszcze sprawdzić, czy powielanie kodu ma negatywny wpływ na wydajność (rozmiar kodu tworzy ciśnienie pamięci podręcznej L1).

PYTANIE: Jak zrobić hierarchiczne transformacje bez pushMatrix/popMatrix? (a może dokonamy transformacji hierarchicznej za pomocą naszych VBO, czy jest to możliwe?)

VBO nie mają z tym nic wspólnego. To, co daje większość użytkowników staromodnych problemów OpenGL, to funkcje stosu macierzy, które sprawiają, że OpenGL wygląda trochę jak wykres sceny. Ale to nie jest.

Jeśli zapomnisz o stosie macierzy starej OpenGL, stanie się oczywiste, jak wykonać transformacje hierarchiczne: W każdym oddziale w hierarchii utwórz kopię macierzy transformacji i na niej działaj. Otrzymujesz hierarchiczne drzewo transformacji, w każdym węźle przechowywana jest odpowiednia macierz. Następnie przekazujesz te macierze jako mundury do wierzchołka modułu cieniującego; lub tylko jedną macierz, jeśli rysujesz sztywny obiekt, który ma tylko jedną transformację. Wiele matryce zwykle wystarczy dla deformables jak szkieletowych animacji o charakterze jak ten

worldtransform -> 
    pelvis -> 
     left upper leg -> left lower leg -> left foot 
     right upper leg -> right lower leg -> right foot 
    torso -> 
     neck -> head -> 
      left eye 
      right eye 
      facial deformation // this is a whole chapter of it's own 
     left upper arm -> left lower arm -> left hand 
     right upper arm -> right lower arm -> right hand 

Everytime enounter się -> w taki hierarchię zrobić kopię matrycy i kontynuować pracę na jednym. Powracając do wyższego poziomu drzewa, ponownie zaczynasz pracę z tą macierzą.

+1

"deformacja twarzy" // jest to cały rozdział jego własnego => zawiera spadek szczęki :) – mlvljr

4

Tak, jeśli trzeba hierarchiczne transformacje, to trzeba to zrobić na własną rękę. Jest to jednak dość banalne, jeśli potrzebujesz tylko stosu. Po prostu weź ostatni wpis na stos i pomnóż go kolejną macierzą, którą chcesz zastosować, i popchnij wynik na stos.

[Twoje edytowane pytanie]: W tym celu nie potrzebujesz żadnego stosu, a także nie ma transformacji hierarchicznej. Wystarczy mieć pojedynczą matrycę i zastosować swoje tłumaczenie, narysować, pomnożyć je za pomocą macierzy rotacji, narysować, pomnożyć skalowanie, narysować.

+1

Er? Jeśli masz początkową macierz M i translację T, rotację R i skalę S, to twoja pierwsza macierz to M = T, druga to M * = R = (T * R == tłumaczenie najpierw, obrót sekunda), a trzeci to M * = S = (T * R * S == wszystkie macierze.) W przypadku ramienia robota można równie dobrze zacząć od góry i wywoływać połączenia typu draw podczas schodzenia do drzewa. Nie ma znaczenia, czy "stos" to std :: stack, czy tylko część twojej cyklicznej rekurencyjnej traversal sceny. – Anteru

+0

Jeśli nie wykonasz M * = S, ale po prostu użyj M * S (kopia!), Wtedy oryginalna macierz nie zostanie zmieniona. Twój stos będzie wyglądał następująco: [M], następnie naciskasz T (co daje stos [M, M * T]), następnie pop ([M]), a następnie naciśnij ponownie R ([M, M * R]). Nie mam twojego problemu? – Anteru

+0

Przestań edytować znaczenie swoich komentarzy. Powiedziałem, że możesz go zaimplementować za pomocą stosu, lub że możesz po prostu skopiować swoje macierze wewnątrz funkcji rekurencyjnego losowania (która niejawnie tworzy stos). [M, ..] _jest stosem, jeśli tego chcesz, po prostu użyj go . Ale możesz łatwo uciec bez std :: stack. – Anteru

4

Jeśli renderowanie odbywa się już w sposób hierarchiczny za pomocą na przykład rekursji funkcji, to masz już stos macierzy!

void renderMesh(Matrix transform, Mesh mesh) 
{ 
    // here call glDrawElements/glDrawArrays and send transform matrix to MVP uniform 
    mesh->draw(transform); 

    // now render all the sub-meshes, then will be transformed relative to current mesh 
    for (int i=0; i<mesh->subMeshCount(); i++) 
    { 
     Matrix subMeshTransform = mesh->getSubMeshTransform(i); 
     Mesh subMesh = mesh->getSubMesh(); 

     renderMesh(subMeshTransform * transform, subMesh); 
    } 
} 

// somwhere in main function 
... 
Matrix projection = Matrix::perspective(...); 
Matrix view = camera->getViewMatrix(); 

Matrix transform = view * projectIon; 
renderMesh(transform, rootMesh); 
0

W odniesieniu do wydajności vào i VBO nie zgadzam się, że VBO jest szybsza, sugeruję, aby zobaczyć ten link

http://www.openglsuperbible.com/2013/12/09/vertex-array-performance/

widać z wyników powyższych, że przynajmniej dla naszego małego zestawu próbek VAO jest szybszy we wszystkich implementacjach. Ma to uzasadnienie - mniej jest parametrów do sprawdzenia podczas wywoływania glBindVertexArray niż glBindBuffer lub glVertexAttribPointer. Nawet jeśli istnieje tylko jeden atrybut werteksów, liczba połączeń w OpenGL z przełącznikiem VAO jest o połowę mniejsza niż w przypadku jawnej aktualizacji globalnego VAO. Poza oczywistą relacją "mniej połączeń API oznacza szybszą realizację", VAO jest miejscem, w którym sterownik OpenGL może przechować informacje wymagane do zaprogramowania podstawowego GPU. Całkowita liczba zmian stanu wysłanych do GPU jest taka sama w obu przypadkach.

+0

Jak to jest związane z pytaniem? –