渋谷ほととぎす通信

「Unityをわかりやすく」初心者のためのゲーム作りブログ

Unityのアルファテストがレガシーなものになっていた件

Unityのアルファテストがレガシーなものになっていた件

こんにちは、Unityエンジニアのオオバです。

アルファテストとは、ピクセルのアルファ値で判定して描画可否を決めるコマンドで描画される直前で行われます。

AlphaTest "比較文字列" "比較するアルファ値"  

という構文で比較文字列は以下の8種類あります。

  • Greater : ピクセルのアルファ値が AlphaValue より大きい場合のみレンダリング。
  • GEqual : ピクセルのアルファ値が AlphaValue より大きいか等しい場合のみレンダリング。
  • Less : ピクセルのアルファ値が AlphaValue より小さい場合のみレンダリング。
  • LEqual : ピクセルのアルファ値が AlphaValue より小さいか等しい場合のみレンダリング。
  • Equal : ピクセルのアルファ値が AlphaValue と等しい場合のみレンダリング。
  • NotEqual : ピクセルのアルファ値が AlphaValue と等しくない場合のみレンダリング。
  • Always : すべてのピクセルをレンダリング。AlphaTest Off と同等の機能
  • Never : すべてのピクセルをレンダリングしない。

公式より参照

AlphaTest LEqual 0  

とすれば、アルファ値が0以下のピクセルは破棄され描画されないようになります。

しかし公式リファレンスを確認すると現在、アルファテストはレガシーなものとして扱われています。

この構文はサーフェースシェーダーでのみ動作します。
※フラグメントシェーダーで書いても何も起きません

現在はHLSLの組み込み関数clipをフラグメントシェーダーで書いてアルファテスト同様の処理をさせる方が理にかなっているとのことです。

ちなみにclipを使うとこうなります。

fixed4 frag (v2f_img i) : SV_Target  
{
    fixed4 c = tex2D(_MainTex, i.uv);  
    clip(c.a - 0.0001);  
    return c;  
}

これはとあるフラグメントシェーダーですが、ピクセルのカラーに対して clip(c.a - 0.0001); という処理を加えることで実質的なアルファテストを行います。

clip関数は以下のように説明されています。

指定された値が 0 より小さい場合に、現在のピクセルを破棄します。

HLSL clipより

注意点としてclip関数は0以下ではなく、0より小さい値(マイナス値)にしなければ破棄されません。


アルファテストのクオリティを見ていきます。

Unityのアルファテストがレガシーなものになっていた件_0

例えばこの256☓256pxの画像を、先のフラグメントシェーダーの処理でアルファテストしてみます。

Unityのアルファテストがレガシーなものになっていた件_1

この六角形の各辺のアンチエイリアス処理がかかった半透明部分をアルファテストしているところでがジャギが生まれていおり、画像の解像度に対して表示する解像度が大きいとこのジャギは目立っていきます。

Unityのアルファテストがレガシーなものになっていた件_2

ちなみに、画像の解像度を2048☓2048pxと大きくしてみると、当然綺麗にはなりますが、出来る限り解像度を上げたくはありません。

そこで、解像度は256pxのままで破棄する範囲を広げてみます。ソースを以下ように修正します。

clip(c.a - 0.1);  

Unityのアルファテストがレガシーなものになっていた件_3

するとこのように綺麗なラインを出すことが可能です。
ただ破棄する範囲を広げているため、一回り六角形は小さくはなっていることに注意です。

まとめ

アルファテストではなくアルファブレンドを使えば良いのでは?という話も出てくると思いますが、アルファテストでなければ成立しないケースもあるため頭の片隅に置いておこうと思います。

そしてAlphaTestではなくclipを使いましょう。
もちろんサーフェースシェーダーではAlphaTestは現役プレーヤーとして使用できます。

オススメ記事
参考サイト