PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [OpenGL] VBOs: Verständnisproblem mit glDrawElements()


Nasenbaer
2010-02-23, 14:35:37
Hi,
ich beschäftige mich gerade mit VBOs unter OpenGL und habe dazu eine Frage wie ich die Daten abspeichern soll. Wenn ich glDrawElements() nutzen will muss ich ja ein Array aus Vertex-Daten (und je eins für Normalen, TextCoords, ...) und eins mit Index-Daten speichern.
Allerdings habe ich gelesen (http://www.gamedev.net/community/forums/topic.asp?topic_id=45350), dass ich nur ein Index-Array nutzen kann. Also wenn ich für 3 Vertices die gleiche Normale nutzen will, so muss ich die Normale auch mehrfach speichern?

Beispiel:

GLfloat vertex[] = { -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f};
GLfloat normal[] = { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f};
GLFloat indices[] = {0, 1, 2};


Hab ich das so richtig verstanden? Und wenn ja, kann man nichts gegen die reduntante Speicherung der Daten tun?

Neomi
2010-02-23, 15:30:47
Erstmal ist da ein kleines Verständnisproblem auszuräumen. Was du in deinem Codebeispiel "vertex" genannt hast, solltest du in "position" umbenennen. Der Vertex ist dann die Kombination aus Position und Normale (und anderen Daten abhängig davon, was noch gebraucht wird). Indizieren kannst du nur ganze Vertices, nicht einzelne Vertexelemente.

Die Konsequenz hast du schon richtig erfaßt. Jeder Vertex benötigt seine eigene Kopie der Daten, die benötigt werden. Wenn du einen Vertex nicht als Ganzes wiederverwenden kannst, mußt du seine Elemente klonen.

Nasenbaer
2010-02-23, 15:49:13
Erstmal ist da ein kleines Verständnisproblem auszuräumen. Was du in deinem Codebeispiel "vertex" genannt hast, solltest du in "position" umbenennen. Der Vertex ist dann die Kombination aus Position und Normale (und anderen Daten abhängig davon, was noch gebraucht wird). Indizieren kannst du nur ganze Vertices, nicht einzelne Vertexelemente.

Die Konsequenz hast du schon richtig erfaßt. Jeder Vertex benötigt seine eigene Kopie der Daten, die benötigt werden. Wenn du einen Vertex nicht als Ganzes wiederverwenden kannst, mußt du seine Elemente klonen.
Ja da hast du natürlich recht - gibt ja wohl auch irgendeine VertexAttrib Funktion um die Attribute zu setzen - da wird das natürlich klarer, dass die Position nur ein Teil ist.

Die Frage kam nur auf, weil ich mir nen OBJ-Reader bastel und dort natürlich Positionen, Normalen, etc. separat und darum auch redundanzfrei gespeichert werden.

Neue Frage
Wie speichere ich in diesem Fall die Daten denn effizient? Als Interleaved Arrays (also Vertex-Color-Normal, Vertex-Color-Normal, ...) oder in separaten Arrays? Letztere sind leichter von Hand zu manipulieren, weil ein verrechnen bei den Indizies eher auszuschließen ist. Wenn dann auf die Daten jedes Vertices zugegriffen wird liegen die Adressen aber warscheinlich weit auseinander und ein effizientes Caching wird dadurch womöglich verhindert.
Oder ist der Unterschied gar vernachlässigbar?

Neomi
2010-02-23, 16:41:51
Mach es einfach so, wie du es besser handhaben kannst. Solange du nicht vertexlimitiert bist, dürfte das keinen nennenswerten Unterschied machen. Im Zweifelsfall kann man immer noch benchen.

Ich würde eher interleaved speichern. Wenn es wirklich drauf ankommt, gibt es sogar diverse weitere Dinge zu beachten. Beispielsweise kann man wiederverwendbare Vertices klonen und 1:1 nochmal in die Daten einbringen, wenn sie seit der letzten Verwendung aus dem Cache verschwunden sind, weil lineares Lesen performanter ist. Oder auch, wenn ein Vertex 28 Byte groß ist, ihn auf 32 Bytes aufzublasen, ein 4fach unterteiltes 256 Bit Speicherinterface liest nämlich immer jeweils 8 Bytes und Vielfache davon können unter Umständen günstiger sein. Im Extremfall können bei bekannten Cachegrößen usw. (auf Hardwarekennung basierend in einer Tabelle nachgeschlagen oder sogar durch kurze Minibenches automatisch ermittelt) die einzelnen Meshes für die vorhandene GPU optimiert werden. Aber um all das solltest du dir erstmal keine Sorgen machen, sondern erst, wenn es zum Flaschenhals wird.

PS: Ich benutze inzwischen eigentlich nur noch Direct3D, dagegen OpenGL schon ewig nicht mehr. Deshalb kann ich zu API-spezifischen Dingen unter OpenGL kaum sinnvolles sagen, bloß zu allgemeinen Konzepten.

Nasenbaer
2010-02-23, 20:39:48
Ok Danke für die Infos. Ist aber glaube ich sowieso gar nicht so wichtig für mich. Das Einlesen ber OBJ-Datei ist nur als Test gedacht ob alles geht und als Vergleich. Später möchte ich die Meshes als Geometry Images einlesen und erzeuge die Vertices dann ja erst auf der GPU und nicht im System-RAM.
Aber bis dahin ist noch einiges zu lesen - so ganz weiß ich noch nicht wie ich da rangehen muss.