您的位置:首页 > 其它

D3D学习笔记之一---创建D3D环境的窗口

2009-06-26 15:38 393 查看
今天是第一次在这里开张,先做下说明:写这个并不是一个教程,我也不是专家,只是想更深的理解一下Direct3D,同时如果我写的这些东西如果你“不幸”看到了,希望能对你有点帮助。

同时本人郑重声明:本贴谢绝转载,本人非专家,犯错是在所难免,但是如果误导了别人可就是自己的大错了,希望大家见谅。在这里先谢谢大家。。。

我这里写到的代码和说明并非自己所悟,是参考了SDK和其他一些书籍和网上的一些说明,由于过多,就没有一一列举,关于版权问题(如果这么简陋的东西有人追究版权的话。呵呵),请大家不要过多的追究,这一切都是为了学习。

虽然已经用D3D了点东西出来,但是如果说到对D3D的了解程度,只能说自己还是个门外汉,现在决定系统的学习一下D3D的知识,从基层开始:
下面开始:
­
我们是在windows下的编程,免不了要生成一个窗口:
在Windows下的窗口,有一个WinMain函数,是窗口程序的入口:
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT );
这个是函数头.
表示是WinMain函数。HINSTANCE hInst是一个实例对象,由于后面的几个参数在D3D程序里没有用到,就没有增加参数名。
下面是WinMain函数的函数体:内涵详细的解释。(包含了D3D环境的初始化)
{
//注册窗口类
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
L"ClassName", NULL };
//Windows下生成一个窗口都需要先注册一个窗口类,并用该类的对象去创建一个窗口,下面是改结构体的结构
typedef struct _WNDCLASS {
­
UINT style; //窗口的风格*
­
WNDPROC lpfnWndProc; //指定窗口的消息处理函数的远指针*
­
int cbClsExtra; //指定分配给窗口类结构之后的额外字节数*
­
int cbWndExtra; //指定分配给窗口实例之后的额外字节数
­
HANDLE hInstance; //指定窗口过程所对应的实例句柄*
­
HICON hIcon; //指定窗口的图标HCURSOR hCursor; //指定窗口的鼠标
­
HBRUSH hbrBackground; //指定窗口的背景画刷
­
LPCTSTR lpszMenuName; //窗口的菜单资源名称
­
LPCTSTR lpszClassName; //该窗口类的名称*
­
} WNDCLASS;
­
­
­
//可以看到这个结构体很复杂,但是比较庆幸的是我们不用全部都去赋值,我们需要的只有里面的几项。比如上面我只指定了里面的几项,利用上面的窗口类去注册窗口:
RegisterClassEx( &wc );//这句话是注册窗口 //创建窗口
HWND hWnd = CreateWindow( L"ClassName", L"基本图元",
WS_OVERLAPPEDWINDOW, 100, 100, 600, 300,
GetDesktopWindow(), NULL, wc.hInstance, NULL );
­
在注册窗口以后,调用CreateWindow创建窗口,该函数的声明如下:
­
HWND CreateWindow(
LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam);
对该函数的具体参考参见:http://msdn.microsoft.com/zh-cn/library/ms632679(en-us,VS.85).aspx
­
下面是初始化D3D的环境,该初始化函数没有在这里实现,稍后会给出InitD3D的内容
//初始化Direct3D
if( SUCCEEDED( InitD3D( hWnd ) ) )//初始化D3D环境,稍后给出实现步骤。
{
//显示主窗口
ShowWindow( hWnd, SW_SHOWDEFAULT );
//调用WindowsAPI,显示刚刚生成的窗口,hWnd是刚刚生成窗口时候产生的窗口句柄
UpdateWindow( hWnd );//更新窗口
//进入消息循环
MSG msg;//Windows下的消息结构体
ZeroMemory( &msg, sizeof(msg) );//清空消息结构体。
while( msg.message!=WM_QUIT )//进入消息循环,在消息是退出时结束。
{
if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
//从Windows消息队列里得到消息,函数详细用法请参见MSDN
{
TranslateMessage( &msg );//翻译消息
DispatchMessage( &msg );//传递消息
}
else
{
Render(); //如果没有消息,渲染图形,函数实现,稍后给出
}
}
}
UnregisterClass( L"ClassName", wc.hInstance );//退出时,注销刚刚注册的窗口类对象。
return 0;
}
­
­
­
以上是WinMain函数的全部内容,下面解释一下InitD3D函数的实现:
­
HRESULT InitD3D( HWND hWnd )
{
//创建Direct3D对象, 该对象用来创建Direct3D设备对象
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
return E_FAIL;
//设置D3DPRESENT_PARAMETERS结构, 准备创建Direct3D设备对象
D3DPRESENT_PARAMETERS d3dpp; //声明结构体
ZeroMemory( &d3dpp, sizeof(d3dpp) );//清空结构体
d3dpp.Windowed = TRUE;//允许窗口化
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
//将后台缓冲区直接拷贝到前台,并清空后台缓冲区。
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;//显示格式与当前显卡显示格式相同。
//创建Direct3D设备对象
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice ) ) )
{
return E_FAIL;
}
return S_OK;
}
上面是InitD3D的内容:
­
//创建Direct3D对象, 该对象用来创建Direct3D设备对象
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
return E_FAIL;
创建Direct3D对象,该对象用来创建Direct3D设备对象,
上面的内容都有具体的解释,在此再详细解释一下D3DPRESENT_PARAMETERS结构体该结构体的构成如下
­
BackBufferWidth:全屏幕式后备缓冲的宽度
BackBufferHeight :全屏幕式后备缓冲的高度
BackBufferFormat: 后备缓冲的格式
BackBufferCount: 后备缓冲数目
MultiSampleType: 全屏抗锯齿类型
MultiSampleQuality: 全屏抗锯齿质量等级
SwapEffect: 交换缓冲类型
hDeviceWindow: 设备窗口句柄
Windowed: 全屏或窗口
EnableAutoDepthStencil: 激活深度缓冲
AutoDepthStencilFormat: 深度缓冲格式
FullScreen_RefreshRateInHz: 显示器刷新率
PresentationInterval: 图像最大刷新速度
上面我们用到了三个量,其他均采用系统默认,均有说明。
当创建好D3DPRESENT_PARAMETERS后,用刚刚创建的Direct3D对象调用CreateDevice函数进行设备的创建,如下
g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice )
­
­
­
­
关于该函数的介绍如下:
HRESULT CreateDevice(
UINT Adapter,
D3DDEVTYPE DeviceType,
HWND hFocusWindow,
DWORD BehaviorFlags,
D3DPRESENT_PARAMETERS * pPresentationParameters,
IDirect3DDevice9 ** ppReturnedDeviceInterface
);
­
Adapter:
指定显卡的序列号,指定用那块显卡创建该环境。通常用默认值D3DADAPTER_DEFAULT
DeviceType:
指定设备类型。我们这里用硬件加速。D3DDEVTYPE_HAL,请确保自己的机器能够支持硬件加速哦。不支持的也不多了,呵呵
hFocusWindow:
指定当Direct3D程序从前台变换到后台时的提示窗口,当Direct3D运行于全屏模式时,该窗口必须是顶级窗口,当运行于窗口模式时,该成员可以设置成NULL,这时该窗口就是D3DPRESENT_PARAMETERS结构中hDeciveWindow成员指定的窗口。
BehaviorFlags:
指定Direct3D设备进行工作的方式,我们采用的是D3DCREATE_SOFTWARE_VERTEXPROCESSING由Direct3D软件进行定点运算。
pPresentationParameters
这个参数就用到了我们刚刚声明的D3DPRESENT_PARAMETERS结构体,将我们设置好的d3dpp填写到这里就行了。
ppReturnedDeviceInterface
设备环境的入口指针,这个可要好好保存着,我们费这么大的力气,就是为了把它给弄出来,如果弄丢了,呵呵,后果很严重呃。
­
这下我们的D3D环境的窗口就要创建成功了,呵呵,高兴吧,下面就看看剩下的几个函数:
­
Render();
这个函数负责渲染我们的场景。怎么渲染的呢,拭目以待吧:(呵呵)
VOID Render()
{
//清空后台缓冲区
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(45, 50, 170), 1.0f, 0 );

//开始在后台缓冲区绘制图形
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
//在此在后台缓冲区绘制图形

//结束在后台缓冲区渲染图形
g_pd3dDevice->EndScene();
}
//将在后台缓冲区绘制的图形提交到前台缓冲区显示
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}
­
看看,其实也没什么神秘的是吧,呵呵,当然,就是如此的简单,因为这只是个框架嘛,呵呵,所以里面只是对渲染做了准备,并没有对什么东西进行渲染。
首先是这个函数:g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(45, 50, 170), 1.0f, 0 );
­
他的作用是清空视口,缓冲区等一个面或者多个面的内容。该函数的声明如下:
HRESULT Clear(
DWORD Count,
CONST D3DRECT * pRects,
DWORD Flags,
D3DCOLOR Color,
float Z,
DWORD Stencil);
Count:
该参数指定了下个参数pRects指向的矩形数组中矩形的数量,如果pRects为空,该参数必须是0,相反如果pRects不是空该参数不可以为0.我们将它设置成0
pRects:
该参数是一个指向D3DRECT的指针。该结构数组包含需要清空的矩形区域。我们将它设置成NULL
Flags
指定需要清空的缓冲区。是D3DCLEAR_TARGET,D3DCLEAR_ZBUFFER,D3DCLEAR_STENCIL的任意组合,分别表示清空颜色缓冲区、深度缓冲区、模板缓冲区或它们的组合。这里我们采用的是清空颜色缓冲区。
Color:
指定清空颜色缓冲区后的填充颜色。我们指定为了蓝色
Z:
指定清空深度缓冲区后深度缓冲区中每个像素的对应深度值。
Stencil:
指定清空模板缓冲区后缓冲区中每个像素对应的模板值。
不懂的地方以后还会介绍。
恩,不错,渲染中的一个重要的函数介绍完了,现在进度感觉有点慢呵,没关系,为了搞清楚,清晰点是应该的,不能很是急于求成,那样会做不好的,呵呵。加油吧。我们继续..
下面是
g_pd3dDevice->BeginScene()
很明显我们这里就用到了我们刚刚好不容易才弄出来的环境入口,其实上面也用到了,看到了吧,这个东西很重要的,不能随便的丢掉。
那么BeginScene这个函数是干什么的呢?
其实BeginScene和EndScene是渲染的时候必须用到的两个函数,BeginScene是通知Direct3D设备开始绘图渲染,否则会出错的,所以我们还是老老实实的通知一声吧,呵呵,在渲染结束后呢,我们在用EndScene通知一声,结束渲染了。这样才不会出现异常。
恩,就剩下一个函数了。
Present
这个函数嘛,是把我们绘制好的后台缓冲区内的图像提交到前台进行显示,声明如下:
HRESULT Present(
CONST RECT * pSourceRect,
CONST RECT * pDestRect,
HWND hDestWindowOverride,
CONST RGNDATA * pDirtyRegion
);
­
其实这个函数在绝大多数的情况下,前两个参数和最后一个参数赋值为NULL,表示更新缓冲区的所有区域,
pSourceRect:
复制源的矩形区域指针。
pDestRect:
复制目标的矩形区域指针。
hDestWindowOverride:
指向当前绘制的图形窗口句柄。如果该参数为0,表示当前窗口句柄为我们创建的设备环境时,
g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice )
中d3dpp中hDeviceWindow的值。
­
pDirtyRegion:
最小的更新区域。
到此。render函数的内容介绍完毕。还真有点累了,呵呵
坚持介绍完毕吧,不多了。。。
下面的函数都比较简单,没有多少可以研究的了,但是呢,也很重要。
VOID Cleanup()
{
//释放Direct3D设备对象
if( g_pd3dDevice != NULL)
g_pd3dDevice->Release();
//释放Direct3D对象
if( g_pD3D != NULL)
g_pD3D->Release();
}
­
­
上面的这些代码是释放我们所创建的环境和资源对象。程序结束后不释放资源可不是个好习惯
下面是我们的Windows消息回调函数:
­
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY:
Cleanup();
PostQuitMessage( 0 );
return 0;
case WM_PAINT:
Render();
ValidateRect( hWnd, NULL );
return 0;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
­
相信大家对这个回调函数比较熟悉了,我就不多说了,这里处理了一些基本的消息信息。
­
以上就是基于Win32的d3d环境窗口的创建,一来为了自己的学习,如果你“不幸”看到了呢,希望能对你有一定的帮助,呵呵。下面是这个程序的所有源码,建立一个空的win32工程,将这些源码拷贝进去,在环境配置好的情况下应该没有什么问题的,关于环境的配置网上有很多介绍,我就不再说了,呵呵。休息,休息一会。。。。
­
源码:
­
//=============================================================================
// Desc: 最简单的Direct3D程序,
//=============================================================================
#include <d3d9.h>
­
//-----------------------------------------------------------------------------
// 全局变量
//-----------------------------------------------------------------------------
LPDIRECT3D9 g_pD3D = NULL; //Direct3D对象
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; //Direct3D设备对象
­
//-----------------------------------------------------------------------------
// Desc: 初始化Direct3D
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
//创建Direct3D对象, 该对象用来创建Direct3D设备对象
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
return E_FAIL;
//设置D3DPRESENT_PARAMETERS结构, 准备创建Direct3D设备对象
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
//创建Direct3D设备对象
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice ) ) )
{
return E_FAIL;
}
return S_OK;
}
­
//-----------------------------------------------------------------------------
// Desc: 释放创建对象
//-----------------------------------------------------------------------------
VOID Cleanup()
{
//释放Direct3D设备对象
if( g_pd3dDevice != NULL)
g_pd3dDevice->Release();
//释放Direct3D对象
if( g_pD3D != NULL)
g_pD3D->Release();
}
­
//-----------------------------------------------------------------------------
// Desc: 渲染图形
//-----------------------------------------------------------------------------
VOID Render()
{
//清空后台缓冲区
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(45, 50, 170), 1.0f, 0 );

//开始在后台缓冲区绘制图形
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
//在此在后台缓冲区绘制图形

//结束在后台缓冲区渲染图形
g_pd3dDevice->EndScene();
}
//将在后台缓冲区绘制的图形提交到前台缓冲区显示
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}
­
//-----------------------------------------------------------------------------
// Desc: 消息处理
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY:
Cleanup();
PostQuitMessage( 0 );
return 0;
case WM_PAINT:
Render();
ValidateRect( hWnd, NULL );
return 0;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
­
//-----------------------------------------------------------------------------
// Desc: 程序入口
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
//注册窗口类
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
L"ClassName", NULL };
RegisterClassEx( &wc );
//创建窗口
HWND hWnd = CreateWindow( L"ClassName", L"最简单的Direct3D程序",
WS_OVERLAPPEDWINDOW, 200, 100, 600, 500,
NULL, NULL, wc.hInstance, NULL );
//初始化Direct3D
if( SUCCEEDED( InitD3D( hWnd ) ) )
{
//显示主窗口
ShowWindow( hWnd, SW_SHOWDEFAULT );
UpdateWindow( hWnd );
//进入消息循环
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"ClassName", wc.hInstance );
return 0;
}

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/luoya263547560/archive/2008/11/18/3330896.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: