Dx11DemoBase 基类(二) 初始化 DirectX11 的 4个基本步骤

上文说的 要用现实现象来模拟解释 初始化 Direct3D11的过程, 呃... 暂时想不出了, 呵呵.

一般初始化 Direct3D11的过程, 分为四步:

 

bool Dx11DemoBase::Initialize( HINSTANCE hInstance, HWND hwnd)
{
    //store members
View Code

//
steop 1. Description of driver types and feature level
View Code
    D3D_DRIVER_TYPE driverTypes[] = {
        D3D_DRIVER_TYPE_HARDWARE, 
        D3D_DRIVER_TYPE_WARP, 
        D3D_DRIVER_TYPE_SOFTWARE
    };
    unsigned int totalDriverTypes = ARRAYSIZE( driverTypes);

    D3D_FEATURE_LEVEL featureLevels[] = {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0
    };
    unsigned int toalFeatureLevels = ARRAYSIZE( featureLevels);

 

// step 2. create swap-chain, device and context
View Code
    bool result = false;
    result = CreateDeviceAndSwapChain( totalDriverTypes, driverTypes, toalFeatureLevels, featureLevels);
    assert( result == true);

 

// step 3. set render target view
View Code
    result = SetRenderTargetView();
    assert( result == true);

 

// step 4. set viewport
View Code
result = SetViewport();
    assert( result == true);

 

  return LoadContent();
}

开始接触Direct3D时, 觉得很烦, 需要很多的初始化对象, 还不是最终直接需要的东西, 如 step 1 中定义的一些 的结构数据; 对这种初始化创建方式的不熟悉, 应该是我自己 接触的代码量还是相当匮乏, 了解的编程编码方式不了解; 还好 前段时间在进行 linux的网络库开发时, 用到了 pthread_mtex_t 锁, 创建方式如:

//声明并定义 mutex结构体 
pthread_mutex_t  mutex;

//声明定义 mutex使用的 属性设置 结构体 attr
pthread_mutexattr_t attr;
attr.xxx = yyy;
attr.... = ...;

//使用 属性结构体attr 初始化 mutex
pthread_mutex_init( &mutex, &attr);

创建线程也有类似的方式:

//声明 线程tid
pthread_t    tid;
 
//声明 线程属性 
pthread_attr_t    attr;
//接着是 该属性的设置 
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

//最后使用 属性结构体 attr 创建线程:  
pthread_create(&tid, &attr, callback_func, NULL);

这种使用属性结构体来初始化/或创建 最终目的对象的方式 也可转换到 directx11 编程中; 如 swap-chain( 只不过这里不适用 attr类的 标记单词, 而使用 Desc后缀):

// step 2. create swap-chain(其实不仅仅是 swap-chain 啦, 还包括 device, context等, 这里是为了说明 attr/desc - creation的 编码方式)
bool Dx11DemoBase::CreateDeviceAndSwapChain( unsigned int totalDriverTypes, D3D_DRIVER_TYPE driverTypes[], unsigned int totalFeatureLevels, D3D_FEATURE_LEVEL featureLevels[]) { RECT dimensions; GetClientRect( hwnd_, &dimensions ); unsigned int width = dimensions.right - dimensions.left; unsigned int height = dimensions.bottom - dimensions.top; //第一步声明并定义 swap-chain 描述: DXGI_SWAP_CHAIN_DESC swapChainDesc; ZeroMemory( &swapChainDesc, sizeof( swapChainDesc)); swapChainDesc.BufferCount = 1; swapChainDesc.BufferDesc.Width = width; swapChainDesc.BufferDesc.Height = height; swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferDesc.RefreshRate.Numerator = 60; swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.OutputWindow = hwnd_; swapChainDesc.Windowed = true; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; //第二步才是 创建 swap-chain, 不过 unsigned int creationFlags = 0; #ifdef _DEBUG creationFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif HRESULT result; unsigned int driver = 0; for( driver = 0; driver < totalDriverTypes; ++ driver) { //匹配当前的 driver 和 feature-level result = D3D11CreateDeviceAndSwapChain( 0, driverTypes[ driver], 0, creationFlags, featureLevels, totalFeatureLevels, D3D11_SDK_VERSION, &swapChainDesc, //就是这里啦 &swapChain_, //主体讨论的对象 &d3dDevice_, //同时被创建了 &featureLevel_, //同时被创建了 &d3dContext_ //同时被创建了 ); if( SUCCEEDED( result)) { driverType_ = driverTypes[ driver]; break; } } if( FAILED( result)) { DXTRACE_MSG( "Failed to create the Direct3D device!"); return false; } return true; }

 

step 1. 进行 driver , feature-level 的确定;

step 2. 产生 device, context 和 swap-chain . 这三者的关系( 通过书本的解释)如下图:

Direct3D device   : 与硬件设备通信          
Direct3D context   : 告诉 Direct3D device 如何进行 draw
swap-chain      : Direct3D device 和 Direct3D context 绘制的 目的地

 

 step 3. Set render target view
View Code

其实 第3步 还是没有超出上图的 描述, 这一步主要是针对 swap-chain 和 device 的设置( 按照我刚开始学习directx11 而言), 因为 swap-chain分为 多层, 需要设置一层为 候补层 backBufferTarget, 而 其中一层 用来实际直接渲染 , that are the primary and secondary rendering buffers of a swapchain. 如下图:

 

// step 4. set viewport
View Code

最后的 step 4. 也没有超出上述范围, 不下图所示的 ④ 标记, 用以设置 "how to draw", 主要是坐标 /大小:

 

 整个新的 Dx11DemoBase 基类为:

#ifndef _DEMO_BASE_H_
#define _DEMO_BASE_H_

#include <d3d11.h>
#include <d3dx11.h>
#include <DxErr.h>

class Dx11DemoBase{
public:
    Dx11DemoBase();
    virtual ~Dx11DemoBase();

    bool Initialize( HINSTANCE hInstance, HWND hwnd);
    void Shutdown();


    virtual bool LoadContent();
    virtual void UnloadContent();

protected:
    HINSTANCE hInstance_;
    HWND hwnd_;

    D3D_DRIVER_TYPE driverType_;
    D3D_FEATURE_LEVEL featureLevel_;

    ID3D11Device *d3dDevice_;
    ID3D11DeviceContext *d3dContext_;
    IDXGISwapChain *swapChain_;
    ID3D11RenderTargetView *backBufferTarget_;

    unsigned int width_ ;
    unsigned int height_ ;

private:
    bool CreateDeviceAndSwapChain( unsigned int totalDriverTypes, D3D_DRIVER_TYPE driverTypes[], unsigned int totalFeatureLevels, D3D_FEATURE_LEVEL featureLevels[]);
    bool SetRenderTargetView();
    bool SetViewport();
};


#endif

 最新文件: Dx11DemoBase.tar

 

 

 这篇写到这里, 发现跟原文叙述的过程也差不多, 但通过自己的一层层刨释, 即使是仅仅 抄写代码, 但考虑到 本随笔还是可能会被其他 观客 看到, 不能马虎, 不能行文前后矛盾, 一深入思考, 反而提升了自己对 DirectX11 的认识.

posted @ 2012-11-28 02:56  Wilson-Loo  阅读(1103)  评论(0编辑  收藏  举报