AWT Graphics での描画処理を高速化してみる
ゲーム開発は引き続き土台整備をしています。LWJGL でテクスチャーを読み込んでいたら、サイズが 1024 * 1024 以上の画像が 3 枚くらいになってからロード時間の長さが気になるようになりました。
画像 1 枚読み込むたびに 1 秒くらいかかるとなると、さすがに見過ごせないなーということで、きっちりプロファイリングして原因を探ってみました。
結論から言うと、読み込んだ BufferedImage を LWJGL の glTexImage2D() に渡す ByteBuffer に変換する際に Java AWT の Graphics を使っていたのが問題でした。
glTexImage2D() に渡す画像のバイトデータには、ある形式の ColorModel・Raster を使っているのですが、読み込んだ画像の画像データ形式がこれと同じという保証はないため、正しいデータ形式の BufferedImage を作って、Graphics.drawImage() で描き直していました。が、この Grpahics を使った処理が思いの外重いのです。
AWT の Graphics を使わずに、BufferedImage のピクセルデータを直接 ByteBuffer に積み直すという処理に変えてみたところ、かなり高速化することができました。
改良前後の速度差はこちら。
画像の大きさとファイルサイズが違う画像をいくつか読み込んで処理時間を計測してみました。
PNG 800*400 32.6KB
212.79561 mili sec. → 36.39858 mili sec.
PNG 500*250 13.4KB
29.673136 mili sec. → 18.440008 mili sec.
JPG 2048*2048 347KB
640.6848 mili sec. → 79.925674 mili sec.
PNG 1024*1024 1.22MB
618.1265 mili sec. → 45.179134 mili sec.
PNG 960*480 240KB
104.69864 mili sec. → 14.152516 mili sec.
のきなみ速くなってます。212.79561 mili sec. → 36.39858 mili sec.
PNG 500*250 13.4KB
29.673136 mili sec. → 18.440008 mili sec.
JPG 2048*2048 347KB
640.6848 mili sec. → 79.925674 mili sec.
PNG 1024*1024 1.22MB
618.1265 mili sec. → 45.179134 mili sec.
PNG 960*480 240KB
104.69864 mili sec. → 14.152516 mili sec.
Graphics 使用時に数百ミリ秒かかっていたのが数十ミリ秒で変換できるとなると、まさに効果は抜群だ!という感じ。1 桁減るのは大きいですよねー。
……うーん、ゲーム用途では AWT Graphics は使っちゃだめだということですね。
今回は LWJGL 用ということで ByteBuffer に積み直してますが、AWT でゲームを作る際にも、Raster に対して直接ピクセルデータを読み書きするとか、Raster から DataBufferByte(等)→ byte 配列を取り出し、直接ビット演算して BufferedImage 再構築するとかした方が早くなりそう。とにかく Graphics を介しちゃうと重くなってしまいます。
続きを読む ゲーム製作 コメント (0) 2012/06/15 22:44:20