Projektionstransformation (Direct3D 9)
Sie können sich die Projektionstransformation als Steuerung der Inneren der Kamera vorstellen; es ist analog zur Auswahl eines Objektivs für die Kamera. Dies ist die komplizierteste der drei Transformationstypen. Diese Diskussion über die Projektionstransformation ist in die folgenden Themen unterteilt.
Die Projektionsmatrix ist in der Regel eine Skalierungs- und perspektivische Projektion. Die Projektionstransformation wandelt das Anzeige-Frustum in eine cuboide Form um. Da das nahe Ende des Seh-Frustums kleiner als das weit entfernte Ende ist, hat dies die Wirkung, Objekte zu erweitern, die nahe an der Kamera liegen; So wird die Perspektive auf die Szene angewendet.
In dem Anzeige-Frustumwird der Abstand zwischen der Kamera und dem Ursprung des Sichttransformationsraums beliebig als D definiert, sodass die Projektionsmatrix wie die folgende Abbildung aussieht.
Die Anzeigematrix übersetzt die Kamera in den Ursprung, indem sie in z-Richtung um - D übersetzt wird. Die Übersetzungsmatrix ähnelt der folgenden Abbildung.
Wenn Sie die Übersetzungsmatrix mit der Projektionsmatrix (T*P) multiplizieren, wird die zusammengesetzte Projektionsmatrix wie in der folgenden Abbildung dargestellt.
Die perspektivische Transformation wandelt ein Anzeige-Frustum in einen neuen Koordinatenbereich um. Beachten Sie, dass das Frustum kuboid wird und dass der Ursprung von der oberen rechten Ecke der Szene in die Mitte wechselt, wie im folgenden Diagramm dargestellt.
Bei der Perspektivtransformation werden die Grenzen der X- und Y-Richtungen -1 und 1. Die Grenzen der Z-Richtung sind 0 für die Vorderebene und 1 für die Hintergrundebene.
Diese Matrix übersetzt und skaliert Objekte basierend auf einem angegebenen Abstand von der Kamera zur nahen Clippingebene, berücksichtigt jedoch nicht das Sichtfeld (fov), und die z-Werte, die sie für Objekte in der Entfernung erzeugt, können nahezu identisch sein, was Tiefenvergleiche erschwert. Die folgende Matrix behebt diese Probleme und passt Scheitelpunkte an, um das Seitenverhältnis des Viewports zu berücksichtigen, wodurch sie für die perspektivische Projektion eine gute Wahl ist.
In dieser Matrix ist Zn der Z-Wert der nahe geschnittenen Ebene. Die Variablen w, h und Q haben die folgenden Bedeutungen. Beachten Sie, dass fovw und fovk die horizontalen und vertikalen Ansichtsfelder des Viewports in Bogenmaßen darstellen.
Für Ihre Anwendung ist die Verwendung von Ansichtswinkeln zum Definieren der X- und Y-Skalierungskoeffizienten möglicherweise nicht so praktisch wie die Verwendung der horizontalen und vertikalen Abmessungen des Viewports (im Kamerabereich). Wie die Mathematik funktioniert, verwenden die folgenden beiden Formeln für w und h die Abmessungen des Viewports und entsprechen den vorherigen Gleichungen.
In diesen Formeln stellt Zn die Position der nahe Ausschnittebene dar, und die Variablen Vw und Vh stellen die Breite und Höhe des Viewports im Kamerabereich dar.
Bei einer C++-Anwendung entsprechen diese beiden Dimensionen direkt den Elementen "Width" und "Height" der D3DVIEWPORT9 Struktur.
Unabhängig davon, welche Formel Sie verwenden möchten, legen Sie Zn so groß wie möglich fest, da Z-Werte sehr nahe an der Kamera nicht sehr unterschiedlich sind. Dies macht Tiefenvergleiche mit 16-Bit-Z-Puffern etwas kompliziert.
Wie bei den Welt- und Ansichtstransformationen rufen Sie die IDirect3DDevice9::SetTransform Methode auf, um die Projektionstransformation festzulegen.
Einrichten einer Projektionsmatrix
Mit der folgenden Beispielfunktion "ProjectionMatrix" werden die Ebenen "Vorder- und Hintergrundausschnitt" sowie das horizontale und vertikale Feld der Ansichtswinkel festgelegt. Die Ansichtsfelder sollten kleiner als Pi-Bogenmaße sein.
D3DXMATRIX
ProjectionMatrix(const float near_plane, // Distance to near clipping
// plane
const float far_plane, // Distance to far clipping
// plane
const float fov_horiz, // Horizontal field of view
// angle, in radians
const float fov_vert) // Vertical field of view
// angle, in radians
{
float h, w, Q;
w = (float)1/tan(fov_horiz*0.5); // 1/tan(x) == cot(x)
h = (float)1/tan(fov_vert*0.5); // 1/tan(x) == cot(x)
Q = far_plane/(far_plane - near_plane);
D3DXMATRIX ret;
ZeroMemory(&ret, sizeof(ret));
ret(0, 0) = w;
ret(1, 1) = h;
ret(2, 2) = Q;
ret(3, 2) = -Q*near_plane;
ret(2, 3) = 1;
return ret;
} // End of ProjectionMatrix
Nachdem Sie die Matrix erstellt haben, legen Sie sie mit IDirect3DDevice9::SetTransform angeben D3DTS_PROJECTION fest.
Die Hilfsprogrammbibliothek D3DX bietet die folgenden Funktionen, mit denen Sie Ihre Projektionsmatrix einrichten können.
- D3DXMatrixPerspectiveLH-
- D3DXMatrixPerspectiveRH-
- D3DXMatrixPerspectiveFovLH
- D3DXMatrixPerspectiveFovRH
- D3DXMatrixPerspectiveOffCenterLH-
- D3DXMatrixPerspectiveOffCenterRH
Eine W-freundliche Projektionsmatrix
Direct3D kann die w-Komponente eines Scheitelpunkts verwenden, der von den Welt-, Ansichts- und Projektionsmatrizen transformiert wurde, um tiefenbasierte Berechnungen in Tiefenpuffer- oder Nebeleffekten durchzuführen. Berechnungen wie diese erfordern, dass ihre Projektionsmatrix w normalisieren muss, damit sie dem Weltraum z entspricht. Kurz gesagt, wenn Ihre Projektionsmatrix einen (3,4) Koeffizienten enthält, der nicht 1 ist, müssen Sie alle Koeffizienten um die Umkehrung des (3,4) Koeffizienten skalieren, um eine richtige Matrix zu erstellen. Wenn Sie keine kompatible Matrix bereitstellen, werden Nebeleffekte und Tiefenpuffer nicht ordnungsgemäß angewendet.
Die folgende Abbildung zeigt eine nicht kompatible Projektionsmatrix und die gleiche Matrix, die so skaliert wird, dass der augenrelative Nebel aktiviert wird.
In den vorangehenden Matrizen werden alle Variablen als nonzero angenommen. Weitere Informationen zum augenrelativen Nebel finden Sie unter Eye-Relative vs. Z-Based Depth. Informationen zum w-basierten Tiefenpuffern finden Sie unter Tiefenpuffer (Direct3D 9).
Direct3D verwendet die derzeit festgelegte Projektionsmatrix in den w-basierten Tiefenberechnungen. Daher müssen Anwendungen eine kompatible Projektionsmatrix festlegen, um die gewünschten w-basierten Features zu erhalten, auch wenn sie Direct3D nicht für Transformationen verwenden.
Verwandte Themen