"DirectX zeichnet nur Polygone mit einem [X, Y] von [-1, -1] bis [1,1] und mit einem Z von 0 bis 1.", Was bedeutet das und wie kann man es umgehen?

7

Ich habe die D3D11-Tutorials zu Rastertek befolgt , um mein Wissen über das Rendern zu erweitern, das ich brauche, um meine eigene Engine als Hobby zu bauen.

Nachdem ich endlich ein Modell im 3D-Raum auf den Bildschirm gerendert hatte und sowohl die Kamera als auch das Modell bewegen und drehen konnte, wollte ich stattdessen benutzerdefinierte FBX-Modelle importieren, die nicht im Tutorial enthalten sind. Ich fand dieses Tutorial online zu genau dem, was ich zusammen mit der Dokumentation des fbx SDK befolgte.

Es funktioniert jetzt zum Laden und Rendern von FBX-Modellen. Bei einigen Modellen sind die Scheitelpunkte jedoch ziemlich durcheinander, und bei einigen funktioniert es perfekt. Dann habe ich im Tutorial gelesen und zitiere:

"Wenn Sie die oben in diesem Beitrag angehängte Scheiß-FBX nicht verwenden, beachten Sie dies. Im Standardzustand zeichnet DirectX nur Polygone mit einem [X, Y] von [-1, -1 ] bis [1,1] und mit einem Z von 0 bis 1. Schauen Sie durch die Eckpunkte in Ihrer FBX und stellen Sie sicher, dass sich alles in diesem Bereich befindet! "

Wie Sie sich vorstellen können, funktioniert diese "beschissene Glocke" perfekt zum Zeichnen. Was bedeutet es überhaupt, dass Polygone in diesem Bereich gezeichnet werden? Wie kann ich das beim Modellieren umgehen?

Larssonmartin
quelle
Ich bin nicht mit DirectX vertraut, aber nachdem Sie andere Bibliotheken verwendet haben, haben Sie versucht, ein Dreieck zu zeichnen, dessen Scheitelpunkt auf (2, 0, 0) oder so ähnlich ist? Die Grenzen [-1, -1] und [1, 1] scheinen homogene Koordinaten zu sein, aber diese sollten für jemanden, der ein Netz zeichnet, nicht zugänglich sein und sollten hinter den Kulissen erfolgen. Gibt es eine Chance, dass Sie etwas falsch verstanden haben?
TomTsagk
@TomTsagk Ich könnte definitiv etwas falsch verstehen, obwohl ich nicht versucht habe, etwas manuell durch Eingabe eines manuell erstellten Scheitelpunkts und Indexpuffers zu zeichnen (nun ja, das habe ich schon, aber das hat nichts damit zu tun). Sie sind auch nicht zugänglich, ich habe nur nicht verstanden, was sie überhaupt sind. Ich dachte, ich müsste die Art und Weise ändern, wie Blender die FBX exportiert, damit sie zu einem bestimmten Zeitpunkt mit D3D funktioniert, aber ich bin einfach alleine weggeflogen Gedanken, und nach einigem googeln gab ich auf und stellte stattdessen hier meine Frage. Lesen Sie trotzdem die Antwort, die Josh gepostet hat und die meine Gedanken sehr gut beantwortet!
Larssonmartin

Antworten:

15

Obwohl dies technisch wahr ist, ist die Aussage in diesem Tutorial etwas irreführend und alarmierend formuliert.

Im Allgemeinen brauchen Sie sich darüber keine Sorgen zu machen.

Was bedeutet es überhaupt, dass Polygone in diesem Bereich gezeichnet werden?

Modellscheitelpunkte in der Grafikpipeline durchlaufen verschiedene Phasen, während sie die Grafikpipeline durchlaufen. Jede dieser Stufen ist ein eigenes Koordinatensystem , und zwischen diesen Koordinatensystemen verläuft ein Scheitelpunkt über Transformationsmatrizen.

Dieses Tutorial bezieht sich auf eine der letzten Phasen in der Pipeline, in denen Scheitelpunkte unmittelbar vor der Rasterung vorhanden sind, die als homogener Bildschirmbereich bezeichnet werden (beachten Sie jedoch, dass sie auch andere Namen hat). Der Zweck dieses Koordinatenraums besteht darin, alle Scheitelpunktdaten in einen bekannten, normalisierten Bereich zu skalieren, so dass sie auf den Pixelraum des Zielfensters abgebildet werden können. Typische Bereiche für Achsen in diesem Bereich in verschiedenen Grafik-APIs sind -1 bis 1 oder 0 bis 1, da beide einfach auf den Pixelraum 0 bis einige große Ganzzahlen des Zielfensters abgebildet werden können.

Normalerweise konfigurieren Sie die Modell-, Ansichts- und Projektionsmatrizen (sowie die Ansichtsfenster-Transformation, falls erforderlich) entsprechend Ihrer Szene. In dem von Ihnen verlinkten Tutorial werden diese Schritte möglicherweise aus Gründen der Kürze weggelassen. Wenn Sie keine explizite Transformation von Scheitelpunktdaten in Ihren Shadern oder dergleichen durchführen, ist das Nettoergebnis so, als wären alle Ihre Transformationen Identitätsmatrizen, was bedeutet, dass alle Transformationen, die automatisch von der Pipeline durchgeführt werden, im Wesentlichen auch so sind No-Ops (mit Ausnahme der Ansichtsfenster-Transformation) und Sie haben effektiv einen sichtbaren Bereich, der den Bereichen des homogenen Bildschirmbereichs entspricht.

Wie kann ich das beim Modellieren umgehen?

Das tust du nicht. Modellieren Sie Ihre Objekte nach Bedarf und passen Sie Direct3D dann wie oben beschrieben an diese Anforderungen an und nicht umgekehrt. Während es letztendlich wahr ist, dass Ihre Koordinaten unmittelbar vor dem Zeichnen in einer normalisierten Form von -1 zu 1 enden, können Sie D3D so konfigurieren, dass jeder gewünschte Koordinatenbereich in diesen vorletzten Bereich transformiert und skaliert wird.


quelle
11
Dies gilt auch nicht nur für DirectX. Dies gilt für OpenGL und andere 3D-Grafik-APIs. Möglicherweise finden Sie diesen älteren Artikel hilfreich. Die API-Anweisungen sind veraltet, da es sich um Direct3D 9 handelt, aber die Konzepte sind alle korrekt.
Chuck Walbourn
@ChuckWalbourn Danke für den Artikel, ich werde ihn auf jeden Fall lesen.
Larssonmartin
2
TL: DR Wenn der Autor des Tutorials "In seinem Standardzustand ..." schreibt, bedeutet er "Wenn Sie keine Szenen- / Kameratransformation einstellen", was hoffentlich in weiteren Teilen erklärt wird.
IMil
13
Wow, die Aussage im OP-Tutorial scheint ungefähr so ​​genau zu sein, als würde man jemandem sagen: "Hier ist eine Kamera auf einem Stativ. Sie erhalten nur dann ein anständiges Foto, wenn Sie Ihr Objekt an einer Stelle davor in der richtigen Entfernung platzieren Fokus "- es ist nicht falsch , aber das Auslassen der Idee, die Kamera zu bewegen oder ihren Fokus anzupassen, führt selbst der Einfachheit halber zu genau der Verwirrung von OP ...
AC
@lMil Okay, was ich in meinem Vertex-Shader basierend auf den Vertices-Positionen mache, habe es verstanden, danke!
Larssonmartin
7

Der [-1 ; 1] x [-1 ; 1] x [0 ; 1]im Tutorial erwähnte Bereich bezieht sich auf das kanonische Ansichtsvolumen . Dies ist der endgültige Koordinatenraum, auf den Scheitelpunktdaten abgebildet werden, bevor alles auf Ihrem Bildschirm gerastert wird. Um zu verstehen, was genau dies bedeutet, ist es hilfreich, einen Blick darauf zu werfen, wie eine Rendering-Pipeline normalerweise aussieht.

Räume koordinieren

Ein Koordinatenraum bezieht sich auf das Koordinatensystem, mit dem Sie die Positionen der Scheitelpunkte darin definieren. Stellen Sie sich als Beispiel aus der Praxis vor, Sie haben einen Schreibtisch mit einer Tastatur darüber und möchten die Position der Tastatur ausdrücken. Sie können die vordere linke Ecke des Schreibtisches als Position definieren (0, 0, 0)- dies wird als Ursprung bezeichnet -, die X-Achse entlang der Länge des Schreibtisches (von links nach rechts) und die Y-Achse entlang der Tiefe des Schreibtisches Schreibtisch (nah bis fern) und die Z-Achse senkrecht vom Schreibtisch nach oben. Befindet sich Ihre Tastatur 50 Zentimeter rechts von dieser Ecke und 10 Zentimeter von der nächsten Kante entfernt, befindet sie sich an der Position (50, 10, 0).

Alternativ können Sie die Ecke Ihres Raums als Position definieren (0, 0, 0). Nehmen wir an, Ihr Schreibtisch befindet sich 200 cm von der linken Wand, 300 cm von der Vorderwand entfernt und der Schreibtisch ist 70 cm hoch. In diesem Fall befindet sich die Tischplatte an (200, 300, 70)Ihrer Position und Ihre Tastatur an (250, 310, 70).

Dies sind zwei Beispiele für unterschiedliche Koordinatenräume und wie sie sich auf die Positionskoordinaten der Objekte in ihnen auswirken. In ähnlicher Weise werden Scheitelpunktdaten in einer 3D-Rendering-Pipeline über verschiedene Koordinatenräume hinweg transformiert, bevor sie auf Ihrem Bildschirm angezeigt werden.

Koordinieren Sie Räume in einer 3D-Rendering-Pipeline

Einzelne Objekte werden in 3D-Software wie Autodesk Maya, Blender ... modelliert. Sie werden häufig zentriert um den Ursprung modelliert. Dieser Koordinatenraum wird als Modellraum bezeichnet . Wenn Sie mehrere Objekte im Modellraum zusammen rendern würden, würden sie alle zentriert um den Ursprung gestapelt.

Stattdessen wird ein neuer Koordinatenraum definiert, der als Weltraum bezeichnet wird. Stellen Sie sich dies als Ihre Spielwelt vor, wobei der Ursprung das Zentrum der Welt ist. Bei der Transformation des Modellraums in Weltraumkoordinaten werden Übersetzungen, Rotationen, Skalierungen und andere Operationen ausgeführt. Wenn Sie beispielsweise eine Tastatur an der Position (250, 310, 70)Ihrer Welt rendern möchten , würden Sie alle ihre Scheitelpunkte um diesen Vektor versetzen. Mathematisch gesehen erfolgt dies unter Verwendung einer Transformationsmatrix . Sie können auf jedes einzelne Objekt eine andere Transformation anwenden, um Objekte in Ihrer Spielwelt zu platzieren.

Sie haben jetzt einen großen Stapel von Eckpunkten, an denen jedes Objekt an der richtigen Position platziert ist. Sie müssen jetzt definieren, welchen Teil der Welt Sie betrachten möchten. Dies erfolgt durch Verschieben aller Scheitelpunktdaten in den Kameraraum . Eine häufig eingesetzte Konvention ist die Kamera in dem Ursprung des positioniert hat Kameraraum , um es in Richtung der positiven Z-Achse sehen zu haben (der Blickvektor ) und den positiven Aufwärts Y-Achsenpunkt zu haben (den Aufwärtsvektor ). Bei der Konvertierung vom Weltraum in den Modellraum möchten wir daher alle Scheitelpunktdaten so verschieben und drehen, dass sich unsere Fokusobjekte in der Nähe des Ursprungs befinden und positive Z-Koordinaten haben.

Wenn Sie Objekte im wirklichen Leben betrachten, werden Sie ein Phänomen bemerken, das als Verkürzung bezeichnet wird . Dies bedeutet, dass Objekte in Ihrer Nähe größer erscheinen (dh mehr von Ihrer Ansicht einnehmen), während Objekte, die weit von Ihnen entfernt sind, kleiner erscheinen (dh weniger von Ihrer Ansicht einnehmen). Wir simulieren dies, indem wir eine perspektivische Transformation anwenden , die die Scheitelpunktkoordinaten unseres Kameraraums in den projizierten Raum verschiebt .

Beachten Sie schließlich, dass wir 3D-Scheitelpunktdaten haben, die auf einem 2D-Bildschirm gerendert werden müssen (z. B. 1920 x 1080 Pixel). Die Scheitelpunktdaten im Kameraraum werden daher in Bildschirmraum umgewandelt . Ihre Grafik-API sorgt dafür, dass die Scheitelpunktdaten des Bildschirmbereichs auf Ihrem Bildschirm gerendert werden. Das Konvertieren von Scheitelpunktdaten in Pixel auf Ihrem Bildschirm wird als Rasterisierung bezeichnet . Aber welche Scheitelpunktkoordinaten landen wo auf Ihrem Bildschirm? Hier kommt das kanonische Ansichtsvolumen ins Spiel.

DirectX gibt an, dass die X-Koordinate des Scheitelpunkts der horizontalen Position auf dem Bildschirm zugeordnet wird. Insbesondere: Der Bereich [-1 ; 1]wird zugeordnet [0 ; 1920](bei einem 1920 x 1080-Bildschirm). Die Y-Koordinate des Scheitelpunkts wird der vertikalen Position auf dem Bildschirm zugeordnet. Insbesondere: Der Bereich [-1 ; 1]wird zugeordnet [0 ; 1080](bei einem 1920 x 1080-Bildschirm). Die Z-Koordinate wird verwendet, um zu bestimmen, welche Eckpunkte vor oder hintereinander gerendert werden müssen. Insbesondere befinden sich Scheitelpunkte in der Nähe von 0 in der Nähe der Kamera und sollten vor gerendert werden. Scheitelpunkte in der Nähe von 1 sind weit von der Canera entfernt und werden hinterher gerendert. Scheitelpunkte mit einer Z-Koordinate kleiner als 0 befinden sich hinter der Kamera und werden daher abgeschnitten - dh nicht gerendert. Scheitelpunkte mit einer Z-Koordinate größer als 1 sind zu weit entfernt und werden ebenfalls abgeschnitten.

Ihre Perspektiventransformation muss daher alle Scheitelpunkte verschieben, die auf Ihrem Bildschirm in diesem kanonischen Ansichtsvolumen sichtbar sein sollen. In dem Tutorial, dem Sie gefolgt sind, werden alle diese Transformationen weggelassen, um das Tutorial einfach zu halten. Sie rendern somit direkt auf das kanonische Ansichtsvolumen. Aus diesem Grund sagt der Autor, dass alles außerhalb des Bereichs [-1 ; 1] x [-1 ; 1] x [0 ; 1]nicht sichtbar ist.

Verweise

Einen Artikel mit Bildern zur Veranschaulichung dieser verschiedenen Koordinatenräume finden Sie unter Welt-, Ansichts- und Projektionstransformationsmatrizen von CodingLabs .

Jelle van Campen
quelle
1
Ich habe aus Neugier viel Mathematik und Theorie hinter den Rendering-Pipelines gelesen, während der Schulkurse und zu Hause. Ihre einfache Erklärung hat jedoch mehr als lange Artikel geliefert. Es ist einfacher, tief in Artikel einzutauchen, wenn Sie die Grundlagen verstehen Konzepte, die ich noch nie zuvor von der kanonischen Ansicht gehört hatte, erklären meine Verwirrung über den kleinen Bereich für die Eckpunkte. Vielen Dank, dass Sie sich damit Zeit genommen haben!
Larssonmartin