Udostępnij przez


Konfigurowanie funkcji Depth-Stencil

W tej sekcji opisano kroki konfigurowania buforu wzornika głębokości i stanu wzornika głębokości dla etapu fuzji danych wyjściowych.

Gdy wiesz, jak używać buforu wzornika głębi i odpowiedniego stanu wzornika głębokości, zapoznaj się z zaawansowanymi technikami wzornika.

Tworzenie zasobu Depth-Stencil

Utwórz bufor głębokości i szablonu przy użyciu zasobu tekstury.

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 );

Tworzenie stanu Depth-Stencil

Stan wzornika głębokości informuje etap fuzji danych wyjściowych, jak wykonać test wzornika głębokości. Test głębokości i wzornika określa, czy dany piksel powinien być rysowany.

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 i StencilEnable włącz (i wyłącz) głębokość i testowanie wzornika. Ustaw wartość DepthEnable na wartość FALSE, aby wyłączyć testowanie głębokości i uniemożliwić zapisywanie w buforze głębokości. Ustaw parametr StencilEnable na FALSE, aby wyłączyć testowanie szablonu i zapobiec zapisowi do bufora szablonu (kiedy parametr DepthEnable jest FALSE, a StencilEnable jest TRUE, test głębokości zawsze przechodzi w operacji szablonu).

DepthEnable wpływa tylko na etap scalania wyników — nie ma wpływu na przycinanie, przesunięcie głębokości lub zaciskanie wartości przed wejściem danych do shadera pikseli.

Powiąż dane Depth-Stencil z etapem OM

Wiązanie stanu wzornika głębokości.

// Bind depth stencil state
pDevice->OMSetDepthStencilState(pDSState, 1);

Powiąż zasób wzornika głębokości przy użyciu widoku.

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

Tablica widoków obiektów docelowych renderowania może zostać przekazana do ID3D11DeviceContext::OMSetRenderTargets, jednak wszystkie te widoki obiektów docelowych renderowania odpowiadają jednemu widokowi wzornika głębokości. Tablica docelowa renderowania w wersji Direct3D 11 jest funkcją, która umożliwia aplikacji renderowanie na wielu obiektach docelowych renderowania jednocześnie na poziomie pierwotnym. Renderowanie tablic docelowych oferuje zwiększoną wydajność w porównaniu z indywidualnym ustawieniem obiektów docelowych renderowania z wieloma wywołaniami ID3D11DeviceContext::OMSetRenderTargets (zasadniczo metoda zastosowana w usłudze Direct3D 9).

Wszystkie cele renderowania muszą być tego samego typu zasobem. Jeśli jest używane wieloprzykładowe antyaliasowania, wszystkie powiązane docelowe bufory renderujące i bufory głębokości muszą mieć tę samą liczbę próbek.

Jeśli bufor jest używany jako element docelowy renderowania, testowanie wzornika głębi i wiele obiektów docelowych renderowania nie są obsługiwane.

  • Jednocześnie można powiązać aż 8 obiektów docelowych renderowania.
  • Wszystkie cele renderowania muszą mieć taki sam rozmiar we wszystkich wymiarach (szerokość i wysokość oraz głębokość dla 3D lub rozmiar tablicy dla typów *Array).
  • Każdy element docelowy renderowania może mieć inny format danych.
  • Maski zapisu kontrolują, jakie dane są zapisywane w celu renderowania. Maski zapisu wyjściowego kontrolują na poziomie poszczególnych render-terów, jakie dane są zapisywane na nich, w odniesieniu do każdego składnika.

Zaawansowane techniki wzornika

Fragment bufora głębi i wzornika może służyć do tworzenia efektów renderowania, takich jak kompozycja, dekalowanie i obrysowywanie.

Kompozycja

Twoja aplikacja może używać buforu wzornika do kompozycji obrazów 2D lub 3D na scenie 3D. Maska w buforze wzornika służy do zasłaniania obszaru docelowej powierzchni renderowania. Przechowywane informacje 2D, takie jak tekst lub bitmapy, można następnie zapisywać w zasłoniętym obszarze. Alternatywnie aplikacja może renderować dodatkowe prymitywy 3D w obszarze zamaskowanym wzornikiem na docelowej powierzchni renderowania. Może nawet renderować całą scenę.

Gry często komponują wiele scen 3D. Na przykład gry jazdy zwykle wyświetlają lusterko wsteczne. Lustro zawiera widok sceny 3D za kierowcą. Jest to zasadniczo druga scena 3D złożona z widokiem kierowcy do przodu.

Dekalowanie

Aplikacje Direct3D używają dekalowania do kontrolowania, które piksele z określonego obrazu prymitywnego są odwzorowywane na powierzchni docelowej renderowania. Aplikacje stosują naklejki na obrazy prymitywów, aby umożliwić poprawne renderowanie wielokątów współpłaszczyznowych.

Na przykład podczas stosowania znaków opon i żółtych linii na jezdni oznaczenia powinny pojawiać się bezpośrednio na górze drogi. Jednak wartości z dla oznaczeń i drogi są takie same. W związku z tym bufor głębokości może nie produkować czystego rozdzielenia między nimi. Niektóre piksele w tylnej prymitywie mogą być renderowane na przednim prymitywie i odwrotnie. Wynikowy obraz wydaje się migotać od klatki do klatki. Ten efekt nosi nazwę z-fighting lub flimmering.

Aby rozwiązać ten problem, użyj wzornika, aby zamaskować sekcję tylnego elementu bazowego, w którym pojawi się naklejka. Wyłącz buforowanie Z i renderuj obraz przedniego prymitywu w zamaskowany obszar powierzchni docelowej renderowania.

Aby rozwiązać ten problem, można użyć mieszania wielu tekstur.

Kontury i sylwetki

Możesz użyć buforu wzornika, aby uzyskać bardziej abstrakcyjne efekty, takie jak obrysowanie i tworzenie sylwetek.

Jeśli aplikacja wykonuje dwa przebiegi renderowania — jeden w celu wygenerowania maski szablonu, a drugi w celu zastosowania maski szablonu do obrazu, ale z prymitywami nieco mniejszymi na drugim przebiegu — wynikowy obraz będzie zawierać tylko kontur prymitywów. Aplikacja może następnie wypełnić obszar maskowany wzornikiem na obrazie jednolitym kolorem, nadając prymitywowi wygląd wytłoczonego.

Jeśli maska wzornika ma taki sam rozmiar i kształt jak renderowane elementy pierwotne, wynikowy obraz zawiera dziurę, w której powinien znajdować się element pierwotny. Aplikacja może następnie wypełnić dziurę kolorem czarnym, aby stworzyć sylwetkę prymitywu.

szablon Two-Sided

Wolumeny cieniowe są używane do rysowania cieni z buforem szablonu. Aplikacja oblicza wolumeny cieni rzucane przez geometrię zasłaniającą, obliczając krawędzie sylwetki i wydłużając je w kierunku od światła do zestawu wolumenów 3D. Te woluminy są następnie renderowane dwa razy w buforze wzornika.

Pierwsze renderowanie rysuje wielokąty skierowane do przodu i zwiększa wartości buforu wzornika. Druga renderowanie renderuje tył-widoczne wielokąty woluminu cienia, dekrementując wartości buforu wzornika. Zwykle wszystkie wartości przyrostowe i dekrementowane znoszą się nawzajem. Jednak scena została już renderowana z normalną geometrią, co powoduje, że niektóre piksele nie przechodzą testu bufora Z w miarę jak renderowany jest wolumin cieni. Wartości pozostawione w buforze wzornika odpowiadają pikselom, które znajdują się w cieniu. Pozostałe zawartości bufora wzornika są używane jako maska, aby w scenie pojawił się duży czarny prostokąt poprzez stosowanie mieszania alfa. Dzięki buforowi wzornika działającemu jako maska wynik polega na ciemnieniu pikseli, które znajdują się w cieniu.

Oznacza to, że geometria cienia jest rysowana dwa razy na źródło światła, dlatego wywiera presję na przepływność wierzchołka procesora GPU. Funkcja dwustronnego wzornika została zaprojektowana w celu złagodzenia tej sytuacji. W tym podejściu istnieją dwa zestawy stanu szablonu, których nazwy podano poniżej: jeden dla trójkątów skierowanych przodem, a drugi dla trójkątów skierowanych w tył. W ten sposób dla każdego woluminu cienia i każdego źródła światła rysowane jest tylko jedno przejście.

Przykład implementacji wzornika dwustronnego można znaleźć w przykładzie ShadowVolume10 Sample.

Odczytywanie buforu Depth-Stencil jako tekstury

Nieaktywny bufor głębokości-stencil może być odczytywany przez shader jako tekstura. Aplikacja, która odczytuje bufor wzornika głębokości jako tekstura renderowana w dwóch przebiegach, pierwsze przekazanie zapisów do buforu wzornika głębokości i drugie przekazywanie odczytów z buforu. Dzięki temu shader umożliwia porównanie wartości głębokości lub wartości wzornika wcześniej zapisanych w buforze z wartością dla piksela aktualnie renderowanego. Wynik porównania może służyć do tworzenia efektów, takich jak mapowanie cieni lub miękkie cząstki w układzie cząstek.

Aby utworzyć bufor wzornika głębi, który może być używany zarówno jako zasób wzornika głębokości, jak i zasób cieniowania, należy wprowadzić kilka zmian w przykładowym kodzie w sekcji Tworzenie Depth-Stencil zasobu.

  • Zasób wzornika głębokości musi mieć format bez typu, taki jak DXGI_FORMAT_R32_TYPELESS.

    descDepth.Format = DXGI_FORMAT_R32_TYPELESS;
    
  • Zasób typu depth-stencil musi jednocześnie używać flag powiązania D3D10_BIND_DEPTH_STENCIL i D3D10_BIND_SHADER_RESOURCE.

    descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL | D3D10_BIND_SHADER_RESOURCE;
    

Ponadto należy utworzyć widok zasobów cieniowania dla buforu głębokości przy użyciu struktury D3D11_SHADER_RESOURCE_VIEW_DESC i ID3D11Device::CreateShaderResourceView. Widok zasobu cieniowania będzie używać formatu typizowanego, takiego jak DXGI_FORMAT_R32_FLOAT, który jest odpowiednikiem formatu bez typów określonego podczas tworzenia zasobu wzornika głębokości.

W pierwszym przebiegu renderowania bufor głębokości jest powiązany zgodnie z opisem w sekcji Bind Depth-Stencil Data to the OM Stage. Należy pamiętać, że format przekazany do D3D11_DEPTH_STENCIL_VIEW_DESC. Format będzie używać formatu wpisanego, takiego jak DXGI_FORMAT_D32_FLOAT. Po pierwszym przejściu renderowania bufor głębokości będzie zawierać wartości głębokości dla sceny.

W drugim przebiegu renderowania funkcja ID3D11DeviceContext::OMSetRenderTargets jest używana do ustawiania widoku głębokości-szablonu na NULL lub innego zasobu głębokości-szablonu, a widok zasobów cieniowania jest przekazywany do shadera przy użyciu ID3D11EffectShaderResourceVariable::SetResource. Dzięki temu shader może odczytać wartości głębokości obliczone w pierwszym przebiegu renderowania. Należy pamiętać, że należy zastosować przekształcenie w celu pobrania wartości głębokości, jeśli punkt widzenia pierwszego przebiegu renderowania różni się od drugiego przebiegu renderowania. Jeśli na przykład jest używana technika mapowania cieni, pierwsze przejście renderowania będzie z perspektywy źródła światła, natomiast drugie przejście renderowania będzie z perspektywy obserwatora.

Output-Merger Etap

etapy potoku (Direct3D 10)