现在的位置: 首页 > 综合 > 正文

菜鸟生活在次时代

2012年08月18日 ⁄ 综合 ⁄ 共 3017字 ⁄ 字号 评论关闭

“如何入门DX呢?”这句话不知道被说过多少次。

“看红龙书。”这句话也不知道被说过多少次。

这就是一个菜鸟在次时代的困惑,而那个答案,也许是对的,但绝对不适合所有人。

DX11已经几个年头,这到底是个什么东西呢?本菜决定去看看究竟:

传送门:DX11教程1

这个教程言简意赅,所有重要的也都说了(虽然是用英语说- -!),我不知道大家怎么样,我时常抓不住重点,从小上课就是,所以我决定这次自己总结下重点。

撇开使用win32 api创建窗口部分,单纯说说DX11的基础使用流程。其实你不必担心自己会不会窗口创建哪部分代码,因为它其实跟初始化DX一样是固定流程,然后你以后写代码的时候会一次又一次的遇到,现在不必可以花时间去背,随着使用的频率你慢慢就胸有成竹了,好了说正题。

我发现这个教程的代码里有几个全局变量,可以说是建一个正常的DX11程序所需要的最少变量数了,它们是:

ID3D11Device,它表示一个显卡对象,它是虚拟的,也就是说你一个显卡可以有多个代表它的Device对象存在,但你一个Device只能表示一个真实的物理显卡。它是干嘛呢?主要用来创建DX要用的资源以及提供显卡的性能信息。

ID3D11DeviceContext,在DX11的世界里,就这个接口和上面那个能耐最大,也最主要。因为上面的负责创建,这个负责使用。文档描述它产生commandlist,这个东西由于我在DX9中没见过,所以没太深感触(远处飘渺的声音:吹吧,你就是DX9也没什么感触。。。),目前我理解它就是直接对显卡发送指令,显卡工作。而cmdlist可以把runtime时候它发过的指令存起来,然后重复使用,而这个从cmdlist就好像CPU的cache一样可以是运行速度加快。

IDXGISwapChain,交换链,dx9就有的概念,不过现在被更加明确化了。初学者比如我,一般就用一个后备缓冲和一个前屏表面。

ID3D11RenderTargetView,在dx9我保证没有的东西,这个接口的出现是因为DX11中资源与view概念的出现,资源就是一块内存,然后不同的view就好像强类型转换一样使GPU明白它要用的那块内存是什么资源。同时,DX11里没有默认的视口,在DX9中加入我们完成初始化后直接运行,被渲染的是整个窗口或全屏,而在dx11里你没有这种默认设定,所以你必须自己指定视口的大小。一般他们要和你的窗口一样大,但有一点需要注意的是窗口的大小包括标题栏这些非客户区。

看看这个例子的代码,你会发现,上面4个主要接口,有3个可以在一个API调用中初始化,那就是:

D3D11CreateDeviceAndSwapChain, 在调用前你需要填充一个DXGI_SWAP_CHAIN_DESC,然后可以在每一个你不懂的参数上用NULL代替。

建立完之后,设置视口就可以了。

总结下就是:每当想到DX11,你会想到显卡,所以你就会想到你要用显卡的话必须有它的引用你才能用。于是想到了Device,它就是一个虚拟的显卡一样,接着你想到要使用,于是你又想到了contex。然后你决定创建一个实例来起动显卡工作,你会记起那个createDev&chain,填充参数时候你会被提示需要什么东西。最后要记得的就是万事俱备,就差设置视口了。设置后,DX11就为你所用了。

下面是我一个修改过的源码,它更加纯粹也更加清楚一点初始化的过程,去掉了一些“繁文缛节”,替换例子中的对应函数就可以运行了:

HRESULT InitDevice()
{
    HRESULT hr = S_OK;

    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( sd ) );
    sd.BufferCount = 1;
    sd.BufferDesc.Width = 640; //width和height你可以调整为适合你的视口
    sd.BufferDesc.Height = 480;
    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;
    sd.SampleDesc.Quality = 0;
    sd.Windowed = TRUE;

   
        g_driverType = driverTypes[driverTypeIndex];
        hr = D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0,featureLevels, numFeatureLevels,
                                            D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext );
       
    if( FAILED( hr ) )
        return hr;

    // Create a render target view
    ID3D11Texture2D* pBackBuffer = NULL;
    hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )&pBackBuffer );
    if( FAILED( hr ) )
        return hr;

    hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView );
    pBackBuffer->Release();
    if( FAILED( hr ) )
        return hr;

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

    // Setup the viewport
    D3D11_VIEWPORT vp;
    vp.Width = 640f;
    vp.Height = 480f;
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    vp.TopLeftX = 0;
    vp.TopLeftY = 0;
    g_pImmediateContext->RSSetViewports( 1, &vp );

    return S_OK;
}

抱歉!评论已关闭.