Seite 1 von 1

Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 14.03.2010, 16:52
von Eisflamme
Hey ho,

Ich habe jetzt ein Model geladen, welches allerdings 38 Meshes enthält. Eigentlich muss ich ja jetzt für jedes einzelne Mesh einen eigenen Vertex- und IndexBuffer anlegen, oder? Ich stelle mir das alles allerdings sehr grausam vor, wenn ich das Objekt jetzt 100 Mal rendern möchte. In dem Fall würde sich dann ja wiederum anbieten, erst 100 Mal Mesh 1 zu rendern, dann 100 Mal Mesh 2 zu rendern etc....

Ist so was jetzt nicht super inperformant? Wie render ich so was denn am Besten?

Re: Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 14.03.2010, 16:57
von Krishty
Du kannst alle Meshes in einem gemeinsamen Vertex- und Index-Buffer batchen. Du schreibst sie einfach hintereinander und merkst dir in jedem Mesh, bei welchem Index jeweils die Vertex- und Indexdaten anfangen. Wenn du dann DrawIndexed() aufrufst, übergibst du als StartIndexLocation den Index, bei dem die Indexdaten des jeweiligen Meshes im Index-Buffer beginnen und als BaseVertexLocation den Index, bei dem die Vertexdaten im Vertex-Buffer beginnen. Da BaseVertexLocation auf alle Indizes aufaddiert wird, verweisen die Indizes beim Rendern wieder auf die richtigen Vertices.

So ein Batching ist weit verbreitet – man benutzt es, um Vertex-Buffer auf die optimale Größe von 65536 Vertices zu bekommen.

Re: Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 14.03.2010, 17:08
von Eisflamme
Hi,

Danke für die schnelle Antwort!

Das klingt sehr interessant. Macht es denn dann Sinn, einen globalen VertexBuffer-Verwalter für alle Objekte überhaupt zu basteln und die Objekte dort einzutragen? Wenn Du sagst, man solle VertexBuffer immer auf 65536 Vertices auffüllen, sollte man ja offensichtlich Vertex- und IndexBuffer-Objekte weder anzahlig 1 : 1 zu den Meshes, aber doch auch nicht 1 : 1 zu den 3D-Modellen erstellen, oder?

Weiterhin klingt es für mich sinnvoll, wenn man Objekt A 10 Mal rendern möchte, jeweils Mesh 1 10 Mal zu rendern und dann Mesh 2. Das würde wiederum erfordern, dass wir uns irgendwo merken, wie oft Objekt A gerendet wird, damit wir das Rendern optimieren können, oder?

Re: Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 14.03.2010, 17:30
von Krishty
Eisflamme hat geschrieben:Das klingt sehr interessant. Macht es denn dann Sinn, einen globalen VertexBuffer-Verwalter für alle Objekte überhaupt zu basteln und die Objekte dort einzutragen? Wenn Du sagst, man solle VertexBuffer immer auf 65536 Vertices auffüllen, sollte man ja offensichtlich Vertex- und IndexBuffer-Objekte weder anzahlig 1 : 1 zu den Meshes, aber doch auch nicht 1 : 1 zu den 3D-Modellen erstellen, oder?
Um das zu beantworten habe ich leider zuwenig Erfahrung. Batching war, insbesondere zu Direct3D8- und -9-Zeiten, Common Practice … heute ist das Ändern eines Vertex-Buffers, solange der neue Puffer dasselbe Input-Layout hat, nur das Ändern eines Zeigers … ich bezweifle, dass es noch den Schub bringt, für den es früher bekannt geworden ist.
Eisflamme hat geschrieben:Weiterhin klingt es für mich sinnvoll, wenn man Objekt A 10 Mal rendern möchte, jeweils Mesh 1 10 Mal zu rendern und dann Mesh 2. Das würde wiederum erfordern, dass wir uns irgendwo merken, wie oft Objekt A gerendet wird, damit wir das Rendern optimieren können, oder?
Ist das klassische Renderproblem … darauf gibt es genauso wenig eine universelle Antwort wie darauf, wie man mit transparenten Objekten umgeht. Ist immer stark implementationsabhängig und erfordert ein Abwägen, ob die GPU das nicht schneller runtergerendert kriegt (Instancing!) als du die Ausganslage auf der CPU optimieren kannst.

Bei beiden Fragen hängt die Antwort davon ab, ob das Problem überhaupt eine gewisse Relevanz besitzt (sind Vertex-Buffer-Switches Bottlenecks?), wieviel Zeit du zu investieren bereit bist und wie weit du gehen willst.

Re: Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 15.03.2010, 00:10
von Eisflamme
Ein sehr philosophischer Post. :) Dann spar ich mir die Mühe von solch einer Verwaltungsklasse und mache es halt erstmal objektweise.

Ich bin allerdings auf ein Problem gestoßen: Ich nutze OpenGL. Wie kann ich bei der Verwendung von VertexBuffer-Objekten denn ein Offset festlegen? Wenn ich die Vertexdaten so vorliegen habe, addiere ich das Offset einfach zum Pointer, hier habe ich als letzten Parameter bei glVertexPointer aber die 0.

Re: Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 15.03.2010, 13:45
von kimmi
Du übergibst beim Rendern als Vertexarray doch einen Pointer. Mittels Pointerarithmetik kannst du dir die jeweilige Position des Mesh-bezogenen VertexBatches ermitteln und den dann rendern.

Gruß Kimmi

Re: Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 15.03.2010, 14:09
von Aramis
addiere ich das Offset einfach zum Pointer, hier habe ich als letzten Parameter bei glVertexPointer aber die 0.
Wenn meine Erinnerung mich nicht trügt ist der letzte Parameter dann in der Tat der Offset (zum Pointer casten …). Außerdem haben einige der OpenGL-Zeichenfunktionen die Möglichkeit den Startindex anzugeben (ganz mal davon abgesehen dass der Offset ja auch im Indexbuffer hinterlegt sein kann …).

Re: Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 15.03.2010, 14:26
von kimmi
Stimmt, Aramis hat natürlich recht. Man legt einen großen VBO und rendert das Submesh dann einfach per IndicesRender-Calls.

Gruß Kimmi

Re: Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 15.03.2010, 18:55
von Eisflamme
Hi,

Also ich drawe ja über glDrawElements. Wenn das: "
Wenn meine Erinnerung mich nicht trügt ist der letzte Parameter dann in der Tat der Offset (zum Pointer casten …).
", dann ist das Problem natürlich gelöst. Aber anderenfalls habe ich jetzt keine Ahnung, wie ich vorgehen sollte.

Re: Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 15.03.2010, 23:19
von Fred Feuerstein
Hio.
Ich weis nicht ob das hilfreich ist , aber Instancing ist ggf. auch ne Lösung.
Allerdings auch nur bis zu einem gewissen Grad.
Hab leider grad keinen guten Link parat:
http://blogs.msdn.com/manders/archive/2 ... ncing.aspx
Der veranschaulicht das ganze für 2D-Objekte, das Prinzip bleibt
davon unberührt.
MfG Fred

Re: Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 16.03.2010, 08:21
von kimmi
Da habe ich mal eine Frage: gibt es Instanting unter OpenGL? Ich habe bisher diesbezüglich noch nie Infos finden können. Vielleicht weiß hier ja einer mehr, wie man das dort anstellen beziehiungsweise implementieren könnte.

Gruß Kimmi

Re: Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 16.03.2010, 10:40
von glassbear
kimmi hat geschrieben:Da habe ich mal eine Frage: gibt es Instanting unter OpenGL?
Ja, gibt es. Sogar verschiedene Optionen
Dann hier noch eine Demo, die verschiedene Instancing-Methoden implementiert und vergleicht, mit Performance-Werten verschiedener Grafikkarten.

Re: Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 16.03.2010, 10:50
von kimmi
Cool, den Link kannte ich nicht. Vielen Dank dafür. @Eisflamme: Wäre das nichts für dich ;)?

Gruß Kimmi

Re: Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 16.03.2010, 18:46
von Eisflamme
Sieht auf alle Fälle interessant aus und ich hab's mir Mal abgelegt. :)

Ich würde gerne mein Problem mit den Buffern noch lösen. Also über "glDrawElements" sehe ich nach wie vor kein Offset, wenn der Pointer 0 ist. Einfach eine Zahl in einen Pointer zu konvertieren, würde ja auf Speicherbereiche jenseits von Gut und Böse führen bzw. müsste die Extension diese Bereiche ja als unsinnig identifizieren und dementsprechend das Offset auf das Vertexbuffer-Objekt anwenden - ich gehe nicht davon aus, dass das der Fall ist!?

Danke für eure Zeit und Mühe!

Re: Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 16.03.2010, 19:24
von Dirk Schulz
Hi,

hier nochmal die Doku zur Funktion, damit wir über dieselben Definitionen reden:
http://www.opengl.org/sdk/docs/man/xhtm ... ements.xml

der letzte Parameter "indices" will einen Pointer auf deinen Index-Array haben. Das heißt, du hast wahrscheinlich irgendwo ein unsigned int indices[num_indices], oder über new [] erstelltes Array mit den Indexwerten.

die Funktion erwartet von dir jetzt einen Pointer auf den ersten Eintrag im Indexarray, den du rendern willst.

Das wäre dann z.b: glDrawElements(GL_TRIANGLES, num_vertices, GL_UNSIGNED_INT, &indices[offset]);


Hoffe das war verständlich. :)

Re: Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 16.03.2010, 19:39
von anonym
Eisflamme hat geschrieben:[...] bzw. müsste die Extension diese Bereiche ja als unsinnig identifizieren und dementsprechend das Offset auf das Vertexbuffer-Objekt anwenden - ich gehe nicht davon aus, dass das der Fall ist!?
Genau das ist der Fall: Wenn ein Index-Buffer mittels glBindBuffer gesetzt wurde, dann gibt der indices-Zeiger in glDrawElements den Offset (in Bytes) in den Index-Buffer an. Anonsten wird ein Zeiger auf den ersten Index im Speicher erwartet.
Genauso: Wenn ein Vertex-Buffer gesetzt ist, geben die pointer-Zeiger in gl(Color|Normal|Vertex|...)Pointer den Offset in den Vertex-Buffer hinein an.

Re: Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 17.03.2010, 11:53
von Eisflamme
Hi,

Dirk: Ja, aber das Ding ist 0, wenn ich ein Buffer-Objekt nutze, das war der Hintergrund.

anonym: Ehrlich? Das ist ja schick. Super, dann kann ich das ja umsetzen, danke :)

Re: Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 17.03.2010, 14:06
von kimmi
Hierzu kann ich den Rendercode der ZFXCE mal als beispiel anbringen:
http://zfxce.git.sourceforge.net/git/gi ... 56;hb=HEAD
Die DrawElement-Calls bekommen einen entsprechenden Pointer auf die Vertexdaten. Hier kann man per Offset den Pointer entsprechend an die gewünschte Stelle shiften.

Gruß Kimmi

Re: Pro Mesh einen Vertex+IndexBuffer?

Verfasst: 18.03.2010, 10:40
von Eisflamme
Okay, ich denke, ich komm jetzt klar, vielen Dank. :) Wenn noch was is, post ich wieder...