Поделиться через


Многосамплинг в приложениях универсальная платформа Windows (UWP)

Узнайте, как использовать многосамплинг в приложениях универсальная платформа Windows (UWP), созданных с помощью Direct3D. Мультисамплинг, также известный как многофакторная защита, — это графический метод, используемый для уменьшения внешнего вида псевдонимированных ребер. Он работает путем рисования большего количества пикселей, чем фактически в конечном целевом объекте отрисовки, а затем усреднения значений для поддержания внешнего вида "частичного" края в определенных пикселях. Подробное описание того, как мультисамплинг фактически работает в Direct3D, см. в разделе "Правила многофакторной защиты от псевдонима".

Многосамплинг и цепочка буферов модели переверки

Приложения UWP, использующие DirectX, должны использовать цепочки буферов модели переверки. Переключение цепочек буферов модели не поддерживает многосамплинирование напрямую, но многосамплинг по-прежнему можно применить другим способом, отрисовав сцену в многофакторное представление целевого представления отрисовки, а затем разрешив многофакторную целевую отрисовку в буфер обратно перед представлением. В этой статье описываются действия, необходимые для добавления многосамплинга в приложение UWP.

Использование многосамплинга

Уровни функций Direct3D гарантируют поддержку конкретных, минимальных возможностей подсчета выборок и гарантируют, что некоторые форматы буферов будут доступны, поддерживающие многофакторную настройку. Графические устройства часто поддерживают более широкий диапазон форматов и выборок, чем минимальный обязательный. Поддержка многофакторной поддержки можно определить во время выполнения, проверив поддержку функций для нескольких форматов DXGI, а затем проверив количество примеров, которые можно использовать с каждым поддерживаемым форматом.

  1. Вызов ID3D11Device::CheckFeatureSupport , чтобы узнать, какие форматы DXGI можно использовать с многосамплингом. Укажите целевые форматы отрисовки, которые может использовать ваша игра. Целевой объект отрисовки и целевой объект разрешения должны использовать один и тот же формат, поэтому проверьте наличие D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET и D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE.

    **Уровень компонентов 9. ** Хотя устройства уровня компонентов 9 гарантируют поддержку многофакторных форматов целевых форматов отрисовки, поддержка не гарантируется для целевых объектов для многосамплексного разрешения. Поэтому эта проверка необходима, прежде чем пытаться использовать многофакторную методику, описанную в этом разделе.

    В следующем коде проверяется поддержка многосамплинга для всех значений 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. Для каждого поддерживаемого формата запрос на поддержку количества примеров путем вызова ID3D11Device::CheckMultisampleQualityLevels.

    Следующий код проверяет поддержку размера примера для поддерживаемых форматов DXGI:

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

    Примечание. Используйте ID3D11Device2::CheckMultisampleQualityLevels1, если необходимо проверить поддержку многофакторных буферов ресурсов.

     

  3. Создайте буфер и представление целевого объекта отрисовки с требуемым числом выборок. Используйте ту же DXGI_FORMAT, ширину и высоту, что и цепочка буферов, но укажите выборку, превышающую 1, и используйте многофакторное измерение текстуры (например, D3D11_RTV_DIMENSION_TEXTURE2DMS ). При необходимости можно повторно создать цепочку буферов с новыми параметрами, оптимальными для мультисамплинга.

    Следующий код создает многофакторную целевую отрисовку:

    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. Буфер глубины должен иметь ту же ширину, высоту, количество выборок и измерение текстуры, чтобы соответствовать целевому объекту многофакторной отрисовки.

    Следующий код создает многофакторный буфер глубины:

    // 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. Теперь рекомендуется создать окно просмотра, так как ширина окна просмотра и высота должны соответствовать целевому объекту отрисовки.

    Следующий код создает окно просмотра:

    // 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. Отрисовка каждого кадра в многофакторную целевую отрисовку. После завершения отрисовки вызовите id3D11DeviceContext::ResolveSubresource перед представлением кадра. Это указывает Direct3D провести многофакторную операцию, вычислив значение каждого пикселя для отображения и размещения результата в обратном буфере. Затем буфер задней части содержит окончательный анти псевдоним изображения и может быть представлен.

    Следующий код разрешает подресурс перед представлением кадра:

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