Dela via


Konfigurera Depth-Stencil funktioner

Det här avsnittet beskriver stegen för att konfigurera djupstencilbufferten och djupstenciltillståndet för utdatablandarfasen.

När du väl vet hur du använder djupstencilbufferten och motsvarande djupstenciltillstånd, kan du läsa om avancerade stenciltekniker i avsnittet .

Skapa en Depth-Stencil resurs

Skapa djupstencilbufferten med hjälp av en strukturresurs.

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

Skapa Depth-Stencil Tillstånd

Tillståndet djupstencil anger hur djupstenciltestet ska utföras. Djupstenciltestet avgör om en viss pixel ska ritas eller inte.

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 och StencilEnable aktiverar (och inaktiverar) djup- och stenciltestning. Ange DepthEnable till FALSE- för att inaktivera djuptestning och förhindra skrivning till djupbufferten. Ange StencilEnable till FALSE för att inaktivera stenciltestning och förhindra skrivning till stencilbufferten (när DepthEnable är FALSE och StencilEnable är TRUE, kommer djuptestet alltid att passera i stenciloperationen).

DepthEnable påverkar endast utdatasammanslagningssteget – det påverkar inte klippning, djupförskjutning eller klämning av värdena innan de matas in till en pixelshader.

Binda Depth-Stencil data till OM-fasen

Binda djupstenciltillståndet.

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

Binda djupstencilresursen med hjälp av en vy.

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

En matris med renderingsmålvyer kan skickas till ID3D11DeviceContext::OMSetRenderTargets, men alla dessa återgivningsmålvyer motsvarar en enda djupstencilvy. Rendermålmatrisen i Direct3D 11 är en funktion som möjliggör för ett program att rendera till flera renderingsmål samtidigt på prismatisk nivå. Rendera målmatriser ger bättre prestanda jämfört med att individuellt ange återgivningsmål med flera anrop till ID3D11DeviceContext::OMSetRenderTargets (i huvudsak den metod som används i Direct3D 9).

Återgivningsmål måste alla vara av samma typ av resurs. Om multisample-antialias används måste alla bundna återgivningsmål och djupbuffertar ha samma antal exempel.

När en buffert används som återgivningsmål stöds inte djupstenciltestning och flera återgivningsmål.

  • Upp till 8 rendering mål kan bindas samtidigt.
  • Alla återgivningsmål måste ha samma storlek i alla dimensioner (bredd och höjd samt djup för 3D- eller matrisstorlek för *Matristyper).
  • Varje återgivningsmål kan ha olika dataformat.
  • Skrivmasker styr vilka data som skrivs till ett återgivningsmål. Utdataskrivmaskerna styr på varje renderingsmål och varje komponentnivå vilka data som skrivs till renderingsmålen.

Avancerade stenciltekniker

Stencildelen av djupstencilbufferten kan användas för att skapa renderingseffekter som sammanställning, dekalering och konturering.

Montage

Ditt program kan använda stencilbufferten för att sammansätta 2D- eller 3D-bilder i en 3D-scen. En mask i stencilbufferten används för att dölja ett område på rendermålytan. Lagrad 2D-information, till exempel text eller bitmappar, kan sedan skrivas till det ockluderade området. Alternativt kan ditt program rendera ytterligare 3D-primitiver till den stencilmaskerade regionen på renderingsmålytan. Det kan till och med återge en hel scen.

Spel sammanställer ofta flera 3D-scener tillsammans. Körspel visar till exempel vanligtvis en backspegel. Spegeln innehåller vyn av 3D-scenen bakom föraren. Det är i huvudsak en andra 3D-scen sammansatt med förarens framåtvy.

Avskalning

Direct3D-program använder avskalning för att styra vilka bildpunkter från en viss primitiv bild som ritas till återgivningsmålytan. Applikationer tillämpar dekaler på bilder av grundläggande former för att göra det möjligt för koplanära polygoner att återges korrekt.

När du till exempel tillämpar däckmärken och gula linjer på en vägbana bör märkningarna visas direkt ovanpå vägen. Z-värdena för markeringen och vägen är dock desamma. Därför kanske djupbufferten inte ger en ren separation mellan de två. Vissa bildpunkter i den bakre primitiven kan återges ovanpå den främre primitiva och vice versa. Den resulterande bilden verkar skimra från ram till ram. Den här effekten kallas z-fighting eller flimmering.

Lös problemet genom att använda en stencil för att maskera avsnittet i den bakre primitiven där dekalen visas. Inaktivera z-buffring och återge bilden av den främre primitiven till det maskerade området på render-målytan.

Flera texturblandningar kan användas för att lösa det här problemet.

Konturer och silhuetter

Du kan använda stencilbufferten för mer abstrakta effekter, till exempel konturering och silhuettskuggning.

Om programmet gör två återgivningspass – en för att generera stencilmasken och den andra för att tillämpa stencilmasken på bilden, men med primitiverna något mindre vid det andra passet – innehåller den resulterande bilden endast primitivens kontur. Programmet kan sedan fylla det stencilmaskerade området i bilden med en enfärgad färg, vilket ger den primitiva ett präglat utseende.

Om stencilmasken har samma storlek och form som den primitiva du återger, innehåller den resulterande bilden ett hål där primitiven ska vara. Ditt program kan sedan fylla hålet med svart för att producera en silhuett av grundformen.

Two-Sided schablon

Skuggvolymer används för att rita skuggor med stencilbuffert. Programmet beräknar skuggvolymerna som kastas av skymmande geometri genom att beräkna silhuettkanterna och förlänga dem bort från ljuset till en uppsättning 3D-volymer. Dessa volymer renderas sedan två gånger i stencilbufferten.

Den första återgivningen ritar framåtriktade polygoner och ökar stencilbuffertvärdena. Den andra återgivningen ritar skuggvolymens bakåtriktade polygoner och minskar stencilbuffertvärdena. Normalt tar alla ökade och minskade värden ut varandra. Scenen hade dock redan renderats med normal geometri, vilket gjorde att vissa pixlar misslyckades med z-bufferttestet när skuggvolymen renderades. Värden som finns kvar i stencilbufferten motsvarar bildpunkter som finns i skuggan. Dessa återstående innehåll i stencilbufferten används som en mask för att alfablanda in en stor, alltövergripande svart fyrkant i scenen. När stencilbufferten fungerar som en mask blir resultatet att mörka pixlar som finns i skuggorna.

Det innebär att skugggeometrin ritas två gånger per ljuskälla, vilket sätter press på GPU:ns hörngenomflöde. Den tvåsidiga stencilfunktionen har utformats för att minimera den här situationen. I den här metoden finns det två uppsättningar stenciltillstånd (namngivna nedan), en uppsättning vardera för de framåtriktade trianglarna och den andra för de bakåtriktade trianglarna. På så sätt ritas endast ett enda pass per skuggvolym, per ljus.

Ett exempel på tvåsidig stencilimplementering finns i ShadowVolume10 Sample.

Läsa Depth-Stencil-bufferten som en textur

En inaktiv djupstencilbuffert kan läsas av en skuggning som en struktur. En applikation som läser en djupstencilbuffert som en textur renderas i två pass, där det första passet skriver till djupstencilbufferten och det andra passet läser från bufferten. Detta gör att en shader kan jämföra djup- eller stencilmärkesvärden som tidigare skrivits till bufferten med värdet för pixeln som renderas. Resultatet av jämförelsen kan användas för att skapa effekter som skuggmappning eller mjuka partiklar i ett partikelsystem.

För att skapa en djupstencilbuffert som kan användas som både en djupstencilresurs och en skuggningsresurs måste några ändringar göras i exempelkoden i avsnittet Skapa en Depth-Stencil resurs.

  • Djupstencilresursen måste ha ett typlöst format, till exempel DXGI_FORMAT_R32_TYPELESS.

    descDepth.Format = DXGI_FORMAT_R32_TYPELESS;
    
  • Resursen för djup-stencil måste använda sig av både bindningsflaggorna D3D10_BIND_DEPTH_STENCIL och D3D10_BIND_SHADER_RESOURCE.

    descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL | D3D10_BIND_SHADER_RESOURCE;
    

Dessutom måste en shaderresursvy skapas för djupbufferten med hjälp av en D3D11_SHADER_RESOURCE_VIEW_DESC struktur och ID3D11Device::CreateShaderResourceView. Skuggningsresursvyn använder ett skrivet format, till exempel DXGI_FORMAT_R32_FLOAT som motsvarar det typlösa format som angavs när djupstencilresursen skapades.

I det första återgivningspasset binds djupbufferten enligt beskrivningen i avsnittet Bind Depth-Stencil data till OM Stage. Observera att formatet som skickades till D3D11_DEPTH_STENCIL_VIEW_DESC. kommer att använda ett typsatt format, till exempel DXGI_FORMAT_D32_FLOAT. Efter det första återgivningspasset kommer djupbufferten att innehålla djupvärdena för scenen.

I den andra renderingspasset används funktionen ID3D11DeviceContext::OMSetRenderTargets för att ange djupstencilvyn till NULL eller en annan djupstencilresurs, och skuggningsresursvyn överförs till skuggningen med hjälp av ID3D11EffectShaderResourceVariable::SetResource. Detta gör det möjligt för shadern att hämta de djupvärden som beräknades i det första återgivningspasset. Observera att en transformering måste tillämpas för att hämta djupvärden om vyn för det första återgivningspasset skiljer sig från det andra återgivningspasset. Om till exempel en skuggmappningsteknik används kommer det första återgivningspasset att vara från en ljuskällas perspektiv medan det andra återgivningspasset kommer från visningsprogrammets perspektiv.

Output-Merger fas

Pipeline-steg (Direct3D 10)