その5 高速フォント表示
ホーム < ゲームつくろー! < DirectX技術編 < 高速フォント表示
その5 高速フォント表示
この章のサンプルプログラムはこちら
Direct3Dはフォントの扱いが苦手です。一応画面に簡単に文字を出すためのID3DXFontインターフェイスがありますが、背後でWindows APIを用いてフォント形状を取得しているので、描画が異常なほど遅いのです。あまりに遅くて、特にノベルス系のように画面にフォント文字が沢山出て来るゲームではまともに使えません。
ID3DXFontを介して描画するのがなぜ遅いのか?それは、1フレームごとにフォントを一から作成して描画しているためです。フォントの情報を得て、それを点の情報に変換して画面に打つ。これでは、どれだけ頑張ったって速度は出ません。ところで、DirectXは「絵」の描画については異常な程高速です(それがDirectX最大の売りですよね)。ということは、フォントを毎回「打つ」のではなく、フォントの絵を「描画」すれば、高速なフォント描画があっさりと実現できるわけです。
破損したデータベースは何ですか
フォントの絵を用意する手法は、ゲームのスコアのような特定の数字フォントしか扱わない場合に良く使われるます。しかし、ノベルス系のゲームには数万文字の文章があり、数千のフォントが使用されます。それ全て絵として用意するわけにはいきません。ですから、動的にフォントを作成し、それを絵に変換する作業がどうしても必要になります。
DirectXで絵と言うとサーフェイスかテクスチャです。Direct7の時には2Dの矩形領域であるサーフェイスの扱いは結構楽だったのですが、Direct8になってDirect Graphicsとして2D処理がまとめられた際、いきなり扱いにくくなってしまいました。また、サーフェイスは回転したり、拡大縮小したりという事が本来苦手です。一方、テクスチャは板ポリゴンに貼ってしまえば何でもできますし、取替えが非常に簡単です。よって、ここではテクスチャを絵として採用することにします。
↑テクスチャ+板ポリなら、こういう事が自由にできます
フォントをテクスチャに書き込む場合�lockRect.Pitch * iFnt_h, 0);
// フォント情報の書き込み
for(int y=iOfs_y; y
DWORD color = 0x00ffffff | (Trans<<24);
memcpy((BYTE*)lockRect.pBits + lockRect.Pitch*y + 4*x ), &color, sizeof(DWORD));
}
サーバのUNIXでCPU数を確認する方法
// サーフェイスアンロック
pTexture->UnlockRect(0);
サーフェイスの左上からオフセット(iOfs_x, iOfs_y)させて、ビットマップの幅と高さだけループを回しています。α情報の付加(colorの部分)は単純なビット演算ですね。メモリコピーはDWORD単位ですからポインタ演算を4倍して(4*xの部分)、4BYTEずつ書き込み位置をずらす必要があります。
これでα情報+アンチエイリアス付きのテクスチャが出来ました。後は、これを板ポリゴンいっぱいに貼り付ければ、1文字完成です。
A 板ポリゴンにテクスチャ貼り付け
テクスチャの貼り付けは難しくありませんが、α情報を用いるためにいくつか設定が必要になります。デバイスに対して次のような設定をするとOKです。
お使いのコンピュータを更新する方法
// テクスチャセット
g_pD3DDev->SetTexture(0, pTexture);
g_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
g_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP , D3DTOP_MODULATE );
g_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
g_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
g_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAOP , D3DTOP_MODULATE );
g_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); // 板ポリのα値を利用// レンダリングステート
g_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
g_pD3DDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_pD3DDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
あとはデバイスにポリゴンを指定して描画すれば、美しい透過処理のかかった高速フォント描画が完了です。実際に作ってみましたが、ちゃんとアンチエイリアスのかかったフォントが描画できました。
640×480(Full Screen) MSゴシック 200pixcel 10文字 半透明処理・回転中
ここまでの作業は大変面倒なのですが、一度テクスチャサーフェイスへの書き込みをしてしまえば、後はポリゴンの描画だけになるので非常に高速です。また、こうする事によって、板ポリゴンを動かせばフォントも自由に動かす事が出来ます。もちろん、回転や拡大縮小、半透明化、色の変化なども通常の絵と同じように扱えるのです。板ポリゴンのメッシュを増やせば、曲げたりもできるでしょうね。この自由度の高さがこの方法の最大の魅力です。
ここまで読んで頂いてお分かりの通り、この方法は板ポリゴンを1文字単位で作成しています。これには訳があって、ノベルス系のゲームの場合「文字送り」が必要になるからです。文字が1文字ずつ出てくるあれを行うには、1文字ずつ板ポリゴン文字を作り、それを整列させる必要があります。板ポリゴンをフォント領域(空白を含めた大きさ)にしたのは、その整列を簡単に行えるよう考慮したためです。特にフォントを固定ピッチにすると、単純に並べるだけで済んでしまいます。
テクスチャステージステートでは、実は板ポリゴンのα値を利用できるようにしています。これは、フォント文字を半透明にする時に非常に重宝します。これをうまく使うと、単なる文字送りではなくて、透明から半透明に文字がす〜っと出てくるような美しい効果も簡単に作ることが出来ます。そういうエフェクトは、ノベルスの雰囲気アップにもつながりますね。
最後にクラス化の話です。上の方法を整理すれば、1文字板ポリゴンを生成するクラスは割と簡単に出来そうです。さらに、文字を並べて文字列にするクラスがあれば、従来の文字列を扱うのとほぼ同様の手軽さが手に入ります。それをノベルス系の文字送りを行うクラスなどに派生することも可能でしょう。
0 コメント:
コメントを投稿