楽天モバイル[UNLIMITが今なら1円] ECナビでポインと Yahoo 楽天 LINEがデータ消費ゼロで月額500円〜!


無料ホームページ 無料のクレジットカード 海外格安航空券 解約手数料0円【あしたでんき】 海外旅行保険が無料! 海外ホテル

log

2009.11.25 LW:バジリコ、跳ぶ!

ファイル 214-1.jpg

今日はひさしぶりに昔制作していたバジリコのモデルを修正しておりました。

ウェイトの設定もある程度完成してきたので、さっそく適当に
ポーズをつけて遊んでいたところ、なかなか俯瞰のアングルが
ダイナミックで面白かったので、記念にキャプチャ。

ただ、体のラインを見せようと思ったんですが、スカートを
外すと完全にお尻が丸見えだったので、急遽パンツを作成笑。

なんとなく陸上競技の1シーンのような感じになりました。
お尻の部分は前からウェイト付けがすごく苦手だったので、
綺麗にできて、とりあえず嬉しい。

あとはパッと見で気になるところは足の甲位です。
けど、依然テクスチャが中途半端なのは相変わらずだな笑。

2009.11.25 C++:続・微調節

ファイル 213-1.jpg

微調節作業は今回も続きます。

今回は、キャラクタのポリゴンを削減したり、テクスチャを修正したり、
ウェイトを1頂点1ウェイトに設定したりしておりました。

キャラクタのポリゴン数は2000ポリゴンから1800ポリゴン以下まで
削減することができました。地球にやさしい10%カットです!笑
テクスチャも表情を大幅に修正。ちょっとだけ雰囲気が
でたような気がしますが、何だか別人になってしまったというか。
まだ納得いかないですね。

ポリゴン数を削減したことでプログラムがちょっとくらい早くなったかなと、
さっそく試してみたのですが。。前回28FPSだったのが
30FPSまでしか回復しませんでした。

まあ、全体でたかだか1000ポリ分の頂点計算が減っただけなので
こんなものです。1FPSを笑うものは1FPSに泣く、と。

エコといえば。今の鳩山さんの政権、すごい国債発行することに
なるらしいじゃないですか。あれだけ負債をこれ以上増やさないと
謳っていたのに。。

なんだか世界全体の景気は除々に回復してきてるそうなのに、
日本はまたデフレ経済に逆戻りしてるそうで。。
なんだかなあ。何とかならんもんかね。

2009.11.22 C++:一番のボトルネックはモーションのCPU計算でした

前回の惨事を踏まえて。頂点ブレンディング数が4つだったのを
減らしてみるとどうなるかという実験を行ってみたところ、

・ブレンディング数4:19FPS
・ブレンディング数3:23FPS
・ブレンディング数2:28FPS
という結果になりました。よかったー、そこそこ回復して。

けどブレンディング数を1にしてみると1頂点1ウェイトに
なるかなと思ったのですが、基本ポーズになってしまいました。。

自分のプログラムなのに、あまり把握できていないという苦笑。駄目だな。

ちなみにこの計算を踏まえると、モーションの毎フレーム計算を
12FPS程度にすれば、一応今のクオリティのままで10体まで
動かせるということが分かりました。

12FPSとか。。超ギリギリですね。というよりアウト?

そういえば、試しにテクスチャサイズも小さくしたり圧縮テクスチャを
使用したりしてみたのですが。これが全然FPSが変わらないんですよね。
E3Dを使っていたころはテクスチャサイズを変えただけで
ガラッとFPSが変わったりしたのに。。なんでなんだろ?

それと後々になって気がついたんですが。
僕の自作モーション関数はCPUで処理させてるから、それが
一番のネックになってるんじゃないかと思いました。
普通だったら頂点計算はGPUで計算させると思うので。

DirectXでモーションをやる場合、ほぼ9割近くの人は
ID3DXAllocateHierarchyインターフェイスというのを
扱うと思うのですが。ネットで調べてみてもなんだかとっつきにくそうで
今まで避けてたんですよ、こいつ。。けれどこれ以上の
クオリティを求めようと思うと、やっぱり覚えないといけないですね。

まあCPUでモーション計算できたっていうのはそれはそれでよかったかな。
状況によってはCPUよりもGPUの方が負荷が大きくなることもあるので、
状況に応じてモーション計算をCPUとGPUに分散できるように
なれば。。今までやってきたことも無駄ではないはず!

2009.11.21 C++:すごく重いよ、モーションが。

ファイル 211-1.jpg

                  ドドドドドド。

って感じでキャラを複製させようとしてみたのですが。なんと
3体目にして処理落ちが顕著になってしまったので、5対表示中、
モーションを行うモデル数を変えながらFPSを測定してみたところ、

・モーション1体:57FPS
・モーション2体:55FPS
・モーション3体:30FPS
・モーション4体:23FPS
・モーション5体:19FPS
という惨々たる結果になってしまいました…。

うーん。テクスチャサイズが大きいからというのもあるけど、
やっぱりある程度モーションの頂点バッファをあらかじめ生成しないと
駄目なようです。かといって全てのモーションの頂点バッファを
メモリに格納してしまうと、少なく見積もっても300MB以上はいきそうなので、
アイドリング・走り等の指定した基本動作だけあらかじめ生成した
頂点バッファを利用できるようにしようかな。
まあ、結局は容量を考えるとビデオメモリではなくシステムメモリに
格納することになっちゃう訳で。ビデオメモリに転送する手間を考えると
あまり効果がないような気もしますが。。

それと、メインの1体以外のモーションをOFFにした状態で
色々テストしていて気がついたんですが。どうもZバッファへの書き込み
というのはかなり処理速度が重いということが分かりました。

僕のプログラムではメインキャラを一番先に描画して、その後に
順番にオーバーライドモデルを描画してるのですが、メインキャラが
オーバーライドモデルより手前にいる場合と後ろにいる場合では
それぞれ56FPSと40FPSという差がでてしまいました。

これはおそらくメインキャラが後ろにいる場合、メインキャラをZバッファに
書き込んだ後、オーバーライドモデルを描画する際、同じピクセルに
結局また同じようにZバッファに書き込むことになるので
その分のロスによるものだと思います。

なので、一番効率のいい描画順序で行いたい場合は、
前のフレームで描画した際のモデルごとのピクセル数を格納しておいて、
描画する前にそのピクセル数を要素としてモデルの描画順序を
ソートしてあげればいいわけです。

て、まあ理屈は単純なんですが。描画したピクセル数なんて
どうやって取得すればいいのやら、さっぱりです。。
最近になって、少しずつシェーダを勉強し始めてるのですが、
ピクセルシェーダで取得でき…たらいいんですけどね。
まあ、そんなことしなくても単純にカメラ距離でソートする
っていうのもありかもしれない。

2009.11.21 C++:すごく怖いよ、表情が。

ファイル 210-1.jpg

モデルをオーバーライド読み込みできるようにしてみました。
よく分からない人のために説明すると、頂点バッファを新しく確保せずに
前に読み込んだモデルのデータを使いまわそうぜ!ってことです。
なのでその分読み込みが早くなります。なんせ、読み込まないので笑。

とりあえずキャラクターを2人表示させてみたのですが、
表示させてみて改めて分かったことがあります。それは、

表情がすごく堅くて怖い…。

こんなゲーム、僕だったらやりたいとは思いません苦笑。
とりあえず、なんとかしませう。

そういえば、UNREALエンジンに続いてCRYエンジンも
アカデミックの場合は無料になったそうです。
まあ、僕は学生ではないのですが。CRYエンジンのサイトを
色々見てみると。やっぱりすごいですね、クオリティが。
色々参考になると同時に、なんだか少し脱帽してしまいました。

2009.11.20 C++:微調節作業

ファイル 209-1.jpg

今回は色々と微調整作業をしておりました。
キャラクターにスペキュラを設定したり、ライティングを調節したり
フォグを設定してみたりといった感じです。

フォグは色々試してみましたが、どうしても深海の中や暗がりの中に
いるような、おどろおどろしい印象になってしまいます。
ちなみに画像だと、個人的には朝方の静かな時間帯の印象です。

卒制の時は深く考えなくても、フォグの演出がシーンと
合っていたんですが。今回の場合は少し難しいです。
自作でフォグを処理してみるのもいいかもしれないな。

それと前々から気づいてましたが、キャラの足が地面に埋まってます。
そろそろモーションを作ろうか、自分。

2009.11.18 C++:ミップマップできました

ファイル 208-1.jpg

色々プログラムをいじってたら、いつの間にかミップマップが出来てました笑。

テクスチャオブジェクトを作成する際、MipFilterの引数を
D3DX_FILTER_NONE以外にすると正しく描画されました。
この引数、今まではレンダーステートのフィルタ指定と
同じものなのかと思ってましたが、どうやら違うようだ。。

DirectXのテクスチャ生成関数にはFilterとMipFilterの
二つの引数が用意されてますが、これらはどうもテクスチャ生成時の
補間を指定している感じです。つまり、Fileterの引数は
読み込むテクスチャが2の累乗サイズでない場合、標準の
テクスチャ生成関数では自動的に2の累乗サイズに拡大して
くれるのですが、その拡大する時のサンプリング処理の指定を
表していて、MipFilter引数も同様にミップマップ生成時の
縮小のサンプリング処理の指定を表しているのかなと思いました。

それとUsage部分にD3DUSAGE_AUTOGENMIPMAPを指定すると
なぜかテクスチャが真っ黒になります。。なのでUsageには0を指定します。
なんだかD3DUSAGE_AUTOGENMIPMAPの必要性が
分からなくなってしまいました笑。

けど、前に色々いじった時も同じような設定を試したような気がするので、
原因は此処だけでは無いかもしれません。
まぁとりあえず出来たので、良しとしよう。


で、とりあえずミップマップができたので、レンダーステートの
ミップマップ補間を色々変更して実験してみました。(画像参照)
D3DX_FILTER_POINTだとミップ境界がはっきり分かる感じでした。
D3DX_FILTER_LINEARの場合、正面方向のポリゴンだと
ほとんど気がつかなくなりますが、視線と垂直なポリゴンだと、
境界はぼやけるものの何だか妙に気になります。(画像の"さ"部分の少し左)

一応D3DTEXF_ANISOTROPICも試してみましたが。
テクスチャが大きすぎたのか、またもやミップマップ使用前と同じように
ちらつきが発生してしまいました。おまけにフィールドを移動していると
定期的にFPSがガクッと下がる問題も発生!
(おそらくミップマップ境界と関係してそうですが)

今のところ、D3DX_FILTER_LINEARが安定かな。

2009.11.17 C++:カメラ視線に沿って移動(サンプルつき)

ミップマップの自動生成方法をネットで調べてみても、あまり
詳しくのっておらず、よく分からず終いだったので。。
(まぁ自動生成でなくとも手動生成が分かっているので別にいいのですが…。)
今回は少し嗜好を変えて、新しくモデルの移動命令を導入することにしました。

ちょっと前にO3Dを使っていたときに、カメラの視線方向に沿って
モデルを移動させる処理をやっていて。これは面白いなと
思ったので、C++でもさっそく自作で導入してみることにしました。

ちょうど日記にまとまる程度のコード量だったので、以下に
処理を記述してみることにします。

// カメラの視線ベクトルの角度CameraDirZを求める
float CameraDirZ = atan2f(
(CameraTarget.z - CameraPos.z),
(CameraTarget.x - CameraPos.x)
);
// カメラの視線ベクトルとアップベクトルに対して
// 垂直なベクトルの角度CameraDirXを求める
float CameraDirX = CameraDirZ - D3DX_PI/2;
// カメラ視線の角度を元に移動量を計算して座標値に増分
Pos.x += cosf( CameraDirX ) * directionX +
cosf( CameraDirZ ) * directionZ;
Pos.z += sinf( CameraDirX ) * directionX +
sinf( CameraDirZ ) * directionZ;

これだけです笑。
ちなみに変数の説明をすると、
・CameraPos,CameraTarget:カメラの座標と注視点の座標
・directionX:上/下キーが押されている場合+/-移動量が格納されている
・directionZ:右/左キーが押されている場合+/-移動量が格納されている
・Pos:モデルの座標
こんな感じです。CameraPos,CameraTargetは
E3Dを使っている人ならおそらくピンと来るだろうと思います。
directionX,ZはO3Dのチュートリアルサンプルそのままの使い方です笑。

ベクトルや行列を普段から使っているプログラマーさんにとっては
何でもない処理だろうと思いますが。僕みたいに今まで
ライブラリで楽してきたエセプログラマにとっては意外と
参考になるのではないかなと、そう思います。

簡単な処理なのでE3Dでももちろん導入可能だと思います。
最近E3Dから離れていたので、これで少しくらいお役に立てるといいな。

2009.11.15 C++:ミップマップことはじめ

ファイル 206-1.jpg

とりあえずモーション読み込みはある程度完成したので背景も
読み込ませてみたところ、テクスチャ解像度が大きすぎたせいで
カメラを動かすとテクスチャがノイズのようにちらついてしまったので
ミップマップを導入してみました。

とりあえずミップマップのバイアス値を-1にして試してみたところ…。
とりあえずテクスチャ解像度が下がったように見えたと思いきや。

な、なんだこりゃ!

明らかにテクスチャの表示がおかしいです。(画像参照)
実際の画像ファイルと照らし合わせてみたところ、どうやら
ただ単純に画像の左上4分の1だけ使用していることが判明。

うーん。とりあえず、バイアス値について調べてみよ。

2009.11.14 C++:スキンメッシュ読み込みまであと少し!

ファイル 205-1.jpg

ある程度きれいにモーションが読み込めるようになりました。
モーション読み込みに、ある程度も糞もあるかい!って云いたくなりますが笑。

とりあえず分かったことを以下にメモしてみます。

XファイルはAnimation Keyの中にフレーム(骨)のモーション量を
格納していて。Keyの種類は全部で4種類あり、
Key Typeが0だと回転、1だとスケール、2だと移動、
3だと行列をそれぞれ格納しているのですが。回転の要素が特別な値を
格納していたので、どう使用していいのか今まで全く分からなかったのです。

スケール・移動は要素数が3つ、行列は要素数が16なので
それぞれX,Y,Zと行列の中身を格納しているんだなというのが
分かったのですが。回転の要素数は、なんと"4つ"なのです。

3Dをやっている方ならピンと来るのだと思いますが、こいつはX,Y,Z値を
そのまま格納している訳ではなくて、4元数つまりクォータニオン
というものを格納しているらしいです。

クォータニオンについて今まで全く勉強してこなかったので、
それはもう悪戦苦闘することになりました。。

結論を先にいってしまうと、
回転のAnimation Key要素は、おそらく先頭から順番に
Quaternion.w、Quaternion.x~zの要素を格納しているようです。
そのクォータニオンをD3DXMatrixRotationQuaternionで行列に
変換してしまえば他と同じように行列で統一できます。


これでとりあえず回転の処理は完成しましたが、なんだか
頭の頂点が後ろに引っ張られてしまってます(画像参照)。
まぁ、これはDirectX標準ビュアーでもこうなっていたので
おそらく単なるウェイトの設定ミスだろうと思います。

後は背景はアニメーション頂点バッファを生成していない為、描画できて
いないので、アニメーション有り無しで描画処理を切り替えれば完成!

そういえば、いままでC++はHSPと比べて軽い軽いと謳ってましたが、
モーション処理を考慮に入れることをすっかり忘れておりました。。
(HSP+E3Dの作者・ユーザーさんごめんなさい。)

モーション処理を考慮にいれると描画毎に頂点バッファを書き換えて、
ビデオメモリにバッファを転送しなければならないので、
それなりに処理が重くなりそうです。

あらかじめアニメーション分の頂点バッファをビデオメモリに
格納するという手もありそうですが。。それだとモーション補間できないからなあ。
けど、噂ではベイグラントストーリーはモーションの指定フレームだけ
あらかじめ作成しておいたモデルに差し替えることで
処理速度とクオリティを向上させていたんだそうな。

なるほど、少しだけやってみる価値がありそうだ。