[DX10] Vertexformate und Buffer

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

[DX10] Vertexformate und Buffer

Beitrag von Zudomon »

Wie bekommt man Vertexformate, Vertex- und Indexbuffer und Effekte unter einen Hut? Sind verschiedene Vertexstreams ( außer bei Instanzierung ) sinnvoll? Wie baut man das alles Effektiv zusammen und wie viel an Flexiblität reicht man weiter durch? Fragen über Fragen... vielleicht habt ihr einige Antworten parat... :D
Gelöschter Benutzer
Beiträge: 92
Registriert: 26.02.2009, 22:09

Re: [DX10] Vertexformate und Buffer

Beitrag von Gelöschter Benutzer »

Die Shaderfunktion für einen Vertex- oder Pixelshader enthält ja für Eingabedaten Semantiken (POSITION, NORMAL, TEXCOORD, TANGENT, BINORMAL, COLOR etc.): OutStruct Shader_main(float 3 pos : POSITION) { ... } etc..

Diese Eingabedaten müssen identisch mit den Eingabedaten des Input Layouts sein. Da kommst du dran nicht vorbei.

Was du natürlich machen kannst, ist eine eigene simulierte FVF (FVF.Pos|FVF.Normal|FVF.Texcoord...) zu basteln - aber auch hier müssen Shader mit den Eingabedaten kompatibel sein. Designen? Hier braucht man ein intelligentes Objektformat oder einen guten Asset Importer.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4854
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [DX10] Vertexformate und Buffer

Beitrag von Schrompf »

Das Fragegebiet ist ehrlich gesagt so riesig, dass ich nicht weiß, was ich da beantworten soll. Da musst Du schlicht Deine eigenen Erfahrungen machen. Für den Anfang würde ich Dir empfehlen, eine einzelne Vertex-Struktur zu definieren, die erstmal alles abdeckt, was Du so brauchen wirst. Damit hast Du ein definiertes Format, um die VertexBuffer zu erzeugen. Bei uns sieht diese AllesInEinem-Struktur so aus:

Code: Alles auswählen

float3 mPosition;
float3 mNormale;
float4 mTangente; // mit Bitangenten-Richtung (+1 oder -1) in .w
float4 mFarbe;   // bei uns reserviert für's indirekte Licht, Vertexfarben hab ich noch nicht gebraucht
float2 mTexKoords;
float4 mZeuch;  // allgemeine Daten zur freien Verwendung

// Zusatz für Vertex-Skinning
UBYTE4 mBoneIndizes;
UBYTE4 mBoneGewichte;

// Zusatz für Instancing
column_major float4x3 mObjektMatrix;
USHORT4 mSHKoeffs[7]; // SHKoeff[7] ist in .w von 0,1,2 - SHKoeff[8] ist in .w von 3,4,5
Der obere Teil ist die Basis-Vertexstruktur. Die float4-Zeuch-Komponente enthält allen möglichen zusätzlichen Kram - z.B. den Entfaltungsvektor und die Rotation für Billboards. Die beiden Zusätze kommen für Render-Sonderfälle zum Einsatz. Unsere Engine versteht drei verschiedene Zeichenaufträge: normal, verboned (mit std::vector<Matrix> der Bone-Matrizen) und instanced (mit separatem Instanz-Buffer).

Bei verbonten Zeichenaufträgen wird die Vertexstruktur mitsamt dem Zusatz für Vertex-Skinning benutzt, die Vertexdaten müssen dazu dann auch in diesem Format vorliegen.

Bei Instancing-Zeichenaufträgen wird ein separater Instanzen-Buffer mit der unteren Datenstruktur erwartet. Die Vertex-Eingabestruktur im VertexShader ist dann natürlich eine Kombination aus den beiden Teilen. Ich hab ein bisschen stapeln müssen, damit ich beide zusammen noch am DX9-Limit von 16 VertexShader-Eingaberegistern vorbeibekomme. Pro Instanz wird eine Transformationsmatrix gegeben (im Shader als column_major markiert, damit sie 3 Eingaberegister mit Viererbreite anstatt 4 Eingaberegister mit Dreierbreite einnimmt) und außerdem pro Instanz eine Spherical Harmonic mit dem indirekten Licht. Die Vertex-Farbe enthält dann nur noch die Selbstverdeckung des Objekts, also wieviel Umgebungslicht von außen an die jeweilige Stelle rankommt. Das multipliziert mit der SH pro Instanz sorgt für recht angenehmes Umgebungslicht auf Farnen, Gräsern und Geröll. Wenn ich mal groß bin, bau ich noch SSAO an, damit die Übergänge zur Umgebung nicht so kantig aussehen.

Wir haben bei uns irgendwann eine kleine Vertex-Verwaltung eingebaut, die aus einer zugeworfenen Liste von Elementen die drei oben genannten Varianten erstellt. Den Vertexstruktur-Identifier gibt man dann zusammen mit der Verwendungsform bei der Erstellung eines MeshBuffers an, damit die Engine zur Laufzeit prüfen kann, ob der übergebene Mesh zur Form des Zeichenauftrags passt. Funktioniert angenehm, und ermöglicht dann auch stark reduzierte Vertexstrukturen für z.B. Partikel. Aber mit der oben vorgeschlagenen AllesRein-Struktur fährst Du auch nicht schlecht... mit angepassten Vertexstrukturen spart man nur ein bisschen VideoRAM.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: [DX10] Vertexformate und Buffer

Beitrag von Zudomon »

Hallo!

Danke für eure Antworten! Bisher hatte ich das bei mir auch immer mit einer Art Alroundvertexformat gelöst. Aber ich habe einfach das Gefühl, dass das so noch nicht der Weisheit letzter Schluss ist...
Meine Frage war vielleicht sehr Allgemein gestellt. Ich starte ja gerade mit einer neuen Engine und stelle deswegen so viele Fragen. Würde das gerne einmal richtig hinbekommen, so das es dynamisch und flexibel ist, auch für die Zukunft ( wobei ich nicht weiß, ob man das überhaupt bewerkstelligen kann ).

Es gibt zwei Brennpunkte, die mir besonders Kopf zerbrechen bereiten:
1. Bringt es Vorteile, wenn man mehrere Vertexstreams für ein Objekt benutzt?
2. Kann man im Effektfile flexibel die Eingabedaten definieren, wie bekommt man diese Flexiblität auf Applikationsebene durchgereicht, um dann da auch Flexibel jedes gewünschte Format bereitstellen zu können?

Und dann ist da noch die Frage, wie viel dieser ganzen Flexiblität man bis auf Anwenderebene durchreicht. Also wäre es sinnvoll, in einem Editor das Vertexformat bestimmen zu können? Eigentlich ist es das ja, weil man sonst die Eingabedaten im Effektfile auch direkt vorgeben könnte.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4854
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [DX10] Vertexformate und Buffer

Beitrag von Schrompf »

Zudomon hat geschrieben: Meine Frage war vielleicht sehr Allgemein gestellt. Ich starte ja gerade mit einer neuen Engine und stelle deswegen so viele Fragen. Würde das gerne einmal richtig hinbekommen, so das es dynamisch und flexibel ist, auch für die Zukunft ( wobei ich nicht weiß, ob man das überhaupt bewerkstelligen kann ).
Kann man nicht. Lass Dir aus Erfahrung gesagt sein, dass Du nicht aus dem Stand den idealen Weg finden wirst. Das ist unmöglich, aber bis Du das bemerkst, kannst Du noch eine Menge Zeit mit Planungen und Bedenken verschwenden. Programmiere eine halbwegs saubere Lösung, die alle aktuell anliegenden Anforderungen erfüllt, und scheue Dich nicht, sie später nochmal umzuschreiben, wenn Du weitere Anforderungen hast. Aber das Schlimmste, was Du Deiner Engine antun kannst, ist für Gott Und Die Welt zu planen und es allen recht machen zu wollen.

Entwickle ein Spiel zusammen mit Deiner Engine. Dann wirst Du ganz automatisch immer neue Anforderungen bekommen, an denen Du erkennst, welcher Teil der Engine noch Überarbeitung braucht.
1. Bringt es Vorteile, wenn man mehrere Vertexstreams für ein Objekt benutzt?
Nein, damit ist das Zugriffsmuster im Graka-Speicher nur etwas unangenehmer für die PreVertex-Caches. Aber den Unterschied wirst Du kaum messen können, weil die Performance praktisch nie am VertexFetch hängt. Es kann sich zur Speicherersparnis lohnen, wiederverwendbare Teile der Daten in separate Streams rauszuziehen. Aber abgesehen von extremen Spezialanwendungen wie z.B. einer HeightMap gibt es dafür kaum praktische Anwendungsfälle... und die VertexBuffer sind wie gesagt praktisch nie die großen Speicherfresser. Von daher seh ich da keinen Handlungsbedarf.
2. Kann man im Effektfile flexibel die Eingabedaten definieren, wie bekommt man diese Flexiblität auf Applikationsebene durchgereicht, um dann da auch Flexibel jedes gewünschte Format bereitstellen zu können? Und dann ist da noch die Frage, wie viel dieser ganzen Flexiblität man bis auf Anwenderebene durchreicht. Also wäre es sinnvoll, in einem Editor das Vertexformat bestimmen zu können? Eigentlich ist es das ja, weil man sonst die Eingabedaten im Effektfile auch direkt vorgeben könnte.
Nein, den Anwender interessiert das definitiv nicht. Wer auch immer die Buffer für die Engine erstellt, bestimmt damit auch das Vertexformat. Der Nutzer bestimmt dagegen das Material und damit auch den Shader, der den Buffer zum Rendern in die Hände bekommt. Du kannst nach meiner Betrachtung auf keinem Weg sicherstellen, dass das Vertexformat der Shader-Erwartung entspricht. Du solltest lieber versuchen, evtl. Fehlzuordnungen abzufangen. Haben wir uns aber komplett gespart, und das Ergebnis ist im schlimmsten Fall ein unsichtbares Modell oder ein auf amüsante Weise fehlgerendertes Modell. Tut also keinem weh.

Bye, Thomas
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: [DX10] Vertexformate und Buffer

Beitrag von Zudomon »

Danke! Ich werde mir deinen Rat zu Herzen nehmen!
Also ab jetzt wird nur noch so programmiert, dass es für das, was man haben will, passt und nicht mehr darauf Rücksicht genommen, was man später eventuell noch dazu bauen könnte. :D
Das erleichtert das ganze doch schon ungemein! :D
Antworten