Wenn ich ein Dokument über WebGL oder OpenGL lese, sind einige Muster in der Verwendung von Funktions- und Objektnamen zu sehen. Aber ich kann den Unterschied zwischen einem Pufferobjekt und einem Array nicht verstehen.
Es gibt "Vertex-Buffer-Objekte", "Vertex-Array-Objekte" und sogar eine Art "Buffer-Array" oder "Array-Buffer".
Im OpenGL-Kontext: Wann ist etwas "Array" und wann sollte es stattdessen "Puffer" genannt werden?
char* buffer = socketRead();
(Pseudocode). Das Protokoll hingegen durchläuft den gesamten Lebenszyklus der App. Sie erstellen also irgendwo ein Array und beginnen mit dem Lesen des Sockets, sobald Sie Daten erhalten, die Sie in das Array geschrieben haben. Auf diese Weise erhalten Sie eine übersichtliche Liste aller empfangenen Daten.Antworten:
Die Benennung von Vertex Array Object ist etwas unglücklich. Es gibt drei verschiedene Dinge, die in / mit / um Ihre Anwendung herum vorkommen (früher vorkommen) und die (historisch) unterschiedlich benannt wurden, wobei der Name "array" oder "buffer" enthält (nun, es gibt auch Framebuffer-Objekte). aber ich werde das ignorieren).
Ziel war es, den Zugriff effizienter zu gestalten, da OpenGL zu einem genau definierten Zeitpunkt, zu dem Sie versprochen haben, dass die Daten konsistent sind, das Ganze auf einmal kopieren und über AGP oder was auch immer in einem Block übertragen kann. Das gibt es nicht mehr.
OpenGL kann diese Daten mehr oder weniger frei bewegen, und Sie dürfen / können nur über die entsprechende API in den / aus dem Puffer kopieren oder auf die Daten zugreifen, während sie zugeordnet werden. Das ist, was Sie ein Pufferobjekt nennen (Scheitelpunkt-Pufferobjekt, wenn es Scheitelpunkte enthält, aber es muss nicht unbedingt Bilddaten oder Uniformen sein, nur Scheitelpunkte waren die ersten, die einmal unterstützt wurden).
Damit soll sichergestellt werden, dass OpenGL (im Prinzip) tun kann, was es will, und sogar spekulativ den Puffer über PCIe schieben kann, bevor Sie überhaupt zeichnen. Das funktioniert, weil Sie die Daten nicht besitzen (OpenGL!) Und Sie nur über die angegebene API darauf zugreifen können, sodass jederzeit bekannt ist, dass die Daten gültig sind. Der Treiber kann sich sogar dafür entscheiden, Pufferspeicher auf der Grafikkarte zu löschen, wenn Speicher für etwas anderes benötigt wird, und ihn später bei Bedarf von seiner geheimen Kopie wiederherzustellen.
Die Absicht des Vertex-Array-Objekts besteht nun darin, die Anzahl der API-Aufrufe und die Anzahl der Konsistenzprüfungen zu verringern, die OpenGL intern durchführen muss, und natürlich die Hardware so zu verwenden, wie sie funktioniert. Wenn Sie 5 Puffer binden, muss jeder einige möglicherweise teure Prüfungen durchlaufen, und jeder ist ein Kandidat für Cache-Fehler im Treiber, und jeder einzelne erfordert die Kommunikation mit der Grafikkarte, um einen Deskriptor usw. zu ändern binde eine VAO, der Treiber kann (oft) einfach den auf der Grafikkarte eingestellten Deskriptor umschalten und fertig.
quelle
(aus khronos gezogen )
Jeder Puffer neigt dazu, ein Attribut eines Vertex-Arrays (Objekts) zu bilden. Ein VAO kann viele Scheitelpunktattribute enthalten (z. B. Position, Farbe, UV). Jeder kann in einem eigenen Puffer gespeichert werden, in dem der Puffer eine unformatierte Folge zusammenhängender Bytes angibt und in dem Sie die Größe (Typ) pro Pufferelement für OpenGL-Aufrufe auf der CPU-Seite und für Shader-Arbeiten auf der GPU-Seite explizit angeben müssen.
Das ist ein Weg. Die anderen Möglichkeiten, wie dies funktionieren kann, sind:
Das folgende Diagramm veranschaulicht diese beiden letzteren Fälle.
Fazit: Wenn der Ausdruck "Vertex-Array" in OpenGL unqualifiziert verwendet wird, können Sie davon ausgehen, dass dies VAO bedeutet, was sich in einem OpenGL-Kontext (speziell) in der Tat von einem Puffer unterscheidet.
BEARBEITEN bezüglich Ihres Kommentars: Weist
GL_ARRAY_BUFFER
darauf hin, dass dieses Pufferobjekt wie oben beschrieben für Scheitelpunktattributdaten verwendet werden soll. Dies liegt daran, dass Puffer nicht nur für Scheitelpunktattribute verwendet werden. Da dies jedoch der häufigste Anwendungsfall ist und Sie nach VAOs fragen, gehe ich nicht auf die anderen ein. Hier ist jedoch eine Liste der anderen Arten von Puffern, die eingerichtet werden können.quelle
struct
Typ sein. Die Daten können pro Puffer verschachtelt oder vollständig einheitlich sein. Sie können sie wie bei einem herkömmlichen C-Array auf der CPU indizieren. Array- Objekte (Verwenden Sie diese korrekte Terminologie oder verwirren Sie sich selbst!) ... (Fortsetzung unten)Diese Terminologie ist in der Geschichte von OpenGL verwurzelt. Es ist wichtig zu wissen, dass OpenGL für die meisten GL-Versionen, die hier relevant sind, schrittweise weiterentwickelt wurde, indem einer bereits vorhandenen API neue Funktionen hinzugefügt wurden, anstatt die API zu ändern.
Die erste Version von OpenGL hatte keinen dieser Objekttypen. Das Zeichnen wurde durch das Ausgeben mehrerer glBegin / glEnd-Aufrufe erreicht, und ein Problem bei diesem Modell war, dass es hinsichtlich des Funktionsaufruf-Overheads sehr ineffizient war.
OpenGL 1.1 hat die ersten Schritte unternommen, um dies durch die Einführung von Vertex-Arrays zu beheben. Anstatt Vertex-Daten direkt anzugeben, können Sie sie jetzt aus C / C ++ - Arrays beziehen - daher der Name. Ein Vertex-Array ist also genau das - ein Array von Vertices und der GL-Status, der erforderlich ist, um sie anzugeben.
Die nächste wichtige Entwicklung kam mit GL 1.5 und ermöglichte das Speichern von Vertex-Array-Daten im GPU-Speicher anstatt im Systemspeicher ("clientseitig"). Eine Schwäche der GL 1.1 Vertex-Array-Spezifikation bestand darin, dass der vollständige Satz von Vertex-Daten jedes Mal, wenn Sie ihn verwenden wollten, auf die GPU übertragen werden musste. Wenn es sich bereits auf der GPU befand, konnte diese Übertragung vermieden und potenzielle Leistungssteigerungen erzielt werden.
Daher wurde ein neuer Typ eines GL-Objekts erstellt, um das Speichern dieser Daten auf der GPU zu ermöglichen. Genau wie ein Texturobjekt zum Speichern von Texturdaten verwendet wird, speichert ein Scheitelpunktpufferobjekt Scheitelpunktdaten. Dies ist eigentlich nur ein Sonderfall eines allgemeineren Pufferobjekttyps, der unspezifische Daten speichern kann.
Die API für die Verwendung von Vertex-Pufferobjekten wurde in die bereits vorhandene Vertex-Array-API integriert. Aus diesem Grund sehen Sie darin seltsame Dinge wie das Konvertieren von Byte-Offsets in Zeiger. Jetzt haben wir eine Vertex-Array-API, die nur den Status speichert, wobei die Daten aus Pufferobjekten und nicht aus speicherinternen Arrays stammen.
Dies bringt uns fast zum Ende unserer Geschichte. Die resultierende API war ziemlich ausführlich, wenn es darum ging, den Vertex-Array-Status anzugeben. Ein weiterer Weg der Optimierung bestand darin, einen neuen Objekttyp zu erstellen, der diesen gesamten Status zusammenfasste, mehrere Änderungen des Vertex-Array-Status in einem einzigen API-Aufruf zuließ und GPUs zuließ um möglicherweise Optimierungen durchzuführen, weil Sie im Voraus wissen, welcher Status verwendet werden soll.
Geben Sie das Vertex-Array-Objekt ein, das all dies zusammenfasst.
Zusammenfassend begann ein Vertex-Array als Sammlung von Status und Daten (in einem Array gespeichert) zum Zeichnen mit. Ein Vertex-Puffer ersetzt den speicherinternen Array-Speicher durch einen GL-Objekttyp, sodass das Vertex-Array nur noch den Status aufweist. Ein Vertex-Array-Objekt ist nur ein Containerobjekt für diesen Status, sodass es einfacher und mit weniger API-Aufrufen geändert werden kann.
quelle
Ich habe eine Weile nicht mehr mit OpenGL gearbeitet, daher bin ich vielleicht nur zur Hälfte richtig. Allgemein gesagt: Puffer speichern ein Array von unformatiertem Speicher. Ein Array ist ein allgemeiner Begriff für zusammenhängenden Speicher.
Ein Puffer muss an den Kontext gebunden sein, während ein Array nur ein Array von Daten ist. Wenn ich mich richtig erinnere, sollen die Daten im Puffer auf die Grafikkarte (daher die Bindung) kopiert werden.
Hoffe das hilft ein bisschen
quelle