任何 Windows 应用程序运行时必须做的第一件事情是要创建一个应用程序窗口显示给用户。
要做到这一点, CreateDevice 示例项目开始在 WinMain 函数的执行。下面的示例代码执行窗口的初始化。
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
//
注册一个窗口类
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
"Direct3D Tutorial", NULL };
RegisterClassEx( &wc );
//
创建这个应用程序的视口
HWND hWnd = CreateWindow( "Direct3D Tutorial", "Direct3D Tutorial 01: CreateDevice",
WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
GetDesktopWindow(), NULL, wc.hInstance, NULL );
1 、前面的代码示例是标准的 Windows 编程。
2 、该示例开始于定义和注册一个名为“ Direct3D Tutorial ”的窗口类。
3 、在这个类被注册后,示例代码使用了这个被注册的类创建了一个基本的 300*300 顶层窗 4 、口,这个窗口没有菜单或者子窗口。
5 、该示例使用 WS_OVERLAPPEDWINDOW 窗口样式,以创建一个窗口,其中包括最小化,最大化和关闭按钮就像是最常见的窗口应用程序一样。 (如果这个示例是运行在全屏幕模式,首选的窗口样式应该是 WS_EX_TOPMOST ,它指定所创建的窗口应放在高于一切非最顶层窗口,应该留在他们上面,甚至当窗口被停用。)
6 、当窗口创建,代码示例调用标准的 Win32 函数来显示和更新窗口。
随着应用程序窗口准备就绪,可以开始建立必要的 Direct3D 对象,描述在第 2 步 - 初始化 Direct3D 的。
1 、 CreateDevice 项目示例 展示了 Direct3D 在 initD3D 方法下的初始化。 ( initD3D 方法被 WinMain 当一个 Windows 创建之后调用)
2 、在你创建了一个应用视口之后,你就准备好了要去初始化这个 Direct3D 对象,你将在只有使用这个对象来渲染你的屏幕。
3 、这个过程包括创建一个对象、设置显示的属性、并且在最后创建 Direct3D 驱动
1 、在创建完 Direct3D 对象之后,使用 IDirect3D9::CreateDevice 方法创建一个驱动、设置驱动器、驱动类型、和一些设置。
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
return E_FAIL;
1 、传给 Direct3DCreate9 的唯一的参数应当总是 D3D_SDK_VERSION .
2 、这表明了 Direct3D 使用了一个正确的头文件。
3 、无论什么时候,只要当一个头文件或者其他的改动使得应用程序被重新建立,这个值就会自增
4 、如果这个版本不匹配, Direct3DCreate9 这个方法就会执行失败
1、 通过填写 D3DPRESENT_PARAMETERS 的字段,你可以指定你想要的 3D 应用程序做的事情。
2、 CreateDevice 项目示例设置 Windowed 为 True 、 SwapEffect 为 D3DSWAPEFFECT_DISCARD 、 BackBufferFormat 为 D3DFMT_UNKNOWN.
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
1 、最后一步就是使用 IDirect3D9::CreateDevice 方法去创建一个 Direct3D 驱动, 如下:
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp, &g_pd3dDevice ) ) )
1、 之前的代码实例创建了一个驱动,它通过使用标记 D3DADAPTER_DEFAULT 使用默认适配器。
2、 在绝大多是情况下,系统将仅有一个单独的适配器,除非多图像处理卡被安装。
3、 你可以通过指定 DeviceType 的值为 D3DDEVTYPE_HAL 选择硬件驱动而不是软件驱动
1、 示例代码使用了 D3DCREATE_SOFTWARE_VERTEXPROCESSING, 来告诉系统使用用软件坐标处理。
2、 请注意,如果你通过指定 D3DCREATE_HARDWARE_VERTEXPROCESSING 来告诉系统使用硬件坐标处理,你会看到通过显卡处理坐标得到的绚丽的画面。
3 、现在 Direct3D 对象已经被初始化完毕,下一步将要做的就是确保你有一个消息处理机制。
1、 在你已经成功创建一个应用视口并且初始化了一个 Direct3D 对象之后,你就已经准备酒席去渲染一个舞台了。
2、 在绝大多数情况下, Windows 应用程序会在他们的消息循环中监听系统消息,并且在消息队列中没有消息时对屏幕进行刷新。
3、 无论如何, CreateDevice 这个项目示例将会等待,直到一个 WM_PAINT 消息进入队列,告诉应用程序,它需要重绘全部或者部分的视口。
// 消息循环
MSG msg;
while( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
1、 每次循环, DispatchMessage 方法就会调用消息处理器(它管理着队列中的消息)。
2、 当 WM_PAINT 这个消息入队时,应用程序调用 Render 方法,程序自定义的这个方法就会被调用去重绘这个视口。
3、 然后 Win32 的 ValidateRect 方法就会被调用去作用客户端的区域。如下:
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;
case WM_PAINT:
Render();
ValidateRect( hWnd, NULL );
return 0;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
现在,系统的消息机制已经实现,下一步就是渲染屏幕了!
1 、为了渲染和现实一个舞台,示例代码在这一步清除了后台缓冲区为蓝色 ,并且将后台缓冲区的内容传输到前台缓冲区,最终将前台缓冲区的内容显示在屏幕上。
2 、为了清除一个舞台,必须调用 IDirect3DDevice9::Clear 方法
//
清除了后台缓冲区为蓝色
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
1、 前 2 个被 IDirect3DDevice9::Clear 接受的参数表明了 Direct3D 对象的尺寸和将要被清空的指针矩形数组的首地址。
2、 指针矩形数组表述了将要被渲染的区域
1、 在绝大多数情况下,你可以使用一个单独的矩形来表示整个将被渲染的目标区域。
2、 你通过设置第一个参数 0 并且设置第二个参数 NULL 来完成这项工作。
3、 第三个参数定义的是方法的具体行为,你可以指定一个标记去清除一个目标区域或者关联一个深度缓冲区,模版缓冲区,或者结合这 3 者。
4、 最后 3 个参数被设置用来渲染参数,深度缓冲区和模版缓冲区。
5、 CreateDevice 示例项目设置了清屏颜色为蓝色
6、 最后 2 个参数使用缺省值,因为这 2 个标记没有被显示使用。
1、 在清除视口之后, CreateDevice 示例项目通知 Direct3D 对象,渲染可以开始了,然后提示它渲染完成。如下:
//
提示渲染将要开始
g_pd3dDevice->BeginScene();
//
在这里处理渲染过程
//
提示渲染结束
g_pd3dDevice->EndScene();
1、 IDirect3DDevice9::BeginScene 和 IDirect3DDevice9::EndScene 这 2 个方法提示系统什么时候渲染将要开始和已经结束。你仅可以在这 2 个方法之间调用渲染方法。
2、 即使当渲染方法执行失败的时候,你也应当在再次调用 BeginScene 之前事先调用 EndScene 。
1 、在渲染结束之后,你就可以通过 IDirect3DDevice9::Present 方法显示它了。
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
1、 前 2 个参数表示的是源矩阵和目标矩阵。
2、 在这一步,示例代码通过将这 2 个参数设置为 NULL 来将后台缓冲区交付给前台缓冲区。
3、 第三个参数设置了要显示的目标窗口。
4、 因为这个参数被设置为 NULL ,所以 D3DPRESENT_PARAMETERS 的成员对象 hWndDeviceWindow 被使用。
5、 第四个参数是脏数据参数,在绝大多数情况下将被设置为 NULL 。
1、 在运行的有些时候,你的应用程序需要被关闭。关闭一个 DX 应该程序并仅仅意味着你需要销毁一个应该窗口,而且你还要找出所有你的应用程序使用到的 DirectX 对象,释放指向他们的指针。
2、 CreateDevice 示例项目在 WM_DESTROY 消息发生时,调用了 Cleanup 方法,一个程序自定义的方法来处理这个清理。
VOID Cleanup()
{
if( g_pd3dDevice != NULL)
g_pd3dDevice->Release();
if( g_pD3D != NULL)
g_pD3D->Release();
}
1、 前面提到的方法通过调用 IUnknown 方法来清理各个对象。
2、 因为这份学习手册遵行 COM 规范,绝大多是对象应该被清零并且自动从内存中移除。
1、 除了关闭之外,有时候也会在正常运行时,例如当用户改变了屏幕的分辨率或颜色的深度、当你可能需要销毁并重新创建微软正在使用的 Direct3D 对象是。
2、 正因如此,为了随时在需要的时候使用它,在一个地方定义你的清理代码将会是一个不错的主意。
这份手册展示了如何创建一个驱动,手册 2 将展示你如歌使用坐标来绘制图形