ひとことで
半透明の物体は、本来奥から手前へ順番に重ねて描く必要があります。重み付きブレンド OIT(Order-Independent Transparency、McGuire & Bavoil 2013)は、この並べ替えをせずに、描く順序に関係なく色を足し合わせ、深さに応じた重みで平均することで、それらしい半透明の重なりを近似する手法です。交差する半透明物や、大量の粒子を並べ替えなしで描けます。
ゲームでの使いどころ
- 交差する半透明物:ガラスの板、エネルギーシールド、ホログラムが互いに貫通していても破綻しない。
- 大量の半透明粒子:煙、雲、魔法のエフェクトを、粒子ごとの並べ替えなしで描く。
- 半透明の複雑なメッシュ:髪の毛、葉、透けた布のように、1 つのメッシュの中で面の順序が入れ替わるもの。
- CAD・可視化:透けて見える内部構造の表示。
しくみ
通常の半透明の問題:アルファ合成 は、描く順序によって結果が変わります。ゲームエンジンは物体の中心の距離で並べ替えますが、
- 交差する物体は、1 枚の中で手前と奥が入れ替わるので正しく並べられない
- 視点が動くと並び順が入れ替わり、ちらつく(ポッピング)
- 粒子を毎フレーム並べ替えるのは重い
という問題があります。
重み付きブレンド OIT:次の 2 つのバッファに、描く順序に関係なく書き込みます。
足し算と掛け算は順序に依存しないので、並べ替えは不要です。最後に合成します。
重み は、手前(深度が小さい)ほど、不透明度が高いほど大きくします。こうすると、手前の色が優先されて、正しく並べ替えた結果に近くなります。
実装のポイント
- 浮動小数点のバッファ:累積値は大きくなるので、16 ビット浮動小数点のレンダーターゲットが必要です。
- 不透明物の深度を使う:半透明物は不透明物の深度バッファで深度テストし(書き込みはしない)、不透明物の後ろの半透明物を隠します。
- 重みの関数を調整する:シーンの奥行きの範囲に合わせて、重みの関数を調整すると精度が上がります。
つまずきやすい点
- 近似である:不透明度の高い物が重なると、手前の物が奥を完全に隠すべきところで、奥の色が混ざって見えます。完全に正確にしたい場合は、深度ピーリングやピクセルごとのリンクリスト(A-Buffer)などの正確な方法が必要ですが、重くなります。
- 似た深さでの色の混ざり:深さがほぼ同じ物同士では、重みの差が小さく、平均された色になります(デモの交差部分)。
- 加算的な光るエフェクト:炎や光のように加算で描くエフェクトは、もともと順序に依存しないので、OIT を使う必要はありません。
デモで試すこと
- 「並べ替えなし」では、深度を書き込んだ手前の板が、後から描く奥の板や球を消してしまいます。
- 「物体単位で並べ替え」では、4 枚の板が中心で交差しているため、どこかで必ず前後関係が間違います。視点が回るにつれて、重なり方がパッと入れ替わるのが分かります。
- 「重み付き OIT」では、順序を気にせず、交差部分も自然に色が混ざります。視点が回ってもちらつきません。
- 「不透明度」を上げると、近似の限界(奥の色が少し透けて見える)が分かりやすくなります。