Partager via


Configuration des fonctionnalités de Depth-Stencil

Cette section décrit les étapes de configuration de la mémoire tampon du gabarit de profondeur et de l’état du gabarit de profondeur pour l’étape de fusion de sortie.

Une fois que vous savez comment utiliser la mémoire tampon de profondeur-gabarit et l’état de profondeur-gabarit correspondant, reportez-vous à techniques avancées de gabarit.

Créer une ressource Depth-Stencil

Créez la mémoire tampon de gabarit de profondeur à l’aide d’une ressource de texture.

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

Créer un état Depth-Stencil

L’état du gabarit de profondeur indique à l’étape de fusion de sortie comment effectuer le test de profondeur-gabarit . Le test de profondeur et pochoir détermine ou non si un pixel donné doit être dessiné.

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 et StencilEnable activent et désactivent les tests de profondeur et de pochoir. Définissez DepthEnable sur FALSE pour désactiver les tests de profondeur et empêcher l’écriture dans la mémoire tampon de profondeur. Définissez StencilEnable sur FALSE pour désactiver les tests de gabarit et empêcher l’écriture dans la mémoire tampon de gabarit (lorsque DepthEnable a la valeur FALSE et StencilEnable a la valeur TRUE, le test de profondeur réussit toujours dans l’opération de gabarit).

DepthEnable affecte uniquement l’étape de fusion de sortie : elle n’affecte pas le découpage, le biais de profondeur ou la réduction des valeurs avant que les données ne sont entrées dans un nuanceur de pixels.

Lier des données Depth-Stencil à l’étape om

Lier l’état du gabarit de profondeur.

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

Lier la ressource de gabarit de profondeur à l’aide d’une vue.

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

Un tableau de vues render-target peut être passé dans ID3D11DeviceContext ::OMSetRenderTargets, mais toutes ces vues render-target correspondent à une vue de gabarit de profondeur unique. Le tableau de cibles de rendu dans Direct3D 11 est une fonctionnalité qui permet à une application de s’afficher sur plusieurs cibles de rendu simultanément au niveau primitif. Les tableaux de cibles de rendu offrent des performances accrues par rapport à la définition individuelle des cibles de rendu avec plusieurs appels à ID3D11DeviceContext ::OMSetRenderTargets (essentiellement la méthode utilisée dans Direct3D 9).

Les cibles de rendu doivent toutes être du même type de ressource. Si l’anticrénelage multisample est utilisé, toutes les cibles de rendu liées et les mémoires tampons de profondeur doivent avoir le même nombre d’échantillons.

Lorsqu’une mémoire tampon est utilisée comme cible de rendu, les tests de profondeur-gabarit et plusieurs cibles de rendu ne sont pas prises en charge.

  • Autant que 8 cibles de rendu peuvent être liées simultanément.
  • Toutes les cibles de rendu doivent avoir la même taille dans toutes les dimensions (largeur et hauteur, et profondeur pour 3D ou taille de tableau pour les types *Array).
  • Chaque cible de rendu peut avoir un format de données différent.
  • Les masques d'écriture contrôlent les données écrites dans une cible de rendu. Le masque de contrôle d'écriture de sortie détermine, pour chaque cible de rendu et pour chaque composant, quelles données sont écrites dans la ou les cibles de rendu.

Techniques avancées de gabarit

La partie stencil de la mémoire tampon de profondeur-stencil peut être utilisée pour créer des effets de rendu tels que la composition, la décalcomanie et le tracé.

Compositing

Votre application peut utiliser le tampon de pochoir pour composer des images 2D ou 3D sur une scène 3D. Un masque dans la mémoire tampon de gabarit est utilisé pour masquer une zone de la surface cible de rendu. Les informations 2D stockées, telles que du texte ou des bitmaps, peuvent ensuite être écrites dans la zone obstruée. Votre application peut également rendre des primitives 3D supplémentaires dans la région masquée par le stencil de la surface cible de rendu. Il peut même restituer une scène entière.

Les jeux compositent souvent plusieurs scènes 3D ensemble. Par exemple, les jeux de conduite affichent généralement un miroir arrière. Le miroir contient la vue de la scène 3D derrière le pilote. Il s’agit essentiellement d’une deuxième scène 3D composite avec la vue avant du pilote.

Décalquage

Les applications Direct3D utilisent la mise à l’échelle pour contrôler quels pixels d’une image primitive particulière sont dessinés vers l’aire cible de rendu. Les applications appliquent des décalques aux images de primitives pour permettre aux polygones coplanaires de s’afficher correctement.

Par exemple, lors de l’application de marques de pneus et de lignes jaunes à une route, les marquages doivent apparaître directement au-dessus de la route. Toutefois, les valeurs z des marquages et de la route sont identiques. Par conséquent, la mémoire tampon de profondeur peut ne pas produire de séparation propre entre les deux. Certains pixels de la primitive arrière peuvent être rendus sur la primitive avant et vice versa. L’image résultante semble scintiller du cadre au cadre. Cet effet est appelé "z-fighting" ou scintillement.

Pour résoudre ce problème, utilisez un gabarit pour masquer la section de l'objet de fond où le décalque apparaîtra. Désactivez le z-buffering et affichez l'image de la primitive avant dans la zone masquée de la surface de rendu cible.

Plusieurs fusions de textures peuvent être utilisées pour résoudre ce problème.

Contours et silhouettes

Vous pouvez utiliser le tampon de pochoir pour des effets abstraits supplémentaires, tels que le contour et la mise en silhouette.

Si votre application effectue deux passes de rendu : une pour générer le masque de gabarit et la seconde pour appliquer le masque de gabarit à l’image, mais avec les primitives légèrement plus petites sur la deuxième passe, l’image résultante contiendra uniquement le contour de la primitive. L’application peut ensuite remplir la zone masquée par gabarit de l’image avec une couleur unie, donnant à la primitive une apparence embossée.

Si le masque de gabarit est de la même taille et de la même forme que la primitive que vous affichez, l'image résultante contient un trou là où la primitive devrait se trouver. Votre application peut ensuite remplir la cavité avec du noir pour produire une silhouette du modèle primitif.

pochoir Two-Sided

Les volumes d'ombre sont utilisés pour dessiner des ombres avec le tampon de stencil. L'application calcule les volumes d'ombre produits par la géométrie occultante, en calculant les bords de silhouette et en les extrudant à partir de la source de lumière pour former un ensemble de volumes 3D. Ces volumes sont ensuite rendus à deux reprises dans la mémoire tampon de gabarit.

Le premier rendu dessine des polygones orientés vers l'avant et incrémente les valeurs du tampon de stencil. Le deuxième rendu dessine les polygones arrière du volume d’ombre et décrémente les valeurs du tampon de masquage. Normalement, toutes les valeurs incrémentées et décrémentées s’annulent. Toutefois, la scène a déjà été rendue avec une géométrie standard, provoquant l’échec du test du tampon Z pour certains pixels lorsque le volume d'ombre est rendu. Les valeurs laissées dans la mémoire tampon de stencil correspondent aux pixels qui se trouvent dans l’ombre. Ces contenus restants de mémoire tampon de gabarit sont utilisés comme masque, pour réaliser une combinaison alpha d'un quad noir de grande taille couvrant l'ensemble de la scène. Avec le tampon de stencil agissant comme masque, le résultat est d'assombrir les pixels qui se trouvent dans la zone d'ombre.

Cela signifie que la géométrie de l’ombre est dessinée deux fois par source de lumière, ce qui entraîne une pression sur le débit de vertex du GPU. La fonctionnalité de gabarit à deux côtés a été conçue pour atténuer cette situation. Dans cette approche, il existe deux ensembles d’états de gabarit (nommés ci-dessous), un ensemble pour les triangles orientés vers l'avant et l’autre pour les triangles orientés vers l'arrière. De cette façon, une seule passe est dessinée par volume d’ombre, pour chaque source lumineuse.

Vous trouverez un exemple d’implémentation de gabarit à deux côtés dans l’exemple ShadowVolume10.

Lecture de la mémoire tampon Depth-Stencil en tant que texture

Une mémoire tampon de profondeur inactive peut être lue par un nuanceur sous forme de texture. Une application qui lit une mémoire tampon de profondeur-gabarit comme texture effectue le rendu en deux passes : la première passe écrit dans la mémoire tampon de profondeur-gabarit et la seconde passe lit dans la mémoire tampon. Cela permet à un nuanceur de comparer les valeurs de profondeur ou de gabarit précédemment écrites dans la mémoire tampon par rapport à la valeur du pixel en cours de rendu. Le résultat de la comparaison peut être utilisé pour créer des effets tels que le mappage d’ombres ou les particules douces dans un système de particules.

Pour créer un tampon de profondeur-gabarit qui peut être utilisé à la fois comme ressource de profondeur et ressource de shader, il est nécessaire de modifier l'exemple de code dans la section Créer une ressource Depth-Stencil.

  • La ressource de gabarit de profondeur doit avoir un format sans type tel que DXGI_FORMAT_R32_TYPELESS.

    descDepth.Format = DXGI_FORMAT_R32_TYPELESS;
    
  • La ressource de tampon de profondeur doit utiliser les indicateurs de liaison D3D10_BIND_DEPTH_STENCIL et D3D10_BIND_SHADER_RESOURCE.

    descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL | D3D10_BIND_SHADER_RESOURCE;
    

En outre, une vue de ressource de nuanceur doit être créée pour la mémoire tampon de profondeur à l’aide d’une structure D3D11_SHADER_RESOURCE_VIEW_DESC et ID3D11Device::CreateShaderResourceView. La vue de ressources du shader utilisera un format typé tel que DXGI_FORMAT_R32_FLOAT qui est équivalent au format sans type spécifié lors de la création de la ressource de profondeur-stencil.

Dans le premier rendu, la mémoire tampon de profondeur est liée, comme décrit dans la section Liaison Depth-Stencil Données à la phase om . Notez que le format passé à D3D11_DEPTH_STENCIL_VIEW_DESC.Format utilisera un format typé tel que DXGI_FORMAT_D32_FLOAT. Après le premier rendu, la mémoire tampon de profondeur contient les valeurs de profondeur de la scène.

Dans le deuxième rendu, la fonction ID3D11DeviceContext ::OMSetRenderTargets est utilisée pour définir la vue profondeur-gabarit sur NULL ou une autre ressource de gabarit de profondeur et la vue de ressource de nuanceur est transmise au nuanceur à l’aide de l’ID3D11EffectShaderResourceVariable ::SetResource. Cela permet au nuanceur de rechercher les valeurs de profondeur calculées dans la première passe de rendu. Notez qu’une transformation doit être appliquée pour récupérer des valeurs de profondeur si le point de vue du premier passage de rendu est différent du deuxième passage de rendu. Par exemple, si une technique de mappage d’ombres est utilisée, la première passe de rendu sera du point de vue d’une source de lumière tandis que la deuxième passe de rendu sera du point de vue de la visionneuse.

Output-Merger étape

étapes de pipeline (Direct3D 10)