\\ Home : Articoli : Stampa
Depth Stencil Test
Di RobyDx (del 03/10/2010 @ 12:06:58, in Direct3D11, linkato 3003 volte)

Il depthbuffer è una caratteristica ormai presente in DirectX dalla notte dei tempi. Se un oggetto è distante dalla telecamera 10 unità allora registra nei pixel di questo buffer il valore 10. Ogni oggetto che andrà ad occupare la stessa posizione nella scena dovrà confrontare la distanza dei suoi pixel con quelli già presenti nello stesso punto e verrà renderizzato se i suoi valori sono inferiori, rimpiazzando i precedenti, oppure verrà eliminato. Il buffer utilizzato è di fatto una grossa matrice di dimensioni pari al back buffer ed in ogni punto è presente un valore a 16, 24,32 o 64bit. DirectX permette di utilizzare parte di questo valore per il depth e di lasciare l’altra parte per una seconda funzionalità: lo Stencil.

Lo stencil permette all’utente di definire delle regole di scrittura dell’oggetto. Ad esempio si può volere che un oggetto lasci sui pixel che occupa sullo schermo il valore 1 e fare in modo che tutti gli oggetti non possano scrivere su valori diversi da 1. Quando un pixel rispetta le regole di depth o di stencil vengono scritti i pixel sul back buffer e si dice che il pixel ha superato il depth test o lo stencil test.

Un utilizzo è il seguente:

  1. Si usa un oggetto come maschera creando una zona sporca sullo stencil (esempio un cerchio)
  2. Si imposta la regola per cui in quella zona non si può scrivere e si renderizza la scena che non occuperà quel punto
  3. Si imposta la regola per cui si può scrivere solo in quella zona e si renderizza una seconda scena

Il risultato sarà che aumentando e diminuendo il cerchio si potrà avere una transizione tra una scena e l’altra

Gli effetti ottenibili sono numerosissimi (anche alcune tecniche d’ombra si basano sullo stencil).

Impostare il DepthStencil è un’operazione relativamente semplice.

Innanzitutto è necessario al momento della creazione del depthbuffer impostare il suo formato al valore che ci è più utile:

  • DXGI_FORMAT_D32_FLOAT_S8X24_UINT : format a 64bit, 32 per il depth, 8 per lo stencil e 24 non utilizzati
  • DXGI_FORMAT_D32_FLOAT: depth a 32bit ma senza stencil
  • DXGI_FORMAT_D24_UNORM_S8_UINT: 24 bit per il depth ed 8 per lo stencil
  • DXGI_FORMAT_D16_UNORM: 16bit per il depth

Ora al momento del clear del depthStencil si utilizza il comando ClearDepthStencilView a cui si passa la superficie, le opzioni con le superfici da pulire (D3D11_CLEAR_DEPTH , D3D11_CLEAR_STENCIL o entrambe separate da | ) ed i valori che saranno impostati sulle superfici.

context->ClearDepthStencilView(renderTargetDepth,D3D11_CLEAR_DEPTH,1,0);

Ora non resta altro che creare un oggetto ID3D11DepthStencilState con le opzioni desiderate e passarlo prima del rendering.

Potete creare diversi oggetti e cambiarli prima di ogni rendering per creare gli effetti che volete.

D3D11_DEPTH_STENCIL_DESC descD=D3D11_DEPTH_STENCIL_DESC();

ID3D11DepthStencilState* depthState;

descD.DepthEnable=true;

descD.DepthWriteMask=D3D11_DEPTH_WRITE_MASK_ALL;

descD.DepthFunc=D3D11_COMPARISON_LESS_EQUAL;

device->CreateDepthStencilState(&descD,&depthState);

Utilizzando OMSetDepthStencilState inserite il depthStencilState nel context insieme allo stencilRef, il valore da utilizzare nelle formule.

context->OMSetDepthStencilState(depthState,0);

Come impostare il depthStencil

La struttura D3D11_DEPTH_STENCIL_DESC contiene tutte le proprietà con cui si definiscono le nostre regole

DepthEnable : impostato a true o false attiva o disattiva il depth test (a false un oggetto dietro ad un altra lo sovrascriverà se renderizzato dopo di esso)

DepthWriteMask : permette di decidere attraverso l’enum D3D11_DEPTH_WRITE_MASK se scrivere (ALL) o impedire la scrittura (Zero)

DepthFunc : indica il tipo di controllo da fare tramite l’enum D3D11_COMPARISON_FUNC. Ogni pixel dovrà rispettare la regola imposta per passare il depth test e quindi comparire sul video. Le opzioni sono

  • D3D11_COMPARISON_NEVER : I pixel non superano mai il test, in pratica un oggetto non compare mai a video
  • D3D11_COMPARISON_LESS : se minore del precedente passano il test
  • D3D11_COMPARISON_EQUAL : se uguali passano il test
  • D3D11_COMPARISON_LESS_EQUAL : se minori o uguali passano il test (è l’impostazione classica)
  • D3D11_COMPARISON_GREATER : se maggiori passano il test
  • D3D11_COMPARISON_NOT_EQUAL : se diversi passano il test
  • D3D11_COMPARISON_GREATER_EQUAL : se maggiori o uguali passano il test
  • D3D11_COMPARISON_ALWAYS : ogni pixel supera sempre il test

StencilEnable : attiva o disattiva lo stencil

StencilReadMask : permette di impostare una maschera di bit in lettura. Una maschera di bit è un valore che confrontato in AND con un altro permette di far passare solo determinati valori dell’altro. Esempio

1110 mascherato con 0011 fa passare solo gli ultimi 2 valori del primo ossia 0010. I valori saranno passati come insigned int.

StencilWriteMask : permette di impostare una maschera di bit in scrittura.

FrontFace e BackFace: sono le impostazioni di stencil da applicare differentemente per I triangoli rivolti verso di noi o meno. Ognuno è una struttura D3D11_DEPTH_STENCILOP_DESC

La struttura si compone come segue

StencilFailOp, StencilDepthFailOp, StencilPassOp : sono le operazioni da eseguire nel caso il pixel fallisca lo stencil test, fallisca il depth test o passi lo stencil test. Queste impostano come il valore dello stencil muterà. Il valore utilizzato sarà quello passato (StencilRef) in fase di impostazione.

  • D3D11_STENCIL_OP_KEEP : mantiene il valore
  • D3D11_STENCIL_OP_ZERO : lo imposta a zero
  • D3D11_STENCIL_OP_REPLACE : sostituisce il valore corrente
  • D3D11_STENCIL_OP_INCR_SAT : incrementa senza superare il massimo
  • D3D11_STENCIL_OP_DECR_SAT : decrementa senza mai scendere sotto lo zero
  • D3D11_STENCIL_OP_INVERT : inverte il valore
  • D3D11_STENCIL_OP_INCR : incrementa ma se supera il massimo torna a zero
  • D3D11_STENCIL_OP_DECR : decrementa ma se scende sotto lo zero torno al minimo

StencilFunc: la funzione da utilizzare come regola (sono le stesse del depth test)

Non tutte le condizioni sono accettate e la creazione darà errore. Non rimane che fare prove su prove per capire il funzionamento e trovare idee sul suo utilizzo.