Direct3D で構築されたユニバーサル Windows プラットフォーム (UWP) アプリでマルチサンプリングを使用する方法について説明します。 マルチサンプリング (マルチサンプル アンチエイリアシングとも呼ばれます) は、エイリアス化されたエッジの外観を減らすために使用されるグラフィックス手法です。 最終的なレンダー ターゲットよりも多くのピクセルを描画し、値を平均して特定のピクセルで "部分" エッジの外観を維持することで機能します。 Direct3D でのマルチサンプリングの実際の動作の詳細については、「 マルチサンプルアンチエイリアシング ラスター化ルール」を参照してください。
マルチサンプリングとフリップ モデル スワップ チェーン
DirectX を使用する UWP アプリでは、フリップ モデル スワップ チェーンを使用する必要があります。 フリップ モデル スワップ チェーンでは、直接マルチサンプリングはサポートされていませんが、マルチサンプリングターゲット ビューにシーンをレンダリングし、表示する前にマルチサンプリングされたレンダー ターゲットをバック バッファーに解決することで、マルチサンプリングを別の方法で適用できます。 この記事では、UWP アプリにマルチサンプリングを追加するために必要な手順について説明します。
マルチサンプリングの使用方法
Direct3D 機能レベルでは、特定の最小サンプル数機能のサポートが保証され、マルチサンプリングをサポートする特定のバッファー形式が使用可能になることが保証されます。 グラフィックス デバイスでは、多くの場合、必要最小限の形式とサンプル数よりも広い範囲がサポートされます。 マルチサンプリングのサポートは、特定の DXGI 形式でのマルチサンプリングの機能サポートを確認し、サポートされている各形式で使用できるサンプル数を確認することで、実行時に決定できます。
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); } }
サポートされている形式ごとに、 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 を使用してください。
バッファーを作成し、目的のサンプル数でターゲット ビューをレンダリングします。 スワップ チェーンと同じ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 ) );
深度バッファーは、マルチサンプリングされたレンダー ターゲットと一致するように、同じ幅、高さ、サンプル数、およびテクスチャ ディメンションを持つ必要があります。
次のコードは、マルチサンプリングされた深度バッファーを作成します。
// 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 ) );
ビューポートの幅と高さもレンダー ターゲットと一致する必要があるため、ビューポートを作成することをお勧めします。
次のコードは、ビューポートを作成します。
// 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);
マルチサンプリングされたレンダー ターゲットに各フレームをレンダリングします。 レンダリングが完了したら、フレームを表示する前に 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);