Partager via


Configuration des fonctionnalités de Depth-Stencil

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

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

Créer une ressource Depth-Stencil

Créez la mémoire tampon de profondeur-gabarit à 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 profondeur-gabarit indique à l’étape sortie-fusion comment effectuer le test profondeur-gabarit. Le test de profondeur-gabarit détermine si un pixel donné doit être dessiné ou non.

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 gabarit. 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 le test 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 l’opération de gabarit).

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

Lier des données Depth-Stencil à la phase om

Lier l’état profondeur-gabarit.

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

Liez la ressource depth-stencil à 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 de cible de rendu peut être passé dans ID3D11DeviceContext::OMSetRenderTargets, mais toutes ces vues de cible de rendu 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 simultanément sur plusieurs cibles de rendu au niveau primitif. Les tableaux de cibles de rendu offrent des performances accrues en définissant individuellement 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 à échantillonnage multiple 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 pris en charge.

  • 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 la taille 3D ou de tableau pour les *types de tableau).
  • 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 contrôle d’écriture de sortie masque sur une cible par rendu, au niveau des composants, quelles données sont écrites dans la ou les cibles de rendu.

Techniques de gabarit avancées

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

Compositing

Votre application peut utiliser la mémoire tampon de gabarit pour compositer des images 2D ou 3D sur une scène 3D. Un masque dans la mémoire tampon de gabarit est utilisé pour obstruer 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 occluse. Votre application peut également afficher des primitives 3D supplémentaires dans la zone masquée du gabarit de la surface cible de rendu. Il peut même afficher une scène entière.

Les jeux sont souvent composés de plusieurs scènes 3D. Par instance, les jeux de conduite affichent généralement un miroir de vue 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 composée avec la vue avant du pilote.

Détcalage

Les applications Direct3D utilisent le décalquer pour contrôler les pixels d’une image primitive particulière qui sont dessinés vers la surface cible de rendu. Les applications appliquent des décalques aux images de primitives pour permettre aux polygones coplanaires de s’afficher correctement.

Pour instance, lors de l’application de marques de pneus et de lignes jaunes sur une chaussée, les marquages doivent apparaître directement au-dessus de la route. Toutefois, les valeurs z des marquages et de la route sont les mêmes. 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 affichés par-dessus la primitive avant et vice versa. L’image résultante semble scintiller d’un cadre à l’autre. Cet effet est appelé z-fighting ou scintillement.

Pour résoudre ce problème, utilisez un gabarit pour masquer la section de la primitive arrière où la décalal apparaît. Désactivez la mise en mémoire tampon z et restituez l’image de la primitive avant dans la zone masquée de la surface cible de rendu.

Le mélange de textures multiples peut être utilisé pour résoudre ce problème.

Contours et silhouettes

Vous pouvez utiliser la mémoire tampon de gabarit pour des effets plus abstraits, tels que le plan et le silhouetting.

Si votre application effectue deux passes de rendu : l’une pour générer le masque de gabarit et l’autre pour appliquer le masque de gabarit à l’image, mais avec les primitives légèrement plus petites au deuxième passage, l’image résultante contient uniquement le contour de la primitive. L’application peut ensuite remplir la zone masquée du gabarit de l’image avec une couleur unie, donnant à la primitive un aspect en relief.

Si le masque de gabarit a la même taille et la même forme que la primitive que vous affichez, l’image résultante contient un trou où doit se trouver la primitive. Votre application peut ensuite remplir le trou de noir pour produire une silhouette de la primitive.

gabarit Two-Sided

Les volumes d’ombres sont utilisés pour dessiner des ombres avec la mémoire tampon de gabarit. L’application calcule les volumes d’ombres projetés en occludant la géométrie, en calculant les bords de silhouette et en les extrayant loin de la lumière dans un ensemble de volumes 3D. Ces volumes sont ensuite rendus deux fois dans la mémoire tampon de gabarit.

Le premier rendu dessine des polygones orientés vers l’avant et incrémente les valeurs de stencil-buffer. Le deuxième rendu dessine les polygones orientés vers l’arrière du volume d’ombre et décrémente les valeurs de mémoire tampon du gabarit. Normalement, toutes les valeurs incrémentées et décrémentées s’annulent mutuellement. Toutefois, la scène a déjà été rendue avec une géométrie normale, ce qui a entraîné l’échec du test de la mémoire tampon z à mesure que le volume d’ombre est restitué. Les valeurs laissées dans la mémoire tampon de gabarit correspondent aux pixels qui se trouvent dans l’ombre. Le contenu de la mémoire tampon de gabarit restant est utilisé comme masque pour mélanger un grand quad noir englobant dans la scène. Avec la mémoire tampon de gabarit agissant comme un masque, le résultat est d’assombrir les pixels qui se trouvent dans les ombres.

Cela signifie que la géométrie d’ombre est dessinée deux fois par source de lumière, ce qui exerce une pression sur le débit de vertex du GPU. La fonctionnalité de gabarit double face a été conçue pour atténuer cette situation. Dans cette approche, il existe deux ensembles d’état de gabarit (nommés ci-dessous), l’un défini chacun pour les triangles avant et l’autre pour les triangles arrière. De cette façon, une seule passe est dessinée par volume d’ombre, par lumière.

Vous trouverez un exemple d’implémentation de gabarit double face dans l’exemple ShadowVolume10.

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

Un tampon de gabarit de profondeur inactif peut être lu par un nuanceur en tant que texture. Une application qui lit une mémoire tampon de profondeur-gabarit en tant que texture s’affiche en deux passes, la première passe écrit dans la mémoire tampon profondeur-gabarit et la seconde passe lit à partir de la mémoire tampon. Cela permet à un nuanceur de comparer des 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 des ombres ou des particules molles dans un système de particules.

Pour créer une mémoire tampon de profondeur-gabarit qui peut être utilisée à la fois comme ressource de profondeur-gabarit et comme ressource de nuanceur, quelques modifications doivent être apportées à 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 gabarit 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 des ressources du nuanceur doit être créée pour la mémoire tampon de profondeur à l’aide d’une structure D3D11_SHADER_RESOURCE_VIEW_DESC et d’ID3D11Device::CreateShaderResourceView. L’affichage des ressources du nuanceur utilise un format typé tel que DXGI_FORMAT_R32_FLOAT qui est l’équivalent du format sans type spécifié lors de la création de la ressource de gabarit de profondeur.

Dans le premier rendu, la mémoire tampon de profondeur est liée comme décrit dans la section Lier des données Depth-Stencil à l’étape de modèle modèle. Notez que le format passé à D3D11_DEPTH_STENCIL_VIEW_DESC. Le format utilise un format typé tel que DXGI_FORMAT_D32_FLOAT. Une fois le premier rendu passé, la mémoire tampon de profondeur contient les valeurs de profondeur de la scène.

Dans le deuxième passage de rendu, la fonction ID3D11DeviceContext::OMSetRenderTargets est utilisée pour définir la vue de gabarit de profondeur sur NULL ou sur une autre ressource de profondeur-gabarit, et l’affichage des ressources du nuanceur est passé au nuanceur à l’aide de 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 de la première passe de rendu est différent de la deuxième passe 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.

Étape de sortie-fusion

Phases de pipeline (Direct3D 10)