マルチ サンプリングでは、ユニバーサル Windows プラットフォーム (UWP) アプリ Multisampling in Universal Windows Platform (UWP) apps

Direct3D を使って構築されたユニバーサル Windows プラットフォーム (UWP) アプリでマルチサンプリングを使う方法について説明します。Learn how to use multisampling in Universal Windows Platform (UWP) apps built with Direct3D. マルチサンプリングとは、マルチサンプル アンチエイリアシングとも呼ばれ、エッジを滑らかに描画するために使用されるグラフィックス技法です。Multisampling, also known as multi-sample antialiasing, is a graphics technique used to reduce the appearance of aliased edges. 最終的なレンダー ターゲットの実際のピクセルよりも多くのピクセルを描画し、その値を平均して、特定のピクセルで "部分的" エッジの外観を維持するというしくみです。It works by drawing more pixels than are actually in the final render target, then averaging values to maintain the appearance of a "partial" edge in certain pixels. Direct3D で実際にマルチサンプリングがどのように働くかについて詳しくは、「マルチサンプル アンチエイリアシング ラスタライズ規則」をご覧ください。For a detailed description of how multisampling actually works in Direct3D, see Multisample Anti-Aliasing Rasterization Rules.

マルチサンプリングとフリップ モデル スワップ チェーンMultisampling and the flip model swap chain

DirectX を使う UWP アプリでは、フリップ モデル スワップ チェーンを使う必要があります。UWP apps that use DirectX must use flip model swap chains. フリップ モデル スワップ チェーンは、マルチサンプリングを直接サポートするわけではなく、方法は異なりますが、マルチサンプリングされたレンダー ターゲット ビューにシーンをレンダリングした後、マルチサンプリングされたレンダー ターゲットをバック バッファーに解決して表示することで、マルチサンプリングを適用することができます。Flip model swap chains don't support multisampling directly, but multisampling can still be applied in a different way by rendering the scene to a multisampled render target view, and then resolving the multisampled render target to the back buffer before presenting. この記事では、UWP アプリにマルチサンプリングを追加するための手順を説明します。This article explains the steps required to add multisampling to your UWP app.

マルチサンプリングを使う方法How to use multisampling

Direct3D 機能レベルは、特定の最小サンプル数機能のサポートを保証し、マルチサンプリングをサポートする特定のバッファー形式が使用できることを保証します。Direct3D feature levels guarantee support for specific, minimum sample count capabilities, and guarantee certain buffer formats will be available that support multisampling. グラフィックス デバイスは、多くの場合、最小限必要なものよりも広い範囲の形式とサンプル数をサポートしています。Graphics devices often support a wider range of formats and sample counts than the minimum required. マルチサンプリング サポートは、特定の DXGI 形式を使うマルチサンプリング機能がサポートされているか確認し、サポートされている形式ごとに使うことのできるサンプル数を確認することで、実行時に判断できます。Multisampling support can be determined at run-time by checking feature support for multisampling with specific DXGI formats, and then checking the sample counts you can use with each supported format.

  1. ID3D11Device::CheckFeatureSupport を呼び出して、どの DXGI 形式をマルチサンプリングで使うことができるか確認します。Call ID3D11Device::CheckFeatureSupport to find out which DXGI formats can be used with multisampling. ゲームで使うことのできるレンダー ターゲット形式を指定します。Supply the render target formats your game can use. レンダー ターゲットおよび解決するターゲットの両方必要があります、同じ形式を使用して、両方のチェック D3D11_形式_サポート_マルチ サンプリング_レンダリング ターゲットD3D11_形式_サポート_マルチ サンプリング_解決します。Both the render target and resolve target must use the same format, so check for both D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET and D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE.

    **9 の機能レベル:  **機能レベルの 9 デバイスがのマルチ サンプリングされたレンダー ターゲット形式のサポートを保証、multisample 解決ターゲットにサポートが保証されていません。**Feature level 9:  ** Although feature level 9 devices guarantee support for multisampled render target formats, support is not guaranteed for multisample resolve targets. そこで、このトピックで説明するマルチサンプリング技法を使おうとする前に、この確認が必要になります。So this check is necessary before trying to use the multisampling technique described in this topic.

    次のコードはすべて、DXGI のマルチ サンプリング サポートを確認します。_形式の値。The following code checks multisampling support for all the DXGI_FORMAT values:

    // 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 を呼び出して、サンプル数のサポートを照会します。For each supported format, query for sample count support by calling ID3D11Device::CheckMultisampleQualityLevels.

    次のコードは、サポートされている DXGI 形式についてサンプル サイズのサポートを確認します。The following code checks sample size support for supported DXGI formats:

    // 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 代わりに並べて表示されたリソースのバッファーのマルチ サンプリング サポートを確認する必要がある場合。Note   Use ID3D11Device2::CheckMultisampleQualityLevels1 instead if you need to check multisample support for tiled resource buffers.

     

  3. 目的のサンプル数を使って、バッファーとレンダー ターゲット ビューを作成します。Create a buffer and render target view with the desired sample count. 使用して、同じ DXGI_形式、幅、および、スワップ チェーンと高さが 1 より大きいサンプル数を指定し、マルチ サンプリングされたテクスチャのディメンションを使用して (D3D11_RTV_ディメンション_TEXTURE2DMSなど)。Use the same DXGI_FORMAT, width, and height as the swap chain, but specify a sample count greater than 1 and use a multisampled texture dimension (D3D11_RTV_DIMENSION_TEXTURE2DMS for example). 必要な場合、マルチサンプリングに最適な新しい設定を使ってスワップ チェーンを再作成することもできます。If necessary, you can re-create the swap chain with new settings that are optimal for multisampling.

    次のコードでは、マルチサンプリングされたレンダー ターゲットが作成されます。The following code creates a multisampled render target:

    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. 深度バッファーは、マルチサンプリングされたレンダー ターゲットと一致する、同じ幅、高さ、サンプル数、テクスチャ ディメンションを待つ必要があります。The depth buffer must have the same width, height, sample count, and texture dimension to match the multisampled render target.

    次のコードでは、マルチサンプリングされた深度バッファーが作成されます。The following code creates a multisampled depth buffer:

    // 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. ここでビューボートを作成します。ビューポートの幅と高さもレンダー ターゲットと一致している必要があるためです。Now is a good time to create the viewport, because the viewport width and height must also match the render target.

    次のコードでは、ビューポートが作成されます。The following code creates a viewport:

    // 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. マルチサンプリングされたレンダー ターゲットに各フレームをレンダリングします。Render each frame to the multisampled render target. レンダリングが完了したら、フレームを表示する前に ID3D11DeviceContext::ResolveSubresource を呼び出します。When rendering is complete, call ID3D11DeviceContext::ResolveSubresource before presenting the frame. これにより Direct3D はマルチサンプリング操作を実行し、表示する各ピクセルの値を計算して、結果をバック バッファーに配置します。This instructs Direct3D to peform the multisampling operation, computing the value of each pixel for display and placing the result in the back buffer. バック バッファーには最終的なアンチエイリアシングされた画像が格納され、表示できるようになります。The back buffer then contains the final anti-aliased image and can be presented.

    次のコードは、フレームを表示する前に、サブリソースを解決します。The following code resolves the subresource before presenting the 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);