龙书11_chapter_4 一: GameTime解读

看龙书DX11,首先是第四章,本文对GameTime类进行解释

问:此类主要实现了什么功能?

答:Returns the total time elapsed since Reset() was called, NOT counting any time when the clock is stopped.

     从渲染窗口Reset开始记时,记录总共的时间。不包括此间的pause时间。

问:关键时间接口?

答:

1.

//获取频率(取决于主板 OS相关,不是CPU的主频)参考:http://www.gn00.com/t-253523-1-1.html   http://www.cppblog.com/deane/articles/113151.html
BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
//计数,在此频率下的 数值,那么(Count1-Count2)/Frequently即是此阶段的时间,以秒为单位 BOOL QueryPerformanceCounter (LARGE_INTEGER
*lpCount);

2.另外一个是Pause,注意每次stop后,需要进行累加记录下来:

void GameTimer::Start()
{
    __int64 startTime;
    QueryPerformanceCounter((LARGE_INTEGER*)&startTime);
    // Accumulate the time elapsed between stop and start pairs.
    //
    //                     |<-------d------->|
    // ----*---------------*-----------------*------------> time
    //  mBaseTime       mStopTime        startTime     
    if( mStopped )
    {
        mPausedTime += (startTime - mStopTime);    

        mPrevTime = startTime;
        mStopTime = 0;
        mStopped  = false;
    }
}

 

问:在dxApp的实际应用?

答:

1.在计算FPS。例子中以1S为限来进行FPS更新,计算1S内程序运行的次数。其中currentTime使用的即是gameTime.Total()接口。

void D3DApp::CalculateFrameStats()                        //本函数计算FPS和1S内每帧的平均时间
{                                                         //刚开始 TotalTime为0,timeElapsed也为0
    static int frameCnt = 0;                              //然后TotalTime不断增大,直到TotalTime-timeElapsed大于1,即1S过去了,进行FPS的刷新计算
    static float timeElapsed = 0.0f;                       
    frameCnt++;
    // Compute averages over one second period.
    if( (mTimer.TotalTime() - timeElapsed) >= 1.0f )
    {
        float fps = (float)frameCnt; // fps = frameCnt / 1
        float mspf = 1000.0f / fps;// Reset for next average.
        frameCnt = 0;
        timeElapsed += 1.0f;
    }
}

 2.在对win窗口的拖动、拉伸长宽、Pause时,需要调用不同记时接口。

// If user is dragging the resize bars, we do not resize  the buffers here because as the user continuously  drags the resize bars, a stream of WM_SIZE messages are sent to the window, and it would be pointless (and slow)  to resize for each WM_SIZE message received from dragging the resize bars. So instead, we reset after the user is done resizing the window and releases the resize bars, which  sends a WM_EXITSIZEMOVE message.

上文大致意思: 在不停拖动改变size时,我们并不需要resize  buffer(即调用dx OnResize()接口,来重置backBuffer和depthBuffer等),因为这样做无意义而且效率低。 所以,等 release拖动操作后,即WM_EXITSIZEMOVE  后,才进行resize和Time.Start()操作。在此之间,即WM_ENTERSIZEMOVE时,为timer.Stop()

// WM_EXITSIZEMOVE is sent when the user grabs the resize bars.
    case WM_ENTERSIZEMOVE:
        mAppPaused = true;
        mResizing  = true;
        mTimer.Stop();
        return 0;
    // WM_EXITSIZEMOVE is sent when the user releases the resize bars.
    // Here we reset everything based on the new window dimensions.
    case WM_EXITSIZEMOVE:
        mAppPaused = false;
        mResizing  = false;
        mTimer.Start();
        OnResize();
        return 0;

 

posted @ 2015-05-23 04:13  dust_fly  阅读(256)  评论(0编辑  收藏  举报