意外と知られていない?MSAAの副産物「AlphaToCoverage」について
掲載日: 2025/03/19 更新日: 2025/04/22
皆さんはAlphaToCoverageという機能についてご存じでしょうか?
この記事のターゲット
・ゲーム内で草を描画したいけど、透明部分と不透明部分の間のエッジが気になる方
・MSAAは知ってるけどDeferredRenderingで使えないから使っていない方
目次
・概要
・仕組み
→MSAAの仕組み
メリットデメリット
→A2Cの仕組み
・各APIやエンジンでの有効化の手順
・注意点
概要
AlphaToCoverage(A2C)とはGPUに搭載されているMSAA(Multi Sample Anti-Ailiasing)の機能を
利用したテクスチャサンプル時のエッジ表現を改善するための機能です。
仕組み
→MSAAの仕組み
ポリゴンのラスタライズ時にピクセルの中の特定のポイントがどの程度覆われているか
(カバレッジ)をチェックして、その情報を見て最終的な画像に出力する(Resolveと呼ばれる)
機能です
ピクセル内のチェックするポイントの数はクオリティの設定によって変わってきます
(2x、4x、8x等)
→メリット
ポリゴンのエッジ部分が滑らかになる
→デメリット
データ量がサンプル数分増える
DeferredRenderingに不向き(ほぼ使えない)
→AlphaToCoverageの仕組み
AlphaToCoverageでは、ピクセルシェーダーから出力されたアルファ値に応じてカバレッジ数を変えて描画します。
実際に適用した画像を見てみましょう
ほとんど変わりませんね…
ではメリットは何でしょうか?
以下のGIFでメリットは分かります。
なんとアルファブレンドの場合とAlphaToCoverageの場合でこのような違いが現れました。
これがメリットです。
なぜこのようなことが起こるのでしょうか?
答えはAlphaToCoverageは不透明で描画できるため、描画順の影響を受けないからです。
少し不親切でしょうか
もう少し詳しく考えてみましょう
アルファブレンドの場合、深度値を書き込むと見た目が透明でも深度値でクリップされてしまい、空白の領域ができます。
ではアルファブレンドを使わずに透明な部分を破棄してみるとどうでしょう?
結果はこのように境界部分が際立ってしまいます。
改めてAlphaToCoverageを使った描画を見てみましょう
深度値を書き込めるので、ポリゴンの前後関係を気にすることなくかつ、きれいに草のようなエッジのある者の描画ができました
とてもきれいですね!
ただ、ちょっとぼやけてる気がしますね。。。
ここでこちらのサイトで紹介されているアプローチを見てみましょうhttps://bgolus.medium.com/anti-aliased-alpha-test-the-esoteric-alpha-to-coverage-8b177335ae4f
col.a = (col.a – _Cutoff) / max(fwidth(col.a), 0.0001) + 0.5;
fwidthの定義は以下になります。
abs(ddx(value)) + abs(ddy(value))
結果を見てみましょう。
左がAlphaToCoverageそのままの結果、右が上記の補正をかけた結果です。
いかがでしょうか?
とてもきれいでぼやけなくなったと思いませんか?
各APIやエンジンでの有効化の手順
VulkanやDirectXではパイプライン設定での初期化になります。
Vulkanでは
VkPipelineMultisampleStateCreateInfoという構造体で設定できるようです。
DirectX12では
D3D12_BLEND_DESCという構造体で設定できるようです。
Unityの場合は簡単で、シェーダーに
AlphaToMask On
の記述を入れるだけです。
Unrealではフォワードシェーディングがモバイル向けなのかマテリアルのモバイル向けの設定項目にあります。
注意点
MSAAがディファードシェーディングにそのままでは対応できない都合上、AlphaToCoverageはフォワードシェーディング向けになります。
AlphaToCoverageを有効にしたい場合、透過パスで描画することになるでしょう