#DirectXTKのMakeSpriteFontの問題と解決策
##はじめに
DirectX11からDirectX9に存在したD3DXライブラリが標準搭載されなくなった。そのせいで、便利なクラスが使えなくなった。Font表示も同様、使えなくなった。一応、D3DXライブラリのDX11版は存在するものの、ライブラリを個別にインストール・使用しなければならない(参考:DirectX 補助ライブラリ - Wikipedia)。
Font表示処理を独自に実装することは可能だが、こういう汎用的な処理はフリーウェアとして存在するのが望ましい。そこで登場するのが「DirectX Tool Kit=DirectXTK」である。
DirectXTKとは?
DirectXTKは、C++ で作られている。February 24, 2012に最初のリリースが行われた。DirectXTKが提供する機能は、Oct 10, 2018の時点で以下の通り(参考:DirectXTK)。
ヘッダ名 | 内容 |
---|---|
Audio.h | XAudio2を使用した低レベルのオーディオAPI(Audioパブリックヘッダ用のDirectXTK) |
CommonStates.h | 一般的に使用されるD3Dステートオブジェクトを提供するファクトリ |
DDSTextureLoader.h | 軽量なDDSファイルテクスチャローダー |
DirectXHelpers.h | D3Dプログラミングのための色々な C++ヘルパー |
Effects.h | 一般的なレンダリングタスク用の組み込みシェーダのセット |
GamePad.h | XInputを使用したゲームパッドコントローラヘルパー |
GeometricPrimitive.h | キューブや球などの基本図形を描画します。 |
GraphicsMemory.h | 動的グラフィックスのメモリ割り当てを管理するヘルパー |
Keyboard.h | キーボードステートトラッキングヘルパー |
Model.h | .CMO、.SDKMESH、または.VBOファイルから読み込まれたメッシュの描画 |
Mouse.h | マウスヘルパー |
PostProcess.h | 一般的なプリプロセス処理用の組み込みシェーダのセット |
PrimitiveBatch.h | ユーザプリミティブを簡単かつ効率的に描画する方法 |
ScreenGrab.h | 軽量なスクリーンショットセーバー |
SimpleMath.h | DirectXMathの簡略化された C++ ラッパー |
SpriteBatch.h | シンプルで効率的な2Dスプライトレンダリング |
SpriteFont.h | ビットマップベースのテキストレンダリング |
VertexTypes.h | 一般的に使用される頂点データフォーマットの構造 |
WICTextureLoader.h | WICベースのイメージファイルテクスチャローダー |
XboxDDSTextureLoader.h | Xbox OneのDDSTextureLoader専用アプリケーション |
今回はFontを描画したいので SpriteFont.h の SpriteFontクラスを使う。このSpriteFontクラスは、「spritefontデータ」を作成しておく必要がある。このデータには、テクスチャ・テクスチャ情報・フォント描画に必要な情報が含まれている。このデータを作成するのがDirectXTKに含まれている「MakeSpriteFont.exe」だ。以下はそのフォルダ構造である。
MakeSpriteFontフォルダに MakeSpritFont.exe がある。
##MakeSpriteFontの問題点
MakeSpriteFont.exeは「使用するフォントの文字を切り出して、テクスチャファイルと付属情報を生成し、「spritefontデータ」にするツールだ。使用する文字の数が多ければ、それだけ変換に時間を要す。加えてそのアルゴリズムが問題で、テクスチャ画像の空き領域を1ピクセル単位で探しているらしい。漢字がだいたい2万文字あるので、変換に多大な時間が必要になる。ちなみに、私の環境では12時間経っても終わらなかった( Intel Core2Quad 2.85 GHz)。
##MakeSpriteFontの解決策
既にこの問題について解決策を提示し、記事にしてくれてる方がいた。ZeroGramさんのDirectXTKでフォント表示、日本語対応(2013/4/29)である。記事の日付が2013/4/29なのでとても古い。ここで書かれている内容が現在(Oct 10, 2018)でも通用するのかを検証してみた。
**結果からいうと上手くいった。**その御蔭で「spritefontデータ」の作成が約1分で完了した。大幅な時間改善である。
以下にその手順を記す。
- ZeroGramさんのサンプルプログラム MakeSpriteFontModify.zip をダウンロードする。
- zipを展開すると、modifyフォルダに2つのファイルがある(GlyphPacker.cs, TrueTypeImporter.cs)。
- DirectXTK/MakeSpriteFontフォルダに、TrueTypeImporter.cs をコピーする。
- DirectXTK/MakeSpriteFontフォルダの、GlyphPacker.cs をテキストエディタで開く。
- ZeroGramさんの GlyphPacker.csのArrangeGlyphs関数を探して、関数ごとコピーする。MakeSpriteFontフォルダGlyphPacker.cs の ArrangeGlyphs関数と差し替える。
- ZeroGramさんのGlyphPacker.csからPositionGlyph関数を探し、関数ごとコピーする。MakeSpriteFontフォルダGlyphPacker.cs の ArrangeGlyphs関数の後に「貼り付け」る。
- DirectXTK/MakeSpriteFontフォルダの MakeSpriteFont.csproj をVisualStudio2015 で開き、ビルドする。
##MakeSpriteFontの解決策の結果
以下のコマンドを実行すると、約2万5千字もの漢字変換が行われる。所要時間は約1分。オリジナルよりも変換時間が短縮され、データも問題なく変換された。実際に表示させた所、問題なく表示された。
MakeSpriteFont.exe "MS ゴシック" myfile.spritefont /FontSize:12 /CharacterRegion:32-126 /CharacterRegion:0x3000-0x30ff /CharacterRegion:0xff00-0xffef /CharacterRegion:0x4e00-0x9fff /CharacterRegion:0x2000-0x2fff
MakeSpriteFont.exeに渡すCharacterRegionオプションの意味は以下の通り。
説明 | オプション |
---|---|
アスキー文字 | /CharacterRegion:32-126 |
ひらがなカタカナ | /CharacterRegion:0x3000-0x30ff |
記号 | /CharacterRegion:0xff01-0xffe5 |
全角漢字 | /CharacterRegion:0x4e00-0x9fff |
全角特殊記号 | /CharacterRegion:0x2000-0x2fff |
【DirectX11でSpriteFontクラスを使って表示させてみた結果】は以下の通り。
##まとめ
ZeroGramさんのサイトにある解決法で、問題は解決した。ただし、差し替え対象の2つのファイルをまるごとコピーすることはできず、ファイルの一部を直接編集しなければならなかった。GitHubに公開されている MakeSpriteFont.exe は、常に更新されているせいで、2018年現在だと今回のような対応が必要になった。
ZeroGramさん、ありがとうございました。