Aus einer einfachen Perspektive können Sie sich ein Array mit zwei Teilen vorstellen:
Informationen zu Größe, Form und Typ des Arrays (z. B. 32-Bit-Gleitkommazahlen mit Vektorreihen mit jeweils vier Elementen).
Die Array-Daten, die kaum mehr als ein großer Byte-Blob sind.
Obwohl das Low-Level-Konzept größtenteils gleich geblieben ist, hat sich die Art und Weise, wie Sie Arrays angeben, im Laufe der Jahre mehrmals geändert.
OpenGL 3.0 / ARB_vertex_array_object
So sollten Sie heute wahrscheinlich vorgehen. Es ist sehr selten, dass Leute gefunden werden, die OpenGL 3.x nicht ausführen können und dennoch Geld für Ihre Software haben.
Ein Pufferobjekt in OpenGL ist ein großer Bitklumpen. Stellen Sie sich den "aktiven" Puffer nur als globale Variable vor, und es gibt eine Reihe von Funktionen, die den aktiven Puffer anstelle eines Parameters verwenden. Diese globalen Statusvariablen sind die hässliche Seite von OpenGL (vor dem direkten Statuszugriff, der unten behandelt wird).
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
Jetzt verwendet Ihr typischer Vertex-Shader Scheitelpunkte als Eingabe, keinen großen Bit-Blob. Sie müssen also angeben, wie der Bit-Blob (der Puffer) in Scheitelpunkte dekodiert wird. Das ist die Aufgabe des Arrays. Ebenso gibt es ein "aktives" Array, das Sie sich nur als globale Variable vorstellen können:
GLuint array;
glGenVertexArrays(1, &array);
glBindVertexArray(array);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glVertexAttribPointer(attr, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(attr);
OpenGL 2.0 (der alte Weg)
In OpenGL 2.x gab es keine Vertex-Arrays und die Daten waren nur global. Sie haben noch zu nennen glVertexAttribPointer()
und glEnableVertexAttribArray()
, aber man musste sie anrufen , jedes Mal , dass Sie einen Puffer verwendet. In OpenGL 3.x haben Sie das Array nur einmal eingerichtet.
Zurück zu OpenGL 1.5, Sie könnten tatsächlich Puffer verwenden, aber Sie haben eine separate Funktion verwendet, um jede Art von Daten zu binden. Zum Beispiel glVertexPointer()
für Scheitelpunktdaten und glNormalPointer()
für normale Daten. Vor OpenGL 1.5 gab es keine Puffer, aber Sie konnten Zeiger in Ihren Anwendungsspeicher verwenden.
OpenGL 4.3 / ARB_vertex_attrib_binding
In 4.3 oder wenn Sie die Erweiterung ARB_vertex_attrib_binding haben, können Sie das Attributformat und die Attributdaten separat angeben. Dies ist hilfreich, da Sie auf einfache Weise ein Scheitelpunktarray zwischen verschiedenen Puffern wechseln können.
GLuint array;
glGenVertexArrays(1, &array);
glBindVertexArray(array);
glEnableVertexAttribArray(loc_attrib);
glEnableVertexAttribArray(normal_attrib);
glEnableVertexAttribArray(texcoord_attrib);
glVertexAttribFormat(loc_attrib, 3, GL_FLOAT, GL_FALSE, 0);
glVertexAttribFormat(normal_attrib, 3, GL_FLOAT, GL_FALSE, 12);
glVertexAttribFormat(texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 24);
glVertexAttribBinding(loc_attrib, 0);
glVertexAttribBinding(normal_attrib, 0);
glVertexAttribBinding(texcoord_attrib, 0);
glBindVertexBuffer(0, buffer, 0, 32);
glBindVertexBuffer(0, buffer2, 0, 32);
OpenGL 4.5 / ARB_direct_state_access
In OpenGL 4.5 oder wenn Sie die Erweiterung ARB_direct_state_access haben, müssen Sie nicht mehr aufrufen glBindBuffer()
oder glBindVertexArray()
nur noch Dinge einrichten ... Sie geben die Arrays und Puffer direkt an. Sie müssen das Array nur am Ende binden, um es zu zeichnen.
GLuint array;
glCreateVertexArrays(1, &array);
glEnableVertexArrayAttrib(array, loc_attrib);
glEnableVertexArrayAttrib(array, normal_attrib);
glEnableVertexArrayAttrib(array, texcoord_attrib);
glVertexArrayAttribFormat(array, loc_attrib, 3, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribFormat(array, normal_attrib, 3, GL_FLOAT, GL_FALSE, 12);
glVertexArrayAttribFormat(array, texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 24);
glVertexArrayAttribBinding(array, loc_attrib, 0);
glVertexArrayAttribBinding(array, normal_attrib, 0);
glVertexArrayAttribBinding(array, texcoord_attrib, 0);
glVertexArrayVertexBuffer(array, 0, buffer, 0, 32);
glVertexArrayVertexBuffer(array, 0, buffer2, 0, 32);
glBindVertexArray(array);
glDrawArrays(...);
ARB_direct_state_access ist aus vielen Gründen nett. Sie können das Binden von Arrays und Puffern vergessen (außer beim Zeichnen), damit Sie nicht an versteckte globale Variablen denken müssen, die OpenGL für Sie verfolgt. Sie können zwischen „Erzeugen Sie einen Namen für ein Objekt“ und „Erstellen eines Objekts“ , weil über den Unterschied vergessen glCreateBuffer()
und glCreateArray()
beides zugleich.
Vulkan
Vulkan geht noch weiter und lässt Sie Code wie den Pseudocode schreiben, den ich oben geschrieben habe. Sie sehen also so etwas wie:
VkVertexInputAttributeDescription attrib[3];
attrib[0].location = 0;
attrib[0].binding = 0;
attrib[0].format = VK_FORMAT_R32G32B32_SFLOAT;
attrib[0].offset = 0;
GL_EXT_direct_state_access
, aber das schließt leider aus, dass Ihr Code auf Mesa-, Intel- oder Apple-Treibern ausgeführt wird: - \ Ich denke jedoch, dass es wichtig ist, darauf hinzuweisen, dass Vertex-Arrays seit GL 1.1 existieren. Das einzige, was sich in GL 2.0 geändert hat, war die Einführung generischer Vertex-Attribut-Slots.