Créer des ressources de périphérique pour un tampon de profondeurCreate depth buffer device resources

Découvrez comment créer les ressources de périphérique Direct3D nécessaires pour prendre en charge le test de profondeur des volumes d’ombre.Learn how to create the Direct3D device resources necessary to support depth testing for shadow volumes. Partie 1 de la Procédure pas à pas : implémenter des volumes d’ombre à l’aide de tampons de profondeur dans Direct3D 11.Part 1 of Walkthrough: Implement shadow volumes using depth buffers in Direct3D 11.

Ressources nécessairesResources you'll need

Le rendu d’un plan de profondeur pour les volumes d’ombre nécessite les ressources suivantes liées aux périphériques Direct3D :Rendering a depth map for shadow volumes requires the following Direct3D device-dependent resources:

  • une ressource (tampon) pour le plan de profondeur ;A resource (buffer) for the depth map
  • une vue de profondeur/gabarit et une vue de ressource de nuanceur pour la ressource ;A depth stencil view and shader resource view for the resource
  • un objet d’état de l’échantillonneur de comparaison ;A comparison sampler state object
  • des tampons constants pour matrices PdV légères ;Constant buffers for light POV matrices
  • une fenêtre d’affichage pour le rendu du plan d’ombres (généralement une fenêtre d’affichage carrée) ;A viewport for rendering the shadow map (typically a square viewport)
  • un objet d’état de rendu pour activer l’élimination de la face avant.A rendering state object to enable front face culling
  • Vous aurez aussi besoin d’un objet d’état de rendu pour revenir à l’élimination de la face arrière, si ce n’est pas déjà le cas.You will also need a rendering state object to switch back to back face culling, if you don't already use one.

Notez que la création de ces ressources doit être incluse dans une routine de création de ressources liées au périphérique. De cette façon, votre convertisseur peut les recréer si (par exemple) un nouveau pilote de périphérique est installé ou si l’utilisateur déplace votre application sur un moniteur associé à une autre carte graphique.Note that creation of these resources needs to be included in a device-dependent resource creation routine, that way your renderer can recreate them if (for example) a new device driver is installed, or the user moves your app to a monitor attached to a different graphics adapter.

Vérifier la prise en charge des fonctionnalitésCheck feature support

Avant de créer la carte de profondeur, appelez la méthode CheckFeatureSupport sur l’appareil Direct3D, demandez la ** _ _ _ _ prise en charge des clichés instantanés de la fonctionnalité d3d11 d3d9**et fournissez une structure de ** _ _ _ _ _ prise en charge des clichés instantanés d3d9 des données de fonctionnalités d3d11**Before creating the depth map, call the CheckFeatureSupport method on the Direct3D device, request D3D11_FEATURE_D3D9_SHADOW_SUPPORT, and provide a D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT structure.

D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT isD3D9ShadowSupported;
ZeroMemory(&isD3D9ShadowSupported, sizeof(isD3D9ShadowSupported));
pD3DDevice->CheckFeatureSupport(
    D3D11_FEATURE_D3D9_SHADOW_SUPPORT,
    &isD3D9ShadowSupported,
    sizeof(D3D11_FEATURE_D3D9_SHADOW_SUPPORT)
    );

if (isD3D9ShadowSupported.SupportsDepthAsTextureWithLessEqualComparisonFilter)
{
    // Init shadow map resources

Si cette fonctionnalité n’est pas prise en charge, n’essayez pas de charger les nuanceurs compilés pour le modèle de nuanceur 4 niveau 9 _ x qui appellent des exemples de fonctions de comparaison.If this feature is not supported, do not try to load shaders compiled for shader model 4 level 9_x that call sample comparison functions. Dans de nombreux cas, l’absence de prise en charge de cette fonctionnalité signifie que le GPU est un périphérique hérité doté d’un pilote qui n’est pas mis à jour pour prendre en charge au moins WDDM 1.2.In many cases, lack of support for this feature means that the GPU is a legacy device with a driver that isn't updated to support at least WDDM 1.2. Si l’appareil prend en charge au moins le niveau de fonctionnalité 10 _ 0, vous pouvez charger un exemple de nuanceur de comparaison compilé pour le modèle de nuanceur 4 0 à la _ place.If the device supports at least feature level 10_0 then you can load a sample comparison shader compiled for shader model 4_0 instead.

Créer un tampon de profondeurCreate depth buffer

Pour commencer, essayez de créer le plan de profondeur dans un format de profondeur haute précision.First, try creating the depth map with a higher-precision depth format. Configurez d’abord les propriétés de la vue de ressource de nuanceur correspondantes.Set up matching shader resource view properties first. Si la création de ressource échoue, par exemple en raison d’un manque de mémoire du périphérique ou d’un format non pris en charge par le matériel, essayez un format de moindre précision et modifiez la correspondance des propriétés.If the resource creation fails, for example due to low device memory or a format that the hardware doesn't support, try a lower-precision format and change properties to match.

Cette étape est facultative si vous avez uniquement besoin d’un format de profondeur de faible précision, par exemple lors du rendu sur des appareils de niveau de fonctionnalité Direct3D de résolution moyenne _ .This step is optional if you only need a low-precision depth format, for example when rendering on medium-resolution Direct3D feature level 9_1 devices.

D3D11_TEXTURE2D_DESC shadowMapDesc;
ZeroMemory(&shadowMapDesc, sizeof(D3D11_TEXTURE2D_DESC));
shadowMapDesc.Format = DXGI_FORMAT_R24G8_TYPELESS;
shadowMapDesc.MipLevels = 1;
shadowMapDesc.ArraySize = 1;
shadowMapDesc.SampleDesc.Count = 1;
shadowMapDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
shadowMapDesc.Height = static_cast<UINT>(m_shadowMapDimension);
shadowMapDesc.Width = static_cast<UINT>(m_shadowMapDimension);

HRESULT hr = pD3DDevice->CreateTexture2D(
    &shadowMapDesc,
    nullptr,
    &m_shadowMap
    );

Ensuite, créez les vues de ressource.Then create the resource views. Définissez la tranche MIP sur zéro dans la vue de profondeur/gabarit et les niveaux MIP sur 1 dans la vue de ressource du nuanceur.Set the mip slice to zero on the depth stencil view and set mip levels to 1 on the shader resource view. Les deux ont une dimension de texture de TEXTURE2D, et les deux doivent utiliser un _ format dxgicorrespondant.Both have a texture dimension of TEXTURE2D, and both need to use a matching DXGI_FORMAT.

D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
ZeroMemory(&depthStencilViewDesc, sizeof(D3D11_DEPTH_STENCIL_VIEW_DESC));
depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
depthStencilViewDesc.Texture2D.MipSlice = 0;

D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
ZeroMemory(&shaderResourceViewDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
shaderResourceViewDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
shaderResourceViewDesc.Texture2D.MipLevels = 1;

hr = pD3DDevice->CreateDepthStencilView(
    m_shadowMap.Get(),
    &depthStencilViewDesc,
    &m_shadowDepthView
    );

hr = pD3DDevice->CreateShaderResourceView(
    m_shadowMap.Get(),
    &shaderResourceViewDesc,
    &m_shadowResourceView
    );

Créer un état de comparaisonCreate comparison state

À présent, créez l’objet d’état de l’échantillonneur de comparaison.Now create the comparison sampler state object. Le niveau de fonctionnalité 9 _ 1 ne prend en charge que la _ comparaison d3d11 _ moins _ égale.Feature level 9_1 only supports D3D11_COMPARISON_LESS_EQUAL. Les options de filtre sont expliquées plus en détail dans Prise en charge des plans d’ombres sur une gamme de matériels ou vous pouvez choisir le filtrage de points pour des plans d’ombres plus rapides.Filtering choices are explained more in Supporting shadow maps on a range of hardware - or you can just pick point filtering for faster shadow maps.

Notez que vous pouvez spécifier le _ _ mode d’adresse Border de la texture d3d11 et l' _ utiliser sur les appareils de niveau de fonctionnalité 9 _ 1.Note that you can specify the D3D11_TEXTURE_ADDRESS_BORDER address mode and it will work on feature level 9_1 devices. Cela s’applique aux nuanceurs de pixels qui ne testent pas si le pixel figure dans le tronc de cône (frustrum) de vue de la lumière avant d’effectuer le test de profondeur.This applies to pixel shaders that don't test whether the pixel is in the light's view frustum before doing the depth test. En définissant chaque bordure sur 0 ou 1, vous pouvez contrôler si les pixels en dehors du tronc de cône de vue de la lumière réussissent ou échouent au test de profondeur, et par conséquent s’ils sont éclairés ou dans l’ombre.By specifying 0 or 1 for each border, you can control whether pixels outside the light's view frustum pass or fail the depth test, and therefore whether they are lit or in shadow.

Sur le niveau de fonctionnalité 9 _ 1, les valeurs requises suivantes doivent être définies : MinLOD a la valeur zéro, MaxLOD est défini sur d3d11 _ FLOAT32 _ Max, et MaxAnisotropy est défini à zéro.On feature level 9_1, the following required values must be set: MinLOD is set to zero, MaxLOD is set to D3D11_FLOAT32_MAX, and MaxAnisotropy is set to zero.

D3D11_SAMPLER_DESC comparisonSamplerDesc;
ZeroMemory(&comparisonSamplerDesc, sizeof(D3D11_SAMPLER_DESC));
comparisonSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_BORDER;
comparisonSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_BORDER;
comparisonSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_BORDER;
comparisonSamplerDesc.BorderColor[0] = 1.0f;
comparisonSamplerDesc.BorderColor[1] = 1.0f;
comparisonSamplerDesc.BorderColor[2] = 1.0f;
comparisonSamplerDesc.BorderColor[3] = 1.0f;
comparisonSamplerDesc.MinLOD = 0.f;
comparisonSamplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
comparisonSamplerDesc.MipLODBias = 0.f;
comparisonSamplerDesc.MaxAnisotropy = 0;
comparisonSamplerDesc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL;
comparisonSamplerDesc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT;

// Point filtered shadows can be faster, and may be a good choice when
// rendering on hardware with lower feature levels. This sample has a
// UI option to enable/disable filtering so you can see the difference
// in quality and speed.

DX::ThrowIfFailed(
    pD3DDevice->CreateSamplerState(
        &comparisonSamplerDesc,
        &m_comparisonSampler_point
        )
    );

Créer des états de renduCreate render states

Créez maintenant un état de rendu servant à activer l’élimination des faces avant.Now create a render state you can use to enable front face culling. Notez que les _ appareils de niveau de fonctionnalité 9 1 requièrent que DepthClipEnable soit défini sur true.Note that feature level 9_1 devices require DepthClipEnable set to true.

D3D11_RASTERIZER_DESC drawingRenderStateDesc;
ZeroMemory(&drawingRenderStateDesc, sizeof(D3D11_RASTERIZER_DESC));
drawingRenderStateDesc.CullMode = D3D11_CULL_BACK;
drawingRenderStateDesc.FillMode = D3D11_FILL_SOLID;
drawingRenderStateDesc.DepthClipEnable = true; // Feature level 9_1 requires DepthClipEnable == true
DX::ThrowIfFailed(
    pD3DDevice->CreateRasterizerState(
        &drawingRenderStateDesc,
        &m_drawingRenderState
        )
    );

Créez un état de rendu servant à activer l’élimination des faces arrière.Create a render state you can use to enable back face culling. Si votre code de rendu active déjà l’élimination des faces arrière, vous pouvez ignorer cette étape.If your rendering code already turns on back face culling, then you can skip this step.

D3D11_RASTERIZER_DESC shadowRenderStateDesc;
ZeroMemory(&shadowRenderStateDesc, sizeof(D3D11_RASTERIZER_DESC));
shadowRenderStateDesc.CullMode = D3D11_CULL_FRONT;
shadowRenderStateDesc.FillMode = D3D11_FILL_SOLID;
shadowRenderStateDesc.DepthClipEnable = true;

DX::ThrowIfFailed(
    pD3DDevice->CreateRasterizerState(
        &shadowRenderStateDesc,
        &m_shadowRenderState
        )
    );

Créer des tampons constantsCreate constant buffers

N’oubliez pas de créer un tampon constant pour le rendu du point de vue de la lumière.Don't forget to create a constant buffer for rendering from the light's point of view. Vous pouvez aussi l’utiliser pour spécifier au nuanceur la position de la lumière.You can also use this constant buffer to specify the light position to the shader. Utilisez une matrice de perspective pour les lumières à points et une matrice orthogonale pour les lumières directionnelles (comme les rayons du soleil).Use a perspective matrix for point lights, and use an orthogonal matrix for directional lights (such as sunlight).

DX::ThrowIfFailed(
    m_deviceResources->GetD3DDevice()->CreateBuffer(
        &viewProjectionConstantBufferDesc,
        nullptr,
        &m_lightViewProjectionBuffer
        )
    );

Renseignez les données de tampon constant.Fill the constant buffer data. Mettez à jour les tampons constants une fois pendant l’initialisation, puis à nouveau si les valeurs de lumière ont changé depuis la trame précédente.Update the constant buffers once during initialization, and again if the light values have changed since the previous frame.

{
    XMMATRIX lightPerspectiveMatrix = XMMatrixPerspectiveFovRH(
        XM_PIDIV2,
        1.0f,
        12.f,
        50.f
        );

    XMStoreFloat4x4(
        &m_lightViewProjectionBufferData.projection,
        XMMatrixTranspose(lightPerspectiveMatrix)
        );

    // Point light at (20, 15, 20), pointed at the origin. POV up-vector is along the y-axis.
    static const XMVECTORF32 eye = { 20.0f, 15.0f, 20.0f, 0.0f };
    static const XMVECTORF32 at = { 0.0f, 0.0f, 0.0f, 0.0f };
    static const XMVECTORF32 up = { 0.0f, 1.0f, 0.0f, 0.0f };

    XMStoreFloat4x4(
        &m_lightViewProjectionBufferData.view,
        XMMatrixTranspose(XMMatrixLookAtRH(eye, at, up))
        );

    // Store the light position to help calculate the shadow offset.
    XMStoreFloat4(&m_lightViewProjectionBufferData.pos, eye);
}
context->UpdateSubresource(
    m_lightViewProjectionBuffer.Get(),
    0,
    NULL,
    &m_lightViewProjectionBufferData,
    0,
    0
    );

Créer une fenêtre d’affichageCreate a viewport

Vous avez besoin d’une fenêtre d’affichage distincte pour restituer un plan d’ombres.You need a separate viewport to render to the shadow map. La fenêtre d’affichage n’est pas une ressource basée sur un périphérique, vous êtes donc libre de la créer ailleurs dans votre code.The viewport isn't a device-based resource; you're free to create it elsewhere in your code. La création de la fenêtre d’affichage avec le plan d’ombres peut faciliter la mise en relation de leurs dimensions respectives.Creating the viewport along with the shadow map can help make it more convenient to keep the dimension of the viewport congruent with the shadow map dimension.

// Init viewport for shadow rendering
ZeroMemory(&m_shadowViewport, sizeof(D3D11_VIEWPORT));
m_shadowViewport.Height = m_shadowMapDimension;
m_shadowViewport.Width = m_shadowMapDimension;
m_shadowViewport.MinDepth = 0.f;
m_shadowViewport.MaxDepth = 1.f;

Dans la suite de cette procédure pas à pas, vous allez découvrir comment créer le plan d’ombres en effectuant le rendu dans le tampon de profondeur.In the next part of this walkthrough, learn how to create the shadow map by rendering to the depth buffer.