Admin * New entry * Up load * All archives 

C++&DirectXでプチプチゲーム制作をしています。文章力?気合で乗り越えるさ。

 

旧 ゲーム的な何か。

04«1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.»06
このページの記事一覧

    

Posted on --:--:-- «edit»

Category:スポンサー広告

スポンサーサイト 

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

tb: --     com: --

go page top

Posted on 23:30:38 «edit»

Category:プログラミングとか

高速文字列描画クラス 

どうもこんばんは、Signalです。久しぶりの学校は流石につらいですね。眠くてたまりません。

さて、今日は自作の高速文字列描画クラスを紹介しようかと。
文字列描画と言えばDirectXを扱う以上は必ずぶつかる問題かと勝手に想像しています。少なくとも私は苦労しました。
一応前作品の「Project MARCHOSIAS」では「○×つくろー」さんの
ゲームつくろー!→DirectX9技術編→その5「高速フォント表示」
を参考にして文字列描画を実現してはいたのですが、残念なことに等幅表示までしか組めなかったので、今回は変幅表示もできるように組んでみました。

「車輪の再発明」という言葉がある通り、同じ過ちまたは苦労を繰り返すことはあまり望ましいことではありません。ちょっと引っかかりそうな部分を理解する足掛かりになればなー、と思います。

ちなみにこのクラスを作成した後に気付いたのですが、「○×つくろー」さんの所に「文字列描画クラス」はすでにありました。。なんでもありますね、ホント。
ゲームつくろー!→ツール編→その5「ビルボード文字列クラス」を拝見したのですが、私の頭では理解できず、苦労が水の泡、ということは免れましたが、間違いなく動作が速いのはあちらだと思いますね。

まぁ、プロにかなうはずもないので、私の方ではよりシンプルに、楽な方法を使って実用レベルにしていこうと思います。

・ID3DXFONTインターフェース
DirectXにはID3DXFONTと呼ばれるインターフェースがありまして、これを使えば相当簡単に文字列を表示することができます。SDKのサンプルの「Text3D」にて紹介されています。
しかし、DrawText関数を呼ぶたびに文字列表示用のテクスチャを生成するためパフォーマンスが非常に悪く、デバッグぐらいにしか使えません。
ただし、フォントの設定の幅は広く、等幅・変幅などの設定も容易なので、これとDirectX自慢のテクスチャ描画と組み合わせてクラスを作っていきます。

・描画の流れ
通常DrawText関数はバックバッファに直接表示しますが、今回はDrawText関数の呼び出しを最小限に抑えます。
テクスチャに1度文字列を貼ってそのテクスチャを表示することで1枚のテクスチャ並みの負荷に抑えようということです。
以下に流れを示します。

1.描画したいフォント、文字列を受け取る
2.D3DXCreateFont関数でフォントを作成
3. DrawText関数を呼び出す(フラグにDT_CALCRECTを指定)

テクスチャに文字列を書き込むためにはまず必要なテクスチャのサイズを計算しその大きさのテクスチャを作る必要があります。大きさを計算する方法はいくつかあるのですが、DrawText関数にフラグを指定することによって、その文字列を描画した場合に必要な領域のサイズを受け取ることができます(描画はされない)

4. CreateTexture関数で必要な大きさのテクスチャを作成する
5. GetSurfaceLevel関数でサーフェイスを取得
6. レンダリングターゲットをテクスチャに設定

4でテクスチャを作成する際、UsageにD3DUSAGE_RENDERTARGETを指定します。これによってそのテクスチャをレンダリングターゲットにすることができます。

7.テクスチャを透明色でClearする
8.テクスチャにDrawText関数でレンダリング(今度は実際に描画)
9.レンダリングターゲットを元に戻す

レンダリングターゲットを元に戻すためには、あらかじめバックバッファへのポインタが必要です。クラスという形で実装する場合は何らかの形でポインタを受け取っておく必要があります。私の場合は「バックバッファのポインタ」のポインタを受け取って関数を呼び出しました。また、今回はテクスチャに深度バッファを用意せず、省略しています(3Dモデルを描画しないため)

これで晴れて文字列が描画されたテクスチャが完成しました。後は煮ても焼いても構いません。
今回は、

10. 各種レンダリングステートを設定
11. 頂点バッファを用意
12. テクスチャを適用、DrawPrimitiveUpで描画

とくにひねりはないですね。ただ、2つほど注意点があります。
①線形補間は外す
②頂点座標を調整する(丸め誤差の解消)
①は当たり前かもしれませんが、引っかかるとしばらく悩むことになります←実体験
②も既知の問題ですね。各座標値に-0.5して誤差を解消しています。

以上が今回のクラスの描画ステップです。素人製なので初心者の方にもある程度理解できるかなー、と勝手に思っています。

・注意点
レンダリングターゲット用のテクスチャを作成した場合、CreateTextureの引数PoolをD3DPOOL_DEFAULTにする必要があります。そのため、デバイスロスト時は解放、再取得を手動で行う必要があります。これに関してはご自分で処理を記述してください。(私がまだやっていないのと、クラス化すると多少複雑化するため)

ファイルのダウンロード
コチラからお願いします。
readmeにも書きましたが、素人のコードなので正しく動くかわかりません。適当に改変して使ってくださいませ。

ではでは。

テーマ: プログラミング

ジャンル: コンピュータ

 Re: 高速文字列描画クラス

おはようございます、ディムRPです^^

これが「高速文字列描画クラス」ですか……。

というか読んでみて分かったことは、
文字を画像つーかテクスチャに貼る」。

「文字を画像にしちゃえば高速に描画される」って事なんですよね?

んで、そこで質問なんですが。
何故に直接描画するより画像として描画した方が早いんですか?

  by ディムRP

 Re: 高速文字列描画クラス

>ディムRPさん
コメントありがとうございます。あの分かりにくい記事を読んで理解してくださるとは、察しがいいですね。仰るとおりです。
詳しい仕組みを話すとなると私も説明できないので、表面上の話で説明しますね。

元々、DirectXはゲーム向けのライブラリとして誕生したため、初期のころからグラフィックの描画速度を重視して、ハードウェアの機能を最大限に引き出すように作られてきました。そのためテクスチャの描画は非常に早く作られています。

対してID3DXFONTは、DirectXの提供する機能でありながら内部的にはGDI描画と呼ばれる非常に重い描画機構を使っています。GDI描画は(多分)CPUのみで描画を行っており、グラフィックボードを使った高速な描画が全くできないため遅いのだと私は思ってます。

そのため、文字列を速く描画するためには、一度DirectXの得意なテクスチャに変換する必要があるというわけです。今のところはこのように自分で組み立てる以外に方法はないようです。便利な機能が出来るといいのですが。。この自由度がDirectXの特徴なので、妥協するより仕方ない感じです。

  by Signal

 管理人のみ閲覧できます

  by -

Comment-WRITES

go page top

 この記事に対するコメント 

Re: 高速文字列描画クラス

おはようございます、ディムRPです^^

これが「高速文字列描画クラス」ですか……。

というか読んでみて分かったことは、
文字を画像つーかテクスチャに貼る」。

「文字を画像にしちゃえば高速に描画される」って事なんですよね?

んで、そこで質問なんですが。
何故に直接描画するより画像として描画した方が早いんですか?

2010/01/23 12:41 | URL | ディムRP #-  edit

Re: 高速文字列描画クラス

>ディムRPさん
コメントありがとうございます。あの分かりにくい記事を読んで理解してくださるとは、察しがいいですね。仰るとおりです。
詳しい仕組みを話すとなると私も説明できないので、表面上の話で説明しますね。

元々、DirectXはゲーム向けのライブラリとして誕生したため、初期のころからグラフィックの描画速度を重視して、ハードウェアの機能を最大限に引き出すように作られてきました。そのためテクスチャの描画は非常に早く作られています。

対してID3DXFONTは、DirectXの提供する機能でありながら内部的にはGDI描画と呼ばれる非常に重い描画機構を使っています。GDI描画は(多分)CPUのみで描画を行っており、グラフィックボードを使った高速な描画が全くできないため遅いのだと私は思ってます。

そのため、文字列を速く描画するためには、一度DirectXの得意なテクスチャに変換する必要があるというわけです。今のところはこのように自分で組み立てる以外に方法はないようです。便利な機能が出来るといいのですが。。この自由度がDirectXの特徴なので、妥協するより仕方ない感じです。

2010/01/23 22:18 | URL | Signal #-  edit

管理人のみ閲覧できます

このコメントは管理人のみ閲覧できます

2010/01/25 17:12 |  |  #  edit

go page top

 コメント投稿 
Secret

go page top

 トラックバック 
トラックバックURL
→http://frontiersman.blog61.fc2.com/tb.php/177-22f309e1
この記事にトラックバックする(FC2ブログユーザー)

go page top

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。