none
文字コードで全ての文字の一覧を描画するには? RRS feed

  • 質問

  • 3Dゲームで2D文字を使う場合、簡単にフォントを扱うクラスがないので、画像にフォント文字を書いて表示します。

    そのやり方で英数字は対応できたのですが、全角文字の一覧を取得する方法が分かりません。

    Unicodeで文字コードの一覧を指し示すにはどうすればいいのでしょうか?


    • 編集済み たけし 2014年4月10日 15:13
    2014年4月10日 15:12

回答

  • 質問者の人はすでに見てないと思いますが、せっかくなので他の閲覧者のためにもDirect3Dによるテキストレンダリングに関する一般論を記載しておきます。

    3DシーンのレンダリングにDirect3D 10.1もしくはDirect3D 11.1/11.2を使っているならば、それぞれ対応するDirect2D 1.0もしくはDirect2D 1.1/1.2とDirectWriteを使ってDXGI相互運用を行なえば簡単にテキスト描画できます。日本語だけでなく、選択したフォントが対応していればUnicode文字を扱うことも普通にできます(DirectWriteの合成フォントはGDIのフォントリンクよりも優秀で、指定フォントにおいて不足している文字は代わりにメイリオなどが自動的に使われるようになります)。Direct3D/Direct2DのDXGI相互運用に関してはGoogle検索すればいくらでも情報は見つかりますし、Windows SDK 7.xにもサンプルが付属しています。MFCの仕組みを理解していればそれらをCViewに適用するのは造作ないでしょう。WindowsストアアプリのDirect2Dアプリケーションテンプレート(C++/CX)なども参考になります。

    ちなみにMFCで3Dゲーム、しかもCViewを使うというのが第一条件として普通はありえないのですが(普通はゲームアプリケーション本体にはMFCを使いません)、ゲーム本体とは別にレベルエディタやオーサリングツールか何かを作るためにMFCを使っているのでしょうか? レンダリングエンジンのみ共有しているとか……Visual Studio 2010以降のMFCには、Direct2D 1.0のラッパークラスが用意されているので、そちらを利用してDirect3D 10.1のDXGIスワップチェーンに対してテキストをレンダリングする方法もあります。

    なお、Direct2D/DirectWriteを使ったテキストレンダリングは柔軟で高機能なため、テキスト主体のノベルゲームや2Dベースのカジュアルなゲームには向いていますが、マイクロ秒・ナノ秒単位で厳しい最適化が求められる3Dゲームではパフォーマンス的に不利です。また、OpenGLへの移植も視野に入れているならば、フォントのグリフデータをラスター画像としてベイクするツールを作って、それをテクスチャとして利用するスプライトベースの方法のほうが良いです。なお、まれにフォントファイルだけでなくラスターデータの再頒布(商用利用)に関しても許諾や追加の費用が必要なフォントがあるので、フォントの利用規約を必ず確認しておいたほうがよいですダイナフォントなど)。実際インディーズの開発者にとっては技術的な問題よりもこういった著作権的な問題のほうが悩ましいと思います。ちなみに、OSにプリインストールされているフォントを使って、Direct2D/DirectWriteによりテキスト描画する場合はフォントのライセンスを気にする必要はありません。

    下記ではXNAで日本語表示を行なう方法が紹介されてあります。XNAのSpriteFontはDirect2D/DirectWriteのように実行時にグリフデータを取得する方式ではないため、WPFを使ったカスタムコンテンツパイプラインによって日本語テキスト用のスプライトテクスチャを事前生成しています。C#を理解できるならばこちらのソースコードも有用でしょう。

    真・簡単(かもしれない)日本語表示 - ひにけにGD - Site Home - MSDN Blogs

    他にも、DirectXTK (DirectX Tool Kit) には(Direct3D 11用ですが)XNAに似たSpriteFontがあります。こちらはデフォルトではASCII対応のみで、日本語にも対応させるには修正が必要ですが、修正方法はWeb検索すれば見つかるでしょう。ちなみにDirectXTKのMakeSpriteFontはXNAのコンテンツパイプライン相当ですが、こちらはGDI+.NETが使われています。

    もうひとつの方法として、旧DirectX SDKに付属しているD3DXライブラリのID3DXFont(Direct3D 9用)やID3DX10Font(Direct3D 10.x用)を使う方法もあります。内部ではGDIを使ったグリフデータの取得が実行されます。キャッシングの仕組みも備えていますが、D3DXランタイムへの依存が発生する、Direct3D 11用のインターフェイスは存在しない、小さなフォントサイズではアンチエイリアスが効かない、などの問題があり、パフォーマンス的にもあまりお勧めしません。

    • 編集済み sygh 2014年5月11日 13:28
    • 回答としてマーク たけし 2014年5月11日 15:36
    2014年5月10日 12:36
  • まず、Unicodeは国際コードですので、対象の国のコードページを選択しなければなりません。
    日本語だけなのか、全てのコードページなのかを明らかにすべきかもしれません。
    Unicodeについては、以下を参照してください。

    http://ja.wikipedia.org/wiki/Unicode

    次に符号化スキームですが、Windowsでは内部的にはUTF-16を使用しています(たぶん)。
    UTF-16では、一文字を2Byteまたは4Byteで表現します。以下を参照してください。

    http://ja.wikipedia.org/wiki/UTF-16

    以上を読んでみると次の問題点に気づきます。

    1.膨大な量である。
    2.コードと読みに関連がない。
    3.位置が分散している。
    4.つまり結構難しい上に面倒そうだ。

    また、文面から、日本語のUnicodeの全ての文字を、コードを順番に表示しても、
    ひょっとすると目的を達成できないかもしれないという予測がたちました。
    問題点のもうひとつはこれです。

    つまり、もし、最終目的がDirectXに文字を出力したいだけならば、
    また、特にレンダリングする必要もないのならば(文面からそう判断しました)、
    全てのUnicodeの一覧を取得する必要はないのではないか、
    という疑念を持ったわけです。
    そうなると、別の方法を模索したほうが早道になる可能性が考えられるわけですね。
    質問の前提条件を詳しく説明すべきだとお願いしているのは、
    このような理由にによるものです。

    たとえば、メモリービットマップを選択しているメモリーHDCに対して、
    必要な文字をTextOutし、そのビットマップを対象の3Dに表示する。
    といった方法も考えられますが、いかがでしょう。

    2014年4月11日 8:17

すべての返信

  • レス付きませんね。次の点について気づかれていますでしょうか。

     1.質問には前提条件が必要です。
     2.かるく検索すればわかる程度のことをあえて回答する人は少ないです。

    事態の把握と問題点の整理、および他の人に説明するための文書化は、
    プログラミング能力のトレーニングにもなりますし、
    一般に人として当然のように要求される機能といえます。
    加えて

     3.質問内容を詳しく説明するのは質問者の負担すべきコストです。

    あたりまえのことですよね。
    もう一度質問内容を精査してみてはどうでしょう。

    2014年4月11日 2:54
  • 仲澤@失業者さん、ありがとうございます。

    文字コードでフォントの全ての文字の一覧を表示するには、どうすればいいでしょうか?

    できればMFCのCViewでpDC->TextOutを使って画面いっぱいに表示させたいです。

    検索してもわからなかったので、どんな検索ワードで検索したらいいか教えてください。

    2014年4月11日 7:12
  • フォーラム オペレーターの星 睦美です。

    >そのやり方で英数字は対応できたのですが

    おそらく同じやり方でUnicode も対応したいと考えられているのではと思います。
    英数字に対応したコードの例などを紹介していただくと、たけし さんの質問と同じプログラミングをした経験がなくても、関連したノウハウをもっているユーザーから情報を集めることができるかも知れません。


    フォーラム オペレーター 星 睦美 - MSDN Community Support

    2014年4月11日 7:29
  • GDIならGetFontUnicodeRanges functionが使えそうですね。

    // Win32 テキスト API の比較によるとDirect WriteではIDWriteFont::HasCharacter メソッドをループで呼び出すらしい。

    2014年4月11日 7:41
  • まず、Unicodeは国際コードですので、対象の国のコードページを選択しなければなりません。
    日本語だけなのか、全てのコードページなのかを明らかにすべきかもしれません。
    Unicodeについては、以下を参照してください。

    http://ja.wikipedia.org/wiki/Unicode

    次に符号化スキームですが、Windowsでは内部的にはUTF-16を使用しています(たぶん)。
    UTF-16では、一文字を2Byteまたは4Byteで表現します。以下を参照してください。

    http://ja.wikipedia.org/wiki/UTF-16

    以上を読んでみると次の問題点に気づきます。

    1.膨大な量である。
    2.コードと読みに関連がない。
    3.位置が分散している。
    4.つまり結構難しい上に面倒そうだ。

    また、文面から、日本語のUnicodeの全ての文字を、コードを順番に表示しても、
    ひょっとすると目的を達成できないかもしれないという予測がたちました。
    問題点のもうひとつはこれです。

    つまり、もし、最終目的がDirectXに文字を出力したいだけならば、
    また、特にレンダリングする必要もないのならば(文面からそう判断しました)、
    全てのUnicodeの一覧を取得する必要はないのではないか、
    という疑念を持ったわけです。
    そうなると、別の方法を模索したほうが早道になる可能性が考えられるわけですね。
    質問の前提条件を詳しく説明すべきだとお願いしているのは、
    このような理由にによるものです。

    たとえば、メモリービットマップを選択しているメモリーHDCに対して、
    必要な文字をTextOutし、そのビットマップを対象の3Dに表示する。
    といった方法も考えられますが、いかがでしょう。

    2014年4月11日 8:17
  • 星 睦美さん、ありがとうございます。

    数字は0~9を書いた画像を用意して、数値×数字の幅でできました。

    2014年4月11日 12:06
  • Hongliangさん、ありがとうございます。

    GetFontUnicodeRangesを参考にします。

    2014年4月11日 12:07
  • 仲澤@失業者さん、ありがとうございます。

    Unicodeは扱いが難しそうですね。

    扱う文字は日本語と英語の全てです。

    txtファイルを開いて、Direct3Dのテクスチャにその文章をレンダリングしたかったです。

    2014年4月11日 12:10
  • 既に解決されたでしょう。 それならば、余計なお世話と思いますが、、、

    > 扱う文字は日本語と英語の全てです。

    これってすごく曖昧と思いませんか?
    Windows7のIMEパッドで文字一覧を表示すると大量の文字が表示されますが、これら全てを対象とするのでしょうか。多分、日本語の範囲は、漢字とかなを意味すると思いますが、かなはともかく、漢字は、Unicodeでは、CJK互換文字等に割り付けられて、中国文字も多数含まれています。(混じっています)
    また、かなと言った場合、かな記号はどうするかとか、全角英字、半角カナ、罫線文字などの記号の扱いも悩ましいと思いますが、どう考えていますか? 簡単には、Shift-JISの範囲のみ対応とかするのが、容易そうですが、それで良いでしょうか。
    そのとき、フォントの種類にも注意です。フォントの種類によっては、字形が無いものがあったりするので。
    (MSゴシックにするとかなり少ない様に見えます)

    参考までに

    2014年4月12日 15:20
  • 質問者の人はすでに見てないと思いますが、せっかくなので他の閲覧者のためにもDirect3Dによるテキストレンダリングに関する一般論を記載しておきます。

    3DシーンのレンダリングにDirect3D 10.1もしくはDirect3D 11.1/11.2を使っているならば、それぞれ対応するDirect2D 1.0もしくはDirect2D 1.1/1.2とDirectWriteを使ってDXGI相互運用を行なえば簡単にテキスト描画できます。日本語だけでなく、選択したフォントが対応していればUnicode文字を扱うことも普通にできます(DirectWriteの合成フォントはGDIのフォントリンクよりも優秀で、指定フォントにおいて不足している文字は代わりにメイリオなどが自動的に使われるようになります)。Direct3D/Direct2DのDXGI相互運用に関してはGoogle検索すればいくらでも情報は見つかりますし、Windows SDK 7.xにもサンプルが付属しています。MFCの仕組みを理解していればそれらをCViewに適用するのは造作ないでしょう。WindowsストアアプリのDirect2Dアプリケーションテンプレート(C++/CX)なども参考になります。

    ちなみにMFCで3Dゲーム、しかもCViewを使うというのが第一条件として普通はありえないのですが(普通はゲームアプリケーション本体にはMFCを使いません)、ゲーム本体とは別にレベルエディタやオーサリングツールか何かを作るためにMFCを使っているのでしょうか? レンダリングエンジンのみ共有しているとか……Visual Studio 2010以降のMFCには、Direct2D 1.0のラッパークラスが用意されているので、そちらを利用してDirect3D 10.1のDXGIスワップチェーンに対してテキストをレンダリングする方法もあります。

    なお、Direct2D/DirectWriteを使ったテキストレンダリングは柔軟で高機能なため、テキスト主体のノベルゲームや2Dベースのカジュアルなゲームには向いていますが、マイクロ秒・ナノ秒単位で厳しい最適化が求められる3Dゲームではパフォーマンス的に不利です。また、OpenGLへの移植も視野に入れているならば、フォントのグリフデータをラスター画像としてベイクするツールを作って、それをテクスチャとして利用するスプライトベースの方法のほうが良いです。なお、まれにフォントファイルだけでなくラスターデータの再頒布(商用利用)に関しても許諾や追加の費用が必要なフォントがあるので、フォントの利用規約を必ず確認しておいたほうがよいですダイナフォントなど)。実際インディーズの開発者にとっては技術的な問題よりもこういった著作権的な問題のほうが悩ましいと思います。ちなみに、OSにプリインストールされているフォントを使って、Direct2D/DirectWriteによりテキスト描画する場合はフォントのライセンスを気にする必要はありません。

    下記ではXNAで日本語表示を行なう方法が紹介されてあります。XNAのSpriteFontはDirect2D/DirectWriteのように実行時にグリフデータを取得する方式ではないため、WPFを使ったカスタムコンテンツパイプラインによって日本語テキスト用のスプライトテクスチャを事前生成しています。C#を理解できるならばこちらのソースコードも有用でしょう。

    真・簡単(かもしれない)日本語表示 - ひにけにGD - Site Home - MSDN Blogs

    他にも、DirectXTK (DirectX Tool Kit) には(Direct3D 11用ですが)XNAに似たSpriteFontがあります。こちらはデフォルトではASCII対応のみで、日本語にも対応させるには修正が必要ですが、修正方法はWeb検索すれば見つかるでしょう。ちなみにDirectXTKのMakeSpriteFontはXNAのコンテンツパイプライン相当ですが、こちらはGDI+.NETが使われています。

    もうひとつの方法として、旧DirectX SDKに付属しているD3DXライブラリのID3DXFont(Direct3D 9用)やID3DX10Font(Direct3D 10.x用)を使う方法もあります。内部ではGDIを使ったグリフデータの取得が実行されます。キャッシングの仕組みも備えていますが、D3DXランタイムへの依存が発生する、Direct3D 11用のインターフェイスは存在しない、小さなフォントサイズではアンチエイリアスが効かない、などの問題があり、パフォーマンス的にもあまりお勧めしません。

    • 編集済み sygh 2014年5月11日 13:28
    • 回答としてマーク たけし 2014年5月11日 15:36
    2014年5月10日 12:36
  • syghさん、ありがとうございます。

    DirectWriteを使うことで、3D空間にtxtファイルを縦横無尽に連ねるテキストビューアが作れました。

    ゲーム的にしたかったのですが、デジタルアートっぽくなってしまいました。

    http://vixar.jp/writing/

    2014年5月11日 15:39