Directx11學習筆記【三】 第一個D3D11程序


在先前的解決方案中新建一個新的Win32項目FirstD3D11Demo。在寫代碼之前,我們必須先添加dx11所需要的庫。為了鏈接dx庫,右鍵項目選擇屬性->vc++目錄,在包含目錄中添加你所安裝的SDK根目錄\Include,在庫目錄中添加 根目錄\lib\x86(或x64),在鏈接器->輸入的附加依賴項中添加d3d11.lib、d3dx11.lib、dxerr.lib。

第一次使用d3d,首先應該從初始化開始。

初始化d3d11的步驟主要有以下幾個:

1、定義我們要檢查的設備類型和特征級別

2、創建d3d設備,渲染環境和交換鏈

3、創建渲染對象

4、設置視口觀察區(ViewPort)

下面將對一些概念和用到的d3d對象和函數作具體說明。

 

數據格式

D3D應用程序中,無論是紋理圖片,還是創建的緩沖區,都有着特定的數據格式。D3D11支持有限的數據格式,以枚舉變量形式存在,如下幾種:

DXGI_FORMAT_R32G32B32_FLOAT: 3個32位單精度符點數組成,比如用於代表三維空間坐標,以及24位顏色;

DXGI_FORMAT_R16G16B16A16_UNORM: 4個16位數組成,每個成員位於[0,1.0f]之間,UNORM意指:unsigned normalized,即無符號,且歸一化的;

DXGI_FORMAT_R32G32_UINT:2個32位數組成,每個成員為無符號整型(unsigned int);

DXGI_FORMAT_R8G8B8A8_UNORM:4個8位數組成,每個成員為[0,1.f]之間;

DXGI_FORMAT_R8G8B8A8_SNORM:4個8位數組成,每個成員為[-1.0f, 1.0f]之間,SNORM意指:signed normalized;

DXGI_FORMAT_R8G8B8A8_SINT:4個8位數組成,每個成員為有符號整型;

 

特征級別(Feature Level)

特征級別定義了一系列支持不同d3d功能的相應等級,如果一個用戶的硬件不支持某一特征等級,程序可以選擇較低的等級來運行。

下面是d3d定義的幾個不同級別代表不同的d3d版本

typedef enum D3D_FEATURE_LEVEL { 
  D3D_FEATURE_LEVEL_9_1   = 0x9100,
  D3D_FEATURE_LEVEL_9_2   = 0x9200,
  D3D_FEATURE_LEVEL_9_3   = 0x9300,
  D3D_FEATURE_LEVEL_10_0  = 0xa000,
  D3D_FEATURE_LEVEL_10_1  = 0xa100,
  D3D_FEATURE_LEVEL_11_0  = 0xb000,
  D3D_FEATURE_LEVEL_11_1  = 0xb100,
  D3D_FEATURE_LEVEL_12_0  = 0xc000,
  D3D_FEATURE_LEVEL_12_1  = 0xc100
} D3D_FEATURE_LEVEL;

在初始化過程中,我們可以提供一組不同的特征等級,程序會從第一個開始逐個檢測,碰到第一個合適的來創建設備。因此我們在數組中從高到低放置特征等級提供給初始化程序。

 

交換鏈(SwapChain)

為了實現平滑的動畫,至少需要兩個緩沖區,一個前緩沖區用於顯示,一個后緩沖區用於下一幀的繪制,每次繪制完一幀后通過交換前、后緩沖區對應的指針來顯示新一幀,並在之前的前緩沖區(當前的后緩沖區)上開始繼續繪制下一幀。交換鏈可以有3個或者更多緩沖區,但一般情況下兩個夠用了。通常在游戲中,我們有兩種顏色緩存,一個主緩存,一個輔助緩存,這就是所謂的前向和后向緩存。主緩存是顯示在屏幕上的,輔助緩存則是用於下一幀的繪制。在d3d11中交換鏈對應的接口為IDXGISwapChain。

 

深度/模板緩沖區:Depth/Stencil Buffer

深度緩沖區是與交換鏈緩沖區大小完全一樣的一塊顯存區域,即每個像素在深度緩沖區中對應相應的位置。在渲染管線的最終的混合階段(Output Merger Stage),每個片(Fragment)都有一個深度值z,與深度緩沖區對應位置上的深度相比較,如果該片段z更小,則繪制該片段,並覆蓋當前的嘗試值,否則拋棄該片段。該緩沖區主要用於實現投影在屏幕上同一位置、遠近不同的物體之間相同的遮擋效果。此外,靈活配置嘗試緩沖區,可以實現很多種高級特效。

 

 多重采樣抗鋸齒:Multisampling Atialiasing

       針對光柵化顯示器抗鋸齒的方法有多種,在d3d中采用的多重采樣方法。即在每個像素點內部,設置多個采樣點,繪制多邊形邊緣時,針對每個采樣點判斷是否被多邊形覆蓋,最終的顏色值從采樣點中取均值,以對多邊形的邊緣進行“模糊化",從而減輕鋸齒效果。如下圖所示,這是一個4重采樣的例子,該像素最終的顏色值是多邊形本身顏色值的3/4:

支持d3d11的硬件全部支持4重采樣,因此我們在后面的程序中將普遍使用4個采樣點。在d3d11中通過結構DXGI_SAMPLE_DESC來設置多重采樣,其定義如下:

typedef struct DXGI_SAMPLE_DESC {
  UINT Count;
  UINT Quality;
} DXGI_SAMPLE_DESC;

 

D3D11_CREATE_DEVICE_FLAG 枚舉類型

typedef enum D3D11_CREATE_DEVICE_FLAG { 
  D3D11_CREATE_DEVICE_SINGLETHREADED                                 = 0x1,
  D3D11_CREATE_DEVICE_DEBUG                                          = 0x2,
  D3D11_CREATE_DEVICE_SWITCH_TO_REF                                  = 0x4,
  D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS       = 0x8,
  D3D11_CREATE_DEVICE_BGRA_SUPPORT                                   = 0x20,
  D3D11_CREATE_DEVICE_DEBUGGABLE                                     = 0x40,
  D3D11_CREATE_DEVICE_PREVENT_ALTERING_LAYER_SETTINGS_FROM_REGISTRY  = 0x80,
  D3D11_CREATE_DEVICE_DISABLE_GPU_TIMEOUT                            = 0x100,
  D3D11_CREATE_DEVICE_VIDEO_SUPPORT                                  = 0x800
} D3D11_CREATE_DEVICE_FLAG;

D3D11_CREATE_DEVICE_SINGLETHREADED
如果使用該常量,你的應用程序將只可以在一個線程中的調用 Dierct3D 11接口。在默認情況下ID3D11Device
對象是一個安全線程。使用這個標志,你可以增強性能。然而,如果你使用這個標志並且你的應用程序使用
多線程調用Dierct3D 11接口,可能導致不可預期的結果。

D3D11_CREATE_DEVICE_DEBUG
創建一個設備支持調用層。

D3D11_CREATE_DEVICE_SWITCH_TO_REF
注意 這個標志不支持Direct3D 11.

D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
阻止被多線程創建。當使用WARP標志時,WARP和所有光柵不能夠被線程調用。這個標志不建議使用。

D3D11_CREATE_DEVICE_BGRA_SUPPORT
Dierct2D需要和Direct3D資源交互。

 

下面是每個步驟對應的代碼:

一、指明驅動設備等級和特征等級

 1 HRESULT hResult = S_OK;//返回結果
 2 
 3     RECT rc;
 4     GetClientRect(g_hWnd, &rc);//獲取窗口客戶區大小
 5     UINT width = rc.right - rc.left;
 6     UINT height = rc.bottom - rc.top;
 7 
 8     UINT createDeviceFlags = 0;
 9 #ifdef _DEBUG
10     createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
11 #endif
12 
13     //驅動類型數組
14     D3D_DRIVER_TYPE driverTypes[] = 
15     {
16         D3D_DRIVER_TYPE_HARDWARE,
17         D3D_DRIVER_TYPE_WARP,
18         D3D_DRIVER_TYPE_REFERENCE
19     };
20     UINT numDriverTypes = ARRAYSIZE(driverTypes);
21 
22     //特征級別數組
23     D3D_FEATURE_LEVEL featureLevels[] =
24     {
25         D3D_FEATURE_LEVEL_11_0,
26         D3D_FEATURE_LEVEL_10_1,
27         D3D_FEATURE_LEVEL_10_0
28     };
29     UINT numFeatureLevels = ARRAYSIZE(featureLevels);

 

二、創建設備和交換鏈

交換鏈具體定義

typedef struct DXGI_SWAP_CHAIN_DESC {
  DXGI_MODE_DESC   BufferDesc;
  DXGI_SAMPLE_DESC SampleDesc;
  DXGI_USAGE       BufferUsage;
  UINT             BufferCount;
  HWND             OutputWindow;
  BOOL             Windowed;
  DXGI_SWAP_EFFECT SwapEffect;
  UINT             Flags;
} DXGI_SWAP_CHAIN_DESC;

   BufferDesc指定后緩沖區有關特性;

       SampleDesc指定多重采樣,前面說過;

       BufferUsage,對於交換鏈,為DXGI_USAGE_RENDER_TARGET_OUTPUT;

       BufferCount:我們只創建一個后緩沖區(雙緩沖),因此為1;

       OutputWindow:指定窗口句柄,Win32程序初始化完創建的主窗口;

       Windowed:是否全屏;

       DXGI_SWAP_EFFECT:通常為DXGI_SWAP_EFFECT_DISCARD;

       Flags:可選

其中DXGI_MODE_DESC定義如下
typedef struct DXGI_MODE_DESC {
  UINT                     Width;
  UINT                     Height;
  DXGI_RATIONAL            RefreshRate;
  DXGI_FORMAT              Format;
  DXGI_MODE_SCANLINE_ORDER ScanlineOrdering;
  DXGI_MODE_SCALING        Scaling;
} DXGI_MODE_DESC, *LPDXGI_MODE_DESC;

Width、Height為緩沖區大小,一般設為主窗口大小;

Format為緩沖區類型,一般作為渲染對象緩沖區類型為DXGI_FORMAT_R8G8B8A8_UNORM;

其他參數一般為固定的。

 

交換鏈的設置

 1 //交換鏈
 2     DXGI_SWAP_CHAIN_DESC sd;
 3     ZeroMemory(&sd, sizeof(DXGI_SWAP_CHAIN_DESC));//填充
 4     sd.BufferCount = 1;                              //我們只創建一個后緩沖(雙緩沖)因此為1
 5     sd.BufferDesc.Width = width;
 6     sd.BufferDesc.Height = height;
 7     sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
 8     sd.BufferDesc.RefreshRate.Numerator = 60;
 9     sd.BufferDesc.RefreshRate.Denominator = 1;
10     sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
11     sd.OutputWindow = g_hWnd;
12     sd.SampleDesc.Count = 1;                      //1重采樣
13     sd.SampleDesc.Quality = 0;                      //采樣等級
14     sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;      //常用參數
15     sd.Windowed = TRUE;                              //是否全屏

 

創建設備及交換鏈,d3d設備一般都是設備本身和硬件之間的通信,而d3d上下文是一種描述設備如何繪制的渲染設備上下文,這也包含了渲染狀態和其他的繪圖信息。

而交換鏈是設備和上下文將要繪制的渲染目標。

 

D3D11CreateDeviceAndSwapChain函數原型:

HRESULT D3D11CreateDeviceAndSwapChain(
  _In_opt_        IDXGIAdapter         *pAdapter, D3D_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, _In_opt_ const D3D_FEATURE_LEVEL *pFeatureLevels, UINT FeatureLevels, UINT SDKVersion, _In_opt_ const DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, _Out_opt_ IDXGISwapChain **ppSwapChain, _Out_opt_ ID3D11Device **ppDevice, _Out_opt_ D3D_FEATURE_LEVEL *pFeatureLevel, _Out_opt_ ID3D11DeviceContext **ppImmediateContext );

pAdapter來選擇相應的圖形適配器,設為NULL以選擇默認的適配器;

DriverType設置驅動類型,一般毫無疑問選擇硬件加速,即D3D_DRIVER_TYPE_HARDWARE,此時下一個參數就是NULL;

Flags為可選參數,一般為NULL,可以設為D3D11_CREATE_DEVICE_DEBUG、D3D11_CREATE_DEVICE_SINGLETHREADED,或兩者一起,前者讓要用於調試時收集信息,后者在確定程序只在單線程下運行時設置為它,可以提高性能;

pFeatureLevels為我們提供給程序的特征等級的一個數組,下一個參數為數組中元素個數;

SDKVersion恆定為D3D11_SDK_VERSION;

ppDevice為設備指針的地址,注意設備是指針類型,這里傳遞的是指針的地址(二維指針,d3d程序中所有的接口都聲明為指針類型!);

pFeatureLevel為最后程序選中的特征等級,我們定義相應的變量,傳遞它的地址進來;

ppImmediateContext為設備上下文指針的地址,要求同設備指針。

 

創建設備和交換鏈的相關代碼

 1 for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; ++driverTypeIndex)
 2     {
 3         g_driverType = driverTypes[driverTypeIndex];
 4         hResult = D3D11CreateDeviceAndSwapChain(
 5             NULL,                                //默認圖形適配器
 6             g_driverType,                        //驅動類型
 7             NULL,                                //實現軟件渲染設備的動態庫句柄,如果使用的驅動設備類型是軟件設備則不能為NULL
 8             createDeviceFlags,                    //創建標志,0用於游戲發布,一般D3D11_CREATE_DEVICE_DEBUG允許我們創建可供調試的設備,在開發中比較有用
 9             featureLevels,                        //特征等級
10             numFeatureLevels,                    //特征等級數量
11             D3D11_SDK_VERSION,                    //sdk版本號
12             &sd,
13             &g_pSwapChain,
14             &g_pd3dDevice,
15             &g_featureLevel,
16             &g_pImmediateContext
17             );
18         if (SUCCEEDED(hResult))
19             break;
20     }
21     if (FAILED(hResult))
22         return hResult;

 

三、創建和綁定渲染目標視圖

一個渲染目標視圖是一個由Output MergerStage讀取的D3D資源。交換鏈的主緩存和輔助緩存為彩色的圖像,通過調用交換鏈中的函數GetBuffer來得到它的指針。得到指針后,然后再通過CreateRenderTargetView函數來創建一個渲染目標視圖。創建完渲染目標后,就可以調用Release()釋放指針到交換鏈的后台緩存了。當想渲染一個特定的渲染目標的時,要在繪制函數調用前對它進行設置,這個工作是由OMSetRenderTarget函數完成的。

 

 

CreateRenderTargetView函數原型

HRESULT CreateRenderTargetView(
  [in]                  ID3D11Resource                *pResource, [in, optional] const D3D11_RENDER_TARGET_VIEW_DESC *pDesc, [out, optional] ID3D11RenderTargetView **ppRTView );

pResource為視圖對應資源

pDesc為視圖描述 

ppRTView要創建的視圖,是一個指針的地址

 

這一部分的代碼

 1 //創建渲染目標視圖
 2     ID3D11Texture2D *pBackBuffer = NULL;
 3     //獲取后緩沖區地址
 4     hResult = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
 5     if (FAILED(hResult))
 6         return hResult;
 7 
 8     //創建目標視圖
 9     hResult = g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_pRenderTargetView);
10     //釋放后緩沖
11     pBackBuffer->Release();
12     if (FAILED(hResult))
13         return hResult;
14 
15     //綁定到渲染管線
16     g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, NULL);

 

 

四、創建視口

視口定義了渲染到屏幕上的面積,對於單屏游戲來說一般為全屏的,這樣我們設置視口的width和height為交換鏈對應的width、height就好了;對於分屏游戲,可以創建兩個視口

放在屏幕不同位置,以不同玩家的角度來渲染。

 

D3D11_VIEWPORT定義

typedef struct D3D11_VIEWPORT {
  FLOAT TopLeftX;        //視口左上角x坐標,一般視口占滿屏幕的,所以為0
  FLOAT TopLeftY;        //y坐標
  FLOAT Width;            //視口寬度,一般與后緩沖區一致,以保持圖像不變形
  FLOAT Height;            //高度,同上
  FLOAT MinDepth;        //最小深度值:0.0f
  FLOAT MaxDepth;        //最大深度值:1.0f
} D3D11_VIEWPORT;

 

具體代碼

1 //設置viewport
2     D3D11_VIEWPORT vp;
3     vp.Height = (FLOAT)height;
4     vp.Width = (FLOAT)width;
5     vp.MinDepth = 0.0f;
6     vp.MaxDepth = 1.0f;
7     vp.TopLeftX = 0;
8     vp.TopLeftY = 0;
9     g_pImmediateContext->RSSetViewports(1, &vp);

 

 接下來的Render函數中實現了清除顯示屏幕的功能

float ClearColor[4] = { 0.5f, 0.1f, 0.2f, 1.0f }; //red,green,blue,alpha
    g_pImmediateContext->ClearRenderTargetView(g_pRenderTargetView, ClearColor);
    g_pSwapChain->Present(0, 0);

 

  

下面給出整個工程的代碼:

#include <windows.h>
#include <d3d11.h>
#include <DxErr.h>
#include <D3DX11.h>

HINSTANCE g_hInstance = NULL;
HWND g_hWnd = NULL;
LPCWSTR g_name = L"FirstD3D11Demo";
D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;                //驅動類型
D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;            //特征等級    
ID3D11Device *g_pd3dDevice = NULL;                                    //設備
ID3D11DeviceContext *g_pImmediateContext = NULL;                    //設備上下文
IDXGISwapChain *g_pSwapChain = NULL;                                //交換鏈
ID3D11RenderTargetView *g_pRenderTargetView = NULL;                    //要創建的視圖


HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow);
HRESULT InitDevice();
void CleanupDevice();
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void Render();

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
{
    if (FAILED(InitWindow(hInstance, nShowCmd)))
        return 0;
    if (FAILED(InitDevice()))
    {
        CleanupDevice();
        return 0;
    }
    MSG msg;
    ZeroMemory(&msg, sizeof(MSG));
    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else//渲染
        {
            Render();
        }
    }
    CleanupDevice();
    return static_cast<int>(msg.wParam);
}

HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow)
{
    WNDCLASSEX wcex;
    wcex.cbClsExtra = 0;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.cbWndExtra = 0;
    wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wcex.hCursor = LoadCursor(NULL,IDC_ARROW);
    wcex.hIcon = LoadIcon(NULL, IDI_WINLOGO);
    wcex.hIconSm = wcex.hIcon;
    wcex.hInstance = hInstance;
    wcex.lpfnWndProc = WndProc;
    wcex.lpszClassName = g_name;
    wcex.lpszMenuName = NULL;
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    if (!RegisterClassEx(&wcex))
        return E_FAIL;

    g_hInstance = hInstance;
    RECT rc{0,0,640,480};
    AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
    g_hWnd = CreateWindowEx(WS_EX_APPWINDOW, g_name, g_name, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
        rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, g_hInstance, NULL);
    if (!g_hWnd)
        return E_FAIL;

    ShowWindow(g_hWnd, nCmdShow);

    return S_OK;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wPararm, LPARAM lParam)
{
    switch (message)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wPararm, lParam);
    }
    return 0;
}

//創建設備及交換鏈
HRESULT InitDevice()
{
    HRESULT hResult = S_OK;//返回結果

    RECT rc;
    GetClientRect(g_hWnd, &rc);//獲取窗口客戶區大小
    UINT width = rc.right - rc.left;
    UINT height = rc.bottom - rc.top;

    UINT createDeviceFlags = 0;
#ifdef _DEBUG
    createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

    //驅動類型數組
    D3D_DRIVER_TYPE driverTypes[] = 
    {
        D3D_DRIVER_TYPE_HARDWARE,
        D3D_DRIVER_TYPE_WARP,
        D3D_DRIVER_TYPE_REFERENCE
    };
    UINT numDriverTypes = ARRAYSIZE(driverTypes);

    //特征級別數組
    D3D_FEATURE_LEVEL featureLevels[] =
    {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0
    };
    UINT numFeatureLevels = ARRAYSIZE(featureLevels);

    //交換鏈
    DXGI_SWAP_CHAIN_DESC sd;
    ZeroMemory(&sd, sizeof(DXGI_SWAP_CHAIN_DESC));//填充
    sd.BufferCount = 1;                              //我們只創建一個后緩沖(雙緩沖)因此為1
    sd.BufferDesc.Width = width;
    sd.BufferDesc.Height = height;
    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    sd.BufferDesc.RefreshRate.Numerator = 60;
    sd.BufferDesc.RefreshRate.Denominator = 1;
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.OutputWindow = g_hWnd;
    sd.SampleDesc.Count = 1;                      //1重采樣
    sd.SampleDesc.Quality = 0;                      //采樣等級
    sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;      //常用參數
    sd.Windowed = TRUE;                              //是否全屏

    for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; ++driverTypeIndex)
    {
        g_driverType = driverTypes[driverTypeIndex];
        hResult = D3D11CreateDeviceAndSwapChain(
            NULL,                                //默認圖形適配器
            g_driverType,                        //驅動類型
            NULL,                                //實現軟件渲染設備的動態庫句柄,如果使用的驅動設備類型是軟件設備則不能為NULL
            createDeviceFlags,                    //創建標志,0用於游戲發布,一般D3D11_CREATE_DEVICE_DEBUG允許我們創建可供調試的設備,在開發中比較有用
            featureLevels,                        //特征等級
            numFeatureLevels,                    //特征等級數量
            D3D11_SDK_VERSION,                    //sdk版本號
            &sd,
            &g_pSwapChain,
            &g_pd3dDevice,
            &g_featureLevel,
            &g_pImmediateContext
            );
        if (SUCCEEDED(hResult))
            break;
    }
    if (FAILED(hResult))
        return hResult;

    //創建渲染目標視圖
    ID3D11Texture2D *pBackBuffer = NULL;
    //獲取后緩沖區地址
    hResult = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
    if (FAILED(hResult))
        return hResult;

    //創建目標視圖
    hResult = g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_pRenderTargetView);
    //釋放后緩沖
    pBackBuffer->Release();
    if (FAILED(hResult))
        return hResult;

    //綁定到渲染管線
    g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, NULL);

    //設置viewport
    D3D11_VIEWPORT vp;
    vp.Height = (FLOAT)height;
    vp.Width = (FLOAT)width;
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    vp.TopLeftX = 0;
    vp.TopLeftY = 0;
    g_pImmediateContext->RSSetViewports(1, &vp);

    return S_OK;
}

void Render()
{
    float ClearColor[4] = { 0.5f, 0.1f, 0.2f, 1.0f }; //red,green,blue,alpha
    g_pImmediateContext->ClearRenderTargetView(g_pRenderTargetView, ClearColor);
    g_pSwapChain->Present(0, 0);
}

void CleanupDevice()
{
    if (g_pImmediateContext)
        g_pImmediateContext->ClearState();
    if (g_pSwapChain)
        g_pSwapChain->Release();
    if (g_pRenderTargetView)
        g_pRenderTargetView->Release();
    if (g_pImmediateContext)
        g_pImmediateContext->Release();
    if (g_pd3dDevice)
        g_pd3dDevice->Release();
}

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM