みなさんこんにちは。グリフォンです。![]()
本日東京は台風に見舞われて服がびしょびしょです。
さて今回は真面目なお話です。
以前、デモプログラムの方で
【距離情報によるテクスチャ画像のベクトル化】-Distance Field Texture Vectorization-
というものを紹介しましたが、
つい先日、某プロジェクトで使うためにDistance Field Textureを作る必要が出てきました。
ただ用意するための期間があまり無かった為、今回はUnityを使用してDistance Field Texture生成ツールを作ってみました。
ゲームエンジンとして広く普及しているUnityですが、
色々なファイル読み込みに対応しているので、ちょっとしたツールを作るときも重宝します。![]()
大まかな処理の流れは以下![]()
フォントを1文字ずつ読み出してピクセル情報を取得
ピクセル情報からDistance Field情報を生成
CharacterInfoを生成
アトラステクスチャに書き込む
アトラステクスチャとFontSettingsを出力保存
今回は
を説明していきます。
フォントを1文字ずつ読み出すために今回はUnity標準のuGUIを使用しました。
CanvasとTextとCameraが1つずつあるだけのシンプルなシーンです。
このTextに使用するフォントと文字サイズやスタイルなどを設定しておきます。
このシーンを再生して、Textに1文字ずつ文字を設定し、RenderTexture機能を使ってピクセル情報を取得します。
private IEnumerator GenerateCharacterTexture(string character)
{
// 描画する文字を設定(1文字)
_TextArea.text = character;
// 文字の領域サイズを取得
// フォントによって正しくサイズが取得できない場合があるので、幅・高さの大きいほうで正方形にする。
int width = Mathf.CeilToInt(_TextArea.preferredWidth * _Param_QualityScale);
int height = Mathf.Max(width, Mathf.CeilToInt(_TextArea.preferredHeight * _Param_QualityScale));
width = height;
// 書き出しテクスチャ・レンダーテクスチャを領域サイズに合わせて生成
_BufferTexture = new Texture2D(width, height, TextureFormat.ARGB32, false);
_RenderTexture = new RenderTexture(width, height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default);
_MainCamera.targetTexture = _RenderTexture;
yield return 0; // レンダーテクスチャが反映されるまでの待ち
// キャンパスを強制更新
Canvas.ForceUpdateCanvases();
yield return 0; // キャンバスを最新にするための待ち
// レンダーテクスチャからピクセルを情報取得
RenderTexture.active = _MainCamera.targetTexture;
_BufferTexture.ReadPixels(new Rect(0, 0, width, height), 0, 0);
_BufferTexture.Apply();
}
_TextArea が Textコンポーネントを設定したメンバ変数です。
_MainCamera も同じく Cameraコンポーネントを設定したメンバ変数。
_BufferTexture と _RenderTexture はそれぞれ Texture2D と RenderTexture 型のメンバ変数。
17行目では直前でCameraに設定したRenderTextureに描画するため次のフレームまで待ちます。
ここでuGUIの落とし穴がありました。
本来はこの時点でRenderTextureに描画されているハズですが、uGUIのコンポーネントは設定した内容が直ぐに反映されませんでした。![]()
そこで20行目で Canvas.ForceUpdateCanvases() を呼んで明示的にCanvasを更新します。
その後、描画されるのを待ち次のフレームでようやくRenderTextureの内容が取得できるようになります。
これら2回の待ち時間は回避できないので120FPSなど高速処理することで対処するしかないです。![]()
このあたりはuGUIの処理最適化などの影響だと思われますが、
通常のゲームでも即時でUIを更新する必要がある場合は参考にしてください。
今回はここまで。
以降はまた次回をお楽しみに![]()

