Driect3D初始化演示(第四章內容)

初始化Direct3D演示(第四章內容)

初始化Driect3D類:程序員

#include "Common\d3dApp.h"
#include <DirectXColors.h>

using namespace DirectX;

class InitDirect3DApp : public D3DApp
{
public:
    InitDirect3DApp(HINSTANCE hInstance);
    ~InitDirect3DApp();

    virtual bool Initialize()override;

private:
    virtual void OnResize()override;
    virtual void Update(const GameTimer& gt)override;
    virtual void Draw(const GameTimer& gt)override;
};


InitDirect3DApp::InitDirect3DApp(HINSTANCE hInscance) :D3DApp(hInscance)
{

}

InitDirect3DApp::~InitDirect3DApp()
{

}

bool InitDirect3DApp::Initialize()
{
    if (!D3DApp::Initialize())
    {
        return false;
    }
    return true;
}

void InitDirect3DApp::OnResize()
{
    D3DApp::OnResize();
}

void InitDirect3DApp::Update(const GameTimer& gt)
{

}

void InitDirect3DApp::Draw(const GameTimer& gt)
{
    //重置命令分配器
    ThrowIfFailed(mDirectCmdListAlloc->Reset());
    //重置命令列表
    ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), nullptr));
    //對資源的狀態進行轉變,將資源從呈現狀態轉變到渲染目標狀態
    mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(
        CurrentBackBuffer(),
        D3D12_RESOURCE_STATE_PRESENT,
        D3D12_RESOURCE_STATE_RENDER_TARGET
    ));
    //設置視口和裁剪矩形,他們須要跟隨命令列表的重置而重置
    mCommandList->RSSetViewports(1, &mScreenViewport);
    mCommandList->RSSetScissorRects(1, &mScissorRect);
    //清除後臺緩衝區和深度緩衝區
    mCommandList->ClearRenderTargetView(CurrentBackBufferView(), Colors::LightSteelBlue, 0, nullptr);
    mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL,
        1.0f, 0, 0, nullptr);
    //指定將要渲染的緩衝區
    mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView());
    //再次對資源狀態進行轉變,將資源從渲染目標狀態轉變爲呈現狀態
    mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(
        CurrentBackBuffer(), D3D12_RESOURCE_STATE_RENDER_TARGET,
        D3D12_RESOURCE_STATE_PRESENT
    ));
    //完成命令的記錄
    ThrowIfFailed(mCommandList->Close());
    //將命令列表的命令加入到命令隊列中
    ID3D12CommandList* cmdsList[] = { mCommandList.Get() };
    mCommandQueue->ExecuteCommandLists(_countof(cmdsList), cmdsList);
    //交換先後臺緩衝區
    ThrowIfFailed(mSwapChain->Present(0, 0));;
    mCurrBackBuffer = (mCurrBackBuffer + 1) % SwapChainBufferCount;

    //等待此幀的命令執行完畢
    FlushCommandQueue();

}

主函數:數組

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
{
    //爲調試版本開啓運行時內存檢測,方便監督內存泄漏的狀況
#if defined(DEBUG) | defined(_DEBUG)
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif

    try 
    {
        InitDirect3DApp theApp(hInstance);
        if (!theApp.Initialize())
        {
            return 0;
        }
        return theApp.Run();
    }
    catch (DxException& e)
    {
        MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
        return 0;
    }
}

運行結果ide

接下來咱們將介紹一些在前面沒有提到的方法:函數

一、ClearRenderTargetView():將指定的渲染目標清理爲給定的顏色工具

二、ClearDepthStencilView():清理指定的深度/模板緩衝區性能

三、OMSetRenderTargets():設置咱們但願在渲染流水線上使用的渲染目標和深度/模板緩衝區動畫

調試Direct3D應用程序

大多數的Direct3D函數會返回HRESULT錯誤碼,咱們的示例程序則採用簡單的錯誤處理機制檢測返回的HRESULT值,若是檢測失敗。則拋出異常,顯示調用出錯的錯誤碼,函數名,文件名以及發生錯誤的行號,這些操做都由d3dUtil.h中的代碼實現:spa

class DxException
{
public:
    DxException() = default;
    DxException(HRESULT hr, const std::wstring& functionName, const std::wstring& filName, int lineNumber);

    std::wstring ToString()const;

    HRESULT ErrorCode = S_OK;
    std::wstring FunctionName;
    std::wstring FileName;
    int LineNumber = -1;
};


#ifndef ThrowIfFailed
#define ThrowIfFailed(x)                                              \
{                                                                     \
    HRESULT hr__ = (x);                                               \
    std::wstring wfn = AnsiToWString(__FILE__);                       \
    if(FAILED(hr__)) { throw DxException(hr__, L#x, wfn, __LINE__); } \
}
#endif

由上面的代碼能夠看出來,ThrowifFailed是一個宏而不是一個函數,若是ThrowifFailed是一個函數,那麼__FILE__和__LINE__將會定位到ThrowifFailed函數所在的文件和行,而不是出錯函數的文件和行。3d

L#x會將ThrowifFailed的參數轉換爲Unicode字符串,這樣一來,咱們就能夠將函數調用的錯誤信息輸出到消息框中。調試

第四章小結

  1. Direct3D是一種介於程序員和硬件之間的橋樑,經過這個橋樑,程序員能夠經過調用Direct3D函數來實現把資源視圖綁定到硬件渲染流水線中,配置渲染流水線的輸出以及繪製3D幾何體等操做
  2. 組件對象模型(COM)是一種可使DirectX不依賴任何特定語言且向後兼容的技術
  3. 1D、2D、3D紋理相似於有數據元素構成的1D、2D、3D數組,紋理元素的格式一定是DXGI_FORAMT枚舉類型中的其中一種,紋理除了能夠存儲圖像數據以外,還能夠存儲想深度信息等其餘類型的數據
  4. 前臺緩衝區和後臺緩衝區構成了交換鏈,交換鏈在代碼中能夠經過IDXGISwapChain接口表示,使用兩個緩衝區的狀況稱之爲雙緩衝,交換鏈的存在能夠避免出現動畫中出現閃爍的問題(前臺緩衝區和後臺緩衝區互換的操做稱之爲呈現)
  5. 深度緩衝是一種用於肯定物體在場景中離攝像機最近點的技術,經過深度緩衝,咱們能夠不用考慮物體在場景中繪製的前後順序
  6. 在Driect3D中,資源不能夠直接和渲染流水線相互綁定,所以咱們須要爲繪製調用時所引用的資源指定描述符,描述符能夠視爲GPU識別以及描述資源的一種輕量級結構體,咱們還能夠爲一種資源建立不一樣的描述符,這樣咱們就可讓一種資源具備多種用途。應用程序能夠經過建立描述符堆來存儲描述符。
  7. ID3DDeviec是Direct3D最重要的接口,咱們能夠把它看做是圖形硬件設備的軟件控制器,咱們能夠經過ID3DDevice來建立GPU資源以及其餘一些用於控制圖形硬件設備的特定接口
  8. 每個GPU都有一個命令隊列,CPU能夠經過Direct3D API用命令列表來向該隊列提交命令,這些命令將指揮GPU進行各類操做,在命令沒有到達隊列首部以前,該命令是不會被執行的。
  9. GPU是系統中和CPU一塊兒並行工做的第二種處理器,咱們須要對CPU和GPU進行同步
  10. 性能計數器是一種高精度的計時器,它是測量微小時間差的一種有效工具,性能計數器使用的時間單位是計數,QueryPerformanceFrequency函數輸出的是性能計數器每秒的計數,能夠用它將計數單位轉換爲秒,QueryPerformanceCounter函數輸出的是當前的時間值(以計數爲單位)
  11. 經過統計時間段t內處理的幀數能夠計算出每秒的平均幀數(FPS),不過爲了更直觀的對程序的性能進行考量,咱們通常使用「處理一幀所花費的時間」這個統計信息。以秒爲單位的每幀平均處理時間能夠用幀率的倒數來進行計算,即:1/FPS
相關文章
相關標籤/搜索