Models mit verschiedenen Materialien rendern

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Benutzeravatar
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

Beitrag von Top-OR »

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
--
Verallgemeinerungen sind IMMER falsch.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4855
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Models mit verschiedenen Materialien rendern

Beitrag von Schrompf »

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 :-)
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
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

Beitrag von Top-OR »

Moin Schrompf!

Haaa! Indexbuffer ... GL_ELEMENT_ARRAY_BUFFER ... macht Sinn!

Also dann Variante 2 - VAO vorher zusammenbinden. Ich versuche da mal...
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.
Ja, darum auch meine Frage. Das mit den Indices hat mir ziemlich Kopfzerbrechen bereitet...
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 :-)
Guter Hinweis. Danke, mache ich!


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.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4855
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Models mit verschiedenen Materialien rendern

Beitrag von Schrompf »

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.
Benutzeravatar
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

Beitrag von Top-OR »

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 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.

Ich werds mal bei Gelegenheit vergleichen.
--
Verallgemeinerungen sind IMMER falsch.
Antworten