lwjgl でアニメーションするメッセージウインドウを実装する
ブログ開発も落ち着いてきて、最近はまたちらほらとゲーム作りに戻ってきています。ブログのネタとしては初かな。今日はゲームには欠かせないパラパラとメッセージがアニメーション表示されるやつのチューニングをしてました。
メッセージのアニメーションには、各フレーム毎に追加表示する分だけの文字を書き足していく、という実装をすると思います。今まではこの文字の追加表示のためにフレーム毎にテクスチャを glTexSubImage2D() で修正していて、アニメーション中は 6 ~ 10 FPS くらいしか出てなかったのです。
OpenGL 使いな方に言わせるとかなりあり得ない実装だったんでしょうが、実際やってみてそのあり得なさを実感した感じです。テクスチャ生成系はやっぱり重いですね。私は 60 FPS を目安に作っているので、6 FPS とかに落ちると目に見えてアニメーションがカクカクになります。それこそ中割りの少ないアニメみたいな。動画さんもっとがんばれーみたいな。
2012/06/15 追記
その後の調査でボトルネックはテクスチャー更新というより、Java AWT の Graphics を使った日本語フォントの描画だったのではないかという疑惑が浮上しましたが、今回のチューニングの趣旨(テクスチャー生成回数を減らす)自体は相変わらず有効なので、実証はしていません。脱 AWT Graphics ができれば、さらに高速化を図れると思われます。
文字もテクスチャにしてから表示する
OpenGL や DirectX なんかの場合、文字列の表示は結構な難所です。普通の 2D グラフィクスと違い、あらゆる画像は一度テクスチャ化しておかなければならないからです。java の awt や swt なんかだと、何も考えずに drawString() とかすれば即座に文字を表示できますが、OpenGL では表示する文字を画像として準備し、テクスチャとして読み込み、そのテクスチャを貼り付けるという手順を踏みます。市販のゲームだと、フォントに含まれる文字をあらかじめすべて画像に書き出しておき、表示する時にはその画像(を読み込んだテクスチャ)から必要な文字だけを切り貼りして表示するらしいです。
それが正解なんでしょうが、プロポーショナルフォントの場合、各文字の座標やサイズを逐一マッピングして読み出せるようにしておく必要があります。正直、趣味のゲーム製作でそんなフォントデータなんかまで作っていたらとても完成する気がしません。日本語に漢字がいったいどれだけあるのかという話です。文字を一字一字サイズをチェックしてデータ化しなければなりませんし、フォントを変えようとすると莫大な手戻りが発生します。
なので私は、実行時に java の BufferedImage に Graphics2D で表示する文字だけを描きこみ、テクスチャに変換するという手法を取っています。
今回の件から私が得るべき教訓は、テクスチャ生成は重いということだ
ところで、メッセージウインドウのアニメーションでのポイントは、表示していく文字が時間経過によって増えていく点です。アニメーションが進むにつれて表示する文字の数が増えていくので、すべての文字を画像として用意しておかない場合、表示する分だけの文字をフレーム毎にテクスチャとして用意し直さなければならないわけです。しかし一方で、OpenGL も DirectX も、テクスチャの生成や修正はとてつもなく遅いのです。具体的には、FPS が 6 とかにがた落ちするくらいに。
一度テクスチャを生成してしまえば、それを貼り付けるのは超早いのですけどね。
あらかじめ表示メッセージの全文を用意しておき、そこから切り貼りする
そこで解決策として、表示するメッセージは一部でなく全部テクスチャに描きだしておいて、アニメーション時にはそこから必要な部分だけを貼り付けていくという実装に変えました。市販ゲームで事前に用意しておくというらしい全文字の画像の代わりに、表示する文字だけの画像を実行時に用意するのです。やっぱりテクスチャ生成の処理は必要ですが、それもアニメーション開始前のフレームで1度だけやればいいので、アニメーション中はテクスチャを生成する必要がなくなります。これで FPS は 50 台まで復活しました。あとは駄文。
これを思いついたのは、ウィザードリィオンラインのメッセージ表示を思い出してでした。見てもらうとわかるんですが、文字のアニメーションがドラクエみたく1文字単位じゃなくて、ピクセル単位なんですよね。なので文字が左端とか左半分とかだけ見えてる瞬間が結構あります。ああ、あらかじめメッセージの全文を描き込んだテクスチャを用意しておいて、その表示領域だけ徐々に増やしてるんだな~っていうのがよくわかるのです。
そういう意味では、他のゲームにもちょいちょい触れておく事もいいことだなと思ったのでした。
ゲーム製作 コメント (0) 2012/02/24 00:39:37