1. 程式人生 > >DX11 Without DirectX SDK--01 DirectX11初始化

DX11 Without DirectX SDK--01 DirectX11初始化

由於個人覺得龍書裡面第4章提供的Direct3D 初始化專案封裝得比較好,而且DirectX SDK Samples裡面的初始化程式過於精簡,不適合後續使用,故選擇了以Init Direct3D專案作為框架,然後還使用了微軟提供的示例專案,兩者結合到一起。建議下載專案配合閱讀

專案結構

該專案包含了下面這些檔案

其中標頭檔案的具體功能

標頭檔案功能
d3dApp.hDirect3D應用程式框架類
dxerr.hDirectX錯誤庫
GameApp.h遊戲應用程式擴充套件類,遊戲邏輯在這裡實現,繼承自D3DApp類
GameTimer.h遊戲計時器類

其中d3dApp.hd3dApp.cppGameTimer.h

GameTimer.cpp是龍書原始碼提供的,我們可以搬運過來,但是對d3dApp框架類我們還需要進行大幅度修改,畢竟我們的最終目的就是要完全脫離舊的DirectX SDK,使用Windows SDK來實現DX11.

dxerr.h在Windows SDK是沒有提供的,我們需要尋找新的dxerr進行替代,在後續會提到

GameApp.h則是我們編寫遊戲邏輯的地方,這裡需要進行逐幀的更新及繪製。

初期配置

連結靜態庫

這裡的每一個專案都需要包含靜態庫:d3d11.lib,dxgi.lib,dxguid.lib,D3DCompiler.libwinmm.lib。可以在d3dApp.h新增下面的語句:

#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "D3DCompiler.lib")
#pragma comment(lib, "winmm.lib")

也可以在專案屬性-連結器-輸入-附加依賴項 新增上面的庫。

移植新的dxerr.h和dxerr.cpp

directx-sdk-samples-master的GitHub地址:https://github.com/walbourn/directx-sdk-samples

在directx-sdk-samples-master\DXUT\Core中可以找到dxerr.hdxerr.cpp,把它們拉進我們的專案中。然後使用下面的巨集來進行檢查(加在d3dApp.h

#if defined(DEBUG) | defined(_DEBUG)
#ifndef HR
#define HR(x)                                              \
{                                                          \
    HRESULT hr = (x);                                      \
    if(FAILED(hr))                                         \
    {                                                      \
        DXTrace(__FILEW__, (DWORD)__LINE__, hr, L#x, true);\
    }                                                      \
}
#endif

#else
#ifndef HR
#define HR(x) (x)
#endif
#endif 

由於新的dxerr.h僅提供了DXTrace的Unicode字符集版本,需要將原來的__FILE__替換為__FILEW__,並在專案屬性頁中將字符集設定為Unicode。

COM元件智慧指標

考慮到DirectX11的API是由一系列的COM元件來管理的,我們可以使用智慧指標來管理這些物件,而無需過多擔心記憶體的洩漏。所以該專案並不會用到介面類ID3D11Debug來協助檢查記憶體洩漏。

使用該智慧指標需要包含標頭檔案wrl/client.h,並且智慧指標類模板ComPtr位於名稱空間Microsoft::WRL內。我們主要關注下面這幾個方法:

ComPtr<T>::Get方法返回T*,若需要賦值操作也可以使用過載的=運算子進行

ComPtr<T>::GetAddressOf方法返回T**,也可以用過載的&運算子來獲取

ComPtr<T>::Reset方法將對裡面的物件呼叫Release方法,並將指標置為nullptr

GameTimer類

GameTimer類是一個基於高精度時鐘頻率的計時器,主要用於獲取遊戲時間和每一幀的間隔時間,並進行一些特殊的操作。下面給出了GameTimer類的宣告部分:

class GameTimer
{
public:
    GameTimer();

    float TotalTime()const;     // 總遊戲時間
    float DeltaTime()const;     // 幀間隔時間

    void Reset(); // 在訊息迴圈之前呼叫
    void Start(); // 在取消暫停的時候呼叫
    void Stop();  // 在暫停的時候呼叫
    void Tick();  // 在每一幀的時候呼叫

private:
    double mSecondsPerCount;    // 一個時鐘週期經過的秒數
    double mDeltaTime;          // 幀間隔時間

    __int64 mBaseTime;          // 基準時間
    __int64 mPausedTime;        // 暫停的時間
    __int64 mStopTime;          // 停止的時間
    __int64 mPrevTime;          // 上一幀的時間
    __int64 mCurrTime;          // 當前時間

    bool mStopped;              // 是否停止計時
};

建構函式

Windows.h中,提供了QueryPerformanceFrequency函式用於獲取當前處理器的時鐘頻率(1秒經過的時鐘週期數),然後我們就可以求出1個時鐘週期經過的時間數目了。此時計時器為開啟狀態。觀看建構函式的程式碼:

GameTimer::GameTimer()
: mSecondsPerCount(0.0), mDeltaTime(-1.0), mBaseTime(0), 
  mPausedTime(0), mPrevTime(0), mCurrTime(0), mStopped(false)
{
    __int64 countsPerSec;
    QueryPerformanceFrequency((LARGE_INTEGER*)&countsPerSec);
    mSecondsPerCount = 1.0 / (double)countsPerSec;
}

GameTimer::Reset方法

GameTimer::Reset方法用於重置當前遊戲用時為0,並開啟計時器,具體的做法如下:

void GameTimer::Reset(www.thd178.com)
{
    __int64 currTime;
    QueryPerformanceCounter((LARGE_INTEGER*)&currTime);

    mBaseTime =www.yigouyule2.cn currTime;
    mPrevTime =www.120xh.cn   currTime;
    mStopTime = 0;
    mStopped  = www.feifanyule.cn false;
}

其中,QueryPerformanceCounter函式用於獲取當前經過的時鐘週期數。當前我們是用它獲取的值作為基準時間,然後將暫停的總計時間設定為0,並將暫停狀態設定為否。

GameTimer::Start方法

GameTimer::Start方法用於開啟計時器計時(設定開始時間),並統計上次暫停的總時間:

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;
    }
}

若之前曾經暫停過,則需要統計當前暫停經過的時間,並加進總的暫停用時。然後這時停止時間也要歸零,並將暫停狀態設定為否。

GameTimer::Stop方法

GameTimer::Stop方法用於暫停計時器計時,設定暫停時間點:

void GameTimer::Stop()
{
    if( !mStopped )
    {
        __int64 currTime;
        QueryPerformanceCounter((LARGE_INTEGER*)&currTime);

        mStopTime = currTime;
        mStopped  = true;
    }
}

GameTimer::Tick方法

GameTimer::Tick方法在計時器開啟的時候返回距離上次Tick的間隔時間,若計時器沒有開啟或者間隔時間為負值,則設間隔時間為0:

void GameTimer::Tick()
{
    if( mStopped )
    {
        mDeltaTime = 0.0;
        return;
    }

    __int64 currTime;
    QueryPerformanceCounter((LARGE_INTEGER*)&currTime);
    mCurrTime = currTime;

    // Time difference between this frame and the previous.
    mDeltaTime = (mCurrTime - mPrevTime)*mSecondsPerCount;

    // Prepare for next frame.
    mPrevTime = mCurrTime;

    if(mDeltaTime < 0.0)
    {
        mDeltaTime = 0.0;
    }
}

GameTimer::TotalTime方法

GameTimer::TotalTime方法返回的是距離上次Reset方法呼叫到現在,遊戲執行的總時間(不包括所有暫停過的時間,單位為秒):

float GameTimer::TotalTime()const
{
    // If we are stopped, do not count the time that has passed since we stopped.
    // Moreover, if we previously already had a pause, the distance 
    // mStopTime www.wmyl88.com- mBaseTime includes paused time, which we do not want to count.
    // To correct www.uuweb.cn this, we can subtract the paused time from mStopTime:  
    //
    //                     |<--paused time-->|
    // ----*---------------*-----------------*------------*------------*------> time
    //  mBaseTime       mStopTime        startTime     mStopTime    mCurrTime

    if( mStopped )
    {
        return (float)(((mStopTime - mPausedTime)-mBaseTime)*mSecondsPerCount);
    }

    // The distance www.089188.cn mCurrTime - mBaseTime includes paused time,
    // which we do not want to count.  To correct this, we can subtract 
    // the paused time from mCurrTime:  
    //
    //  (mCurrTime -www.duobaoyule2.cn mPausedTime) - mBaseTime 
    //
    //                     |<--paused time-->|
    // ----*---------------*-----------------*------------*------> time
    //  mBaseTime       mStopTime        startTime     mCurrTime
    
    else
    {
        return (float)(((mCurrTime-mPausedTime)-mBaseTime)*mSecondsPerCount);
    }
}

GameTimer::DeltaTime方法

GameTimer::TotalTime方法返回當前Tick和上次Tick之間的時間間隔,單位為秒:

float GameTimer::DeltaTime()const
{
    return (float)mDeltaTime;
}

D3DApp框架類

D3DApp.h展示了框架類的宣告:

class D3DApp
{
public:
    D3DApp(HINSTANCE hInstance);    // 在建構函式的初始化列表應當設定好初始引數
    virtual ~D3DApp();
    
    HINSTANCE AppInst(www.ruishengks.com)const;       // 獲取應用例項的控制代碼
    HWND      MainWnd()const;       // 獲取主視窗控制代碼
    float     AspectRatio()const;   // 獲取螢幕寬高比
    
    int Run();                      // 執行程式,進行遊戲主迴圈
 
    // 框架方法。客戶派生類需要過載這些方法以實現特定的應用需求
    virtualbool Init();            // 該父類方法需要初始化視窗和Direct3D部分
    virtualvoid OnResize();        // 該父類方法需要在視窗大小變動的時候呼叫
    virtualvoid UpdateScene(float dt)=0;   // 子類需要實現該方法,完成每一幀的更新
    virtualvoid DrawScene(www.ruishengks.com)=0;             // 子類需要實現該方法,完成每一幀的繪製
    virtual LRESULT MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    // 視窗的訊息回撥函式
protected:
    bool InitMainWindow(www.hjha178.com/);      // 視窗初始化
    bool InitDirect3D();        // Direct3D初始化

    void CalculateFrameStats(); // 計算每秒幀數並在視窗顯示

protected:

    HINSTANCE mhAppInst;        // 應用例項控制代碼
    HWND      mhMainWnd;        // 主視窗控制代碼
    bool      mAppPaused;       // 應用是否暫停
    bool      mMinimized;       // 應用是否最小化
    bool      mMaximized;       // 應用是否最大化
    bool      mResizing;        // 視窗大小是否變化
    UINT      m4xMsaaQuality;   // MSAA支援的質量等級

    GameTimer mTimer;           // 計時器

    // DX11
    Microsoft::WRL::ComPtr<ID3D11Device> md3dDevice;                    // D3D11裝置
    Microsoft::WRL::ComPtr<ID3D11DeviceContext> md3dImmediateContext;   // D3D11裝置上下文
    Microsoft::WRL::ComPtr<IDXGISwapChain> mSwapChain;                  // D3D11交換鏈
    // DX11.1
    Microsoft::WRL::ComPtr<ID3D11Device1> md3dDevice1;                  
            
           

相關推薦

DX11 Without DirectX SDK--01 DirectX11初始

由於個人覺得龍書裡面第4章提供的Direct3D 初始化專案封裝得比較好,而且DirectX SDK Samples裡面的初始化程式過於精簡,不適合後續使用,故選擇了以Init Direct3D專案作為框架,然後還使用了微軟提供的示例專案,兩者結合到一起。建議下載專案配合閱讀

01 DirectX11初始

valid mas 枚舉 fine 硬件 後端 組件 setview 適配 由於個人覺得龍書裏面第4章提供的Direct3D 初始化項目封裝得比較好,而且Direct SDK Samples裏面的初始化程序過於精簡,不適合後續使用,故選擇了結合兩者的代碼,並做進一部簡化處理

DX11 Without DirectX SDK--04 使用DirectX Tool Kit幫助開發

一個 結構 基於 sdk 可用 text rim 鼠標 del 回到 DirectX11--使用Windows SDK來進行開發 DirectX Tool Kit下載 DirectX Tool Kit是一個包含許多類的集合,用於為公共Windows平臺編寫Direct3D

DirectX11 Without DirectX SDK--14 深度測試

gif img inpu 取代 分享圖片 一個 basic 能力 方法 前言 當使用加法/減法/乘法顏色混合,或者使用透明混合的時候,在經過深度測試時可能會引發一些問題。例如現在我們需要使用加法混合來繪制一系列對象,而這些對象彼此之間不會相互阻擋。若我們仍使用原來的深度測試

【開源專案】Spring Security三大許可權框架案例講解01—專案初始

GitHub 前言 大致簡介專案主要逐步迭代講解Spring Security + Spring Social + Spring Security OAuth + REST服務開發,通過實際的案例開發來講解,專案註解詳細適合作為教程案例,同時對程式碼的演進還有重構

DirectX入門筆記 00------ 初始D3D

d3dUtility.h #include <d3dx9.h> namespace d3d { bool InitD3D( HINSTANCE hInstance, //Application instance int width, int hei

Directx11基礎教程二之Directx11初始

一,看本節教程前應該掌握:   二,程式的結構如下:        具體在VS2015的程式碼:                                                                                  

ArcGIS Runtime SDK for WPF 初始

event obj env pub ebo als geb 還需要 art 安裝包 管理nuget包 Esri.ArcGISRuntime.WPF 也許還需要 Esri.ArcGISRuntime.Hydrography Esri.ArcGISRuntime.LocalSe

極光IM初始SDK出錯

tle register 方便 ads spa scheme jnilibs opened mas 1.項目的applicationID要和你在極光官網申請的應用ID保持一致 2. 因為我沒有使用JCenter的自動集成功能,而是直接把so文件和極光jar包復制進了Andr

使用kubeadm部署k8s集群01-初始

org state ces docker mes mos per 系統 來安 使用kubeadm部署k8s集群01-初始化 2018/1/3 節點配置 master x3 OS version: centos7 swapoff ### 阿裏雲默認:off hosts

Introduction to 3D Game Programming with DirectX 12 學習筆記之 --- 第四章:Direct 3D初始

學習目標 對Direct 3D程式設計在3D硬體中扮演的角色有基本瞭解; 理解COM在Direct 3D中扮演的角色; 學習基本的圖形學概念,比如儲存2D影象、頁面切換,深度緩衝、多重紋理對映和CPU與GPU如何互動; 學習如何使用效能計數函式讀取高精度時間;

SDk初始的設計參考

0.前言 我們在整合第三方SDK的時候大多都會在Application的onCreate方法裡進行SDK的初始化或配置工作,這好像也沒有什麼問題,不過我們能不能能做的更好一點呢?就是希望使用者在gradle檔案裡compile一下相應的庫就可以直接使用,不需要額外的初始化和配置.這個問題,我

DirectX11 With Windows SDK--20 硬體例項與視錐體裁剪

前言 這一章將瞭解如何在DirectX 11利用硬體例項化技術高效地繪製重複的物體,以及使用視錐體裁剪技術提前將位於視錐體外的物體進行排除。 在此之前需要額外瞭解的章節如下: 硬體例項化(Hardware Instancing) 硬體例項化指的是在場景中繪製同一個物體多次,但是是以不同的位置、旋轉、縮放

DirectX11】【學習筆記(1)番外練習】初始DirectX11

繼續上一章提到的錯誤checking HRESULT值: S_OK - 函式成功 E_NOTIMPL - 函式沒有執行 E_NOINTERFACE - 介面不支援 E_ABORT - 函式越界 E_FAIL - 函式失敗 E_INVALIDARG - 一個或者多

SpringMVC學習(01)--前端控制器DispatcherServlet的初始

一、DispatcherServlet的初始化過程 DispatcherServlet,也就是我們的前端控制器,它是SpringMVC的核心,那麼,Spring容器在初始化DispatcherServlet的時候做了什麼? 先看一下DispatcherSer

K8s-系統初始.01

內容轉載自:https://github.com/opsnull/follow-me-install-kubernetes-cluster/blob/master/01.%E7%B3%BB%E7%BB%9F%E5%88%9D%E5%A7%8B%E5%8C%96%E5%92%8C%E5%85%A8%E

01 MFC的初始

在上一篇簡單的MFC程式中, 還有好多疑惑沒有解開,學C的人都習慣,看程式先找main,但是上篇中程式的main在哪,為啥能弄出一個視窗來還不是很清晰,就算Win32學了,也不一定能想通;這篇主要用寫小例子來從另一個角度來看MFC的初始化過程; 我們都知道,全域性變數的初始化過程在main函

前端起步01-頁面元素的初始

在頁面中使用的HTML標籤,其中某些標籤包含預設的外邊距需要我們對其進行重置,以便於保證樣式的統一。    css reset  :     body,dl,dd,p,h1,h2,h3,h4,h5,h6{margin:0;font

{"code":-1,"error":"`QcloudSecretId`不能為空,請確保 SDK 配置已正確初始"}

微信小程式雲開發登入報錯:{"code":-1,"error":"QcloudSecretId不能為空,請確保 SDK 配置已正確初始化"} 遇到這個錯誤的原因是:騰訊不再幫助使用者無感知的申請騰訊云云 API 金鑰,受此影響,騰訊雲微信小程式解決方案 Wafer2 提供的 sdk.con

Guru of the Week 條款01: 變數的初始

GotW #01 Variable Initialization 著者:Herb Sutter 翻譯:kingofark [宣告]:本文內容取自www.gotw.ca網站上的Guru of the Week欄目,其著作權歸原著者本人所有。譯者kingofark在未經原著者本人