Mengonfigurasi Fungsionalitas Depth-Stencil

Bagian ini mencakup langkah-langkah untuk menyiapkan buffer stensil kedalaman, dan status stensil kedalaman untuk tahap output-merger.

Setelah Anda tahu cara menggunakan buffer stensil kedalaman dan status stensil kedalaman yang sesuai, lihat teknik stensil tingkat lanjut.

Membuat Sumber Daya Depth-Stencil

Buat buffer stensil kedalaman menggunakan sumber daya tekstur.

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

Buat Status Depth-Stencil

Status stensil kedalaman memberi tahu tahap output-merger cara melakukan uji stensil kedalaman. Tes stensil kedalaman menentukan apakah piksel tertentu harus digambar atau tidak.

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 dan StencilEnable mengaktifkan (dan menonaktifkan) pengujian kedalaman dan stensil. Atur DepthEnable ke FALSE untuk menonaktifkan pengujian kedalaman dan mencegah penulisan ke buffer kedalaman. Atur StencilEnable ke FALSE untuk menonaktifkan pengujian stensil dan mencegah penulisan ke buffer stensil (ketika DepthEnable false dan StencilEnable adalah TRUE, pengujian kedalaman selalu lolos dalam operasi stensil).

DepthEnable hanya memengaruhi tahap output-merger - tidak memengaruhi kliping, bias kedalaman, atau penjepitan nilai sebelum data dimasukkan ke shader piksel.

Mengikat Data Depth-Stencil ke Tahap OM

Ikat status stensil kedalaman.

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

Ikat sumber daya stensil kedalaman menggunakan tampilan.

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

Array tampilan target render dapat diteruskan ke ID3D11DeviceContext::OMSetRenderTargets, namun semua tampilan target render tersebut akan sesuai dengan tampilan stensil kedalaman tunggal. Array target render di Direct3D 11 adalah fitur yang memungkinkan aplikasi untuk merender ke beberapa target render secara bersamaan pada tingkat primitif. Array target render menawarkan peningkatan performa melalui pengaturan target render secara individual dengan beberapa panggilan ke ID3D11DeviceContext::OMSetRenderTargets (pada dasarnya metode yang digunakan di Direct3D 9).

Target render semuanya harus jenis sumber daya yang sama. Jika antialias multisample digunakan, semua target render terikat dan buffer kedalaman harus memiliki jumlah sampel yang sama.

Ketika buffer digunakan sebagai target render, pengujian stensil kedalaman dan beberapa target render tidak didukung.

  • Sebanyak 8 target render dapat diikat secara bersamaan.
  • Semua target render harus memiliki ukuran yang sama di semua dimensi (lebar dan tinggi, dan kedalaman untuk ukuran 3D atau array untuk *Jenis array).
  • Setiap target render mungkin memiliki format data yang berbeda.
  • Masker tulis mengontrol data apa yang ditulis ke target render. Output menulis masker kontrol pada target per-render, tingkat per komponen data apa yang ditulis ke target render.

Teknik Stensil Tingkat Lanjut

Bagian stensil dari buffer stensil kedalaman dapat digunakan untuk membuat efek penyajian seperti menyusun, menurun, dan menguraikan.

Menyusun

Aplikasi Anda dapat menggunakan buffer stensil untuk menyusun gambar 2D atau 3D ke adegan 3D. Masker di buffer stensil digunakan untuk menempati area permukaan target penyajian. Informasi 2D yang disimpan, seperti teks atau bitmap, kemudian dapat ditulis ke area okludasi. Secara bergantian, aplikasi Anda dapat merender primitif 3D tambahan ke wilayah bertopeng stensil dari permukaan target penyajian. Bahkan dapat merender seluruh adegan.

Game sering menggabungkan beberapa adegan 3D bersama-sama. Misalnya, game mengemudi biasanya menampilkan cermin tampilan belakang. Cermin berisi tampilan adegan 3D di belakang driver. Ini pada dasarnya adalah adegan 3D kedua yang terdiri dari tampilan maju driver.

Desaling

Aplikasi Direct3D menggunakan decaling untuk mengontrol piksel mana dari gambar primitif tertentu yang digambar ke permukaan target penyajian. Aplikasi menerapkan desal pada gambar primitif untuk memungkinkan poligon koplanar dirender dengan benar.

Misalnya, saat menerapkan tanda ban dan garis kuning ke jalan raya, penandaan akan muncul langsung di atas jalan. Namun, nilai z dari penandaan dan jalannya sama. Oleh karena itu, buffer kedalaman mungkin tidak menghasilkan pemisahan yang bersih antara keduanya. Beberapa piksel di primitif belakang dapat dirender di atas primitif depan dan sebaliknya. Gambar yang dihasilkan tampaknya berkilau dari bingkai ke bingkai. Efek ini disebut z-fighting atau flimmering.

Untuk mengatasi masalah ini, gunakan stensil untuk menutupi bagian primitif belakang tempat desal akan muncul. Matikan z-buffering dan render gambar primitif depan ke area masked-off permukaan render-target.

Beberapa penpaduan tekstur dapat digunakan untuk menyelesaikan masalah ini.

Kerangka dan Siluet

Anda dapat menggunakan buffer stensil untuk efek yang lebih abstrak, seperti kerangka dan silhouetting.

Jika aplikasi Anda melakukan dua pass render - satu untuk menghasilkan masker stensil dan kedua untuk menerapkan masker stensil ke gambar, tetapi dengan primitif sedikit lebih kecil pada pass kedua - gambar yang dihasilkan hanya akan berisi kerangka primitif. Aplikasi kemudian dapat mengisi area gambar yang ditutupi stensil dengan warna solid, memberikan tampilan timbul primitif.

Jika masker stensil berukuran dan bentuk yang sama dengan primitif yang Anda render, gambar yang dihasilkan berisi lubang di mana primitif harus. Aplikasi Anda kemudian dapat mengisi lubang dengan hitam untuk menghasilkan siluet primitif.

Stensil Two-Sided

Volume Bayangan digunakan untuk menggambar bayangan dengan buffer stensil. Aplikasi ini menghitung volume bayangan yang dilemparkan dengan mengapit geometri, dengan menghitung tepi siluet dan mengusirnya dari cahaya ke dalam satu set volume 3D. Volume ini kemudian dirender dua kali ke dalam buffer stensil.

Render pertama menggambar poligon yang menghadap ke depan, dan meningkatkan nilai stensil-buffer. Render kedua menggambar poligon volume bayangan yang menghadap ke belakang, dan mengurangi nilai buffer stensil. Biasanya, semua nilai bertahap dan berkurang saling membatalkan. Namun, adegan sudah dirender dengan geometri normal yang menyebabkan beberapa piksel gagal dalam pengujian z-buffer saat volume bayangan dirender. Nilai yang tersisa di buffer stensil sesuai dengan piksel yang ada di bayangan. Isi stensil-buffer yang tersisa ini digunakan sebagai masker, untuk menyatukan quad hitam besar yang mencakup semua ke dalam adegan. Dengan buffer stensil yang bertindak sebagai masker, hasilnya adalah untuk menggelapkan piksel yang ada di bayangan.

Ini berarti bahwa geometri bayangan digambar dua kali per sumber cahaya, oleh karena itu memberikan tekanan pada throughput puncak GPU. Fitur stensil dua sisi telah dirancang untuk mengurangi situasi ini. Dalam pendekatan ini, ada dua set status stensil (dinamai di bawah), satu set masing-masing untuk segitiga menghadap depan dan yang lainnya untuk segitiga yang menghadap ke belakang. Dengan cara ini, hanya satu pass yang digambar per volume bayangan, per cahaya.

Contoh implementasi stensil dua sisi dapat ditemukan di Sampel ShadowVolume10.

Membaca Buffer Depth-Stencil sebagai Tekstur

Buffer stensil kedalaman yang tidak aktif dapat dibaca oleh shader sebagai tekstur. Aplikasi yang membaca buffer stensil kedalaman sebagai tekstur merender dalam dua lintasan, lulus pertama menulis ke buffer stensil kedalaman dan pass kedua membaca dari buffer. Ini memungkinkan shader untuk membandingkan nilai kedalaman atau stensil yang sebelumnya ditulis ke buffer terhadap nilai untuk piksel yang dirender secara berurutan. Hasil perbandingan dapat digunakan untuk membuat efek seperti pemetaan bayangan atau partikel lunak dalam sistem partikel.

Untuk membuat buffer stensil kedalaman yang dapat digunakan sebagai sumber daya stensil kedalaman dan sumber daya shader, beberapa perubahan perlu dilakukan untuk sampel kode di bagian Buat sumber daya Depth-Stencil .

  • Sumber daya stensil kedalaman harus memiliki format tanpa jenis seperti DXGI_FORMAT_R32_TYPELESS.

    descDepth.Format = DXGI_FORMAT_R32_TYPELESS;
    
  • Sumber daya stensil kedalaman harus menggunakan bendera ikatan D3D10_BIND_DEPTH_STENCIL dan D3D10_BIND_SHADER_RESOURCE.

    descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL | D3D10_BIND_SHADER_RESOURCE;
    

Selain itu tampilan sumber daya shader perlu dibuat untuk buffer kedalaman menggunakan struktur D3D11_SHADER_RESOURCE_VIEW_DESC dan ID3D11Device::CreateShaderResourceView. Tampilan sumber daya shader akan menggunakan format yang ditik seperti DXGI_FORMAT_R32_FLOAT yang setara dengan format tanpa jenis yang ditentukan saat sumber daya stensil kedalaman dibuat.

Di render pertama, lewati buffer kedalaman terikat seperti yang dijelaskan di bagian Ikat data Depth-Stencil ke Tahap OM . Perhatikan bahwa format diteruskan ke D3D11_DEPTH_STENCIL_VIEW_DESC. Format akan menggunakan format bertipe seperti DXGI_FORMAT_D32_FLOAT. Setelah render pertama melewati buffer kedalaman akan berisi nilai kedalaman untuk adegan.

Dalam render kedua, lewati fungsi ID3D11DeviceContext::OMSetRenderTargets digunakan untuk mengatur tampilan stensil kedalaman ke NULL atau sumber daya depth-stencil yang berbeda dan tampilan sumber daya shader diteruskan ke shader menggunakan ID3D11EffectShaderResourceVariable::SetResource. Ini memungkinkan shader untuk mencari nilai kedalaman yang dihitung dalam lulus penyajian pertama. Perhatikan bahwa transformasi perlu diterapkan untuk mengambil nilai kedalaman jika sudut pandang lulus render pertama berbeda dari render pass kedua. Misalnya, jika teknik pemetaan bayangan sedang digunakan, lulus render pertama akan berasal dari perspektif sumber cahaya sementara pass render kedua akan dari perspektif pemirsa.

Tahap Output-Merger

Tahapan Alur (Direct3D 10)