18

OpenGL アプリケーションを画面にレンダリングする FPS を正確に設定できる確実な方法を見つけようとしています。1000/fps ミリ秒スリープすることである程度はできますが、レンダリングに必要な時間は考慮されていません。fps を希望の量に制限する最も一貫した方法はどれですか?

4

7 に答える 7

10

opengl で wglSwapIntervalEXT を使用して vblank に同期できます。素敵なコードではありませんが、機能します。

http://www.gamedev.net/topic/360862-wglswapintervalext/#entry3371062

bool WGLExtensionSupported(const char *extension_name) {
    PFNWGLGETEXTENSIONSSTRINGEXTPROC _wglGetExtensionsStringEXT = NULL;

    _wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)wglGetProcAddress("wglGetExtensionsStringEXT");

    if (strstr(_wglGetExtensionsStringEXT(), extension_name) == NULL) {
        return false;
    }

    return true;
}

PFNWGLSWAPINTERVALEXTPROC       wglSwapIntervalEXT = NULL;
PFNWGLGETSWAPINTERVALEXTPROC    wglGetSwapIntervalEXT = NULL;

if (WGLExtensionSupported("WGL_EXT_swap_control"))
{
// Extension is supported, init pointers.
    wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");

// this is another function from WGL_EXT_swap_control extension
    wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)wglGetProcAddress("wglGetSwapIntervalEXT");
}
于 2013-02-19T22:39:01.980 に答える
8

OpenGL は低レベルのグラフィックス API にすぎないため、このようなものが OpenGL に直接組み込まれていることはありません。

しかし、あなたの論理には少し欠陥があると思います。以下ではなく:

  1. フレームを描く
  2. 1000/fps ミリ秒待機
  3. 繰り返す

これを行う必要があります:

  1. タイマーを開始
  2. フレームを描く
  3. タイマーを停止
  4. 待機 (1000/fps - (停止 - 開始)) ミリ秒
  5. 繰り返す

このようにして、本来あるべき量だけを待っている場合、1 秒あたり 60 フレーム (または目標としているもの) に非常に近くなるはずです。

于 2013-02-19T22:41:44.577 に答える
5

OpenGL 自体には、フレームレートを制限できる機能はありません。限目。

ただし、最新の GPU には、フレームレート、フレーム予測などをカバーする多くの機能があります。John Carmack が、いくつかの機能を利用できるようにするためにプッシュしたイシューがありました。そして、NVidia のアダプティブ シンクがあります。

それはあなたにとって何を意味しますか?それはGPUにお任せください。描画は完全に予測不可能であると想定し (OpenGL のみに固執する場合と同様)、イベントの時間を自分で計り、ロジックの更新 (物理など) を描画とは別に維持します。そうすれば、ユーザーはこれらすべての高度なテクノロジーの恩恵を受けることができ、もう心配する必要はありません。

于 2013-10-23T12:29:49.047 に答える
4

スリープを使用しないでください。その場合、アプリケーションの残りの部分は、それらが終了するまで待機する必要があります。

代わりに、経過時間を追跡し、1000/fps に達した場合にのみレンダリングします。タイマーが満たされていない場合は、スキップして他のことを行います。

シングル スレッド環境では、絶対に 1000/fps で描画することだけを行う場合を除いて、正確に 1000/fps で描画することを確認するのは困難です。より一般的で堅牢な方法は、すべてのレンダリングを別のスレッドで実行し、そのスレッドをタイマーで起動/実行することです。これははるかに複雑な問題ですが、求めているものに最も近いものになります。

また、レンダリングを発行するのにかかる時間を追跡しておくと、いつレンダリングするかをその場で調整するのに役立ちます。

static unsigned int render_time=0;
now = timegettime();
elapsed_time = last_render_time - now - render_time;
if ( elapsed_time > 1000/fps ){
    render(){
        start_render = timegettime();

        issue rendering commands...

        end_render = timegettime();
        render_time = end_render - start_render;
    }
    last_render_time = now;
}
于 2013-10-30T03:12:54.210 に答える
0

もう 1 つのアイデアは、WaitableTimers を使用することです (Windows などで可能な場合)。

基本的な考え方:

while (true) 
{ 
    SetWaitableTimer(myTimer, desired_frame_duration, ...); 
    PeekMsg(...) 
    if (quit....) break; 
    if (msg)
        handle message; 
    else 
    { 
        Render(); 
        SwapBuffers();
    }
    WaitForSingleObject(myTimer); 
}

詳細: fps 情報を制限する方法

于 2014-03-24T20:05:45.903 に答える