0

さて、C ++でopenglを使用して、シーンで昼/夜のサイクルを作ろうとしています。私はglutTimerFuncを試しました。タイム スライスを 10000 ミリ秒 = 10 秒に制限しましたが、非常に高速な反転効果が得られました。

これが私がやったことです。

void turn (int value){
    if(night)
    {
        glDisable(GL_LIGHT0);
        glEnable(GL_LIGHT1);
        night=!night;
    }
    else
    {
        glDisable(GL_LIGHT1);
        glEnable(GL_LIGHT0);
        night=!night;
    }
    //glutPostRedisplay();
    glutTimerFunc(10000,&turn,2);
}

関数では、DrawGLSceneその関数を呼び出しました。WinMain 関数は次のとおりです。

int WINAPI WinMain( HINSTANCE   hInstance,          // Instance
    HINSTANCE   hPrevInstance,      // Previous Instance
    LPSTR       lpCmdLine,          // Command Line Parameters
    int         nCmdShow)           // Window Show State
{
    MSG     msg;                                    // Windows Message Structure
    BOOL    done=FALSE;                             // Bool Variable To Exit Loop

    // Ask The User Which Screen Mode They Prefer
    //if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)
    //{
    fullscreen=FALSE;                           // Windowed Mode
    //}

    // Create Our OpenGL Window
    if (!CreateGLWindow("day night",700,500,16,fullscreen))
    {
        return 0;                                   // Quit If Window Was Not Created
    }
    glutTimerFunc(10000,&turn,2);
    //turn(1);
    while(!done)                                    // Loop That Runs While done=FALSE
    {

        if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))   // Is There A Message Waiting?
        {
            if (msg.message==WM_QUIT)               // Have We Received A Quit Message?
            {
                done=TRUE;                          // If So done=TRUE
            }
            else                                    // If Not, Deal With Window Messages
            {
                TranslateMessage(&msg);             // Translate The Message
                DispatchMessage(&msg);              // Dispatch The Message
            }
        }
        else                                        // If There Are No Messages
        {
            // Draw The Scene.  Watch For ESC Key And Quit Messages From DrawGLScene()
            if (active)                             // Program Active?
            {
                if (keys[VK_ESCAPE])                // Was ESC Pressed?
                {
                    done=TRUE;                      // ESC Signalled A Quit
                }
                else                                // Not Time To Quit, Update Screen
                {
                    DrawGLScene();                  // Draw The Scene
                    SwapBuffers(hDC);               // Swap Buffers (Double Buffering)
                }
            }
            if (keys[VK_F1])                        // Is F1 Being Pressed?
            {
                keys[VK_F1]=FALSE;                  // If So Make Key FALSE
                KillGLWindow();                     // Kill Our Current Window
                fullscreen=!fullscreen;             // Toggle Fullscreen / Windowed Mode
                // Recreate Our OpenGL Window
                if (!CreateGLWindow("day night",700,500,16,fullscreen))
                {
                    return 0;                       // Quit If Window Was Not Created
                }

            }
        }
    }

    // Shutdown
    KillGLWindow();                                 // Kill The Window
    return (msg.wParam);                            // Exit The Program
}
4

2 に答える 2

2

DrawGLScene使用して登録されているため、各フレームを描画するために呼び出される場合、フレームを再描画するたびに、つまり を呼び出すたびにglutDisplayFuncタイマー関数も (再) 登録されます。glutPostRedisplay()

タイマー シーケンスを開始するには、 を呼び出す前に 1 回呼び出す必要がありglutTimerFuncます。glutMainLoopDrawGLScene

次のフリップを開始するには、タイマー関数glutTimerFunc 内で呼び出す必要があります。


編集 を使用していないことがわかりますglutMainLoop。これは、 への呼び出しがglutTimerFunc何もしていないことを意味します。GLUT ベースのハンドラーは、関数によってディスパッチされた場合にのみglutMainLoop機能します。

コードがまったく何もしていない唯一の理由は、 WindowsDrawGLSceneイベント ループ内で呼び出しを行っているためです。これは、Windowsイベント ループの各パスでタイマー関数を直接呼び出すためです。これが意外と高い周波数の元です。

Windows イベント モデルの使用に固執する場合は、標準の Windows タイマー イベント (つまりSetTimer) を使用してフリップを処理する方がよいでしょう。

または、コードを書き直して、glutMainLoopすべてのキー押下とその他のイベントを GLUT で処理するようにします。

于 2012-05-23T14:30:04.547 に答える
0

これは、実際の昼/夜がブール値ではなく、昼と夜の間の段階的な変化であるためです。さらに、わずか 10 秒というのは非常に短い昼/夜のサイクルです。通常、少なくとも数分は必要です。

于 2012-05-23T14:22:56.570 に答える