GL ARB vertex buffer object: Unterschied zwischen den Versionen
I0n0s (Diskussion | Beiträge) K (hat „ARB vertex buffer object“ nach „GL ARB vertex buffer object“ verschoben: In den GL-Namenraum verschoben.) |
DGLBot (Diskussion | Beiträge) K (Der Ausdruck ''<pascal>(.*?)</pascal>'' wurde ersetzt mit ''<source lang="pascal">$1</source>''.) |
||
Zeile 13: | Zeile 13: | ||
==== VOB initialisieren ==== | ==== VOB initialisieren ==== | ||
Zuerst holt man sich sich mit '''glGenBuffers''' für jede VBO einen eindeutigen Namen (Anmerkung: In GL wird ein Handle auf ein Pufferobjekt als Name bezeichnet): | Zuerst holt man sich sich mit '''glGenBuffers''' für jede VBO einen eindeutigen Namen (Anmerkung: In GL wird ein Handle auf ein Pufferobjekt als Name bezeichnet): | ||
− | <pascal>(...) | + | <source lang="pascal">(...) |
var | var | ||
VBO: array[0..2] of TGLuint; | VBO: array[0..2] of TGLuint; | ||
Zeile 23: | Zeile 23: | ||
(...) | (...) | ||
glGenBuffers(3, @VBO); | glGenBuffers(3, @VBO); | ||
− | (...)</ | + | (...)</source> |
Im Beispiel werden für drei VBOs die Namen angefordert. Nun kann man sie mit '''glBindBuffer''' an ein Ziel binden: | Im Beispiel werden für drei VBOs die Namen angefordert. Nun kann man sie mit '''glBindBuffer''' an ein Ziel binden: | ||
− | <pascal>(...) | + | <source lang="pascal">(...) |
// Der Client soll Vertex Arrays bearbeiten können | // Der Client soll Vertex Arrays bearbeiten können | ||
glEnableClientState(GL_VERTEX_ARRAY); | glEnableClientState(GL_VERTEX_ARRAY); | ||
// Das 1., noch leere, VBO an das Ziel "Vertex-Array" binden | // Das 1., noch leere, VBO an das Ziel "Vertex-Array" binden | ||
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]); | glBindBuffer(GL_ARRAY_BUFFER, VBO[0]); | ||
− | (...)</ | + | (...)</source> |
Über das Ziel, im Beispiel das Vertex-Array, kann man das VBO mit Daten füllen. Entweder man kopiert in Hauptspeicher bereits im richtigen Format vorhandene Daten hinein... | Über das Ziel, im Beispiel das Vertex-Array, kann man das VBO mit Daten füllen. Entweder man kopiert in Hauptspeicher bereits im richtigen Format vorhandene Daten hinein... | ||
− | <pascal>(...) | + | <source lang="pascal">(...) |
// Die in MyData vorhandenen Daten in das VBO ablegen | // Die in MyData vorhandenen Daten in das VBO ablegen | ||
glBufferData(GL_ARRAY_BUFFER, SizeOf(MyData), MyData, GL_STATIC_DRAW); | glBufferData(GL_ARRAY_BUFFER, SizeOf(MyData), MyData, GL_STATIC_DRAW); | ||
− | (...)</ | + | (...)</source> |
... dann kümmert '''glBufferData''' sich um das Ein- und Ausblenden des Speichers oder man benutzt die Funktion nur zum Reservieren eines Speicherblocks mit der im 2. Parameter übergebenen Größe. In 3. Parameter wird dann '''nil''' übergeben (keine Daten zum Kopieren vorhanden). Um das VBO in den Arbeitsspeicher einzublenden, benutzt man die Funktion '''glMapBuffer'''. Damit wird ein Zeiger zum Beschreiben des Speicherbereiches angefordert und damit das VBO in den Arbeitsspeicher eingeblendet: | ... dann kümmert '''glBufferData''' sich um das Ein- und Ausblenden des Speichers oder man benutzt die Funktion nur zum Reservieren eines Speicherblocks mit der im 2. Parameter übergebenen Größe. In 3. Parameter wird dann '''nil''' übergeben (keine Daten zum Kopieren vorhanden). Um das VBO in den Arbeitsspeicher einzublenden, benutzt man die Funktion '''glMapBuffer'''. Damit wird ein Zeiger zum Beschreiben des Speicherbereiches angefordert und damit das VBO in den Arbeitsspeicher eingeblendet: | ||
− | <pascal>(...) | + | <source lang="pascal">(...) |
const | const | ||
PointCount =1000; | PointCount =1000; | ||
Zeile 72: | Zeile 72: | ||
VBOPointer := nil; | VBOPointer := nil; | ||
end; | end; | ||
− | (...)</ | + | (...)</source> |
Wichtig ist, dass mit glUnMapBuffer das Einblenden der VBO wieder beendet wird, weil im eingeblendeten Zustand die Anwendung über den Zeiger exklusive Zugriffsrechte auf das VBO bekommt und damit eine gleichzeitige Verwendung durch den Server nicht, oder nur eingeschränkt, möglich ist. | Wichtig ist, dass mit glUnMapBuffer das Einblenden der VBO wieder beendet wird, weil im eingeblendeten Zustand die Anwendung über den Zeiger exklusive Zugriffsrechte auf das VBO bekommt und damit eine gleichzeitige Verwendung durch den Server nicht, oder nur eingeschränkt, möglich ist. | ||
==== VOB beim Rendern benutzen ==== | ==== VOB beim Rendern benutzen ==== | ||
VBOs werden beim Rendern genutzt, indem man die Ziele benutzt, an denen sie gebunden sind. Im obigen Beispiel wurde ein VBO an ein Vektor-Array gebunden. Das Vektor-Array kann man Beispielsweise über die Funktion glDrawArrays benutzen: | VBOs werden beim Rendern genutzt, indem man die Ziele benutzt, an denen sie gebunden sind. Im obigen Beispiel wurde ein VBO an ein Vektor-Array gebunden. Das Vektor-Array kann man Beispielsweise über die Funktion glDrawArrays benutzen: | ||
− | <pascal>procedure TGLForm.ApplicationEventsIdle(Sender: TObject; var Done: Boolean); | + | <source lang="pascal">procedure TGLForm.ApplicationEventsIdle(Sender: TObject; var Done: Boolean); |
begin | begin | ||
(...) | (...) | ||
Zeile 84: | Zeile 84: | ||
glPointSize(5.0); | glPointSize(5.0); | ||
glDrawArrays(GL_POINTS, 0, PointCount); | glDrawArrays(GL_POINTS, 0, PointCount); | ||
− | (...)</ | + | (...)</source> |
==== VOB freigeben ==== | ==== VOB freigeben ==== | ||
Mit der Funktion '''glDeleteBuffers''' werden VBOs freigegeben: | Mit der Funktion '''glDeleteBuffers''' werden VBOs freigegeben: | ||
− | <pascal>(...) | + | <source lang="pascal">(...) |
var | var | ||
VBO: array[0..2] of TGLuint; | VBO: array[0..2] of TGLuint; | ||
Zeile 99: | Zeile 99: | ||
// freigeben der drei VBOs | // freigeben der drei VBOs | ||
glDeleteBuffers(3, VBO); | glDeleteBuffers(3, VBO); | ||
− | (...)</ | + | (...)</source> |
Eine Bindung an ein Ziel im selben Thread-Kontext muss nicht vorher gelöst werden. War eine VBO vor Aufruf der Funktion '''glDeleteBuffers''' gebunden, wird die Bindung im Ziel durch den Null-Namen ersetzt. Dies gilt allerdings nur für den Thread-Kontext, in dem die Freigabe erfolgt. Existieren anderen Thread-Kontexten die das VBO nutzen, müssen die Bindungen dort vorher gelöst werden, damit es nicht zu Zugriffen auf die nicht mehr existierende VBO kommt kann. | Eine Bindung an ein Ziel im selben Thread-Kontext muss nicht vorher gelöst werden. War eine VBO vor Aufruf der Funktion '''glDeleteBuffers''' gebunden, wird die Bindung im Ziel durch den Null-Namen ersetzt. Dies gilt allerdings nur für den Thread-Kontext, in dem die Freigabe erfolgt. Existieren anderen Thread-Kontexten die das VBO nutzen, müssen die Bindungen dort vorher gelöst werden, damit es nicht zu Zugriffen auf die nicht mehr existierende VBO kommt kann. | ||
Aktuelle Version vom 10. März 2009, 19:05 Uhr
Inhaltsverzeichnis
ARB_vertex_buffer_object
Die Extension wurde in die OpenGL 1.5 Spezifikation aufgenommen. Dieser Artikel berücksichtigt dies, indem die mit OpenGL 1.5 eingeführten Bezeichner verwendet werden. Diese entsprechen den zugehörigen Bezeichnern der Extension, unter Weglassung des Suffix "ARB". Im den Abschnitten #Neue Funktionen und #Neue Tokens werden zur besseren Auffindbarkeit des Artikels die alten Bezeichner mit angegeben.
Abfragestring
GL_ARB_vertex_buffer_object
Beschreibung
Diese Erweiterung definiert eine Schnittstelle, mit der verschiedene Arten von Daten im den Speicher des Servers abgelegt werden können. In der Praxis ist der Server oftmals eine Grafikkarte mit eigenem Video Speicher (VRAM). Auf den eigenem VRAM kann die Grafik-Hardware deutlich schneller zugreifen, als auf den clientseitig vorhandenen Hauptspeicher der CPU. Weil es sich bei den abzulegenden Daten hauptsächlich um Vertex-Array-Daten handelt, wurde mit dieser Extension der Begriff "vertex buffer object" abgekürzt VBO eingeführt, was der Extension auch ihren Namen gab.
VBOs sind in ein Speicherblock zusammengefasste Daten, auf die man von der Anwendung aus über die GL zugreifen kann (z.B. glBufferData, glBufferSubData, glGetBufferSubData) oder direkt über ein Zeiger auf das Objekt selbst, als wären die Daten in einen normalen Hauptspeicherbereich abgelegt. Dies wird über eine Technik realisiert, die im Englischen mit "Memory Mapping" und im Deutschen mit "Speichereinblendung" bezeichnet wird. Die API der Extension verdeckt die Details dieser Technik soweit, dass auch für weniger leistungsfähiger Hardware - die das Einblenden von VRAM in den Hauptspeicher nicht unterstützt - ein möglichst optimaler Zugriff gewährleistet werden kann.
Verwendung
VOB initialisieren
Zuerst holt man sich sich mit glGenBuffers für jede VBO einen eindeutigen Namen (Anmerkung: In GL wird ein Handle auf ein Pufferobjekt als Name bezeichnet):
(...)
var
VBO: array[0..2] of TGLuint;
(...)
procedure TGLForm.FormCreate(Sender: TObject);
begin
// hier GL initialisieren
(...)
glGenBuffers(3, @VBO);
(...)
Im Beispiel werden für drei VBOs die Namen angefordert. Nun kann man sie mit glBindBuffer an ein Ziel binden:
(...)
// Der Client soll Vertex Arrays bearbeiten können
glEnableClientState(GL_VERTEX_ARRAY);
// Das 1., noch leere, VBO an das Ziel "Vertex-Array" binden
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
(...)
Über das Ziel, im Beispiel das Vertex-Array, kann man das VBO mit Daten füllen. Entweder man kopiert in Hauptspeicher bereits im richtigen Format vorhandene Daten hinein...
(...)
// Die in MyData vorhandenen Daten in das VBO ablegen
glBufferData(GL_ARRAY_BUFFER, SizeOf(MyData), MyData, GL_STATIC_DRAW);
(...)
... dann kümmert glBufferData sich um das Ein- und Ausblenden des Speichers oder man benutzt die Funktion nur zum Reservieren eines Speicherblocks mit der im 2. Parameter übergebenen Größe. In 3. Parameter wird dann nil übergeben (keine Daten zum Kopieren vorhanden). Um das VBO in den Arbeitsspeicher einzublenden, benutzt man die Funktion glMapBuffer. Damit wird ein Zeiger zum Beschreiben des Speicherbereiches angefordert und damit das VBO in den Arbeitsspeicher eingeblendet:
(...)
const
PointCount =1000;
type
PVertex2f = ^TVertex2f;
TVertex2f = packed record
X,Y: TGLFloat;
end;
PVertex2fArray = ^TVertex2fArray;
TVertex2fArray = packed array[0..0] of TVertex2f;
var
VBOPointer: PVertex2fArray;
i: integer;
Value: double;
begin
(...)
// mit glBufferData ein Speicherblock allokieren
glBufferData(GL_ARRAY_BUFFER, PointCount*SizeOf(TVertex2f), nil, GL_STATIC_DRAW);
// Zeiger mit Schreibrechten auf das VBO holen
VBOPointer := glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
try
// Vertex-Daten in den VRAM kopieren
Value := 240;
for i := 0 to PointCount-1 do begin
VBOPointer^[i].X := i*5.14;
VBOPointer^[i].Y := Value;
Value := Value+Random*50-25;
end;
finally
// Buffer für andere Zugriffe wieder freigeben (VBOPointer ist danach ungültig)
glUnMapBuffer(GL_ARRAY_BUFFER);
VBOPointer := nil;
end;
(...)
Wichtig ist, dass mit glUnMapBuffer das Einblenden der VBO wieder beendet wird, weil im eingeblendeten Zustand die Anwendung über den Zeiger exklusive Zugriffsrechte auf das VBO bekommt und damit eine gleichzeitige Verwendung durch den Server nicht, oder nur eingeschränkt, möglich ist.
VOB beim Rendern benutzen
VBOs werden beim Rendern genutzt, indem man die Ziele benutzt, an denen sie gebunden sind. Im obigen Beispiel wurde ein VBO an ein Vektor-Array gebunden. Das Vektor-Array kann man Beispielsweise über die Funktion glDrawArrays benutzen:
procedure TGLForm.ApplicationEventsIdle(Sender: TObject; var Done: Boolean);
begin
(...)
// Vertex 0 bis PointCount-1 als Linie zeichnen
glDrawArrays(GL_LINE_STRIP, 0, PointCount);
// Vertex 0 bis PointCount-1 als 5x5 Pixel-Punkte zeichnen
glPointSize(5.0);
glDrawArrays(GL_POINTS, 0, PointCount);
(...)
VOB freigeben
Mit der Funktion glDeleteBuffers werden VBOs freigegeben:
(...)
var
VBO: array[0..2] of TGLuint;
(...)
procedure TGLForm.FormDestroy(Sender: TObject);
begin
(...)
// freigeben der drei VBOs
glDeleteBuffers(3, VBO);
(...)
Eine Bindung an ein Ziel im selben Thread-Kontext muss nicht vorher gelöst werden. War eine VBO vor Aufruf der Funktion glDeleteBuffers gebunden, wird die Bindung im Ziel durch den Null-Namen ersetzt. Dies gilt allerdings nur für den Thread-Kontext, in dem die Freigabe erfolgt. Existieren anderen Thread-Kontexten die das VBO nutzen, müssen die Bindungen dort vorher gelöst werden, damit es nicht zu Zugriffen auf die nicht mehr existierende VBO kommt kann.
Neue Funktionen
Die in der OpenGL Spezifikation >=1.5 verwendeten Bezeichner sind verlinkt. In Klammern dahinter die Bezeichner wie sie in der Extension benutzt werden.
- glBindBuffer (glBindBufferARB)
- glDeleteBuffers (glDeleteBuffersARB)
- glGenBuffers (glGenBuffersARB)
- glIsBuffer (glIsBufferARB)
- glBufferData (glBufferDataARB)
- glBufferSubData (glBufferSubDataARB)
- glGetBufferSubData (glGetBufferSubDataARB)
- glMapBuffer (glMapBufferARB)
- glUnmapBuffer (glUnmapBufferARB)
- glGetBufferParameteriv (glGetBufferParameterivARB)
- glGetBufferPointerv (glGetBufferPointervARB)
Neue Tokens
Die in der OpenGL Spezifikation >=1.5 verwendeten Bezeichner sind hier FETT hervorgehoben. In Klammern dahinter die Bezeichner wie sie in der Extension benutzt werden. Für nähere Informationen zu den Token-Werten sollte bei der zugehörigen Funktion nachgeschlagen werden.
Neue Parameterwerte
- Für den <target> Parameter der Funktionen BindBuffer, BufferData, BufferSubData, MapBuffer, UnmapBuffer, GetBufferSubData, GetBufferParameteriv und GetBufferPointerv
GL_ARRAY_BUFFER (GL_ARRAY_BUFFER_ARB) | 0x8892 | Das Ziel ist ein Vertex Array |
GL_ELEMENT_ARRAY_BUFFER (GL_ELEMENT_ARRAY_BUFFER_ARB) | 0x8893 | Das Ziel ist ein Index Array |
- Für den <pname> Parameter der Funktionen GetBooleanv, GetIntegerv, GetFloatv und GetDoublev
GL_ARRAY_BUFFER_BINDING (GL_ARRAY_BUFFER_BINDING_ARB) | 0x8894 |
GL_ELEMENT_ARRAY_BUFFER_BINDING (GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB) | 0x8895 |
GL_VERTEX_ARRAY_BUFFER_BINDING (GL_VERTEX_ARRAY_BUFFER_BINDING_ARB) | 0x8896 |
GL_NORMAL_ARRAY_BUFFER_BINDING (GL_NORMAL_ARRAY_BUFFER_BINDING_ARB) | 0x8897 |
GL_COLOR_ARRAY_BUFFER_BINDING (GL_COLOR_ARRAY_BUFFER_BINDING_ARB) | 0x8898 |
GL_INDEX_ARRAY_BUFFER_BINDING (GL_INDEX_ARRAY_BUFFER_BINDING_ARB) | 0x8899 |
GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB) | 0x889A |
GL_EDGE_FLAG_ARRAY_BUFFER_BINDING (GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB) | 0x889B |
GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING (GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB) | 0x889C |
GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING (GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB) | 0x889D |
GL_WEIGHT_ARRAY_BUFFER_BINDING (GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB) | 0x889E |
- Für den <pname> Parameter der Funktion GetVertexAttribiv
GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING (GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB) | 0x889F |
- Für den <usage> Parameter der Funktion BufferData
GL_STREAM_DRAW (GL_STREAM_DRAW_ARB) | 0x88E0 |
GL_STREAM_READ (GL_STREAM_READ_ARB) | 0x88E1 |
GL_STREAM_COPY (GL_STREAM_COPY_ARB) | 0x88E2 |
GL_STATIC_DRAW (GL_STATIC_DRAW_ARB) | 0x88E4 |
GL_STATIC_READ (GL_STATIC_READ_ARB) | 0x88E5 |
GL_STATIC_COPY (GL_STATIC_COPY_ARB) | 0x88E6 |
GL_DYNAMIC_DRAW (GL_DYNAMIC_DRAW_ARB) | 0x88E8 |
GL_DYNAMIC_READ (GL_DYNAMIC_READ_ARB) | 0x88E9 |
GL_DYNAMIC_COPY (GL_DYNAMIC_COPY_ARB) | 0x88EA |
- Für den <access> Parameter der Funktion MapBuffer
GL_READ_ONLY (GL_READ_ONLY_ARB) | 0x88B8 |
GL_WRITE_ONLY (GL_WRITE_ONLY_ARB) | 0x88B9 |
GL_READ_WRITE (GL_READ_WRITE_ARB) | 0x88BA |
- Für den <pname> Parameter der Funktion GetBufferParameteriv
GL_BUFFER_SIZE (GL_BUFFER_SIZE_ARB) | 0x8764 |
GL_BUFFER_USAGE (GL_BUFFER_USAGE_ARB) | 0x8765 |
GL_BUFFER_ACCESS (GL_BUFFER_ACCESS_ARB) | 0x88BB |
GL_BUFFER_MAPPED (GL_BUFFER_MAPPED_ARB) | 0x88BC |
- Für den <pname> Parameter der Funktion GetBufferPointerv
GL_BUFFER_MAP_POINTER (GL_BUFFER_MAP_POINTER_ARB) | 0x88BD |
Neue States
Es wurden keine neuen States eingeführt.
Abhängigkeiten
Die Extension ARB_vertex_buffer_object wurde auf Basis der OpenGL 1.4 Spezifikation geschrieben und ihre Definition wurde von folgenden Extensionen beeinflusst: