ページ 1 / 1
大きいPNGの高速描画のコツ
Posted: 2009年3月18日(水) 08:34
by Ma
連続ですみません。
BCC Developer で、 DXライブラリ を使用している者です。
透明化してあるPNGファイル(350×250)程度の画像を、タイトル画面の背景として二倍に拡大して画面に表示しようとしています。
これを、DrawExtendGraph 関数を使用して実現しましたが、3,4枚ほど描画すると、段々と重くなり
処理が 62.5fps から 40fps まで低下してしまいました。
これを、なんとか 60fps 程度まで上げたいのですが良い方法はありませんか?
*いままでやってみたこと
DrawExtendGraph は処理が重いので、画像サイズを700×500にしてDrawGraph で挑戦。
結果は、少し早くなっただけで、ファイルサイズが4倍になるので、断念。
画像を LoadDivGraph によって、 32×32 に分割して描画する。
結果は、多少高速化したものの、40fps⇒50fps 程度で、効果は微妙。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月18日(水) 09:35
by fatens
DrawExtendGraph関数を使用してフルカラーの写真(350×250, png, 188kb)を2倍で
1フレームに50回描画してみましたが、FPSの低下はおこりませんでした。
表示する処理の中で、何度も画像をロードしていないかを確認してみてください。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月18日(水) 09:44
by 朽木
>FPSの低下はおこりませんでした。
そもそも1フレームに50回と制限してる時点で、処理能力の高い環境では描画分の処理時間が入る程度の余裕ができ、
その分のずれが実際の結果として見えないため、1フレームに1回と制限するのと同じで、
検証とはいえない気がするのですが。
私が間違ってたらごめんなさい(´・ω・`)
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月18日(水) 09:48
by Ma
すいません、実際には5枚ほどありまして、それらを描画する結果、40fpsに低下しました。
説明不足ですみません。
(毎回ロードはしていません。)
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月18日(水) 09:53
by Mist
処理時間云々はPC(CPU、メモリ、グラボ、OS等々)の影響によるところが大きいですからね。
MaさんがPCのスペックを書いてませんので検証はあまり意味ないかもしれませんね。
Maさんの既に書かれている処理が最良のものだけど、PCの性能不足が原因というのも無いとは言えませんし。
Maさんの環境(PCのスペック等々)と、現象を再現できる最小限のソースがあれば有効な回答を得やすいのではないでしょうか。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月18日(水) 09:58
by fatens
>朽木さん、Mistさん
3,4枚描画するだけでFPSが低下するとは考えられなかったので上のように書いてしまいました。
処理能力については考えてませんでしたね。
すいません。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月18日(水) 10:08
by Ma
環境です。
OS:Windows XP SP3
CPU: AMD Athlon(tm) 4 1.10 Ghz
メモリ: 736MB RAM
カード: Sis 740
5年ぐらい前に、10数万円で買ったものなので、結構スペックは低めです。
(現在作っているゲームでは、12×50 のpngを DrawRotaGraph2 で150枚程度描画しても60fps前後で、処理落ちしません。)
*追記です。
タスクマネージャーより、優先度を通常以上に変更したら 40fps ⇒ 50fps になりました。(ウィンドウモード)
その優先度のままで、フルスクリーンにしてみると、 60fpsまで上昇しました。
優先度を通常にして、最初からフルスクリーンで起動してみると、40 ⇒ 50 fps(ウィンドウ⇒フル)
優先度かえるだけで変化するということは、PCの性能が原因でしょうか・・・
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 08:26
by 朽木
優先度を変えると、そのプログラムに割り当てられる時間が多くなります。
そのため、その分処理できる命令数も増えます(全体的に向上するという意味ではありません)から、
フレームレートが改善されることがあります。そのため、「PCの性能が原因ではないか?」という考えは、
自分のプログラムに非が無く、最適化がされ、良質であるという自信がある(笑)時にするべきだと思います。
大抵は、プログラムが無駄な処理をしています。
もちろん、3Dゲームをするのに Pen3 オンボードグラフィック というのは流石に問題があるとは思いますが…@@;
そういえば、描画関係のみしか書かれていなかったので思いつきませんでしたが、
その他の部分で改善できるような点はないでしょうか。例えば、
for (int i = 0; strlen("文字列") > i; i++) {
/* 適当な処理 */
}
というのは、毎回strlen()を評価するため、その分、1回のループで処理する量が増え、
結果を出すまでの時間が長くなります。また、関数を呼び出すというのは時間が掛かるので、呼び出し時間でも
損をしています。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 10:20
by Ma
たしかに、他の部分に原因があるかもしれませんね。
問題の可能性があるコードを部分的に記してみます。
oid drawMenuBG(){
//以下は、それぞれの画像のx座標です。
static double cloud1left = -100;//雲1
static double cloud2left = -190;//雲2
static double cloud1right = 400;//雲3
static double cloud2right = 200;//雲4
static double logoCloud = 0;//ロゴ
static double planeCord = 0;//画像
DrawGraph(0,0,images[6],FALSE);//BG。
//本来は、ここで、↑の変数の値を変える。
//A地点
DrawExtendGraph(logoCloud,50,logoCloud+350*2,50+125*2,images[37],true);
DrawExtendGraph(cloud2left,600-174*2,cloud2left+373*2,600,images[33],true);
DrawExtendGraph(cloud2right,600-181*2,cloud2right+380*2,600,images[35],true);
DrawExtendGraph(cloud1left,600-127*2,cloud1left+400*2,600,images[32],true);
DrawExtendGraph(cloud1right,600-102*2,cloud1right+336*2,600,images[34],true);
//B地点
}
A地点からB地点をコメントアウトすると、60fpsに回復します。
やっぱり、この部分だけをコメントアウトすると処理落ち回避できるので他は問題ないと思います。
ある数字 *2 ってのは、画像のサイズを二倍にするためです。
images[37] は、350×125 44.1KB のPNGファイル。
images[33] は、373×244 77.5 KB の PNGファイル。
images[35] は、380×181 54.9KB のPNGファイル。
images[32] は 400×127 57.1KB のPNGファイル。
images[34] は、336×102 42.0KB のPNGファイル。
画面全体が 800×600なので、縦軸においての描画範囲は、600-(縦幅*2) から 600 となっています。
(画面の下部分にくっついて移動するようにしたいためです。)
*追加情報
DrawExtendGraph を一個ずつコメントアウトしてみると、画像の枚数に比例して処理落ちをしているようです。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:07
by 朽木
雲の画像を背景で動かしたい感じでしょうか?動的なもののようなので、全統合して一気に表示っていうのは
ダメみたいですね。
ところで、DrawExtendGraph() の引数に double 幅の値が入っていますね。
「カクカクしたくない」「ゆっくり動かしたい」という場合は、?回に1回表示、とすれば良いだけです。
弾幕のように、高い精度で扱う必要がある事以外は、int 幅での扱いで十分でしょう。
実数型の計算は、整数に比べて、環境によって差はありますが、非常に遅いので注意して下さい。
というか、まさか変数全て double にしているなんて事はないですよね。
小数を必要とする時以外は整数で扱って下さい。いちいちキャストさせるとか無駄すぎます。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:09
by 朽木
ごめんなさい。
× ?回に1回表示
○ ?回に1回移動
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:11
by Ma
すいませんdoubleの乱用には気をつけます。
int に直しましたが、変化はありませんでした。
あと、動的に動かさなかったとしても、処理速度は変わらないみたいですorz
それどころか変数を使わずに、DrawExtendGraphの引数に整数値をいれても遅いままで変化ありませんでした。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:20
by バグ
素朴な疑問なのですが、透過処理をしたPNG画像を描画する際にも、第6引数はTRUEにしないといけないのでしょうか?(^_^;)
よく知らずに書き込んでいるので、そうだったらそれで構わないのですが…
もし、そうでないのならば、既に透過処理されている画像に更に透過処理を行ったうえで、縮尺描画処理を行う
という非常に重い処理を内部で行っている可能性があります。
ついでに、TRUEとtrue、FALSEとfalseはそれぞれ別物です。DXライブラリのフラグ変数は、基本的にWINAPIのBOOL型と同じものなので、TRUEとFALSEで書くべきです。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:25
by Ma
>ついでに、TRUEとtrue、FALSEとfalseはそれぞれ別物です。
Σ(∵)!!!まじすか!
これから、DXライブラリの関数では大文字で書くようにします。
なお、 true⇒TRUE に直しましたが処理速度には変化ありませんでした。
>もし、そうでないのならば、既に透過処理されている画像に更に透過処理を行ったうえで、縮尺描画処理を行うという非常に重い処理を内部で行っている可能性があります。
FALSEとやると、PNGの透過が無視されてすごいことになりました。
どうやら、TRUEであっているようです。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:32
by 朽木
>true⇒TRUE に直しましたが処理速度には変化ありませんでした。
そういうことではないかと。扱うビット数が違かったり、それぞれで値が違うんじゃなかったんでしたっけ。
ごめんなさい。忘れました。
あと、一番背面の画像がもし風景(透過部分が無い)の絵なのであれば、は別にFALSEでも良いと思います。
透過しても意味無いですし。
同じように、透過部分が無い絵はなるべくFALSEにするべきです。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:32
by バグ
それだったら、透過処理が有効なPNG画像を使用するメリットはあまりないように思います。
BMP形式に変更すれば、かなり描画速度が上がるんじゃないかと思われますよ(^-^)
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:35
by Mist
> 素朴な疑問なのですが、透過処理をしたPNG画像を描画する際にも、第6引数はTRUEにしないといけないのでしょうか?(^_^;)
ずいぶん前のバージョンではPNG画像の場合はフラグ関係無しとなっていましたが、それじゃおかしいだろという指摘があって変更されましたね。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:35
by 朽木
>BMP形式に変更すれば、かなり描画速度が上がるんじゃないかと思われますよ
あれ、DXライブラリって、読み込んだ画像って圧縮したまま扱うんですか?すごい非効率ですね…@@;;;
全て同じような形式に変換されてから扱われると思ってました。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:38
by Mist
> それだったら、透過処理が有効なPNG画像を使用するメリットはあまりないように思います。
それは違います。
PNG画像のα情報を有効にするか無効にするかの違いだったと思います。
BMPだと指定色しか透過できないから、作る時点での手間とファイルサイズを考えればPNGのメリットはあります。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:40
by Ma
>あと、一番背面の画像がもし風景(透過部分が無い)の絵なのであれば、は別にFALSEでも良いと思います。
やってますよ。
DrawGraph(0,0,images[6],FALSE);//BG。
すこし、説明不足でしたね。透明部分を持つ画像が、5枚動くこととなり、背景の一枚はjpgです。
つまり、image[6]は 800×600 の jpeg画像です。
>BMP形式に変更すれば、かなり描画速度が上がるんじゃないかと思われますよ(^-^)
ちょっと、ファイルサイズがかさばるので、できれば避けたいです><
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:40
by Mist
> あれ、DXライブラリって、読み込んだ画像って圧縮したまま扱うんですか?すごい非効率ですね…@@;;;
そんなことないですよ。
読み込むときの時間は変わりますが描画時は変わらないです。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:40
by バグ
あぁ、なるほど、そういう意味でのフラグでしたか。失礼しました(^_^;)
そうなると、どうして描画にそこまで時間が掛かっているのかが分かりませんね。
プロジェクトごとアップしてもらって、別のPCで試してみる…というくらいしか思いつきません。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:44
by SCI
質問者さんのPCスペックから考えて、さすがにdouble演算やキャストが原因ってことはないでしょう。
DrawRotaGraph2の実験結果から見ても、画像サイズや枚数、実浮動小数点数演算が原因とは考えにくいです。
必要のない部分まで描画していたり、多重のアルファブレンドが多いと重くなりそうな気がしますが、それだけではDrawExtendGraphのときだけ処理落ちすることが説明できませんね・・・
#追記
「画像サイズ」は除外できませんね。上のテストでは小さい画像をたくさん使っているので・・・
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:45
by Ma
>プロジェクトごとアップしてもらって、別のPCで試してみる…というくらいしか思いつきません。
すいません、今のプロジェクトはやはりUPしたくないので、
新しくプロジェクトを作って、同じ状況を作ってみます。
あと、もう一台のPCでも検証してみることにしてみます。
少々お待ちを・・・
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:47
by 朽木
>No:31053(Ma)
あっ、ごめんなさい見逃してました。@@;;;
>No:31054(Mist)
ですよね。
>No:31055(バグ)
最初は助言だけでなんとかなりそうな気もしましたが、、、
まぁ、本人としてはあまり見せたくない部分があるかもしれないので、Helupするかどうかは本人次第です。
追記:
>No:31056(SCI)
いや、それに比べればそうなんですが、気になったので…@@
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:50
by Ma
>DrawExtendGraphのときだけ処理落ちすることが説明できませんね・・・
すいません、もう一度 DrawRotaGraph で実行してみたら、
DrawExtendGraph と同じくらい、処理落ちしていました。
間違った情報申し訳ありません。
先ほどの
DrawExtendGraph(logoCloud,50,logoCloud+350*2,50+125*2,images[37],TRUE);
の代わりに
DrawRotaGraph( logoCloud+175, 50+63, 2, 0, images[37] , TRUE , FALSE ) ;
175は横幅の半分、63は縦幅の約半分というかんじでしたが、
ほぼ同等に処理落ちを確認しました。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:54
by Mist
今回の部分以外では画像の拡大・縮小は使われていないのでしょうか?
グラボのドライバがきちんと対応出来ていないという可能性もなくはないので、最新でないなら最新にしてみるとをお勧めします。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 11:56
by SCI
>Maさん
あぁ、じゃあ画像サイズの問題かも知れませんね。
大量のピクセルを描画するレンダリングは普通に考えて重い処理なので、大量の小さい画像より処理が重くなりそうな気もします。
#テストしていないのでホントはどうか分かりませんが(笑
ついでに、画面からはみ出している部分、たくさん重なっている部分はありませんか?
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 12:01
by Ma
>ついでに、画面からはみ出している部分、たくさん重なっている部分はありませんか?
ありません。
>今回の部分以外では画像の拡大・縮小は使われていないのでしょうか?
使っていますが、その拡大する画像のサイズが20×30 のような小型な画像なので
一切問題なく描画できていました。
使った関数は DrawRotaGraph2 で、1フレームに100枚程度描画しても問題ありませんでした。
>あと、もう一台のPCでも検証してみることにしてみます。
Windows XP
SP3
Intel(R)
Pentium(R) 4 CPU 3.00 GHz
0.99GB RAM
こんな環境で同じように起動してみました。
普通に62.5fps で余裕でした。
明らかに、CPUの性能が違うので当たり前といえば当たり前なのかな?
*追記
>グラボのドライバがきちんと対応出来ていないという可能性もなくはないので、最新でないなら最新にしてみるとをお勧めします。
ドライバは、半年以内に更新したはずなので、大丈夫だと思っていたのですが、更新してみますね。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 12:04
by 朽木
逆に私は小さく分けた方が重くなるのかと思ってました…
640x480 -> 描画
640x480 -> 320x240 -> 描画
320x240 -> 描画
320x240 -> 描画
320x240 -> 描画
->の部分は関数呼び出しになるわけなので、それも無駄ですし…
分割ってSTGとかRPGツクール用の画像を容易に扱うものと思ってました@@;;;
> Pentium(R) 4 CPU 3.00 GHz 普通に62.5fps で余裕
> 明らかに、CPUの性能が違うので当たり前といえば当たり前なのか
Pen3 と i7 を比較するのと同じ考え方ですから、なるべき結果でしょう。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 12:10
by SCI
>朽木さん
大きい画像と小さい画像のどちらが重いかは全くの予想です。
ただ、レンダリングに比べれば関数呼出しのオーバヘッドは無視できるレベルかと。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 12:11
by GPGA
私にはただのPCのスペック不足にしか見えないんですけど・・・。
描画速度は、表示する面積に比例するわけで、枚数とかあまり考える必要がありません。
(PCのスペックにもよりますが2000枚以上とかだと流石に考える必要があります)
例えば、↑で12x50の画像を150枚描画しても処理落ちしないと言っていますが。
12x50x150で書き込んでいるピクセルは90000ピクセルです。
それに対して、
>images[37] は、350×125 44.1KB のPNGファイル。
>images[33] は、373×244 77.5 KB の PNGファイル。
>images[35] は、380×181 54.9KB のPNGファイル。
>images[32] は 400×127 57.1KB のPNGファイル。
>images[34] は、336×102 42.0KB のPNGファイル。
と800x600の背景1枚を描画した際のピクセルは 812364 ピクセルと、実に9倍以上です。
画面に書き込む量を最小限にして、描画するようにしましょう。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 12:19
by GPGA
大きい画像と小さい画像のどちらが速くなるかに関しては、ハードウェアに依存する部分が大きいです。
単なるCPU処理ですと、関数オーバーヘッドの分、小さい画像を複数枚描画するほうが遅くなります。
PSやPSPなんかのゲーム機ですと、VRAMに境界線があり1回の描画でその境界線を跨ぐと描画速度が遅くなります。
例えば32byte単位の境界線があるハードウェアで、256色(1dot/1byte)の64x64の画像を描画する場合は
1回で描画してしまうと、境界線を跨いで遅くなってしまうため、32x64を2回描画したほうが描画速度が向上します。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 12:24
by Ma
>私にはただのPCのスペック不足にしか見えないんですけど・・・。
そんな気がします・・・
>画面に書き込む量を最小限にして、描画するようにしましょう。
たしかに、雲の枚数を減らす事はできますね。
ですが、タイトル画面ですので、他の部分と同じように描画の面積自体を小さくするのは難しいですね。
(またぴよぴよに…w)
最終的には、
環境が悪い。
また、描画面積を減らすという事で改良ができるということになりますね。
一応解決としておきます。皆様の協力ありがとうございます。<(_ _)>
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 12:28
by GPGA
PCスペック的に800x600のゲームに耐えられない気がするのですが
ウインドウサイズを640x480にするのはできないんですか?
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 12:30
by SCI
同じような画像作って実験してみました。
圧縮率が違ったり他の処理が無かったりでなんだかんだ等価なコードではないですが・・・
CPU2GHz、2GBRAM、ノートPCのオンボードで透過グラデーションのPNGを描画しましたが処理落ちはしませんでした。
実験せずに発言してしまったことが恥ずかしい限りですね(笑
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 12:33
by Ma
>ウインドウサイズを640x480にするのはできないんですか?
たしかに、そのほうがいいかもしれませんね。。。
640×480がどうも小さく感じたので、800×600に変えてしまいました。
これから、ウィンドウサイズを変えると、いろいろと変えたり直したりが面倒ですし、
将来的には、友達などに配布、(ネットも?)という予定なので、
800×600のままにしておきたいところです。
(ほとんど皆、自分より良い環境でしょうしw)
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 12:42
by 御津凪
全く関係ない話ですが、
> (またぴよぴよに…w)
どうやら名前が全角文字の時と半角文字の時があるようです。
ポイントは別々にカウントされています。
名前はどちらかに統一したほうが良いでしょう。
(ちなみに、現在、全角文字の方がぴよぴよで、半角文字の方がかけだしとなっていますよ)
# そういえば、他にも同じような方がいましたね。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月19日(木) 23:58
by EX
解決とありますが、一応思い当ったことを。
SetUse3DFlag()という関数を使い、フラグをFALSEにしていませんか?
もしそうであれば、フラグをTRUEにするか、
SetScreenMemToVramFlag()関数のフラグをFALSEにしてみてください。
そうでなくても、試しにSetScreenMemToVramFlag()関数のフラグをFALSEにしてみてください。
もしかしたら、DXライブラリのこの関数のリファレンスに書かれていることが原因かもしれません。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月20日(金) 02:55
by Justy
>SetUse3DFlag()という関数を使い、フラグをFALSEにしていませんか?
そういう意味では、その手の「パフォーマンスを落とし互換性をあげる」フラグが
ライブラリ初期化時に自動的に設定されてしまう可能性もありますね。
大抵そういう場合はデバッグ用のログファイルに描画関連の初期化の中で
「~に失敗しました」とか「ソフトウエアレンダリングモードに変更します」の
メッセージが残っているはずなので、それを確認してみるといいのかもしれません。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月20日(金) 07:07
by Ma
>SetUse3DFlag()という関数を使い、フラグをFALSEにしていませんか?
使っていません。
>SetScreenMemToVramFlag()関数のフラグをFALSEにしてみてください。
40fps ⇒ 10fps に落ちました。
>「~に失敗しました」とか「ソフトウエアレンダリングモードに変更します」
失敗 の文字列はありませんでした。
レンダリング 関連のログもありませんでした。
一応ログを添付しときます。
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月20日(金) 10:39
by Justy
>失敗 の文字列はありませんでした。
>レンダリング 関連のログもありませんでした
たしかにないようですね。
ちなみにこのログは SetScreenMemToVramFlag()を使ったときのログですか?
(「3Dグラフィック描画機能は使用しません」という記述があるようだったので)
Re:大きいPNGの高速描画のコツ
Posted: 2009年3月20日(金) 12:20
by Ma
>ちなみにこのログは SetScreenMemToVramFlag()を使ったときのログですか?
たしか、そうだったと思います。
画像を2数を減らして、ウィンドウモードでも 50fps にまで持ちあえげました。
ご協力ありがとうございました。<(_ _)>
〆