初始化Direct3D

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Spring_24/article/details/77714654

一、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;
	else
		vp = 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;
	else
		vp = 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 scene
	if (SUCCEEDED(g_pd3dDevice->BeginScene()))
	{
		g_pd3dDevice->EndScene();
	}

	// Present the backbuffer contents to the display
	g_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 class
	WNDCLASSEX wc =
	{
		sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
		GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
		L"D3D Tutorial", NULL
	};
	RegisterClassEx(&wc);

	// Create the application's window
	HWND hWnd = CreateWindow(L"D3D Tutorial", L"D3D : CreateDevice",
		WS_OVERLAPPEDWINDOW, 100, 100, 700, 700,
		NULL, NULL, wc.hInstance, NULL);

	// Initialize Direct3D
	if (SUCCEEDED(InitD3D(hWnd)))
	{
			// Show the window
			ShowWindow(hWnd, SW_SHOWDEFAULT);
			UpdateWindow(hWnd);

			// Enter the message loop
			MSG msg;
			ZeroMemory(&msg, sizeof(msg));
			while (msg.message != WM_QUIT)
			{
				if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
				{
					TranslateMessage(&msg);
					DispatchMessage(&msg);
				}
				else
					Render();
			}
	}

	UnregisterClass(L"D3D Tutorial", wc.hInstance);
	return 0;
}


     程序运行效果如下:

     


猜你喜欢

转载自blog.csdn.net/Spring_24/article/details/77714654
今日推荐