This explanation is currently available in Japanese.
ひとことで
文字やアイコンの形を、RGB の 3 チャンネルそれぞれに別々の辺への距離として保存する距離場テクスチャです。描画時に 3 つの値の中央値(median)を取ると、1 チャンネルの SDF では丸まってしまう鋭い角まで再現できます。小さなテクスチャでも、どれだけ拡大しても輪郭がくっきりしたままなので、ゲームの UI やワールド空間の文字表示に広く使われています(Viktor Chlumský の msdfgen が代表的な生成ツール)。
ゲームでの使いどころ
- UI・HUD の文字:解像度やズームに関係なく、くっきりした文字を 1 枚のフォントアトラスで描く。
- ワールド空間の文字:看板、ネームプレート、ダメージ表示など、カメラが近づいても崩れない文字。
- アイコン・ロゴ:角のあるアイコンを拡大縮小自在に描く。
- 文字の装飾:距離が分かるので、縁取り、光彩、影、太さの変更を、しきい値をずらすだけで 1 回の読み込みで描ける。
しくみ
ビットマップ(被覆率)を拡大すると、画素の補間でぼやけます。
1 チャンネルの SDF は、各テクセルに輪郭までの距離を保存します。距離は補間しても意味を保つので、拡大しても「距離 0 の線」をくっきり描けます。ところが、角の近くでは「最も近い点」が角の 1 点になり、距離の等値線が丸くなるため、角が丸まってしまいます。
MSDF は、輪郭の各辺に 3 色(R+G、G+B、R+B の組み合わせ)のどれかを割り当て、隣り合う辺が必ず違う色になるようにします。各チャンネルには、そのチャンネルを含む辺だけから求めた距離(辺の延長線への距離)を保存します。
- 角では、2 つの辺が別々のチャンネルに入っています。それぞれのチャンネルは「角で曲がらない、まっすぐな辺の延長線」を表します。
- 3 つの値の中央値を取ると、2 つの直線が交わる鋭い角が復元されます。
描画時は、画面上で距離 1 テクセルが何画素に当たるかを求めて、ちょうど 1 画素の幅で滑らかに縁を描きます。
実装のポイント
- 生成はツールで:辺の色分け、距離の計算、誤り補正には細かな工夫が必要なので、msdfgen や msdf-atlas-gen などのツールでアトラスを作るのが一般的です。
- MTSDF:アルファチャンネルに通常の SDF(真の距離)も入れておく形式です。縁取りや光彩のように、輪郭から離れた距離を使う効果は、角の再現には向くが遠くでは不正確な MSDF ではなく、アルファの真の距離を使います(デモの「縁取りと光彩」もそうしています)。
- テクスチャの設定:線形の値なので sRGB ではなく線形のテクスチャとして読み込み、補間はバイリニアにします。
- 距離の範囲(pxRange):保存する距離の範囲を広くすると、太い縁取りや光彩が描けますが、同じ 8 ビットの精度で広い範囲を表すので、輪郭の精度は少し落ちます。
つまずきやすい点
- 補間による誤り:隣り合うテクセルでチャンネルの組み合わせが食い違っていると、補間した結果の中央値が誤って 0.5 を超え、輪郭から離れた場所に点や線が現れます。生成ツールは誤り補正でこれを抑えます。デモでも、中央値の内外が真の内外と食い違うテクセルと、輪郭から離れたテクセルを真の距離にそろえる簡易な補正をしています。
- 縮小表示:画面上で文字がテクスチャより小さくなると、1 画素の中に複数のテクセルが入り、にじみやちらつきが出ます。ミップマップは距離の意味を壊しやすいので、小さく表示する文字には別のアトラスを用意することもあります。
- 細い線や小さな穴:テクセルより細い部分は、距離場でも表せません。
デモで試すこと
- 3 枚の看板は、同じ 14×14 画素(1 文字あたり)のテクスチャから描いています。ビットマップはぼやけ、SDF は輪郭はくっきりしても星の先端や「A」の角が丸まり、MSDF は鋭い角を保っています。
- 「テクスチャの解像度」を 8 まで下げても、MSDF は形をかなり保ちます。SDF は角がさらに丸くなります。
- 「テクスチャの中身を表示」で MSDF の RGB を見ると、色の境目が辺ごとに違う位置にあることが分かります。
- 「縁取りと光彩」をオンにすると、距離を使って縁取りと光彩を 1 回の読み込みで描けます。ビットマップではこれができません。