ShaderTips

シェーダーTips

主にUnityシェーダーについての記事を書いています。

【Unity】半透明描画について

半透明とブレンドモード

半透明を描画するときに背景の色とブレンドさせるにはブレンドモードという機能を使用します。
ブレンドモードは以下のように記述します。

Blend SrcFactor DstFactor

SrcFactorとDstFactorはそのまま記述するのではなく、決められたパラメータがあるので、用途に合わせて指定します。

指定したSrcFactorとDstFactorのキーワードを使って、以下のように最終的な色を決定ます。

最終的な色 = SrcFactor * 現在出力した色 + DstFactor * フレームバッファの色

一般的な半透明の描画では以下のように指定します。

Blend SrcAlpha OneMinusSrcAlpha

これで、不透明に近いほど現在出力した色が優先され、透明に近いほど、フレームバッファの色が優先されて合成されます。

最終的な色 = α * 現在出力した色 + (1 - α)  * フレームバッファの色

半透明とデプスバッファ

手前の緑色の球体は半透明ですが赤色の球体の重なっている部分が消えてしまっています。

これはオブジェクトを手前から描画するため、手前のオブジェクトの深度値を後ろの球体の描画時に深度バッファから参照して、消えてしまうからです。

(カメラから離れているオブジェクトから描画すると、手前の方のオブジェクトを描画する時に、既に描画したオブジェクトのピクセルカラーは破棄されます。破棄されるピクセルの描画をするのは無駄になるので、手前から描画されます。)

この問題を解決するには不透明の描画が終わった後に半透明の描画をカメラから離れているオブジェクトから描画していきます。

Unityで描画順を指定するにはQueueというキーワードを使用します。半透明の場合はQueueにTransparentを指定します。

Tags {"Queue"="Transparent"}

RenderQueueの数値が低いシェーダー(マテリアル)から描画されます。 Transparentには列挙型のように3000という数値が入っていおり、 2500までは不透明とみなされ、手前から奥に描画され、2501以上は半透明とみなされ、奥から手前に描画されます。

これにより後ろのオブジェクトの方が先に描画されるようになるため、深度テストによるピクセルの削除が行われず、正常に描画されるようになりました。

半透明を綺麗に描画する

モデルの形状が複雑だと、デプスバッファへの書き込みを行わないと裏面のポリゴンが透けて、汚く見えてしまいます。

【Unityシェーダ入門】綺麗に半透明のモデルが表示できるシェーダを作る - おもちゃラボ引用

これを解決するためには先にデプスバッファにモデルのZ値(デプス値)のみを書き込みます。この時モデルは描画しません。

ただ、半透明なオブジェクト同士が重なると前のオブジェクトしか表示されなくなります。

半透明の負荷は高い

半透明の描画はデプステストによるピクセルの破棄が行われないので、オーバードローが発生するのと、ブレンドが必要なため、負荷が高いです。

参考

www.youtube.com

nn-hokuson.hatenablog.com