DXライブラリでのFPS制御

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
L'z

DXライブラリでのFPS制御

#1

投稿記事 by L'z » 14年前

ScreenFlip関数を使えばディスプレイの更新にあわせて
更新してくれますがリフレッシュレートが60でない場合も
あるので手動で調節したいと思っています

いろいろ調べてみたところ次のフレームを処理するまでの間を
Sleep関数で処理をとめるようなのですがここで疑問があります


まず
60HZでは16.666667ms
80HZでは12.5ms
ごとに画面が更新されます

つまり更新タイミングは
60HZ:16,33,49,66,83
80HZ:12,25,37,50,62
です

fpsを60にしたいときは、
処理が3msのときに完了したとしたら16msまでSleepします
しかし80HZのディスプレイだとScreenFlipを行なっても
ディスプレイの更新が25msなので9ms待つことになります

これではSleepの13msと9msの22ms待つことになり
無駄に待っているし、次は33msまでSleepなので8msしか処理する
時間がないことになります
処理できたとしても次の画面更新が37msなので12.5msの間隔となり
60fpsを保っているとは言えないと思うのですがこの方法でfpsを
制御できてるといえるのでしょうか?


また、60HZのディスプレイでの場合でも
ディスプレイの更新が
16,33,49,66,83・・・
としてCPUが基準となる時刻を取得したのが
20のときとすると、
フレーム制御の部分では20+16.6666で36msまでSleepさせることになります
そしてScreenFlipで49msまでの13ms間も待機することになり、
次は20+16.6666x2の53msまでなので4ms間しか処理や描画をする時間が
ありません

基準となる時間は1秒ごとにとり直しているので常にというわけではないですが
このようなことが起きる可能性があると思うのですが基準となる時間を
ScreenFlipの直前にするようにする、というような処理を入れなくても
fpsが安定するものなのでしょうか?

fps制御の考え方は同じサイト内の
http://dixq.net/rp/43.html
を主に参考にしました




あと、ついでにFPS制御とは関係ない部分ですが質問したいことがあります

次のようなコードがあります

コード:

 
int main(){

	int a,x[10];

	いろいろ

	a=0;
	for(int i=0;i<10;i++){

		a+=x[i];

	}

	いろいろ

	return 0;

}
これのa=0はforの中で使うためなのでforの初期化のところに入れたいのですが
入れて

[code=Cpp]
for(int i=0,a=0;i<10;i++){
[/code]

このようにするとaもfor内での宣言とみなされてmainで宣言したaに反映されません
intを先に書いてはいけないのかと思い

[code=Cpp]
for(a=0, int i=0;i<10;i++){
[/code]

このように書くと、この場所にintは書けない のようなコンパイルエラーになります

forの初期化部分でintなどを宣言する場合はすでにある変数の値を変更できないのでしょうか?


長文失礼しましたm(__)m

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: DXライブラリでのFPS制御

#2

投稿記事 by beatle » 14年前

L'z さんが書きました:ScreenFlip関数を使えばディスプレイの更新にあわせて
更新してくれますがリフレッシュレートが60でない場合も
あるので手動で調節したいと思っています

いろいろ調べてみたところ次のフレームを処理するまでの間を
Sleep関数で処理をとめるようなのですがここで疑問があります


まず
60HZでは16.666667ms
80HZでは12.5ms
ごとに画面が更新されます

つまり更新タイミングは
60HZ:16,33,49,66,83
80HZ:12,25,37,50,62
です

fpsを60にしたいときは、
処理が3msのときに完了したとしたら16msまでSleepします
しかし80HZのディスプレイだとScreenFlipを行なっても
ディスプレイの更新が25msなので9ms待つことになります

これではSleepの13msと9msの22ms待つことになり
無駄に待っているし、次は33msまでSleepなので8msしか処理する
時間がないことになります
処理できたとしても次の画面更新が37msなので12.5msの間隔となり
60fpsを保っているとは言えないと思うのですがこの方法でfpsを
制御できてるといえるのでしょうか?
質問が長かったため,まだここまでしか読んでません.

この質問は,リフレッシュレートが80Hzのディスプレイにおいて,60FPSを出そうとしているのでしょうか?

FPSは,1秒間に何回画面を書き換えたかという数値です.
ScreenFlipは,初期状態だと画面のリフレッシュレートに連動して動作することはL'zさんもご存知のようですね.
L'zさんが仰る方法「3msec処理,Sleepで13msec待ち,ScreenFlipで次回更新まで待ち」を行うと,残念ながら40FPSになってしまうはずです.ScreenFlipが画面のリフレッシュレートに連動する以上,リフレッシュレートの約数以外のFPSは出ません.
ScreenFlipは,実は画面のリフレッシュレートとの連動を切ることができますので,それを利用すればScreenFlipで待つことがなくなり,60FPSが出せるようになります.
参考http://hpcgi2.nifty.com/natupaji/bbs/pa ... ast&no=483

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: DXライブラリでのFPS制御

#3

投稿記事 by softya(ソフト屋) » 14年前

後半についてお答えします。
L'z さんが書きました: forの初期化部分でintなどを宣言する場合はすでにある変数の値を変更できないのでしょうか?
簡単に言えば出来ません。
あと、もし出来たしてもどう書いても読みづらいと思うのでやめたほうが良いと思います。

同期制御の件については、60FPSを絶対守るのか、60FPS以下なら許容するのかなどによっても話が変わってきます。
あと今のシステムで出せるリフレッシュレートに合わせてFPS自体を変えてしまうという設計方法もあります。自キャラの移動距離なども経過時間に合わせて変えてしまうという方法ですね。
液晶全盛のこの時代に80hzのリフレッシュレートのモニタがどのぐらい存在するか分かりませんが利用者はそんなに存在するのでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: DXライブラリでのFPS制御

#4

投稿記事 by ISLe » 14年前

モニタのリフレッシュレートに合わせるとゆらぎが発生します。
リフレッシュレートに合わせないとテアリングが発生します。
これらはトレードオフの関係にありますが、一般向けにはテアリングを避ける傾向が強いと思います。

FPSに対して滑らかさの指標と取るか、ゲーム内時間の基準と取るかで違うと思います。
個人的には後者に重きをおいてます。

わたしのブログの記事ですが…。
処理落ちしても一定のFPS制御

L'z

Re: DXライブラリでのFPS制御

#5

投稿記事 by L'z » 14年前

beatleさん
beatle さんが書きました: 質問が長かったため,まだここまでしか読んでません.

この質問は,リフレッシュレートが80Hzのディスプレイにおいて,60FPSを出そうとしているのでしょうか?

FPSは,1秒間に何回画面を書き換えたかという数値です.
ScreenFlipは,初期状態だと画面のリフレッシュレートに連動して動作することはL'zさんもご存知のようですね.
L'zさんが仰る方法「3msec処理,Sleepで13msec待ち,ScreenFlipで次回更新まで待ち」を行うと,残念ながら40FPSになってしまうはずです.ScreenFlipが画面のリフレッシュレートに連動する以上,リフレッシュレートの約数以外のFPSは出ません.
ScreenFlipは,実は画面のリフレッシュレートとの連動を切ることができますので,それを利用すればScreenFlipで待つことがなくなり,60FPSが出せるようになります.
参考http://hpcgi2.nifty.com/natupaji/bbs/pa ... ast&no=483

長くてすみません > <

作るならどんな環境でもできるようにしたいので
どんなリフレッシュレートでも60FPSにしたいと思っています

そこで一般的な60Hz,120Hzとは違った80Hzの場合を考えたときおかしくなるのではと思い質問しました

ScreenFlipの連動を切ることができるというのは知りませんでした
非公式関数も調べてみるべきでしたね
参考URLとても役立ちました

ただ、この方法を使うと60Hzのディスプレイでもティアリングが発生することがあるようなので
60Hz以上の環境の場合は60Hzにしてもらうようにすることにします

ありがとうございました




softya(ソフト屋)さん
softya(ソフト屋) さんが書きました: 簡単に言えば出来ません。
あと、もし出来たしてもどう書いても読みづらいと思うのでやめたほうが良いと思います。

同期制御の件については、60FPSを絶対守るのか、60FPS以下なら許容するのかなどによっても話が変わってきます。
あと今のシステムで出せるリフレッシュレートに合わせてFPS自体を変えてしまうという設計方法もあります。自キャラの移動距離なども経過時間に合わせて変えてしまうという方法ですね。
液晶全盛のこの時代に80hzのリフレッシュレートのモニタがどのぐらい存在するか分かりませんが利用者はそんなに存在するのでしょうか?
回答ありがとうございます

一行にまとめてしまいたいと思いましたが、見やすさを考えると見づらいしわかりづらいですね

常に60FPSちょうどというのは無理だと思いますがほぼ60FPSであるようにしたいと思っています
なので2つめの質問の60Hzのディスプレイの場合でフレーム制御のプログラムを入れたほうが
FPSが不安定になるようならScreenFlipだけにしたいと思うのですが
http://dixq.net/rp/43.html
http://homepage2.nifty.com/natupaji/DxL ... .html#N14a
これらのページにあるようなフレーム制御のプログラムは入れるべきでしょうか?


私が液晶で見たことがあるリフレッシュレートは59,60,120Hzだけなのですが
リフレッシュレートで調べてみると、他に75,85,90,100,160などが出てきました
これらの値のリフレッシュレートはそこまで少ないものなのですか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: DXライブラリでのFPS制御

#6

投稿記事 by softya(ソフト屋) » 14年前

L'z さんが書きました:私が液晶で見たことがあるリフレッシュレートは59,60,120Hzだけなのですが
リフレッシュレートで調べてみると、他に75,85,90,100,160などが出てきました
これらの値のリフレッシュレートはそこまで少ないものなのですか?
ブラウン管モニタの時代にはよく見た値ですが(160hzは?)液晶モニタになってからは目にしませんね。
L'z さんが書きました:どんなリフレッシュレートでも60FPSにしたいと思っています
それだと描画ループと処理を分けて別スレッドで実行するしか無いと思います。
描画ループはリフレッシュレートでループ。処理は60fpsで行います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

L'z

Re: DXライブラリでのFPS制御

#7

投稿記事 by L'z » 14年前

ISLeさん
ISLe さんが書きました:モニタのリフレッシュレートに合わせるとゆらぎが発生します。
リフレッシュレートに合わせないとテアリングが発生します。
これらはトレードオフの関係にありますが、一般向けにはテアリングを避ける傾向が強いと思います。

FPSに対して滑らかさの指標と取るか、ゲーム内時間の基準と取るかで違うと思います。
個人的には後者に重きをおいてます。

わたしのブログの記事ですが…。
処理落ちしても一定のFPS制御
ティアリングを避けるほうにしたいと思います
ありがとうございました




softya(ソフト屋)さん
softya(ソフト屋) さんが書きました:
L'z さんが書きました:私が液晶で見たことがあるリフレッシュレートは59,60,120Hzだけなのですが
リフレッシュレートで調べてみると、他に75,85,90,100,160などが出てきました
これらの値のリフレッシュレートはそこまで少ないものなのですか?
ブラウン管モニタの時代にはよく見た値ですが(160hzは?)液晶モニタになってからは目にしませんね。
L'z さんが書きました:どんなリフレッシュレートでも60FPSにしたいと思っています
それだと描画ループと処理を分けて別スレッドで実行するしか無いと思います。
描画ループはリフレッシュレートでループ。処理は60fpsで行います。
そうですか・・・
マルチスレッドは使ったことがないので勉強しようかと思います

ありがとうございました

閉鎖

“C言語何でも質問掲示板” へ戻る