Lesson 7: 初始化Direct3D

来源:互联网 发布:猎天使魔女3知乎 编辑:程序博客网 时间:2024/06/05 19:23

原文地址:
http://www.directxtutorial.com/Lesson.aspx?lessonid=11-4-2

COM:
COM是组件对象模型Component Object Model的简称,是一项能够使DirectX独立于编程语言并具备版本向后兼容的技术。
我们常称COM对象为接口,可视它为C++类来使用。在以C++编程语言和COM接口方式开发的DirectX应用程序中,可以直接访问COM接口和对象,许多COM的底层细节都不必考虑。
我们唯一需要知道的一件事情是,我们必须通过特定的函数或其他的COM接口方法来获取指向COM接口的指针,而不能用C++的new关键字来创建COM接口。另外,当我们不再使用某个接口时,必须调用它的Release方法来释放它(所有的COM接口都继承于IUnknown接口,而Release方法是IUnknown接口的成员),而不能用delete语句——COM对象在其自身内部实现所有的内存管理工作。

Direct3D提供的是一组软件接口,我们可以通过这组接口来控制绘图硬件:

device->CreateRenderTargetView()device->Release()

尽管COM为我们隐藏了很多复杂的细节,但仍有四点需要我们知道:

1.一个COM对象是被接口控制的一个类或者类的集合。。上述例子中,device就是一个COM接口对象。

2.每种类型的COM对象都有一个独特的ID

3.当完成对一个COM对象的使用的时候,必须调用Release()函数来释放它的内存以及关闭它的线程。

4.COM对象很容易识别,一般以I开头命名,例如’ID3D10Device’

Direct3D头文件:

// include the basic windows header files and the Direct3D header files#include <windows.h>#include <windowsx.h>#include <d3d11.h>#include <d3dx11.h>#include <d3dx10.h>// include the Direct3D Library file#pragma comment (lib, "d3d11.lib")#pragma comment (lib, "d3dx11.lib")#pragma comment (lib, "d3dx10.lib")// global declarationsIDXGISwapChain *swapchain;             // the pointer to the swap chain interfaceID3D11Device *dev;                     // the pointer to our Direct3D device interfaceID3D11DeviceContext *devcon;           // the pointer to our Direct3D device context// function prototypesvoid InitD3D(HWND hWnd);     // sets up and initializes Direct3Dvoid CleanD3D(void);         // closes Direct3D and releases memory// the WindowProc function prototypeLRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

d3d11.h文件包含了Direct3D的主要部分,d3dx11.h包含了Direct3D的扩展内容,对图形库不是必要的,但是对写游戏和其他图形程序很方便。
注意:不是所有的编译器都能自动定位这些文件,你需要设置你的project去DirectX SDK的文件夹中查找,visual studio设置教程:here

Direct3D 11是Direct3D 10的扩充,因此它从Direct3D 10中延续了许多宏定义,函数和类。d3dx10.h头文件允许我们在程序中使用这些。

“#pragma comment”指令将指定一块信息放置在你的project对象文件中。通过第一个参数,表明我们想为它添加一个库,然后第二个参数指定内容。所以这些指令包含了Direct3D 11的库文件。

ID3D11Device *dev;
这个变量是设备的一个指针。
这行代码意味着我们创建了一个叫ID3D11Device的COM接口对象。我们间接通过这个指针来使用这个接口对象。

ID3D11DeviceContext *devcon;
这个变量是一个设备上下文的COM接口对象的指针。
设备上下文和设备类似,但它用于管理GPU和渲染流水线(大部分用于处理显存)。这个接口对象用于渲染图形以及决定何时被渲染。
IDXGISwapChain *swapchain;
这个变量是交换链的接口对象的指针。
注意到这个接口对象不是属于Direct3D的,而是DXGI的一部分。

启用Direct3D:
第一步实际上就是创建并初始化上述的COM接口对象:

// this function initializes and prepares Direct3D for usevoid InitD3D(HWND hWnd){    // create a struct to hold information about the swap chain    DXGI_SWAP_CHAIN_DESC scd;    // clear out the struct for use    ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));    // fill the swap chain description struct    scd.BufferCount = 1;                                    // one back buffer    scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;     // use 32-bit color    scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;      // how swap chain is to be used    scd.OutputWindow = hWnd;                                // the window to be used    scd.SampleDesc.Count = 4;                               // how many multisamples    scd.Windowed = TRUE;                                    // windowed/full-screen mode    // create a device, device context and swap chain using the information in the scd struct    D3D11CreateDeviceAndSwapChain(NULL,                                  D3D_DRIVER_TYPE_HARDWARE,                                  NULL,                                  NULL,                                  NULL,                                  NULL,                                  D3D11_SDK_VERSION,                                  &scd,                                  &swapchain,                                  &dev,                                  NULL,                                  &devcon);}

DXGI_SWAP_CHAIN_DESC scd;
为了创建swap chain,我们填充一个DXGI_SWAPCHAIN_DESC结构体,这个结构体描述了我们要创建交换链的对象属性。它的变量虽然很多,但是我们只要关心一小部分就可以了。
为了创建swap chain,我们填充一个DXGI_SWAPCHAIN_DESC结构体,DXGI_SWAPCHAIN_DESC结构体描述了我们要创建swap chain的对象属性。DXGI_SWAPCHAIN_DESC结构体的变量虽然多,但是我们只要关心一小部分就可以了。

ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
快速对整个scd结构体清空。

scd.BufferCount = 1;
这个成员决定了我们交换链中要使用的后台缓冲区数量。

scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
这个成员决定了颜色的格式,在前台缓冲区和后台缓冲区,每个像素是以颜色来存储的。

scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
这个成员决定了我们将要如何使用我们的交换链。
这个参数大多数从下面两个中取值:
这里写图片描述
scd.OutputWindow = hWnd;
这个值决定了Direct3D应该绘制在哪个窗口。

scd.SampleDesc.Count = 1;
像素多采样抗锯齿,最小值为1,最大值为4,越高抗锯齿越好。

Multisample Anti-Alias (MSAA):
这里写图片描述

scd.Windowed = TRUE;
Direct3D运行在窗口中设为TRUE,全屏则设为FALSE。

D3D11CreateDeviceAndSwapChain():
这是一个很大的函数,但实际上我们写的每个游戏程序里,大部分参数都是一样的。
这个函数用于创建设备,设备上下文以及交换链的COM接口对象。一旦我们创建好了,我们可以使用它来实现渲染。

函数的原型如下:

HRESULT D3D11CreateDeviceAndSwapChain(    IDXGIAdapter *pAdapter,    D3D_DRIVER_TYPE DriverType,    HMODULE Software,    UINT Flags,    D3D_FEATURE_LEVEL *pFeatureLevels,    UINT FeatureLevels,    UINT SDKVersion,    DXGI_SWAP_CHAIN_DESC *pSwapChainDesc,    IDXGISwapChain **ppSwapChain,    ID3D11Device **ppDevice,    D3D_FEATURE_LEVEL *pFeatureLevel,    ID3D11DeviceContext **ppDeviceContext);

IDXGIAdapter *pAdapter,
这个值表明Direct3D应该使用的图形适配器。图形适配器指的是GPU和它的显存以及数模转换器等等。而我们只要设为NULL,表明使用默认适配器,交给DXGI决定就好了。

D3D_DRIVER_TYPE DriverType,
这个参数决定了Direct3D创建时应该使用的驱动类型。

有下列参数可选:
这里写图片描述

HMODULE Software,
DLL中的一个软件光栅句柄。通过LoadLibrary,LoadLibraryEx,或GetModuleHandle来获取这个句柄。
当D3D_DRIVER_TYPE值为D3D_DRIVER_TYPE_SOFTWARE时,这个值必须不为NULL,否则无效。

UINT Flags,
该参数用于运行层(参考D3D_CREATE_DEVICE_FLAG)。可用逻辑符号OR来操作。

这个参数可有以下取值:
这里写图片描述

D3D_FEATURE_LEVEL *pFeatureLevels,
这个指针指向一个D3D_FEATURE_LEVEL数组,来决定创建时排序的功能级别。默认使用最佳的功能级别。
在Direct3D 11中,我们设置为NULL就好了。

UINT FeatureLevels,
pFeatureLevels中的元素数量.。设置为NULL即可。

UINT SDKVersion,
SDK版本;始终使用D3D11_SDK_VERSION

DXGI_SWAP_CHAIN_DESC *pSwapChainDesc,
这个指针指向一个交换链接描述(参考:DXGI_SWAP_CHAIN_DESC),包含用于这个交换链接的初始化参数。
我们设置为交换链scd的地址。

IDXGISwapChain **ppSwapChain,
返回一个IDXGISwapChain对象的指针地址,这个交换链接用于渲染。

ID3D11Device **ppDevice,
返回一个创建好的 ID3D11Device对象的指针地址。供应一个NULL指针,返回一个pFeatureLevel中所支持的最高功能级别。
这里我们定义了ID3D11Device接口对象的指针为dev,所以设置为dev的地址。

D3D_FEATURE_LEVEL *FeatureLevel,
返回一个D3D_FEATURE_LEVEL指针,它来着pFeatureLevel中设备所支持的第一个元素。
设置为NULL即可。

ID3D11DeviceContext **ppImmediateContext
返回一个ID3D11DeviceContext对象指针,它代表这个设备上下文。
这里我们定义这接口对象为devcon,所以我们将devcon的地址放在这个参数中。

最终,这个函数使用如下:

D3D11CreateDeviceAndSwapChain(NULL,                              D3D_DRIVER_TYPE_HARDWARE,                              NULL,                              NULL,                              NULL,                              NULL,                              D3D11_SDK_VERSION,                              &scd,                              &swapchain,                              &dev,                              NULL,                              &devcon);

关闭Direct3D:
创建Direct3D之后,使用完毕,我们必须将它关闭。

很简单,只有三行命令:

// this is the function that cleans up Direct3D and COMvoid CleanD3D(){    // close and release all existing COM objects    swapchain->Release();    dev->Release();    devcon->Release();}

我们通过调用设备的接口对象的Release()函数来释放内存,以便计算机可以回收不被占有的内存。如果不进行释放,它将一直在后台运行。

补充:
硬件设备(hardware device)是一个运行在显卡上的D3D设备,在所有设备中运行速度是最快的。这将是我们日后讨论最多的一种类型。

软件驱动设备(software driverdevice)是开发人员自己编写的用于Direct3D的渲染驱动软件。这种方式通常不推荐用于高性能或者对性能要求苛刻的应用程序,下面介绍的WARP设备将是更好的选择。

D3D设备一般都是设备本身和硬件之间的通信,而D3D上下文是一种描述设备如何绘制的渲染设备上下文,这也包含了渲染状态和其他的绘图信息。
交换链是设备和上下文将要绘制的渲染目标。

0 0
原创粉丝点击