Hallo Freunde der Sonne.
Ich hätte gerne eure Meinung zu einem Problem/Effekt.
Ich rendere mit OpenGL 3.3 (core) Models.
Ein Model kann aus ja Faces mit verschiedenen Materialien (z.Z. Nur Farb-Textur) bestehen. Diese werden (nach Material) sortiert gerendert, um DrawCalls/Context Switches zu sparen.
Zur Zeit (1) habe ich ein Vertex Array Object [VAO]; daran geknotet ist ein Vertex Buffer Object[VBO] mit allen Vertices des Modells. Für das Rendering der verschiedenen Sektionen (Materialgruppen) benutze übertrage ich per DrawCall die entsprechenden Indices, um nur die Vertices zu rendern, die auch zu Faces des aktuellen Materials zu gehören (glDrawElementsInstanced[ARB]). Nun frage ich mich, ob das nicht noch etwas ineffizient ist. Gerade bei Großer Anzahl der Objekte muss ich ja immernoch die Indices übertragen.
Ich habe mir überlegt, dass es vielleicht praktischer ist, ohne Indices zu rendern (2) und die Vertices einfach in der richtigen Reihenfolge ein Vertex Array Object (VAO) zu stopfen und dieses dann ohne Indices komplett zu rendern (mit glDrawArraysInstanced[ARB]).
Alternativ (3) könnte ich auch Verschiedene Vertex Buffer Objects mit den Vertices der jeweiligen Materialgruppe vorhalten und dieses vorm Rendern an ein globales Vertex Array Object binden.
Ich ahne aber, dass die letzte Methode (3) die unpraktischste ist. Ich tendiere im Moment dazu, so etwas wie (2) zu implementieren. Also alles Vertices, die zu einer Materialgruppe eines Models gehören (also nennen wirs mal ein „Mesh“) komplett seinen eignenen VAO + VBO zu spendieren.
Das würde mir das Übertragen der Indices beim DrawCallen ersparen, würde aber mit sich bringen, dass manche Vertices mehrfach im VBO/A auftreten, da sie an in der korrekten Reihenfolge für Render-Primitive (TRIANGLES, TRIANGLE_STRIPS) im Buffer liegen müssen.
Weiterhin habe ich ein extra VBA für jedes Teil-Model/Mesh. Ich kannn nicht einschätzen, wie groß der Memory-Footprint dieser Strukturen ist. Verschwendet das unnötig (Video-/Treiber-)speicher oder kann man das getrost vernachlässigen?
Was ist der günstigste Weg? Was ist da Best Practice?
Ich hoffe, ich habe hier mein Problem/Frage nicht zu wirr dargestellt… :-/
Danke im Voraus,
Jens
Models mit verschiedenen Materialien rendern
- Top-OR
- Establishment
- Beiträge: 330
- Registriert: 02.03.2011, 16:32
- Echter Name: Jens H.
- Wohnort: Esslingen/Dessau
- Kontaktdaten:
Models mit verschiedenen Materialien rendern
--
Verallgemeinerungen sind IMMER falsch.
Verallgemeinerungen sind IMMER falsch.
- Schrompf
- Moderator
- Beiträge: 4878
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas Ziegenhagen
- Wohnort: Dresden
- Kontaktdaten:
Re: Models mit verschiedenen Materialien rendern
Irgendwie bist Du da auf dem Holzweg. Die Indizes packt man in einen Index Buffer. Und dieser IndexBuffer zusammen mit dem VBO ergeben einen Mesh. Das VAO ist eigentlich eher eine Beschreibung der Eingabestruktur, OpenGL hat das nur im Gegensatz zu allen anderen APIs etwas unglücklich mit der Auswahl der VBOs verknüpft. Der typische Ablauf unter OpenGL wäre also:
1)
- VBO anbinden
- IndexBuffer anbinden
- den einzigen VAO neu beschreiben mit Verweis auf den VBO
- glDrawElements()
oder 2)
- pro Mesh einen VAO anlegen und den binden
- glDrawElements()
Und auch wenn das unintuitiv klingt: irgendwer hat auf GameDev.net mal nachgemessen und festgestellt, dass das Neu-Zusammenstellen des VAO für jeden DrawCall schneller war als das Erstellen eines VAO pro Mesh.
Wovon Du im Sinne der Performance auf jeden Fall Abstand nehmen solltest, ist das Hochladen der Indizes für jedes Frame. Allgemein gilt bei der GPU: je mehr Daten Du konstant halten und über mehrere Frames wiederverwenden kannst, um so besser. Wovon Du aber auch nach Möglichkeit Abstand nehmen solltest, ist das Rendern ohne IndexBuffer. Indizes lohnen sich quasi jederzeit, auch wenn heutzutage durch Unified Shader und die enorme Lastverschiebung zum Fragment Shader die Vorteile des indizierten Renderns üblicherweise gut versteckt sind. Vertrau mir und nimm trotzdem (praktisch) jederzeit IndexBuffer. Weniger Speicher für Vertizes, weniger Speicherbandbreite, Wiederverwendung der VertexShader-Ergebnisse und damit auch weniger Rechenlast auf der GPU. Selbst Sprites und Text Rendering profitieren davon. Tu es :-)
1)
- VBO anbinden
- IndexBuffer anbinden
- den einzigen VAO neu beschreiben mit Verweis auf den VBO
- glDrawElements()
oder 2)
- pro Mesh einen VAO anlegen und den binden
- glDrawElements()
Und auch wenn das unintuitiv klingt: irgendwer hat auf GameDev.net mal nachgemessen und festgestellt, dass das Neu-Zusammenstellen des VAO für jeden DrawCall schneller war als das Erstellen eines VAO pro Mesh.
Wovon Du im Sinne der Performance auf jeden Fall Abstand nehmen solltest, ist das Hochladen der Indizes für jedes Frame. Allgemein gilt bei der GPU: je mehr Daten Du konstant halten und über mehrere Frames wiederverwenden kannst, um so besser. Wovon Du aber auch nach Möglichkeit Abstand nehmen solltest, ist das Rendern ohne IndexBuffer. Indizes lohnen sich quasi jederzeit, auch wenn heutzutage durch Unified Shader und die enorme Lastverschiebung zum Fragment Shader die Vorteile des indizierten Renderns üblicherweise gut versteckt sind. Vertrau mir und nimm trotzdem (praktisch) jederzeit IndexBuffer. Weniger Speicher für Vertizes, weniger Speicherbandbreite, Wiederverwendung der VertexShader-Ergebnisse und damit auch weniger Rechenlast auf der GPU. Selbst Sprites und Text Rendering profitieren davon. Tu es :-)
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
- Top-OR
- Establishment
- Beiträge: 330
- Registriert: 02.03.2011, 16:32
- Echter Name: Jens H.
- Wohnort: Esslingen/Dessau
- Kontaktdaten:
Re: Models mit verschiedenen Materialien rendern
Moin Schrompf!
Haaa! Indexbuffer ... GL_ELEMENT_ARRAY_BUFFER ... macht Sinn!
Also dann Variante 2 - VAO vorher zusammenbinden. Ich versuche da mal...
Thanks a lot, Mr. Schrompf!
Haaa! Indexbuffer ... GL_ELEMENT_ARRAY_BUFFER ... macht Sinn!
Also dann Variante 2 - VAO vorher zusammenbinden. Ich versuche da mal...
Ja, darum auch meine Frage. Das mit den Indices hat mir ziemlich Kopfzerbrechen bereitet...Schrompf hat geschrieben: Wovon Du im Sinne der Performance auf jeden Fall Abstand nehmen solltest, ist das Hochladen der Indizes für jedes Frame. Allgemein gilt bei der GPU: je mehr Daten Du konstant halten und über mehrere Frames wiederverwenden kannst, um so besser.
Guter Hinweis. Danke, mache ich!Schrompf hat geschrieben: Wovon Du aber auch nach Möglichkeit Abstand nehmen solltest, ist das Rendern ohne IndexBuffer. Indizes lohnen sich quasi jederzeit, auch wenn heutzutage durch Unified Shader und die enorme Lastverschiebung zum Fragment Shader die Vorteile des indizierten Renderns üblicherweise gut versteckt sind. Vertrau mir und nimm trotzdem (praktisch) jederzeit IndexBuffer. Weniger Speicher für Vertizes, weniger Speicherbandbreite, Wiederverwendung der VertexShader-Ergebnisse und damit auch weniger Rechenlast auf der GPU. Selbst Sprites und Text Rendering profitieren davon. Tu es :-)
Thanks a lot, Mr. Schrompf!
Zuletzt geändert von Top-OR am 04.02.2016, 17:15, insgesamt 1-mal geändert.
--
Verallgemeinerungen sind IMMER falsch.
Verallgemeinerungen sind IMMER falsch.
- Schrompf
- Moderator
- Beiträge: 4878
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas Ziegenhagen
- Wohnort: Dresden
- Kontaktdaten:
Re: Models mit verschiedenen Materialien rendern
Probier's! Und probiere auch mal Variante 1 - globalen VAO und für jeden DrawCall neu zusammenstellen. So mach ich das hier bisher, und das Internet meint vereinzelt, dass das schneller wäre als 2). Würde mich interessieren, ob und was Du da rauskriegst.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
- Top-OR
- Establishment
- Beiträge: 330
- Registriert: 02.03.2011, 16:32
- Echter Name: Jens H.
- Wohnort: Esslingen/Dessau
- Kontaktdaten:
Re: Models mit verschiedenen Materialien rendern
Ich werds mal mit auf die Liste nehmen. Ich habe auch mal "Im Internet" gelesen, dass das Neu-Zusammenbauen wohl doch recht viel Overhead macht und deswegen besser viele fertige VAO vorgehalten werden sollen.Schrompf hat geschrieben:Probier's! Und probiere auch mal Variante 1 - globalen VAO und für jeden DrawCall neu zusammenstellen. So mach ich das hier bisher, und das Internet meint vereinzelt, dass das schneller wäre als 2). Würde mich interessieren, ob und was Du da rauskriegst.
Ich werds mal bei Gelegenheit vergleichen.
--
Verallgemeinerungen sind IMMER falsch.
Verallgemeinerungen sind IMMER falsch.