DirectX11でMSAA(Multi Sampling Antialias)を試してみました。
検索でよく見つかるのが、プライマリのバッファをMSAA使用する例はよくみかけるのですが、テクスチャレンダリングする場合においてMSAA有効でレンダリングするというサンプルを見つけることはできませんでした。
そんなに難しい話ではないのですが、サンプルプログラムが見つからなかったので今回作成してみました。
まずは結果です。テクスチャを描画先(レンダーターゲット)として三角形を描画しています。その結果をテクスチャとして取得して、四角形のポリゴンに貼り付けて表示しています。
結果を見てもよくわからないので、MSAA OFFの場合の結果を以下に表示します。
これでもよくわからないかもしれません。そこで両者を比較して拡大したものを示してみます。これならば違いがわかるでしょうか?MSAAが有効なものについては、ポリゴン境界がなめらかに見えるように色が補間された結果が見えています。
手順について
レンダーターゲットとしてテクスチャを使う方法についてはここでは説明しません。
ここではMSAAテクスチャを作成する方法と、それをテクスチャとして使う方法の2つを説明したいと思います。
MSAAテクスチャの生成
描画先となるテクスチャを作成する際に、MSAA用のパラメーターを設定します。
D3D11_TEXTURE2D_DESC 構造体の SampleDesc内のパラメータが該当するのですが、ここにパラメータを指定します。
これらのパラメータの設定がよくわかりませんでしたが、下記に示すように CheckMultisampleQualityLevels から取得できる Quality値を指定しておけばよいようです。
UINT SampleCount = 4; UINT Quality = 0; pd3dDevice->CheckMultisampleQualityLevels( DXGI_FORMAT_R8G8B8A8_UNORM, SampleCount, &Quality ); Quality -= 1; ID3D11Texture2D* pRenderTexture = NULL; D3D11_TEXTURE2D_DESC descTex; ZeroMemory( &descTex, sizeof(descTex) ); descTex.ArraySize = 1; descTex.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; descTex.Format = DXGI_FORMAT_R8G8B8A8_UNORM; descTex.Width = 256; descTex.Height= 256; descTex.Usage = D3D11_USAGE_DEFAULT; descTex.SampleDesc.Count = SampleCount; descTex.SampleDesc.Quality = Quality; descTex.MipLevels = 1; hr = pd3dDevice->CreateTexture2D( &descTex, NULL, &pRenderTexture );
この例だとおそらく 4x の MSAA が有効となるようです。
MSAAテクスチャとして使う
上記の pRenderTargetにたいして描画行われた後でテクスチャとして使用するためにはResolve処理を行わなくてはなりません。またこのときに、Resolve結果格納先として別のテクスチャが必要になります。
普通はこのResolveされたのテクスチャを他の描画で使用します(正確にはこのテクスチャのShaderResourceViewを、ですが)。
まずはそのResolveテクスチャの作成についてはこんな感じになります。
ID3D11Texture2D* pResolveTexture = NULL; D3D11_TEXTURE2D_DESC descTex; ZeroMemory( &descTex, sizeof(descTex) ); descTex.ArraySize = 1; descTex.BindFlags = D3D11_BIND_SHADER_RESOURCE; descTex.Format = DXGI_FORMAT_R8G8B8A8_UNORM; descTex.SampleDesc.Count = 1; descTex.SampleDesc.Quality = 0; descTex.Width = 256; descTex.Height= 256; descTex.Usage = D3D11_USAGE_DEFAULT; descTex.MipLevels = 1; ID3D11ShaderResourceView* pRenderTextureSRV = NULL; pd3dDevice->CreateTexture2D( &descTex, NULL, &pResolveTexture ); pd3dDevice->CreateShaderResourceView( pResolveTexture, NULL, &pRenderTextureSRV );
Resolve処理
簡単ですが、D3DDeviceContextについて以下のAPIを呼ぶだけです。
// Resolve pImmediateContext->ResolveSubresource( pResolveTexture, 0, pRenderTexture, 0, DXGI_FORMAT_R8G8B8A8_UNORM );
レンダーテクスチャを使う際の注意点といいますかお作法として、
レンダーテクスチャ(RenderTargetViewとして)セットする前に、そのテクスチャがShaderResourceViewとしてセットされていないか確認し、すでにセットされているならば解除しておくことが望ましいようです。
D3Dのデバッグレイヤー有効にするとわかるのですが、シェーダーリソースとして設定されているものをレンダーターゲットとして設定した際に、警告メッセージが表示されます。これはそのシェーダーリソースがシェーダーで使用されていなくても警告がでますので要注意です。
サンプルプログラム
今回のサンプルプログラム全体です。VisualStudio2012で作成しています。
SampleMSAA11サンプルプログラム(Zip)
まとめ
意外と使われないのか、テクスチャに対するMSAAをやってみました。