Appearance
第05回 TextMeshPro と SDF
前回: 第04回 半透明表現と UV アニメーション / 次回: 第06回 ノイズ
今回の授業内容
- TextMeshProが文字の輪郭を保てる理由を理解する
- SDFが形の境界までの距離を保持することを理解する
- しきい値と
Smoothstepで表示範囲を制御する - 2つのしきい値からアウトラインを作る
- SDF図形を合成し、形を補間する
TextMeshProとSDF
Unityの高品質なテキスト表示機能
TextMeshPro (TMP)は Unity で使われる文字表示用のコンポーネントです
元はサードパーティ製のアセットでしたが現在は Unity に統合されています
UI ラベル、ボタン、スコア表示、会話文などゲーム中の文字表示に広く使われます
リッチテキストや細かなスタイル設定にも対応しており現在の Unity の標準的な文字表示機能です
「TextMesh ProがUnityに参加 2017年3月20日」 https://unity.com/ja/blog/games/textmesh-pro-joins-unity
TextMeshProの特徴

TMPでの文字装飾の例アウトラインや影、太さの調整が可能なばかりか疑似的なライティング表現も可能
- 拡大縮小しても輪郭が崩れづらい高品質な文字表示を実現しています
- アウトライン、影、太さ、ぼかしなど文字の見た目を細かく調整できます
- SDF の距離情報を使うことで TMP は輪郭や装飾を安定して制御しています
通常の文字画像を拡大したときの問題

上がTMP、下がビットマップフォントビットマップフォントは拡大するとぼやける
文字をただのビットマップ画像として持つと拡大した際にピクセルが目立つようになり輪郭が崩れてしまいます
輪郭を保つために高解像度のフォント画像を用意すると今度はデータ量が増えてしまいます
UI では画面解像度や表示サイズが変わるため文字の輪郭を安定して描く仕組みが必要です
境界までの距離を保存する技術
色や透明度を扱う通常のテクスチャー画像と異なり、 SDF では各ピクセルに文字の境界までの符号付き距離を保存します
描画時は得られた距離値を補間し、しきい値で内側と外側を判定します
透明度ではなく距離を扱うため、低解像度でも輪郭を再構成しやすくなります
Improved Alpha-Tested Magnification for Vector Textures and Special Effects Chris Green, Valve, 2007年 https://steamcdn-a.akamaihd.net/apps/valve/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf
文字の形を保存するFont Asset

アトラス化された文字境界からの距離を表すグラデーションが入っている
TextMeshPro の Font Asset には使用する文字を1枚にまとめたフォントアトラスが入っています
各ピクセルには文字の輪郭までの距離がグレースケール値として保存されています
シェーダーはその距離をしきい値で判定し文字本体、ぼかし、アウトライン等の見え方を調整します
SDFを利用した文字修飾

TMPの文字修飾の例アウトラインや影、太さの調整が可能なばかりか疑似的なライティング表現も可能
Face Color で文字本体の色を変える
Outline で文字の外側に縁取りを付ける
Underlay で影のような表現を加える
Dilate や Softness で太さやにじみを調整する
これらは全て SDF の距離情報を活用して実現されています
Signed Distance Fieldの仕組み
境界からの符号付き距離
灰色が元の形、赤が内側、緑が外側円の大きさが境界までの距離を表す出典: Drummyfish, Wikimedia Commons, CC0
SDF は Signed Distance Field の略です
ある点が形の境界からどれだけ離れているかを数値として扱うことで形状を表現する方法です
Signed は符号付きという意味です
形の内側と外側を正負の値で区別できます
シェーダーでは、この距離の値を使って形の表示、輪郭、ぼかしを表現できます
色ではなく距離を扱う


SDF画像と復元の例境界の距離を使うことで拡大しても輪郭が保たれる
通常のテクスチャーはピクセルごとの色を保存します
SDF テクスチャーは形の境界からの距離をグレースケール値として保存します
ぼやけた画像に見えますが値をしきい値で判定することでくっきりした形を復元できます
距離を透明度へ変換する

Shader Graph での SDF 表示の例距離をしきい値で判定して採用している
text
distance = Sample Texture 2D(SDF Texture, UV).r
alpha = distance > threshold ? 1 : 0
Base Color = Color
Alpha = alpha実際の Shader Graph では Sample Texture 2D、Step、Branch などで近い処理を作れます
Smoothstepで境界をなめらかにする

Smoothstepの効果の例しきい値の前後で値がなめらかに変化するため境界のジャギーが目立たなくなる
text
distance = Sample Texture 2D(SDF Texture, UV).r
alpha = smoothstep(threshold - softness,
threshold + softness,
distance)
Base Color = Color
Alpha = alphaStep での表示は境界がはっきりしすぎてジャギーが目立つことがあります
Smoothstep を使えばしきい値の前後で値をなめらかに補間できます
2つのしきい値でアウトラインを作る

外周用の表示と内周用の表示を組み合わせてアウトラインを作っている例 Gradientを使えばより細かな調整が可能
本体より少し外側まで表示する範囲を作りアウトラインの色を乗せれば文字の周りに縁取りを付けることができます
フォントや UI アイコンでは視認性を上げるためによく使われます
TextMeshPro の文字修飾はこの考え方を基本にして実装されています
SDFで図形を操作する
計算だけで図形を作る

Shader Graph に実装されている SDF 関数の例計算で SDF の円形状を作成している
SDF は画像として用意するだけでなく UV や座標から計算することもできます
円のような単純な形の距離を計算すればシェーダー内で図形を作れます
図形そのものではなく距離を扱うため合成や変形を数式で扱いやすくなります
MinとMaxで図形を合成する
SDF 図形の合成の例 Min は共通部分、Max は和集合になる
SDF の距離値を比較すると複数の形を1つの距離場として扱えます
内側を正の値として扱う場合 Minimum は両方の内側だけを残します
Maximum はどちらかの内側を残します
距離を補間してモーフィングする

二つの SDF 画像を補間してのモーフィングの例 Blend の値を変えると円と星型の間で形が変化する
2つの SDF 図形を用意して距離の値を Lerp で補間すれば形をなめらかに変化させることができます
補間量を時間やパラメーターで変えるだけで簡単にモーフィング表現を作ることができます
実習:SDF の操作を体験する
距離を数値として計算し、図形の表示と変形へ利用します
実習1:円のSDFを作る
URP Unlit Shader Graphを作成するUVから中心座標との差を求めるLengthで中心からの距離を計算する- 半径から距離を引いて円の SDF にする
Smoothstepで円として表示する
実習2:SDF画像を補間して変形する
- 2つの SDF 画像を用意する
- サンプリングした距離値を
Lerpで混ぜる FloatのMorphプロパティを追加するMorphを動かして形の変化を確認するTimeを使って自動で変化させる- 境界の硬さも調整できるようにする
授業内課題:2つのSDFで形を変化させる
2つの距離値を合成または補間し、形が変化するマテリアルを制作します
完成条件
- 2つの SDF の距離値を扱っている
Maximumで図形を合成できるMorphで2つの形を補間できるSoftnessで境界の硬さを調整できる- 本体色をマテリアル側から変更できる
- スクリーンショットまたは動画で変化が確認できる
今回のまとめ
- SDF は形の境界からの距離を持つデータです
- 距離情報をしきい値で判定して形を切り抜くことができます
Smoothstepを使えば輪郭の硬さを調整できるなど SDF は様々な表現に応用できます- SDF はフォント描画だけでなく図形の合成やモーフィングにも役立ちます