Partager via


Multisampling dans les applications plateforme Windows universelle (UWP)

Découvrez comment utiliser l’échantillonnage multiple dans les applications plateforme Windows universelle (UWP) créées avec Direct3D. L’échantillonnage multiple, également appelé anticrénelage multi-échantillon, est une technique graphique utilisée pour réduire l’apparence des bords alias. Il fonctionne en dessinant plus de pixels que dans la cible de rendu finale, puis en moyenne les valeurs pour maintenir l’apparence d’un bord « partiel » en certains pixels. Pour obtenir une description détaillée du fonctionnement réel de l’échantillonnage multiple dans Direct3D, consultez Règles de rastérisation anti-aliasing multisample.

Multisampling et la chaîne d’échange de modèle de retournement

Les applications UWP qui utilisent DirectX doivent utiliser des chaînes d’échange de modèle inversées. Les chaînes d’échange de modèle inversé ne prennent pas en charge directement l’échantillonnage multiple, mais l’échantillonnage multiple peut toujours être appliqué de manière différente en rendant la scène à une vue cible de rendu multisamplée, puis en résolvant la cible de rendu multisamplée dans la mémoire tampon arrière avant de présenter. Cet article explique les étapes requises pour ajouter un multisampling à votre application UWP.

Guide pratique pour utiliser l’échantillonnage multiple

Les niveaux de fonctionnalités Direct3D garantissent la prise en charge des fonctionnalités de nombre d’échantillons spécifiques et minimales et garantissent que certains formats de mémoire tampon seront disponibles pour prendre en charge l’échantillonnage multiple. Les appareils graphiques prennent souvent en charge un plus large éventail de formats et de nombres d’échantillons que le minimum requis. La prise en charge multi-échantillonnage peut être déterminée au moment de l’exécution en vérifiant la prise en charge des fonctionnalités pour l’échantillonnage multiple avec des formats DXGI spécifiques, puis en vérifiant le nombre d’exemples que vous pouvez utiliser avec chaque format pris en charge.

  1. Appelez ID3D11Device ::CheckFeatureSupport pour savoir quels formats DXGI peuvent être utilisés avec l’échantillonnage multiple. Fournissez les formats cibles de rendu que votre jeu peut utiliser. La cible de rendu et la cible de résolution doivent utiliser le même format. Vérifiez les deux D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET et D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE.

    **Niveau de fonctionnalité 9 : ** Bien que les appareils de niveau 9 de fonctionnalité garantissent la prise en charge des formats cibles de rendu multisamplés, la prise en charge n’est pas garantie pour les cibles de résolution multisample. Cette vérification est donc nécessaire avant d’essayer d’utiliser la technique multisampling décrite dans cette rubrique.

    Le code suivant vérifie la prise en charge de l’échantillonnage multiple pour toutes les valeurs DXGI_FORMAT :

    // Determine the format support for multisampling.
    for (UINT i = 1; i < DXGI_FORMAT_MAX; i++)
    {
        DXGI_FORMAT inFormat = safe_cast<DXGI_FORMAT>(i);
        UINT formatSupport = 0;
        HRESULT hr = m_d3dDevice->CheckFormatSupport(inFormat, &formatSupport);
    
        if ((formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE) &&
            (formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET)
            )
        {
            m_supportInfo->SetFormatSupport(i, true);
        }
        else
        {
            m_supportInfo->SetFormatSupport(i, false);
        }
    }
    
  2. Pour chaque format pris en charge, interrogez la prise en charge du nombre d’exemples en appelant ID3D11Device ::CheckMultisampleQualityLevels.

    Le code suivant vérifie la prise en charge des exemples de taille pour les formats DXGI pris en charge :

    // Find available sample sizes for each supported format.
    for (unsigned int i = 0; i < DXGI_FORMAT_MAX; i++)
    {
        for (unsigned int j = 1; j < MAX_SAMPLES_CHECK; j++)
        {
            UINT numQualityFlags;
    
            HRESULT test = m_d3dDevice->CheckMultisampleQualityLevels(
                (DXGI_FORMAT) i,
                j,
                &numQualityFlags
                );
    
            if (SUCCEEDED(test) && (numQualityFlags > 0))
            {
                m_supportInfo->SetSampleSize(i, j, 1);
                m_supportInfo->SetQualityFlagsAt(i, j, numQualityFlags);
            }
        }
    }
    

    Remarque : Utilisez ID3D11Device2 ::CheckMultisampleQualityLevels1 à la place si vous devez vérifier la prise en charge multisample des mémoires tampons de ressources en mosaïques.

     

  3. Créez une mémoire tampon et affichez la vue cible avec le nombre d’exemples souhaité. Utilisez les mêmes DXGI_FORMAT, largeur et hauteur que la chaîne d’échange, mais spécifiez un nombre d’échantillons supérieur à 1 et utilisez une dimension de texture multisamplée (D3D11_RTV_DIMENSION_TEXTURE2DMS par exemple). Si nécessaire, vous pouvez recréer la chaîne d’échange avec de nouveaux paramètres optimaux pour l’échantillonnage multiple.

    Le code suivant crée une cible de rendu multisamplée :

    float widthMulti = m_d3dRenderTargetSize.Width;
    float heightMulti = m_d3dRenderTargetSize.Height;
    
    D3D11_TEXTURE2D_DESC offScreenSurfaceDesc;
    ZeroMemory(&offScreenSurfaceDesc, sizeof(D3D11_TEXTURE2D_DESC));
    
    offScreenSurfaceDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    offScreenSurfaceDesc.Width = static_cast<UINT>(widthMulti);
    offScreenSurfaceDesc.Height = static_cast<UINT>(heightMulti);
    offScreenSurfaceDesc.BindFlags = D3D11_BIND_RENDER_TARGET;
    offScreenSurfaceDesc.MipLevels = 1;
    offScreenSurfaceDesc.ArraySize = 1;
    offScreenSurfaceDesc.SampleDesc.Count = m_sampleSize;
    offScreenSurfaceDesc.SampleDesc.Quality = m_qualityFlags;
    
    // Create a surface that's multisampled.
    DX::ThrowIfFailed(
        m_d3dDevice->CreateTexture2D(
        &offScreenSurfaceDesc,
        nullptr,
        &m_offScreenSurface)
        );
    
    // Create a render target view. 
    CD3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc(D3D11_RTV_DIMENSION_TEXTURE2DMS);
    DX::ThrowIfFailed(
        m_d3dDevice->CreateRenderTargetView(
        m_offScreenSurface.Get(),
        &renderTargetViewDesc,
        &m_d3dRenderTargetView
        )
        );
    
  4. La mémoire tampon de profondeur doit avoir la même largeur, hauteur, nombre d’échantillons et dimension de texture pour correspondre à la cible de rendu multisamplée.

    Le code suivant crée une mémoire tampon de profondeur multisamplée :

    // Create a depth stencil view for use with 3D rendering if needed.
    CD3D11_TEXTURE2D_DESC depthStencilDesc(
        DXGI_FORMAT_D24_UNORM_S8_UINT,
        static_cast<UINT>(widthMulti),
        static_cast<UINT>(heightMulti),
        1, // This depth stencil view has only one texture.
        1, // Use a single mipmap level.
        D3D11_BIND_DEPTH_STENCIL,
        D3D11_USAGE_DEFAULT,
        0,
        m_sampleSize,
        m_qualityFlags
        );
    
    ComPtr<ID3D11Texture2D> depthStencil;
    DX::ThrowIfFailed(
        m_d3dDevice->CreateTexture2D(
        &depthStencilDesc,
        nullptr,
        &depthStencil
        )
        );
    
    CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2DMS);
    DX::ThrowIfFailed(
        m_d3dDevice->CreateDepthStencilView(
        depthStencil.Get(),
        &depthStencilViewDesc,
        &m_d3dDepthStencilView
        )
        );
    
  5. Il est maintenant judicieux de créer la fenêtre d’affichage, car la largeur et la hauteur de la fenêtre d’affichage doivent également correspondre à la cible de rendu.

    Le code suivant crée une fenêtre d’affichage :

    // Set the 3D rendering viewport to target the entire window.
    m_screenViewport = CD3D11_VIEWPORT(
        0.0f,
        0.0f,
        widthMulti / m_scalingFactor,
        heightMulti / m_scalingFactor
        );
    
    m_d3dContext->RSSetViewports(1, &m_screenViewport);
    
  6. Affichez chaque image sur la cible de rendu multisamplée. Une fois le rendu terminé, appelez ID3D11DeviceContext ::ResolveSubresource avant de présenter le frame. Cela indique à Direct3D de mettre en forme l’opération multisampling, en calculant la valeur de chaque pixel pour l’affichage et en plaçant le résultat dans la mémoire tampon arrière. La mémoire tampon arrière contient ensuite l’image anti-alias finale et peut être présentée.

    Le code suivant résout la sous-ressource avant de présenter le frame :

    if (m_sampleSize > 1)
    {
        unsigned int sub = D3D11CalcSubresource(0, 0, 1);
    
        m_d3dContext->ResolveSubresource(
            m_backBuffer.Get(),
            sub,
            m_offScreenSurface.Get(),
            sub,
            DXGI_FORMAT_B8G8R8A8_UNORM
            );
    }
    
    // The first argument instructs DXGI to block until VSync, putting the application
    // to sleep until the next VSync. This ensures that we don't waste any cycles rendering
    // frames that will never be displayed to the screen.
    hr = m_swapChain->Present(1, 0);