DirectX11アルファテストはどこへ? discard/clip命令とAlphaToCoverage

DirectX10以降、レンダリングステートからアルファテストがなくなり、シェーダーで同等(またはそれ以上)の処理が行えるようになっています。OpenGL3.0以降でもシェーダーで対応するようです。
シェーダーでアルファテストを行う方法、処理結果をまとめてみました。また、アルファテストを適用させた場所にも、アンチエリアス処理を行えるAlphaToCoverageという機能についても調べてみました。

AlphaToCoverageという機能は知っていたのですが、こんな便利な機能だとは知りませんでした……。

アルファテストとAlphaToCoverage


シェーダーでアルファテスト
シェーダーのdiscard命令を実行するとピクセル出力をしないようになるため、アルファテストと同等の処理を行えます。使用法が違いますが、平面クリップ用の関数clip(x)でも可能です。

AlphaToCoverage

ブレンドステート(ID3D11BlendState)作成時にD3D11_BLEND_DESC::AlphaToCoverageEnableをTRUEにすると有効になります。


ブレンドの半透明処理で透明にした場合

ポリゴンをテクスチャ(α値)の形で切り抜くことで木の葉や草などを少ないポリゴンで表現できるアルファテストは、ゲームの3DCGでは必須といえる機能だと思います。
まずは、アルファテストを使用せずにブレンド機能でα値が0の部分を透明にしてみます。

透明になりますが、デプス値を更新してしまうため後ろのポリゴンが表示されなくなります。

アルファテストで透明にした場合

α値が0のピクセルをdiscard命令で出力しないようにしてみます。

透明になり奥のポリゴンも描画されましたが、境目にアンチエリアスがかからず、テクスチャの解像度が低いためドットが目立っています。

アルファテスト&境界をブレンド処理した場合

境目が目立つためその部分をブレンド処理で滑らかにしてみます。

ブレンドした部分のデプス値が更新されてしまうため、奥のポリゴンが消えてしまいます。

AlphaToCoverageを有効にした場合

AlphaToCoverageを有効にするとα値が1未満の場合、その値に応じてマルチサンプルの出力を抑制します。例えばMSAAx8でα=50%の場合、ピクセル出力で8ピクセルの半分の4ピクセルのみ出力、結果α=50%でのブレンド処理と近い画像になります。AlphaToCoverageはピクセル単位での書き込み制御のため、ポリゴンの描画順番に依存しないアンチエリアス処理が実現できます。また、AlphaToCoverageはα=0のピクセルは出力しないため、シェーダーでのアルファテスト(discard命令)は不要になります。

アンチエリアス処理がかかったアルファテスト(テクスチャでの切り取り)を実現できました。描画順番に依存しないことを確認するため、手前の白いポリゴンを1番最初に描画していますが問題ないようです。

AlphaToCoverageの品質

AlphaToCoverageはピクセル単位での出力有無で半透明効果を実現しているため、マルチサンプル数が少ないとアンチエリアスの品質が低下します。MSAA無効でもAlphaToCoverageは使用可能ですが、昔の色数が少ないPCの画像のようになります。

MSAAx8だとブレンド処理とほぼ同じ結果になるようです。MSAAx4でも問題なさそうです。


AlphaToCoverageで半透明処理

AlphaToCoverageは描画順番に依存しないアンチエリアス処理なので、描画順番に依存しない半透明処理が実現できるかもしれないと思い実験してみました。ポリゴンのα値を50%にして描画しています。

世の中、そんなに甘くないようです。α値が同じポリゴンはマルチサンプルの同じ場所にピクセルを出力するため、このような結果になってしまいました。


サンプルプログラム

AlphaToCoverageを使ってアルファテストとアンチエリアス処理を行うプログラムです。
DirectX11 AlphaTest

制作環境

Windows10 64bit
Visual Studio Community 2017
WindowsSDK 10.0.15063.0
プラットフォーム x86

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

認証:数字を入力してください(必須) * Time limit is exhausted. Please reload CAPTCHA.