Viewports und Clipping (Direct3D 9)

Konzeptionell ist ein Viewport ein zweidimensionales Rechteck (2D), in das eine 3D-Szene projiziert wird. In Direct3D ist das Rechteck als Koordinaten innerhalb einer Direct3D-Oberfläche vorhanden, die das System als Renderingziel verwendet. Die Projektionstransformation konvertiert Scheitelpunkte in das Koordinatensystem, das für den Viewport verwendet wird. Ein Viewport wird auch verwendet, um den Bereich der Tiefenwerte auf einer Renderzieloberfläche anzugeben, in der eine Szene gerendert wird (normalerweise 0,0 bis 1,0).

Das Anzeigen von Frustum

Ein Anzeige frustum ist ein 3D-Volumen in einer Szene, die relativ zur Kamera des Viewports positioniert ist. Die Form der Lautstärke beeinflusst, wie Modelle aus dem Kamerabereich auf den Bildschirm projiziert werden. Die häufigste Art der Projektion, eine perspektivische Projektion, ist dafür verantwortlich, dass Objekte in der Nähe der Kamera größer erscheinen als Objekte in der Ferne. Für die perspektivische Betrachtung kann das Ansichts frustum als Pyramide visualisiert werden, wobei die Kamera wie in der folgenden Abbildung an der Spitze positioniert ist. Diese Pyramide wird von einer vorderen und hinteren Clippingebene überschnitten. Das Volumen innerhalb der Pyramide zwischen den Clippingebenen vorne und hinten ist das Anzeige frustum. Objekte sind nur sichtbar, wenn sie sich in diesem Volume befinden.

Abbildung eines Anzeige-Frustrums mit einem Beschneidungsplan von vorne und hinten

Wenn Sie sich vorstellen, dass Sie in einem dunklen Raum stehen und durch ein quadratisches Fenster schauen, visualisieren Sie ein Sehen frustum. In dieser Analogie ist die nahe Beschneidungsebene das Fenster, und die hintere Clipping-Ebene ist das, was schließlich Ihre Sicht unterbricht - der Wolkenkratzer auf der anderen Straßenseite, die Berge in der Ferne oder überhaupt nichts. Sie können alles in der abgeschnittenen Pyramide sehen, die am Fenster beginnt und mit allem endet, was Ihre Ansicht unterbricht, und Sie können nichts anderes sehen.

Das Anzeige frustum wird durch fov (Sichtfeld) und durch die Entfernungen der vorderen und hinteren Clippingebenen definiert, die in Z-Koordinaten angegeben sind, wie im folgenden Diagramm dargestellt.

Diagramm des Anzeige frustums

In diesem Diagramm ist die Variable D der Abstand zwischen der Kamera und dem Ursprung des Raums, der im letzten Teil der Geometriepipeline definiert wurde – der Anzeigetransformation. Dies ist der Raum, um den Sie die Grenzen Ihres Seh frustums anordnen. Informationen dazu, wie diese D-Variable zum Erstellen der Projektionsmatrix verwendet wird, finden Sie unter Projektionstransformation (Direct3D 9).

Viewport-Rechteck

Sie definieren das Viewportrechteck in C++ mithilfe der D3DVIEWPORT9-Struktur . Die D3DVIEWPORT9-Struktur wird mit den folgenden Viewport-Manipulationsmethoden verwendet, die von der IDirect3DDevice9-Schnittstelle verfügbar gemacht werden.

Die D3DVIEWPORT9-Struktur enthält vier Elemente – X, Y, Width, Height – die den Bereich der Renderzieloberfläche definieren, in der eine Szene gerendert wird. Diese Werte entsprechen dem Zielrechteck oder dem Viewportrechteck, wie im folgenden Diagramm dargestellt.

Diagramm des Viewport-Rechtecks

Die Werte, die Sie für die Elemente X, Y, Width, Height angeben, sind Bildschirmkoordinaten relativ zur oberen linken Ecke der Renderzieloberfläche. Die -Struktur definiert zwei zusätzliche Member (MinZ und MaxZ), die die Tiefenbereiche angeben, in die die Szene gerendert wird.

Direct3D geht davon aus, dass das Viewport-Clipping-Volume von -1,0 bis 1,0 in X und von 1,0 bis -1,0 in Y reicht. Dies waren die Einstellungen, die in der Vergangenheit am häufigsten von Anwendungen verwendet wurden. Sie können das Seitenverhältnis des Viewports vor dem Clipping mithilfe der Projektionstransformation anpassen.

Hinweis

MinZ und MaxZ geben die Tiefenbereiche an, in die die Szene gerendert wird und nicht zum Ausschneiden verwendet wird. Die meisten Anwendungen legen diese Member auf 0.0 und 1.0 fest, damit das System den gesamten Bereich der Tiefenwerte im Tiefenpuffer rendern kann. In einigen Fällen können Sie Spezialeffekte erzielen, indem Sie andere Tiefenbereiche verwenden. Für instance können Sie zum Rendern einer Heads-up-Anzeige in einem Spiel beide Werte auf 0,0 festlegen, um das System zu zwingen, Objekte in einer Szene im Vordergrund zu rendern, oder Sie können beide auf 1,0 festlegen, um ein Objekt zu rendern, das immer im Hintergrund sein soll.

 

Die Dimensionen, die in den Elementen X, Y, Width, Height der D3DVIEWPORT9-Struktur für einen Viewport verwendet werden, definieren die Position und die Dimensionen des Viewports auf der Renderzieloberfläche. Diese Werte befinden sich in Bildschirmkoordinaten relativ zur oberen linken Ecke der Oberfläche.

Direct3D verwendet den Viewportstandort und die Abmessungen, um die Scheitelpunkte zu skalieren, um eine gerenderte Szene an die geeignete Position auf der Zieloberfläche anzupassen. Intern fügt Direct3D diese Werte in die folgende Matrix ein, die auf jeden Scheitelpunkt angewendet wird.

Formel der Matrix, die auf jeden Scheitelpunkt angewendet wird

Diese Matrix skaliert Scheitelpunkte entsprechend den Viewportabmessungen und dem gewünschten Tiefenbereich und übersetzt sie an die entsprechende Position auf der Renderzieloberfläche. Die Matrix kippt auch die y-Koordinate, um einen Bildschirmursprung in der oberen linken Ecke widerzuspiegeln, wobei y nach unten steigt. Nachdem diese Matrix angewendet wurde, sind Scheitelpunkte immer noch homogen - d. h. sie existieren noch als [x,y,z,w]-Vertices - und sie müssen in nicht homogene Koordinaten konvertiert werden, bevor sie an den Rasterisierer gesendet werden.

Hinweis

Die Viewportskalierungsmatrix enthält die MinZ- und MaxZ-Member der D3DVIEWPORT9-Struktur , um Scheitelpunkte entsprechend dem Tiefenbereich [MinZ, MaxZ] zu skalieren. Dies stellt eine andere Semantik als frühere Versionen von DirectX dar, in denen diese Member zum Beschneiden verwendet wurden.

 

Hinweis

Anwendungen legen in der Regel MinZ und MaxZ auf 0,0 bzw. 1,0 fest, damit das System im gesamten Tiefenbereich gerendert wird. Sie können jedoch andere Werte verwenden, um bestimmte Auswirkungen zu erzielen. Sie können beispielsweise beide Werte auf 0,0 festlegen, um alle Objekte im Vordergrund zu erzwingen, oder beide auf 1,0 festlegen, um alle Objekte im Hintergrund zu rendern.

 

Löschen eines Viewports

Durch das Löschen des Viewports wird der Inhalt des Viewportrechtecks auf der Renderzieloberfläche zurückgesetzt. Es kann auch das Rechteck in den Tiefen- und Schablonenpufferoberflächen löschen.

Verwenden Sie IDirect3DDevice9::Clear , um den Viewport zu löschen. Die -Methode akzeptiert ein oder mehrere Rechtecke, die die Bereiche auf der zu löschenden Oberfläche definieren. Wenn Sie den Count-Parameter auf 1 und den pRects-Parameter auf die Adresse eines einzelnen Rechtecks festlegen, das den gesamten Viewportbereich abdeckt, wird der gesamte Viewport gelöscht. Eine weitere Möglichkeit zum Löschen des gesamten Viewports besteht darin, den pRects-Parameter auf NULL und den Count-Parameter auf 0 festzulegen.

Das IDirect3DDevice9::Clear kann zum Löschen von Schablonenbits innerhalb eines Tiefenpuffers verwendet werden. Legen Sie einfach den Flags-Parameter fest, um zu bestimmen, wie IDirect3DDevice9::Clear mit dem Renderziel und allen zugeordneten Tiefen- oder Schablonenpuffern funktioniert. Das D3DCLEAR_TARGET-Flag löscht den Viewport mithilfe einer beliebigen RGBA-Farbe, die Sie im Argument Color angeben (dies ist nicht die Materialfarbe). Das D3DCLEAR_ZBUFFER-Flag löscht den Tiefenpuffer auf eine beliebige Tiefe, die Sie in Z angeben: 0,0 ist die nächste Entfernung, und 1,0 ist die am weitesten entfernte. Das flag D3DCLEAR_STENCIL setzt die Schablonenbits auf den Wert zurück, den Sie im Schablonenargument angeben. Sie können ganze Zahlen im Bereich von 0 bis 2n-1 verwenden, wobei n für die Bittiefe des Schablonenpuffers steht.

In einigen Situationen wird möglicherweise nur auf kleinen Teilen der Renderziel- und Tiefenpufferoberflächen gerendert. Mit den clear-Methoden können Sie auch mehrere Bereiche Ihrer Oberflächen in einem einzigen Aufruf löschen. Legen Sie hierzu den Count-Parameter auf die Anzahl der Rechtecke fest, die gelöscht werden sollen, und geben Sie die Adresse des ersten Rechtecks in einem Array von Rechtecken im pRects-Parameter an.

Einrichten des Viewports für clipping

Die Ergebnisse der Projektionsmatrix bestimmen das Clippingvolumen im Projektionsraum wie folgt:

-wc<= xc<= wc

-wc<= yc<= wc

0 <= zc<= wc

Wobei: x, y, z und w die Vertexkoordinaten darstellen, nachdem die Projektionstransformation angewendet wurde. Alle Scheitelpunkte, die über eine x-, y- oder z-Komponente außerhalb dieser Bereiche verfügen, werden abgeschnitten, wenn clipping aktiviert ist (das Standardverhalten).

Mit Ausnahme von Vertexpuffern aktivieren oder deaktivieren Anwendungen das Clipping über den D3DRS_CLIPPING Renderzustand. Clippinginformationen für Vertexpuffer werden während der Verarbeitung generiert. Weitere Informationen finden Sie unter Fixed Function Vertex Processing (Direct3D 9) und Programmable Vertex Processing (Direct3D 9).

Direct3D klammert transformierte Scheitelpunkte eines Grundtyps nicht aus einem Vertexpuffer ab, es sei denn, er stammt aus IDirect3DDevice9::P rocessVertices. Wenn Sie ihre eigenen Transformationen durchführen und Direct3D für die Beschneidung benötigen, sollten Sie keine Vertexpuffer verwenden. In diesem Fall durchläuft die Anwendung die Daten, um sie zu transformieren. Direct3D durchläuft die Daten ein zweites Mal, um sie zu beschneiden, und dann rendert der Treiber die Daten, was ineffizient ist. Wenn also die Anwendung die Daten transformiert, sollte auch die Daten abgeschnitten werden.

Wenn das Gerät vortransformationierte und beleuchtete Scheitelpunkte (T&L-Scheitelpunkte) empfängt, die beschnitten werden müssen, um den Clippingvorgang auszuführen, werden die Scheitelpunkte mithilfe der reziprokalen homogenen w (RHW) des Scheitelpunkts und der Viewportinformationen zurück in den Clippingraum transformiert. Anschließend wird ein Clipping ausgeführt. Nicht alle Geräte sind in der Lage, diese Rücktransformation durchzuführen, um T&L-Scheitelpunkte zu beschneiden.

Die D3DPMISCCAPS_CLIPTLVERTS Gerätefunktion gibt an, ob das Gerät T&L-Scheitelpunkte abschneiden kann. Wenn diese Funktion nicht festgelegt ist, ist die Anwendung für das Ausschneiden der T&L-Scheitelpunkte verantwortlich, die sie an das zu renderende Gerät senden möchte. Das Gerät ist immer in der Lage, T&L-Scheitelpunkte im Softwarevertexverarbeitungsmodus zu beschneiden (unabhängig davon, ob das Gerät im Softwarevertexverarbeitungsmodus erstellt oder in den Softwarevertexverarbeitungsmodus gewechselt wird).

Die einzige Anforderung zum Konfigurieren der Viewportparameter für ein Renderinggerät ist das Festlegen der Clipping-Lautstärke des Viewports. Dazu initialisieren und legen Sie Clippingwerte für die Clippinglautstärke und für die Renderzieloberfläche fest. Viewports sind in der Regel so eingerichtet, dass sie im gesamten Bereich der Renderzieloberfläche gerendert werden. Dies ist jedoch keine Anforderung.

Sie können die folgenden Einstellungen für die Member der D3DVIEWPORT9-Struktur verwenden, um dies in C++ zu erreichen.

D3DVIEWPORT9 viewData = { 0, 0, width, height, 0.0f, 1.0f };

Nachdem Sie Werte in der D3DVIEWPORT9-Struktur festgelegt haben, wenden Sie die Viewportparameter auf das Gerät an, indem Sie die IDirect3DDevice9::SetViewport-Methode aufrufen. Das folgende Codebeispiel zeigt, wie dieser Aufruf aussehen könnte.

HRESULT hr;

hr = pd3dDevice->SetViewport(&viewData);
if(FAILED(hr))
    return hr;

Wenn der Aufruf erfolgreich ist, werden die Viewportparameter festgelegt und werden beim nächsten Aufruf einer Renderingmethode wirksam. Um Änderungen an den Viewportparametern vorzunehmen, aktualisieren Sie einfach die Werte in der D3DVIEWPORT9-Struktur , und rufen Sie IDirect3DDevice9::SetViewport erneut auf.

Hinweis

Die D3DVIEWPORT9-Strukturmitglieder MinZ und MaxZ geben die Tiefenbereiche an, in die die Szene gerendert wird, und werden nicht zum Ausschneiden verwendet. Die meisten Anwendungen legen diese Member auf 0.0 und 1.0 fest, damit das System den gesamten Bereich der Tiefenwerte im Tiefenpuffer rendern kann. In einigen Fällen können Sie spezielle Effekte erzielen, indem Sie andere Tiefenbereiche verwenden. Für instance können Sie zum Rendern einer Head-Up-Anzeige in einem Spiel beide Werte auf 0,0 festlegen, um das System zu zwingen, Objekte in einer Szene im Vordergrund zu rendern, oder Sie können beide auf 1,0 festlegen, um ein Objekt zu rendern, das sich immer im Hintergrund befinden sollte.

 

Erste Schritte