Homogene Koordinaten
Im vorherigen Abschnitt haben wir einen Vertex mithilfe einer 4×4-Matrix verschoben. Dafür haben wir seine Position (1, 2, 3) um eine vierte Koordinate ergänzt:
(1, 2, 3) → (1, 2, 3, 1)Diese vierte Koordinate heißt w. Zusammen mit den drei Raumkoordinaten x, y und z bildet sie die sogenannten homogenen Koordinaten.
Warum ist diese zusätzliche Koordinate so nützlich?
Die Bedeutung von w
Abschnitt betitelt „Die Bedeutung von w“Erinnern wir uns an unsere Verschiebungsmatrix:
| 1 0 0 2 || 0 1 0 0 || 0 0 1 0 || 0 0 0 1 |Sie verschiebt einen Punkt um zwei Einheiten entlang der X-Achse.
Multiplizieren wir die Matrix mit einem Positionsvektor, erhalten wir:
| 1 0 0 2 | | x | | x + 2 || 0 1 0 0 | | y | | y || 0 0 1 0 | × | z | = | z || 0 0 0 1 | | 1 | | 1 |Entscheidend ist die erste Zeile der Berechnung:
x' = 1 × x + 0 × y + 0 × z + 2 × 1 = x + 2Die Verschiebung entsteht, weil die 2 aus der Matrix mit unserer vierten Koordinate w = 1 multipliziert wird.
Durch die vierte Koordinate können wir eine Verschiebung als Matrix-Vektor-Multiplikation berechnen.
Wie wir mit 4×4-Matrizen auch Drehungen und Skalierungen beschreiben und mehrere Transformationen miteinander kombinieren können, werden wir später noch sehen.
Positionen und Richtungen
Abschnitt betitelt „Positionen und Richtungen“Die vierte Koordinate ermöglicht uns außerdem, zwischen einer Position und einer Richtung zu unterscheiden.
Eine Position beschreibt einen bestimmten Punkt im Raum, beispielsweise die Ecke eines Würfels.
Eine Richtung beschreibt dagegen, wohin etwas zeigt. Ein Richtungsvektor hat keinen festen Ort im Raum.
Diesen Unterschied drücken wir mit w aus:
w = 1.0steht für eine gewöhnliche Position.w = 0.0steht für einen Richtungsvektor.
Warum ist das wichtig?
Stellen wir uns einen Pfeil vor, der nach rechts zeigt. Wenn wir ein Objekt verschieben, verändert sich seine Position. Die Richtung des Pfeils soll sich durch diese Verschiebung aber nicht ändern.
Betrachten wir deshalb unsere Verschiebungsmatrix ein weiteres Mal. Diesmal multiplizieren wir sie mit einem Richtungsvektor, dessen vierte Koordinate 0 ist:
| 1 0 0 2 | | 1 | | 1 || 0 1 0 0 | | 0 | | 0 || 0 0 1 0 | × | 0 | = | 0 || 0 0 0 1 | | 0 | | 0 |Der Richtungsvektor (1, 0, 0, 0) bleibt unverändert.
Der Grund liegt wieder in der ersten Zeile:
x' = 1 × 1 + 0 × 0 + 0 × 0 + 2 × 0 = 1Weil w = 0 ist, trägt die Verschiebung um zwei Einheiten nichts zum Ergebnis bei.
Eine Verschiebung verändert Positionen, aber keine Richtungen.
In WGSL können wir diesen Unterschied direkt nachvollziehen:
let translation = mat4x4f( vec4f(1.0, 0.0, 0.0, 0.0), vec4f(0.0, 1.0, 0.0, 0.0), vec4f(0.0, 0.0, 1.0, 0.0), vec4f(2.0, 0.0, 0.0, 1.0));
let position = vec4f(1.0, 0.0, 0.0, 1.0);let direction = vec4f(1.0, 0.0, 0.0, 0.0);
let movedPosition = translation * position;let movedDirection = translation * direction;Die Ergebnisse unterscheiden sich:
movedPosition = (3, 0, 0, 1)movedDirection = (1, 0, 0, 0)Die Position wurde verschoben, die Richtung nicht.
Das benötigen wir später unter anderem für die Oberflächennormalen unserer 3D-Objekte. Normalen beschreiben Richtungen und dürfen deshalb durch eine reine Verschiebung nicht verändert werden.
Die perspektivische Division
Abschnitt betitelt „Die perspektivische Division“Bisher haben wir für Positionen immer w = 1 verwendet. Homogene Koordinaten erlauben jedoch auch andere Werte.
Beispielsweise beschreiben diese beiden Vektoren denselben Punkt im dreidimensionalen Raum:
(1, 2, 3, 1)(2, 4, 6, 2)Wie kann das sein?
Um aus homogenen Koordinaten wieder die gewöhnlichen dreidimensionalen Koordinaten eines Punktes zu erhalten, teilen wir x, y und z durch w.
Für den zweiten Vektor ergibt das:
x = 2 / 2 = 1y = 4 / 2 = 2z = 6 / 2 = 3Beide Vektoren beschreiben also den Punkt (1, 2, 3).
Diese Umrechnung funktioniert für homogene Punkte mit w ungleich 0.
Die Division durch w spielt auch bei der perspektivischen Darstellung eine wichtige Rolle.
Wenn wir auf gerade Eisenbahnschienen blicken, erscheinen sie in der Ferne immer näher beieinander, obwohl sie tatsächlich parallel verlaufen. Scheinbar treffen sie sich an einem gemeinsamen Fluchtpunkt.
Dass weiter entfernte Dinge kleiner erscheinen, ist ein grundlegender Effekt der Perspektive.
Um diesen Effekt in einer 3D-Szene darzustellen, verwenden wir eine perspektivische Projektionsmatrix. Sie verändert die homogenen Koordinaten eines Vertex so, dass w von seiner Tiefe abhängt.
Anschließend werden die ersten drei Koordinaten durch w geteilt:
x' = x / wy' = y / wz' = z / wDiesen Vorgang nennen wir perspektivische Division.
Ein vereinfachtes Beispiel zeigt, was dabei geschieht:
Vor der Division: (2, 2, 4, 2)Nach der Division: (1, 1, 2)Die X- und Y-Koordinaten werden kleiner. Auf diese Weise trägt die Division dazu bei, dass weiter entfernte Punkte näher an der Bildmitte erscheinen.
In WebGPU müssen wir die perspektivische Division nicht selbst im Shader ausführen. Sie erfolgt automatisch, nachdem der Vertex-Shader die Position über @builtin(position) ausgegeben hat.
Die genaue Berechnung der perspektivischen Projektion lernen wir später bei der Projektionsmatrix kennen.
Zusammenfassung
Abschnitt betitelt „Zusammenfassung“Homogene Koordinaten erweitern unsere drei Raumkoordinaten um die vierte Komponente w.
- Mit
w = 1stellen wir gewöhnliche Positionen dar. Dadurch können wir auch Verschiebungen mithilfe einer 4×4-Matrix berechnen. - Mit
w = 0stellen wir Richtungen dar. Eine reine Verschiebung hat auf diese Vektoren keinen Einfluss. - Durch die Division durch
wkönnen wir homogene Punktkoordinaten wieder in gewöhnliche 3D-Koordinaten umrechnen. Diese Division ist außerdem ein wichtiger Bestandteil der perspektivischen Projektion.
Damit verstehen wir, warum unsere Vertex-Positionen bei der Transformation eine vierte Koordinate erhalten und welche Aufgaben sie erfüllt.
Als Nächstes betrachten wir die einzelnen Transformationen genauer: Verschiebung, Drehung und Skalierung.