原文地址:
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 declarations
IDXGISwapChain *swapchain; // the pointer to the swap chain interface
ID3D11Device *dev; // the pointer to our Direct3D device interface
ID3D11DeviceContext *devcon; // the pointer to our Direct3D device context
// function prototypes
void InitD3D(HWND hWnd); // sets up and initializes Direct3D
void CleanD3D(void); // closes Direct3D and releases memory
// the WindowProc function prototype
LRESULT 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 use
void 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 COM
void CleanD3D()
{
// close and release all existing COM objects
swapchain->Release();
dev->Release();
devcon->Release();
}
我们通过调用设备的接口对象的Release()函数来释放内存,以便计算机可以回收不被占有的内存。如果不进行释放,它将一直在后台运行。
补充:
硬件设备(hardware device)是一个运行在显卡上的D3D设备,在所有设备中运行速度是最快的。这将是我们日后讨论最多的一种类型。
软件驱动设备(software driverdevice)是开发人员自己编写的用于Direct3D的渲染驱动软件。这种方式通常不推荐用于高性能或者对性能要求苛刻的应用程序,下面介绍的WARP设备将是更好的选择。
D3D设备一般都是设备本身和硬件之间的通信,而D3D上下文是一种描述设备如何绘制的渲染设备上下文,这也包含了渲染状态和其他的绘图信息。
交换链是设备和上下文将要绘制的渲染目标。