[過去ログ]
東方関連のツール総合スレ7 (1000レス)
東方関連のツール総合スレ7 http://jbbs.shitaraba.net/bbs/read.cgi/computer/41116/1250234607/
上
下
前次
1-
新
通常表示
512バイト分割
レス栞
抽出解除
レス栞
このスレッドは過去ログ倉庫に格納されています。
次スレ検索
歴削→次スレ
栞削→次スレ
過去ログメニュー
438: ◆swmpLV/75E [sage] フレームレート制御の方法について 単純な制御方法を紹介します void wait_for_next_frame() { static LONGLONG frame_count=0; static LONGLONG last_ticks=0; frame_count++; LONGLONG next_ticks = last_ticks + ( ( frame_count * get_clocks_per_sec() ) / 60 ); LONGLONG current_ticks = get_clocks(); if ( current_ticks <= next_ticks ) { sleep( next_ticks - current_ticks ); } else { frame_count = 0; last_ticks = current_ticks; } } LONGLONG get_clocks_per_sec() 1秒間にカウントアップする量を返す関数 通常はQueryPerformanceFrequencyで得た周波数です LONGLONG get_clocks() 現在時刻を返します 通常はQueryPerformanceCounterで得た時刻です void sleep(LONGLONG ticks) 指定された時間、sleepします できるだけ正確にsleepを行えるよう実装をする必要があります 上記の実装で、正確に60fpsがだせます sleepを正確に行うために、timeBeginPeriod(1)を アプリ起動時に行う必要があります WINAPIのSleepの精度は1msのため、実際にSleepしたい秒数より 少なめにSleepし、Sleepから返った後に現在時刻を調査して、 正確に時間つぶしを行う必要があります(実装の紹介は省略します) http://jbbs.shitaraba.net/bbs/read.cgi/computer/41116/1250234607/438
451: ◆swmpLV/75E [sage] >>438の補足を少し… > LONGLONG next_ticks = last_ticks + ( ( frame_count * get_clocks_per_sec() ) / 60 ); この処理では、次のフレームの開始時刻を算出しています 多くの文献、実装では、1フレームの時間を算出して、 前のフレーム開始時刻に、1フレームの時間を足して、次のフレームの開始時刻を得ています 例: LONGLONG frame_ticks = get_clocks_per_sec() / 60; LONGLONG next_ticks = prev_ticks + frame_ticks; この計算方法では、1フレームの時間間隔が正確に保持できないため、 1秒あたりのフレーム数は、60フレームに近く、誤差も少ないですが、 1時間あたりのフレーム数は、小さな誤差が蓄積して 大きな誤差が発生するため、結構な差が開きます >>438の場合は、get_clocks_per_sec()が1000の場合(timeGetTime()を使う場合)でも、 そこそこ正確に60fpsでループを回すことが出来ます とても細かい話ですが、誤差を考えると>>438のアルゴリズムが、 最も誤差の出にくいアルゴリズムであると思います このコードでは、LONGLONGを使用していますが、これは__int64のtypedefです VC++6では__int64の演算を行うと、間違った値を 返すことがあると聞いたことがあります (本当かどうかは調査していませんが…) >>438のコードを使用する場合は、できるだけ 新しいVC++を使用した方が良いかもしれません また、乗算を使用しているため、LONGの精度では簡単にoverflowします 計算を軽く(あるいはコードを軽く)するためにLONGLONGをdoubleにする人も居ますが、 浮動小数はアルゴリズム上、必ず誤差が発生するため、 誤差を極力抑えるためにも、LONGLONGである必要があります get_clocks_per_sec()がCPUの周波数(例えば3GHz)を返す場合、 frame_countが一定数を超えると、LONGLONGでもoverflowしますが、 overflowするまでには、何億フレームもかかるため、実用上は問題ありません http://jbbs.shitaraba.net/bbs/read.cgi/computer/41116/1250234607/451
865: 854 [sage] >>861 垂直同期の実装についてご解説頂きありがとうございます 拝読した上で幾つか疑問がありましたので、ご質問させてください 1フレームの長さを計測する方法で >そして、さらに次の垂直帰線消去期間の開始時刻を得て とありますが、こちらはGetRasterStatusから得られるScanLineの値が再び有効な値 (InVBlank=FALSE且つScanLineの値が0<=ScanLine<画面縦解像度)になった後に、 そのScanLineの値から次の垂直帰線消去期間を算出する、という認識で間違いないでしょうか? あと、次の垂直帰線消去期間を計算で割り出し、そのタイミングでPresentするということですが、 それはGetRasterStatusで得られるInVBlankがTRUEになったか、 又はScanLineの値が画面縦解像度以上になったかを確認してから Presentするよりも高い精度を期待できるのでしょうか? いえ、期待できるからこそこちらの手段を選択されたのだと思いますが、 よろしければ詳しい理由を教えていただけないでしょうか すみません、あともうひとつだけ ご解説の中で登場するsleepは>>438に登場する独自実装sleepを指していると認識しているのですが間違いないでしょうか? 実装は、私でしたらSetWaitableTimer+WaitForSingleObjectで直前まで眠った後に残りの時間をQueryPerformanceCounterで 得られる値を監視しながらループというベタなものか、SetWatableTimerに十分な精度が期待できるのであれば Present時刻までSetWatableTimer+WaitForSingleObjectで眠るというものになると思いますが・・・それでは甘いでしょうか コンテキストスイッチは考慮していませんでした、考慮すると一段と実装が複雑になりそうですね ソースコードの公開、楽しみにさせていただきます http://jbbs.shitaraba.net/bbs/read.cgi/computer/41116/1250234607/865
869: ◆swmpLV/75E [sage] ※長文で投稿できないため分割しました >>865 > 解説の中で登場するsleepは>>438に登場する独自実装sleepを指していると > 認識しているのですが間違いないでしょうか? 仰るとおりです vpatchでは、SetWaitableTimer+WaitForSingleObjectで大まかなsleepを行い、 あとはビジーループでQueryPerformanceCounterにて時刻をチェックし、 正確なwaitを行います ※iniでSleepType=0にすれば、ビジーループ無しでsleep SetWaitableTimerではなく、WinAPIのSleepを使用する場合は、 正確な時刻待ちをするために、Sleepの引数に実際より少ない時間をミリ秒単位で指定するせいで、 SetWaitableTimerよりも、若干CPU負荷が高めになる傾向があるかもしれません 必ずSleepを使わなければならないような状況で無いなら、 100ナノ秒単位で設定できるSetWaitableTimerを使用した方が良いと思います SetWaitableTimerは環境によって1ms程度誤差があることがあります 実際にSetWaitableTimerを使って誤差の統計を取れば分かると思いますが -1ms〜+1ms程度の誤差がある環境と、ほぼ誤差がゼロの環境があるようです 手元の環境では誤差がある環境しか無いため、誤差がある環境の方が多いと思われます ※調査PC台数が少ないため、世に出ているPC環境の傾向は全くわかりませんが、 ※誤差はあるものと思っておいた方が良いと思われます 通常は、SetWaitableTimerの引数には、1ms減算したものを渡すと良いと思います > コンテキストスイッチは考慮していませんでした、考慮すると一段と実装が複雑になりそうですね ・コンテキストスイッチを起こさせないようにする方法 ・コンテキストスイッチが起こったかどうかをチェックし、起こっていた場合のデータを捨てる方法 この2つが考えられます 詳細は長文になりそうなのでここでは書きませんが、かなり頭を抱える難題です http://jbbs.shitaraba.net/bbs/read.cgi/computer/41116/1250234607/869
メモ帳
(0/65535文字)
上
下
前次
1-
新
書
関
写
板
覧
索
設
栞
歴
スレ情報
赤レス抽出
画像レス抽出
歴の未読スレ
AAサムネイル
Google検索
Wikipedia
ぬこの手
ぬこTOP
0.239s*