这篇是关于Directx 3D 的。
什么是DX、D3D?
DX(DirectX)是一组微软开发的API。旨在服务以windows为平台的游戏或多媒体程序。这是一组较为底层的API。它将形色各异的硬件底层(不同品牌的显卡、声卡、键盘鼠标等)吸纳进来,代以统一的开发接口暴露开放给开发者。这样开发者在开发游戏或者多媒体程序时就不必担心硬件差异,也不用理会底层细节。当然,微软做到这一点不是靠自己的DX去适应不同的硬件,而是由支持DX的硬件厂商(被微软拉拢过去的)负责提供一套HAL(Hardware Abstraction Layer)驱动程序供DX使用。这就使得同一个DX命令在不同品牌的硬件上能够产生的一致的结果。
厂商用自己的方式实现了对某一种标准的支持,反过来令用户几乎注意不到“厂商实现”这一环节,这种现象在计算机行业乃至整个工业,非常普遍。不同的水管厂商会对同一型号的水管口径设计一致的大小;不同的浏览器厂商也会对HTML语言提供一致的解析(尽管像MS这样的往往不屑一顾)、不同的C++编译器厂商会对C++标准提供一致的支持(MS依然例外…)。我们往往关注的是C++、HTML是什么,怎么写。同理,现在我们学习的是DX是什么,怎么写。但脑子我们一定要有一个概念,DX和硬件本身,一定有这样一层HAL的。推而广之对于整个硬件层来说,这层HAL就是驱动程序。
DX中的D,即Direct,意为“直的,直接的”;X比喻为“丰富多彩的,功能多样的”。“用户可以直来直去很方便地实现丰富多样的功能”,这就是DX所表达的涵义。
DX不是一个单独的图形API。它包含有Direct Graphics(Direct 3D+Direct Draw)、Direct Input、Direct Play、Direct Sound、Direct Show、Direct Setup、Direct Media Objects等多个组件,它提供了一整套的多媒体接口方案。只是由于其中的Direct 3D过于优秀,使其它方面显得暗淡无光。
最新DX版本为11,发布于MS的潜力股Windows 7 Beta版本中。
Note:我的学习版本依然使用DX9.
D3D(DirectX 3D)上面提到过,它是DX的一个子组件API。也是DX团队中最抢眼的主力队员,也因此最重要和最复杂。它负责处理图形方面的工作。在版本9之前,它只负责3D图形,2D图形由Direct Draw组件负责;自9开始,D3D全面接管了Direct Draw的工作,统一负责2D图形和3D图形。
D3D在windows平台上几乎是游戏开发者选用的圣经。缺点是跨平台性不够(DX就是为巩固windows的地位设计的)。也因此,它最大的竞争对手是openGL(open Graphic Library)。openGL也是一组图形API。最初由SGI公司开发。它可以在linux、mac OS等多个平台上使用(当然也可以在windows上跑)。8卦一句,openGL一开始还是很猛的(俺之前就是GL这方阵营地…),只是后来不敌MS的“卑劣”商业行径,慢慢失去了市场主导地位。起码现在D3D的用户是越来越多了,相衬下GL就带了那么点悲壮的凉意。
从哪里开始DX?
到官网下载最新DirectX SDK包。我提供的这个链接依然是版本9的。当然这是SDK嘛,没有开发环境的话也就失去了意义。我用的开发环境是VS.NET 2003。DX下载后安装,之后就可以使用了。你会在“开始”->“程序”菜单中找到Microsoft DirectX 9.0 SDK Update (August 2005) (版本号因人而异,我这个很老了)的选项。内有DX各种工具、CHM帮助文档、以及演示Samples。CHM涵盖的资料非常丰富:编程指导、工具介绍、参考手册、教程示例等等,应有尽有(翔实的资料同时也是一种考验耐力的挑战)。教程不光step-by-step,也提供了现成的源码路径,你可以找到源码后在vs环境下直接编译体验。
第一个DX程序?
首先建立一个空的win32工程。添加新c++文件。项目->属性->链接器->输入->附加依赖项 中填入“d3d9.lib”。
接着粘贴以下代码。编译、链接,之后第一个DX程序就出炉了。尽管它除了一个蓝色的窗口外什么都没有。
(NOTE:你也可以从$(DXSDK_DIR)\Samples\C++\Direct3D\Tutorials\Tut01_CreateDevice)中找到该代码。)
1
//-----------------------------------------------------------------------------
2
// File: CreateDevice.cpp
3
//
4
// Desc: This is the first tutorial for using Direct3D. In this tutorial, all
5
// we are doing is creating a Direct3D device and using it to clear the
6
// window.
7
//
8
// Copyright (c) Microsoft Corporation. All rights reserved.
9
//-----------------------------------------------------------------------------
10
#include <d3d9.h>
11
#pragma warning( disable : 4996 ) // disable deprecated warning
12
#include <strsafe.h>
13
#pragma warning( default : 4996 )
14![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
15![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
16![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
17![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
18
//-----------------------------------------------------------------------------
19
// Global variables
20
//-----------------------------------------------------------------------------
21
LPDIRECT3D9 g_pD3D = NULL; // Used to create the D3DDevice
22
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Our rendering device
23![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
24![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
25![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
26![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
27
//-----------------------------------------------------------------------------
28
// Name: InitD3D()
29
// Desc: Initializes Direct3D
30
//-----------------------------------------------------------------------------
31
HRESULT InitD3D( HWND hWnd )
32![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
33
// Create the D3D object, which is needed to create the D3DDevice.
34
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
35
return E_FAIL;
36![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
37
// Set up the structure used to create the D3DDevice. Most parameters are
38
// zeroed out. We set Windowed to TRUE, since we want to do D3D in a
39
// window, and then set the SwapEffect to "discard", which is the most
40
// efficient method of presenting the back buffer to the display. And
41
// we request a back buffer format that matches the current desktop display
42
// format.
43
D3DPRESENT_PARAMETERS d3dpp;
44
ZeroMemory( &d3dpp, sizeof( d3dpp ) );
45
d3dpp.Windowed = TRUE;
46
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
47
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
48![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
49
// Create the Direct3D device. Here we are using the default adapter (most
50
// systems only have one, unless they have multiple graphics hardware cards
51
// installed) and requesting the HAL (which is saying we want the hardware
52
// device rather than a software one). Software vertex processing is
53
// specified since we know it will work on all cards. On cards that support
54
// hardware vertex processing, though, we would see a big performance gain
55
// by specifying hardware vertex processing.
56
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
57
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
58
&d3dpp, &g_pd3dDevice ) ) )
59![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
60
return E_FAIL;
61
}
62![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
63
// Device state would normally be set here
64![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
65
return S_OK;
66
}
67![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
68![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
69![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
70![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
71
//-----------------------------------------------------------------------------
72
// Name: Cleanup()
73
// Desc: Releases all previously initialized objects
74
//-----------------------------------------------------------------------------
75
VOID Cleanup()
76![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
77
if( g_pd3dDevice != NULL )
78
g_pd3dDevice->Release();
79![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
80
if( g_pD3D != NULL )
81
g_pD3D->Release();
82
}
83![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
84![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
85![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
86![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
87
//-----------------------------------------------------------------------------
88
// Name: Render()
89
// Desc: Draws the scene
90
//-----------------------------------------------------------------------------
91
VOID Render()
92![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
93
if( NULL == g_pd3dDevice )
94
return;
95![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
96
// Clear the backbuffer to a blue color
97
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 255 ), 1.0f, 0 );
98![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
99
// Begin the scene
100
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
101![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
102
// Rendering of scene objects can happen here
103![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
104
// End the scene
105
g_pd3dDevice->EndScene();
106
}
107![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
108
// Present the backbuffer contents to the display
109
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
110
}
111![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
112![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
113![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
114![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
115
//-----------------------------------------------------------------------------
116
// Name: MsgProc()
117
// Desc: The window's message handler
118
//-----------------------------------------------------------------------------
119
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
120![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
121
switch( msg )
122![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
123
case WM_DESTROY:
124
Cleanup();
125
PostQuitMessage( 0 );
126
return 0;
127![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
128
case WM_PAINT:
129
Render();
130
ValidateRect( hWnd, NULL );
131
return 0;
132
}
133![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
134
return DefWindowProc( hWnd, msg, wParam, lParam );
135
}
136![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
137![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
138![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
139![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
140
//-----------------------------------------------------------------------------
141
// Name: wWinMain()
142
// Desc: The application's entry point
143
//-----------------------------------------------------------------------------
144
INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
145![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
146
// Register the window class
147
WNDCLASSEX wc =
148![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
149
sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L,
150
GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
151
L"D3D Tutorial", NULL
152
};
153
RegisterClassEx( &wc );
154![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
155
// Create the application's window
156
HWND hWnd = CreateWindow( L"D3D Tutorial", L"D3D Tutorial 01: CreateDevice",
157
WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
158
NULL, NULL, wc.hInstance, NULL );
159![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
160
// Initialize Direct3D
161
if( SUCCEEDED( InitD3D( hWnd ) ) )
162![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
163
// Show the window
164
ShowWindow( hWnd, SW_SHOWDEFAULT );
165
UpdateWindow( hWnd );
166![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
167
// Enter the message loop
168
MSG msg;
169
while( GetMessage( &msg, NULL, 0, 0 ) )
170![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
171
TranslateMessage( &msg );
172
DispatchMessage( &msg );
173
}
174
}
175![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
176
UnregisterClass( L"D3D Tutorial", wc.hInstance );
177
return 0;
178
}
179![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
180![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
181![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
182![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
在这里强调的是,需要包含头文件d3d9.h。
WinMain函数和MsgProc函数,熟悉win32编程的人都很熟悉这两个函数。因为任何一个win32程序都必须有它们俩。前者是入口函数,在这个函数里必须定义窗口类、建立窗口、建立消息循环等等;而后者是消息处理函数,程序运行时接收到各类消息时该怎么反馈,就在这里定义。
还剩下三个函数。其中最关键是InitD3D和Render这两个函数。InitD3D负责D3D环境的初始化,Rnder负责实际的渲染工作。Cleanup的作用是扫尾。不论申请了什么资源使用完毕后应该释放,这个思路对于程序开发而言是非常自然的。
对于实时渲染,无论是用D3D还是openGL,一般都会分为两个阶段。第一个阶段负责环境的初始化,这个阶段只在程序运行开始时运行一次;第二阶段负责实时渲染绘制,这个阶段会在程序中不停循环反复运行。每运行一次,我们就可以看作是绘制了一帧。我们平时说的FPS(帧率)就是指一秒中这第二个阶段循环了多少次。当程序要结束时,触发退出事件跳出循环。然后回收资源,退出程序。我喜欢称第一个阶段为离线阶段,第二个阶段为在线阶段。在我们这个例子里,InitD3D是离线阶段,Render是在线阶段。
(未完待续)
参考资料:
http://baike.baidu.com/view/15762.htm