Yakiimo3D

Mostly DirectX 11 Programming

DX11 Order Independent Transparency with MSAA

はじめに

前回のDX11 OIT デモ(http://www.yakiimo3d.com/2010/07/19/dx11-order-independent-transparency/)を拡張して、MSAAに対応させました。

プログラムのソースとバイナリがDLできるCodePlexリンクは記事の最後の方に貼っています。

関連リンク集

1) http://www.yakiimo3d.com/2010/07/19/dx11-order-independent-transparency/
自分の元DX11 OITデモの記事です。 元デモはMSAA無しなので(オンにしたら本当なら表示がバグるだけのはずだけど、必要がないのにswapchainのbufferをDXGI_USAGE_UNORDERED_ACCESSフラグを立てて生成しているので、swapchain生成で落ちてしまいます)、色付Quadのedgeのジャギーが結構目立っています。

2) http://developer.amd.com/documentation/presentations/Pages/default.aspx
ATIのプレゼンリンク集ページから”GDC 2010: OIT and GI using DX11 linked lists”のプレゼン・パワポがDLできます。プレゼンでは、アルゴリズムのMSAAへの対応方法も記述されていたので、前回と同じく今回のデモもこのプレゼンを参考に実装しています。

デモ・スクリーンショット






上から順番にMSAA none、 MSAA 2x、 MSAA 4x、 MSAA 8xです。none、2x、4x、間では大きな改善が確認できますが、4xと8xの違いはあんまり分からないです 個人的には4x辺りからedgeのジャギーが気にならなくなります。サンプリング数を増やすと処理負荷が増え、fpsがどんどん落ちます。

実装の詳細

元デモからそんなに沢山の変更無しでMSAA対応を実装できました。主な変更点はSV_COVERAGEとSV_SAMPLEINDEX semantic parameterをpixel shaderの入力構造体へ追加して利用した事です。

StoreFragments.hlslへの変更点

struct ScenePS_Input
{
    float4 pos               : SV_POSITION;
    float4 color             : COLOR0;
    uint nCoverage        : SV_COVERAGE;                // Bit set according to which samples are covered.
};

SV_COVERAGE セマンティックのnCoverage parameterをpixel shaderの入力構造体に追加して、pixelのどのsampleがfragmentにcoverされているかの情報を取得しています。例えばnCoverageの1、4ビット目が立っていたら、samples 1 、4がcoverされていたことを意味します。MSAA対応の為に、fragmentの色と深度以外にもsample coverage情報をStructuredBufferの構造体に書き出すように変更しました。

SortFragmentsAndRender.hlslへの変更点

struct QuadPS_Input
{
    float4 pos          : SV_POSITION;
    uint nSampleIndex       : SV_SAMPLEINDEX;        // specify to run pixel shader per sample instead of per pixel  
};
...
// Read and store linked list data to the temporary buffer.
while( nNext != 0xFFFFFFFF )
{
    FragmentLink element = FragmentLinkSRV[nNext];
    aData[ nNumFragment ] = element.fragmentData;

    // Use sample only if the fragment covered it.
    if( aData[ nNumFragment ].nDepthAndCoverage & (1<<input.nSampleIndex) )
    {
        anIndex[ nNumFragment ] = nNumFragment;
        ++nNumFragment;
    }          
    nNext = element.nNext;
}

SV_SAMPLEINDEXはDX10.1で追加されたセマンティックで、DX11でも利用できます。 SV_SAMPLEINDEXセマンティックを持つparameterをpixel shaderの入力構造体に追加することで、pixel shaderをpixel毎ではなくsample毎に走らせる事が可能です。ソートとブレンドのSortFragmentsAndRender.hlslをsample毎に実行し、fragmentによってカバーされていないsampleを破棄する事で、StructuredBufferが入力データにもかかわらず、framebufferへの書き出し時のMSAA anti-aliasingが正しく処理されています。

OIT with MSAA Demo

Source Code & Binary
http://yakiimo3d.codeplex.com/releases/view/49570
デモは4x MSAAの設定から開始します。Change DeviceメニュのMultisample Count項目からMSAAの設定を変更できます。

雑多なコメント

SV_SAMPLEINDEX pixel shader semanticを利用して、pixel単位ではなくsample単位で初めてpixel shaderをまわしました。10.1からできる処理ですが、DX9では出来なかった事ができた、新しいAPIを触っている感を少し感じれました。SV_SAMPLEINDEXはDeferred RenderingのMSAA対応などでも利用するらしいです。今回のblog記事を執筆の休憩中にXBOX Live ArcadeのLimboを少し遊んでみたけど、中々良いゲームみたいです。寓話的でダークな雰囲気や、光、暗闇、霧を使ったグラフィックスの演出が綺麗で、作品として個人的に魅力を感じます。買ってよかったぞ感を感じています。

. This entry was posted on Sunday, July 25th, 2010 at 10:19 PM and is filed under Demo, DirectX11. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Leave a Reply



XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

It may take some time for your comment to appear, it is not necessary to submit it again.