Compartir a través de


Muestreo múltiple en aplicaciones para la Plataforma Universal de Windows (UWP)

Aprende a usar el muestreo múltiple en aplicaciones para la Plataforma universal de Windows (UWP) creadas con Direct3D. El muestreo múltiple, también conocido como suavizado multimuestreo, es una técnica gráfica que se usa para reducir la apariencia de los bordes con alias. Funciona dibujando más píxeles de los que realmente están en el destino de representación final y, a continuación, promediando los valores para mantener la apariencia de un borde "parcial" en determinados píxeles. Para obtener una descripción detallada de cómo funciona realmente el muestreo múltiple en Direct3D, consulte Reglas de rasterización de antialiasing mediante multimuestra.

Muestreo múltiple y la cadena de intercambio del modelo flip

Las aplicaciones para UWP que usan DirectX deben usar cadenas de intercambio de modelos invertida. Las cadenas de intercambio de flip model no admiten el multimuestreo directamente, pero el multimuestreo todavía se puede aplicar de otra manera mediante la representación de la escena en una vista de destino de renderizado multimuestreo y, a continuación, resolver el destino de renderizado multimuestreo al búfer posterior antes de presentarlo. En este artículo se explican los pasos necesarios para agregar el muestreo múltiple a la aplicación para UWP.

Cómo usar el muestreo múltiple

Los niveles de características de Direct3D garantizan la compatibilidad con funcionalidades específicas de recuento de muestras mínimas y garantizan que determinados formatos de búfer estarán disponibles que admiten el muestreo múltiple. Los dispositivos gráficos suelen admitir una gama más amplia de formatos y recuentos de muestras que el mínimo necesario. La compatibilidad con el muestreo múltiple se puede determinar en tiempo de ejecución comprobando la compatibilidad de características para el muestreo múltiple con formatos DXGI específicos y, a continuación, comprobando los recuentos de ejemplo que puede usar con cada formato admitido.

  1. Llame a ID3D11Device::CheckFeatureSupport para averiguar qué formatos DXGI se pueden usar con el muestreo múltiple. Proporcione los formatos de destino de representación que puede usar el juego. Tanto el destino de representación como el destino de resolución deben usar el mismo formato, por lo que asegúrese de comprobar tanto D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET como D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE.

    **Nivel de característica 9: ** Aunque los dispositivos de nivel de característica 9 garantizan la compatibilidad con formatos de destino de representación multimuestreo, no se garantiza la compatibilidad con los destinos de resolución de multimuestreo. Por lo tanto, esta comprobación es necesaria antes de intentar usar la técnica de muestreo múltiple descrita en este tema.

    El código siguiente comprueba la compatibilidad con el muestreo múltiple para todos los valores de 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. Para cada formato admitido, consulte la compatibilidad con el recuento de muestras llamando a ID3D11Device::CheckMultisampleQualityLevels.

    El código siguiente comprueba la compatibilidad con el tamaño de ejemplo para los formatos DXGI admitidos:

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

    Nota Use ID3D11Device2::CheckMultisampleQualityLevels1 en su lugar si necesita comprobar la compatibilidad con multisample para los búferes de recursos en mosaico.

     

  3. Cree un búfer y renderice la vista de destino con el recuento de muestras deseado. Utilice el mismo DXGI_FORMAT, ancho y alto que la cadena de intercambio, pero especifique un recuento de muestras mayor que 1 y use una dimensión de textura de multimuestreo (D3D11_RTV_DIMENSION_TEXTURE2DMS por ejemplo). Si es necesario, puede volver a crear la cadena de intercambio con nuevas configuraciones que sean óptimas para el muestreo múltiple.

    El código siguiente crea un destino de representación multimuestreo:

    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. El búfer de profundidad debe tener el mismo ancho, alto, recuento de muestras y dimensión de textura para coincidir con el objetivo de renderizado de múltiples muestras.

    El código siguiente crea un búfer de profundidad de muestreo múltiple:

    // 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. Ahora es un buen momento para crear la ventanilla, ya que el ancho y el alto de la ventanilla también deben coincidir con el destino de representación.

    El código siguiente crea una ventanilla:

    // 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. Renderizar cada fotograma en el objetivo de renderizado multimuestreado. Cuando se complete el renderizado, llame a ID3D11DeviceContext::ResolveSubresource antes de presentar el cuadro. Esto indica a Direct3D que realice la operación de muestreo múltiple, calculando el valor de cada píxel para mostrar y colocando el resultado en el búfer de reserva. Luego, el búfer trasero contiene la imagen final con antialiasing y se puede presentar.

    El código siguiente resuelve el subrecurso antes de presentar el marco:

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