这些天终于受不了诱惑,决定入手Directx11,看了下一个最basic 的demo,总结下自己的理解。

  先看看整体框架:所有函数的声明。可以看到和D3d9c差不多,都是初始化窗口,创建设备,清理设备,消息循环和渲染。下面我们将看到发生变化的主要是创建设备的InitDevice()函数,其他都是些MFC框架。

  HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ); 

  HRESULT InitDevice();

  void CleanupDevice();

  LRESULT CALLBACK    WndProc( HWND, UINT, WPARAM, LPARAM );

  void Render();

 

  主函数入口,可以看到和Directx9一样,正如前面说的,后面会看到最大的不一样就是在InitDevice()里面初始化不一样的设备而已。

int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )

{

//    UNREFERENCED_PARAMETER( hPrevInstance );

 //   UNREFERENCED_PARAMETER( lpCmdLine );

    if( FAILED( InitWindow( hInstance, nCmdShow ) ) )

        return 0;

    if( FAILED( InitDevice() ) )

    {

        CleanupDevice();

        return 0;

    }

    // Main message loop

    MSG msg = {0};

    while( WM_QUIT != msg.message )

    {

        if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )

        {

            TranslateMessage( &msg );

            DispatchMessage( &msg );

        }

        else

        {

            Render();

        }

    }

    CleanupDevice();

    return ( int )msg.wParam;

}

 

  接下来我们集中讨论下InitDevice()。先看下程序一开始定义的全局变量,并讨论InitDevice()中如何初始化下面一些设备接口。

//--------------------------------------------------------------------------------------

// Global Variables

//--------------------------------------------------------------------------------------

HINSTANCE               g_hInst = NULL;

HWND                    g_hWnd = NULL;

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;

  Directx9里面只有一个设备接口:IDirect3DDevice9,而在Directx11中则有三个:device,immediate contexa swap chain。在d3d9里面,渲染以及创建设备的工作都是有device来负责。但是d3d11里面则分开了,device负责创建resouces,immediate contex负责渲染。而swap chain则是交换链,最典型作用负责交换前后台缓存,front buffer和back buffer。(ps下:swap chain在d3d9里面也有了,不过这个接口在D3d9里面用的很少,因为这个接口都是Direct3D负责管理的,不知道在D3d11里面是不是会用的比较多,有待探索)。 front buffer是现在电脑屏幕上正在展现的内容,back buffer是正在后台被渲染的缓存。当back buffer被绘制好了,则将back buffer和front buffer交换。

  为了创建上面说的device,immediate device和swap chain,可以通过调用D3D11CreateDeviceAndSwapChain函数,其原型如下:

  HRESULT D3D11CreateDeviceAndSwapChain( __in IDXGIAdapter *pAdapter,

  __in D3D_DRIVER_TYPE DriverType,

  __in HMODULE Software,

  __in UINT Flags,

  __in const D3D_FEATURE_LEVEL *pFeatureLevels,

  __in UINT FeatureLevels,

  __in UINT SDKVersion,

  __in const DXGI_SWAP_CHAIN_DESC *pSwapChainDesc,

  __out IDXGISwapChain **ppSwapChain,

  __out ID3D11Device **ppDevice,

  __out D3D_FEATURE_LEVEL *pFeatureLevel,

  __out ID3D11DeviceContext **ppImmediateContext );

 

  调用实例:

  hr = D3D11CreateDeviceAndSwapChain( NULL,

  g_driverType,

  NULL,

  createDeviceFlags,

  featureLevels,

  numFeatureLevels,

  D3D11_SDK_VERSION,

  &sd,

  &g_pSwapChain,

  &g_pd3dDevice,

  &g_featureLevel,

  &g_pImmediateContext );

 

  再看看d3d9中类似的创建设备函数IDirect3D9::CreateDevice():

  HRESULT CreateDevicee( [in] UINT Adapter,

  [in] D3DDEVTYPE DeviceType,

  [in] HWND hFocusWindow,

  [in] DWORD BehaviorFlags,

  [in, out] D3DPRESENT_PARAMETERS *pPresentationParameters,

  [out, retval] IDirect3DDevice9 **ppReturnedDeviceInterface );

  调用实例:

   IDirect3D9* g_pD3D;

   g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,

                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,

                                      &d3dpp, &g_pd3dDevice ) ;

 

  下面我们通过函数CreateRenderTargetView()创建一个render target view(类似于c中用空指针void*创建的一片内存区),并将swap chain的back buffer绑定给它,这样D3d11才能渲染back buffer。我对这个概念也不是很理解,个人感觉像是你想要渲染的东西,必须绑定到一个指定的空显存区,然后d3d11渲染管道的输出会写到这块显存中,即完成渲染。

  if( FAILED( g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (LPVOID*)&pBackBuffer ) ) )

    return FALSE;

  hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView );

  pBackBuffer->Release(); if( FAILED( hr ) ) return FALSE;

   接下来我们通过调用immediate context的OMSetRenderTargets()将刚创建的render target view绑定到渲染管道,这样渲染管道的输出会自动写到back buffer中。

  g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, NULL );

 

  InitDevice()的最后就是创建一个视口viewport,和d3d9差不多,但是d3d11中视口是必须要创建的。

  D3D11_VIEWPORT vp;

  vp.Width = (FLOAT)width;

  vp.Height = (FLOAT)height;

  vp.MinDepth = 0.0f;

  vp.MaxDepth = 1.0f;

  vp.TopLeftX = 0;

  vp.TopLeftY = 0;

  g_pImmediateContext->RSSetViewports( 1, &vp );

 

  最后看看Render().相对d3d9明显简洁了许多,没有了IDirect3DDevice9::begin()和IDirect3DDevice9::end()(连XNA都未能幸免begin和end),直接draw()。

 

void Render()

{

    // Just clear the backbuffer

    float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; //red,green,blue,alpha

    g_pImmediateContext->ClearRenderTargetView( g_pRenderTargetView, ClearColor );

    g_pSwapChain->Present( 0, 0 );

}

 

  剩下几个函数都是和D3d9c差不多了。因为都是一些MFC的框架。

 

 

posted on 2010-12-07 01:50  Bester  阅读(561)  评论(0编辑  收藏  举报