初始化Direct3D

来源:互联网 发布:剪辑音乐软件手机 编辑:程序博客网 时间:2024/06/05 19:08

一、Direct3D概述


        DirectX是微软公司开发的一套功能丰富的底层API,其功能涵盖了:
           2D/3D图形加速的支持、
           各种输入设备的控制、
           声音和音乐输出的混音和采样、
           多玩家网络游戏的控制、
           各种多媒体流媒体模式的控制等。


       DirectX在体系结构上很突出的优点是它使用了两层驱动——HAL和REF,那些为硬件所支持的特定功能可由HAL来控制(即可以充分地发挥硬件的加速功能),从而可以获得理想的运行速度。而对于那些不为硬件所支持的功能,借助REF,程序能够以软件方式来模拟相应的运算或处理过程,从而使得无论硬件配置是否高端,开发人员都可以完整地体验和测试DirectX所提供的全部功能。

       Direct3D是DirectX的三维部分,它是一套底层图形API,借助该API,我们能够利用硬件加速功能来绘制3D场景。Direct3D可以被视作应用程序与图形设备(3D硬件)交互的中介。它们之间的关系如下:  

         在Direct3D和图形设备之间有一个中间环节——HAL(Hardware Abstraction Layer,硬件抽象层)。由于市面上的图形卡品种繁多,每种卡的性能和实现同样功能的机理都有差异,所以Direct3D无法与图形设备直接交互。所以,Direct3D就需要设备制造商实现一个HAL。HAL是一个指示设备完成某些操作的设备相关的代码集。

        有时,Direct3D提供的某些功能不为所使用的图形设备支持,但是仍然希望使用这些功能。为了满足这种需求,Direct3D提供了参考光栅设备(reference rasterizer device),即REF设备,它能以软件运算方式完全支持Direct3D API。

        在Direct3D中,D3DDEVTYPE具有三种类型: 
               D3DDEVTYPE_HAL
               D3DDEVTYPE_REF
               D3DDEVTYPE_SW。
        其中,D3DDEVTYPE_SW是一种外挂的Direct3D设备,用以支持第三方的软件。

二、COM


        COM(Component Object Model,组件对象模型)是一项能够使DirectX独立于编程语言并具有向下兼容的技术。我们常称COM对象为接口,可将其视作为一个C++类来使用。我们所必需知道的仅仅是:
            如何通过某个特定函数或另一个COM接口的方法来获取指向某一COM接口的指针
            创建COM接口时不可以使用C++的关键字new
            使用完一个接口,应该调用该接口相应的Release方法释放资源
        注意:COM接口都有一个前缀I。例如IDirect3D9。

三、Direct3D初始化

         
          Direct3D的初始化过程可以分解为如下四个步骤:
          (1)获取接口IDirect3D9的指针。接口IDirect3D9用于获取系统中物理硬件设备的信息并创建接口IDirect3DDevice9,接口IDirect3DDevice9是一个C++对象,代表了我们用来显示3D图形的物理硬件设备
          (2)检查设备性能(D3DCAPS9),判断主显卡(primary display adapter 或 primary graphics card)是否支持硬件顶点运算。为了创建接口IDirect3DDevice9,我们必须明确显卡是否支持该功能。
          (3)初始化D3DPRESENT_PARAMETERS结构的一个实例。该结构有许多数据成员组成,我们可以通过这些变量来指定即将创建的接口IDirect3DDevice9的特性。
          (4)利用已初始化的D3DPRESENT_PARAMETERS结构创建IDirect3DDevice9对象。


一、获取接口IDirect3D9的指针

   
       要初始化IDirect3D,首先必须获得指向接口IDirect3D9的指针。

       
if (NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))return E_FAIL;

       函数Direct3DCreate9的参数必须是D3D_SDK_VERSION,只有如此方能保证应用程序使用正确的头文件。如果函数调用失败,将返回一个NULL指针。

       IDirect3D9对象主要有两个用途:设备枚举(device enumeration)以及创建IDirect3DDevice9类型的对象。设备枚举是指获取系统中可用的每块图形卡的性能、显示模式、格式及其他信息。

二、校验硬件顶点运算


       创建一个代表主显卡的IDirect3DDevice9类型对象时,必须指定使用该对象进行顶点运算的类型。如果可以,我们希望使用硬件顶点运算,但是由于并非所有的显卡都支持硬件顶点运算,我们必须首先检查图形卡是否支持该类型的运算。

       GetDeviceCaps的声明如下:
       HRESULT IDirect3D9::GetDeviceCaps(
               UINT Adapter,                             //指定物理显卡的序号
               D3DDEVTYPE DeviceType,       //指定设备类型(D3DDEVTYPE_HAL 或者 D3DDEVTYPE_REF)
               D3DCAPS9 * pCaps                   //返回已初始化的设备性能结构实例
       );
        
D3DCAPS9 caps;g_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);int vp = 0;if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;elsevp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;


三、填充D3DPRESENT_PARAMETERS结构


       该结构用于指定所要创建的IDirect3DDevice9类型对象的一些特性,该结构的定义如下:

    
      typedef struct _D3DPRESENT_PARAMETERS_
      {
        UINT            BackBufferWidth;                            //后台缓存中表面的宽度,单位为像素
       UINT            BackBufferHeight;                          //后台缓存中表面的高度,单位为像素
    D3DFORMAT         BackBufferFormat;               //后台缓存的像素格式
    UINT            BackBufferCount;                           //所需使用的后台缓存的个数
    D3DMULTISAMPLE_TYPE  MultiSampleType;    //后台缓存所使用的多重采样类型
    DWORD           MultiSampleQuality;                  //多重采样的质量水平
    D3DSWAPEFFECT      SwapEffect;                      //交换链中缓存页面的置换方式
    HWND            hDeviceWindow;                        //与设备相关的窗口句柄
    BOOL            Windowed;                                   //为true时,表示窗口模式,为false时,表示全屏模式
    BOOL            EnableAutoDepthStencil;  //为true时,则Direct3D自动创建并维护深度缓存或模版缓存
    D3DFORMAT         AutoDepthStencilFormat;   //深度缓存或模版缓存的像素格式
    DWORD            Flags;

    /* FullScreen_RefreshRateInHz must be zero for Windowed mode */
    UINT                FullScreen_RefreshRateInHz;    //刷新频率
    UINT                PresentationInterval;
  } D3DPRESENT_PARAMETERS;


        该结构体填充的一个实例如下:
        
D3DPRESENT_PARAMETERS d3dpp;d3dpp.BackBufferWidth            = width;d3dpp.BackBufferHeight           = height;d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;d3dpp.BackBufferCount            = 1;d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;d3dpp.MultiSampleQuality         = 0;d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD; d3dpp.hDeviceWindow              = hwnd;d3dpp.Windowed                   = windowed;d3dpp.EnableAutoDepthStencil     = true; d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;d3dpp.Flags                      = 0;d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;

四、创建IDirect3DDevice9接口


       CreateDevice函数的声明如下:
       HRESULT IDirect3D9::CreateDevice(
            UINT Adapter,             //物理显卡序号
            D3DDEVTYPEDeviceType,      //设备类型(HAL 或者 REF)
            HWND  hFocusWindow, //与设备相关的窗口句柄
            DWORD BehaviorFlags,  //指定设备进行3D运算的工作方式
            D3DPRESENT_PARAMETERS *pPresentationParameters,   //D3DPRESENT_PATAMETERS类型实例
            IDirect3DDevice9**  ppReturnedDeviceInterface //返回创建的设备
        );
            

       创建实例如下:
       
if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,vp,&d3dpp, &g_pd3dDevice))){return E_FAIL;}

四、代码示例


       代码说明:实现Direct3D的初始化,并将背景置为黄色

       
#include <Windows.h>#include <mmsystem.h>#include <d3dx9.h>#pragma warning( disable : 4996 ) // disable deprecated warning #include <strsafe.h>#pragma warning( default : 4996 )#include <d3dx9math.h>LPDIRECT3D9             g_pD3D = NULL; LPDIRECT3DDEVICE9       g_pd3dDevice = NULL;HRESULT InitD3D(HWND hWnd){// Step1: Create the D3D object.if (NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))return E_FAIL;// Step 2: Check for hardware vp.D3DCAPS9 caps;g_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);int vp = 0;if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;elsevp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;// Step 3: Fill out the D3DPRESENT_PARAMETERS structure.D3DPRESENT_PARAMETERS d3dpp;ZeroMemory(&d3dpp, sizeof(d3dpp));d3dpp.Windowed = TRUE;d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;d3dpp.EnableAutoDepthStencil = TRUE;        d3dpp.AutoDepthStencilFormat = D3DFMT_D16;// Step 4: Create the device.if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,vp,&d3dpp, &g_pd3dDevice))){return E_FAIL;}return S_OK;}VOID Cleanup(){if (g_pd3dDevice != NULL)g_pd3dDevice->Release();if (g_pD3D != NULL)g_pD3D->Release();}VOID Render(){g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255, 255, 0), 1.0f, 0);// Begin the sceneif (SUCCEEDED(g_pd3dDevice->BeginScene())){g_pd3dDevice->EndScene();}// Present the backbuffer contents to the displayg_pd3dDevice->Present(NULL, NULL, NULL, NULL);}LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){switch (msg){case WM_DESTROY:Cleanup();PostQuitMessage(0);return 0;}return DefWindowProc(hWnd, msg, wParam, lParam);}INT WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, INT){UNREFERENCED_PARAMETER(hInst);// Register the window classWNDCLASSEX wc ={sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,GetModuleHandle(NULL), NULL, NULL, NULL, NULL,L"D3D Tutorial", NULL};RegisterClassEx(&wc);// Create the application's windowHWND hWnd = CreateWindow(L"D3D Tutorial", L"D3D : CreateDevice",WS_OVERLAPPEDWINDOW, 100, 100, 700, 700,NULL, NULL, wc.hInstance, NULL);// Initialize Direct3Dif (SUCCEEDED(InitD3D(hWnd))){// Show the windowShowWindow(hWnd, SW_SHOWDEFAULT);UpdateWindow(hWnd);// Enter the message loopMSG msg;ZeroMemory(&msg, sizeof(msg));while (msg.message != WM_QUIT){if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)){TranslateMessage(&msg);DispatchMessage(&msg);}elseRender();}}UnregisterClass(L"D3D Tutorial", wc.hInstance);return 0;}


     程序运行效果如下:

     


























































































































































原创粉丝点击