Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Abschnitt werden die Schritte zum Einrichten des Depth-Stencil-Puffers und des Depth-Stencil-Zustands für die Output-Merger-Phase behandelt.
- Erstellen einer Depth-Stencil-Ressource
- Erstelle Depth-Stencil Zustand
- Binden der Depth-Stencil-Daten an die OM-Stufe
Sobald Sie wissen, wie Sie den Tiefenschablonenpuffer und den entsprechenden Tiefenschablonenzustand verwenden, lesen Sie erweiterten Schablonentechniken.
Eine Depth-Stencil-Ressource erstellen
Erstellen Sie den Tiefenschablonenpuffer mithilfe einer Texturressource.
ID3D11Texture2D* pDepthStencil = NULL;
D3D11_TEXTURE2D_DESC descDepth;
descDepth.Width = backBufferSurfaceDesc.Width;
descDepth.Height = backBufferSurfaceDesc.Height;
descDepth.MipLevels = 1;
descDepth.ArraySize = 1;
descDepth.Format = pDeviceSettings->d3d11.AutoDepthStencilFormat;
descDepth.SampleDesc.Count = 1;
descDepth.SampleDesc.Quality = 0;
descDepth.Usage = D3D11_USAGE_DEFAULT;
descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
descDepth.CPUAccessFlags = 0;
descDepth.MiscFlags = 0;
hr = pd3dDevice->CreateTexture2D( &descDepth, NULL, &pDepthStencil );
Erstellen Sie den Depth-Stencil Status
Der Tiefenschablonenzustand teilt der Ausgabezusammenführungsphase mit, wie der Tiefenschablonentestdurchgeführt werden kann. Der Tiefen-Stencil-Test bestimmt, ob ein bestimmtes Pixel gezeichnet werden soll oder nicht.
D3D11_DEPTH_STENCIL_DESC dsDesc;
// Depth test parameters
dsDesc.DepthEnable = true;
dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
dsDesc.DepthFunc = D3D11_COMPARISON_LESS;
// Stencil test parameters
dsDesc.StencilEnable = true;
dsDesc.StencilReadMask = 0xFF;
dsDesc.StencilWriteMask = 0xFF;
// Stencil operations if pixel is front-facing
dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
// Stencil operations if pixel is back-facing
dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
// Create depth stencil state
ID3D11DepthStencilState * pDSState;
pd3dDevice->CreateDepthStencilState(&dsDesc, &pDSState);
DepthEnable und StencilEnable aktivieren (und deaktivieren) Tiefen- und Schablonentests. Legen Sie DepthEnable auf FALSE fest, um Tiefentests zu deaktivieren und das Schreiben in den Tiefenpuffer zu verhindern. Legen Sie "SchabloneEnable" auf FALSE fest, um Schablonentests zu deaktivieren und das Schreiben in den Schablonenpuffer zu verhindern (wenn DepthEnable FALSE ist und "StencilEnable " WAHR ist, wird der Tiefentest immer im Schablonenvorgang bestanden).
DepthEnable wirkt sich nur auf die Ausgabezusammenführungsstufe aus . Sie wirkt sich nicht auf Clipping, Tiefenverzerrung oder Klammerung von Werten aus, bevor die Daten in einen Pixelshader eingegeben werden.
Binden von Depth-Stencil Daten an die OM-Phase
Binden Sie den Tiefen-Stencil-Zustand.
// Bind depth stencil state
pDevice->OMSetDepthStencilState(pDSState, 1);
Binden Sie die Tiefenschablonenressource mithilfe einer Ansicht.
D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
descDSV.Format = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
descDSV.Texture2D.MipSlice = 0;
// Create the depth stencil view
ID3D11DepthStencilView* pDSV;
hr = pd3dDevice->CreateDepthStencilView( pDepthStencil, // Depth stencil texture
&descDSV, // Depth stencil desc
&pDSV ); // [out] Depth stencil view
// Bind the depth stencil view
pd3dDeviceContext->OMSetRenderTargets( 1, // One rendertarget view
&pRTV, // Render target view, created earlier
pDSV ); // Depth stencil view for the render target
Ein Array von Renderzielansichten kann an ID3D11DeviceContext::OMSetRenderTargets übergeben werden, alle diese Renderzielansichten entsprechen jedoch einer einzelnen Tiefenschablonenansicht. Das Renderzielarray in Direct3D 11 ist ein Feature, mit dem eine Anwendung auf mehreren Renderzielen gleichzeitig auf primitiver Ebene rendern kann. Renderzielarrays bieten eine höhere Leistung gegenüber dem individuellen Festlegen von Renderzielen mit mehreren Aufrufen von ID3D11DeviceContext::OMSetRenderTargets (im Wesentlichen die in Direct3D 9 verwendete Methode).
Renderziele müssen alle denselben Ressourcentyp aufweisen. Wenn Multisample-Antialiasing verwendet wird, müssen alle gebundenen Render-Ziele und Tiefenpuffer dieselbe Sample-Anzahl aufweisen.
Wenn ein Puffer als Renderziel verwendet wird, werden Tiefenschablonentests und mehrere Renderziele nicht unterstützt.
- So viele wie 8 Renderziele können gleichzeitig gebunden werden.
- Alle Renderziele müssen in allen Dimensionen dieselbe Größe aufweisen (Breite und Höhe und Tiefe für 3D- oder Arraygröße für *Arraytypen).
- Jedes Renderziel verfügt möglicherweise über ein anderes Datenformat.
- Schreibmasken steuern, welche Daten auf ein Render-Target geschrieben werden. Die Ausgabe-Schreibmasken steuern auf Ebene jedes Renderziels und jeder Komponente, welche Daten in die Renderziele geschrieben werden.
Erweiterte Schablonentechniken
Der Schablonenanteil des Tiefenschablonenpuffers kann zum Erstellen von Rendering-Effekten wie Compositing, Decaling und Outlining verwendet werden.
- Compositing
- Bekleben
- Konturen und Silhouetten
- Two-Sided Schablone
- Lesen des Depth-Stencil Puffers als Textur
Bildmontage
Ihre Anwendung kann den Schablonenpuffer verwenden, um 2D- oder 3D-Bilder in eine 3D-Szene einzufügen. Eine Maske im Schablonenpuffer wird verwendet, um einen Bereich der Renderzieloberfläche zu verdecken. Gespeicherte 2D-Informationen, z. B. Text oder Bitmaps, können dann in den verdeckten Bereich geschrieben werden. Alternativ kann Ihre Anwendung zusätzliche 3D-Primitiven im stencil-maskierten Bereich der Renderzieloberfläche rendern. Sie kann sogar eine ganze Szene rendern.
Spiele kombinieren häufig mehrere 3D-Szenen. Beispielsweise zeigen Fahrspiele in der Regel einen Rückspiegel an. Der Spiegel enthält die Ansicht der 3D-Szene hinter dem Fahrer. Es handelt sich im Wesentlichen um eine zweite 3D-Szene, die mit der Vorwärtsansicht des Fahrers kombiniert ist.
Dekalierung
Direct3D-Anwendungen verwenden Decaling, um zu steuern, welche Pixel aus einem bestimmten ursprünglichen Bild auf die Render-Zieloberfläche gezeichnet werden. Anwendungen wenden Decals auf die Bilder von Grundformen an, um die korrekte Darstellung koplanarer Polygone zu ermöglichen.
Wenn sie z. B. Reifenmarken und gelbe Linien auf eine Straße aufbringen, sollten die Markierungen direkt auf der Straße erscheinen. Die z-Werte der Markierungen und der Straße sind jedoch identisch. Daher erzeugt der Tiefenpuffer möglicherweise keine saubere Trennung zwischen den beiden. Einige Pixel im Hintergrundgrundtyp werden möglicherweise über dem Frontgrundtyp gerendert und umgekehrt. Das resultierende Bild scheint von Frame zu Frame zu schimmern. Dieser Effekt wird als Z-Fighting oder Flimmern bezeichnet.
Verwenden Sie zur Lösung dieses Problems eine Schablone, um den Abschnitt des Hintergrundobjekts zu maskieren, in dem das Decal erscheinen wird. Deaktivieren Sie die Z-Pufferung und rendern Sie das Bild des vorderen Primitives in den maskierten Bereich der Renderzieloberfläche.
Das Mischen mehrerer Texturen kann verwendet werden, um dieses Problem zu lösen.
Konturen und Silhouetten
Sie können den Schablonenpuffer für abstraktere Effekte wie Umrisse und Silhouettierung verwenden.
Wenn Ihre Anwendung zwei Renderdurchläufe ausführt – einen zum Erzeugen der Stencilmaske und einen weiteren, um die Stencilmaske auf das Bild anzuwenden, aber beim zweiten Durchlauf mit etwas kleineren Primitiven – wird das resultierende Bild nur den Umriss der Primitiven enthalten. Die Anwendung kann dann den schablonierten Bereich des Bildes mit einer Volltonfarbe füllen, sodass das Element ein geprägtes Aussehen erhält.
Wenn die Schablonenmaske die gleiche Größe und Form wie das Element aufweist, das Sie rendern, enthält das resultierende Bild ein Loch, an dem sich das Element befinden soll. Ihre Anwendung kann dann das Loch mit Schwarz füllen, um eine Silhouette des Primitives zu erzeugen.
Two-Sided Schablone
Schattenvolumes werden zum Zeichnen von Schatten mit dem Stencil-Puffer verwendet. Die Anwendung berechnet die Schattenvolumen, die durch verdeckende Geometrie entstehen, indem sie die Silhouettenränder berechnet und diese vom Licht weg in eine Reihe von 3D-Volumen extrudiert. Diese Datenmengen werden dann zweimal im Schablonenpuffer gerendert.
Das erste Rendern zeichnet vorwärtsgerichtete Polygone und erhöht die Stencil-Buffer-Werte. Das zweite Rendern zeichnet die rückseitigen Polygone des Schattenvolumens und verringert die Schablonenpufferwerte. Normalerweise brechen alle inkrementierten und dekrementierten Werte einander ab. Die Szene wurde jedoch bereits mit normaler Geometrie gerendert, sodass einige Pixel beim Rendern des Schattenvolumens den Z-Puffertest fehlschlagen. Werte, die im Schablonenpuffer verbleiben, entsprechen Pixeln, die sich im Schatten befinden. Diese verbleibenden Schablonenpufferinhalte werden als Maske verwendet, um ein großes, komplett schwarzes Quad mittels Alphablending in der Szene zu integrieren. Wenn der Schablonenpuffer als Maske fungiert, besteht das Ergebnis darin, Pixel abzudunkeln, die sich im Schatten befinden.
Dies bedeutet, dass die Schattengeometrie zweimal pro Lichtquelle gezeichnet wird und somit Druck auf den Vertexdurchsatz der GPU setzt. Die zweiseitige Schablonenfunktion wurde entwickelt, um diese Situation abzumildern. Bei diesem Ansatz gibt es zwei Gruppen von Schablonenzuständen (wie unten benannt), eine Gruppe für die nach vorne gerichteten Dreiecke und die andere für die nach hinten gerichteten Dreiecke. Auf diese Weise wird pro Schattenvolumen und Lichtquelle nur ein einzelner Durchlauf durchgeführt.
Ein Beispiel für eine zweiseitige Schablonenimplementierung finden Sie im ShadowVolume10-Beispiel.
Lesen des Depth-Stencil-Speicherpuffers als Textur
Ein inaktiver Depth-Stencil-Puffer kann von einem Shader als Textur gelesen werden. Eine Anwendung, die einen Tiefenschablonenpuffer als Textur rendert, bearbeitet in zwei Durchläufen: Der erste Durchlauf schreibt in den Tiefenschablonenpuffer, und der zweite Durchlauf liest aus dem Puffer. Dadurch kann ein Shader Tiefen- oder Schablonenwerte vergleichen, die zuvor in den Puffer geschrieben wurden, mit dem Wert für das aktuell gerenderte Pixel. Das Ergebnis des Vergleichs kann verwendet werden, um Effekte wie Schattenzuordnung oder weiche Partikel in einem Partikelsystem zu erzeugen.
Zum Erstellen eines Tiefenschablonenpuffers, der sowohl als Tiefenschablonenressource als auch als Shaderressource verwendet werden kann, müssen einige Änderungen am Beispielcode im Abschnitt " Erstellen einer Depth-Stencil Ressource " vorgenommen werden.
Die Depth-Stencil-Ressource muss ein typloses Format haben, z. B. DXGI_FORMAT_R32_TYPELESS.
descDepth.Format = DXGI_FORMAT_R32_TYPELESS;
Die Tiefenschablonenressource muss sowohl die D3D10_BIND_DEPTH_STENCIL als auch D3D10_BIND_SHADER_RESOURCE Bindungskennzeichnungen verwenden.
descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL | D3D10_BIND_SHADER_RESOURCE;
Darüber hinaus muss eine Shaderressourcenansicht für den Tiefenpuffer mithilfe einer D3D11_SHADER_RESOURCE_VIEW_DESC Struktur und ID3D11Device::CreateShaderResourceView erstellt werden. Die Shaderressourcenansicht verwendet ein typiertes Format wie DXGI_FORMAT_R32_FLOAT , das dem typlosen Format entspricht, das beim Erstellen der Tiefenschablonenressource angegeben wurde.
Im ersten Renderdurchlauf ist der Tiefenpuffer gebunden, wie im Abschnitt "Binden Depth-Stencil Daten an die OM-Stufe " beschrieben. Beachten Sie, dass das an D3D11_DEPTH_STENCIL_VIEW_DESC übergebene Format ein typiertes Format wie DXGI_FORMAT_D32_FLOAT verwendet. Nach dem ersten Renderdurchlauf enthält der Tiefenpuffer die Tiefenwerte für die Szene.
Im zweiten Renderdurchlauf wird die ID3D11DeviceContext::OMSetRenderTargets-Funktion verwendet, um die Tiefenschablonenansicht auf NULL oder eine andere Tiefenschablonenressource festzulegen, und die Shaderressourcenansicht wird mithilfe von ID3D11EffectShaderResourceVariable::SetResource an den Shader übergeben. Dadurch kann der Shader die tiefenwerte nachschlagen, die im ersten Renderingdurchlauf berechnet wurden. Beachten Sie, dass eine Transformation angewendet werden muss, um Tiefenwerte abzurufen, wenn sich der Ansichtspunkt des ersten Renderdurchlaufs vom zweiten Renderdurchlauf unterscheidet. Wenn beispielsweise eine Schattenzuordnungstechnik verwendet wird, stammt der erste Renderdurchlauf aus der Perspektive einer Lichtquelle, während der zweite Renderdurchlauf aus Sicht des Betrachters erfolgt.
Zugehörige Themen