学习一个最简单的directx程序时,首先需要了解下win32程序的框架该怎么写,最关键得是要搞清楚windows程序里面的消息映射机制,搞清楚了这一点,在熟悉下具体的win API基本上一个简单的窗口程序框架就被你写出来了。在写directx之前,你首先要保证你的VS IDE中,已进行了相关的设置。通过工具->选项下的项目与解决方案里选vc++目录,进行包含文件,库文件两项的相关设置,一般情况下,你安装完了directx sdk,它会默认得在这几个设置的地方自动加进去。你可以查看一下,如果没有加进去,那么包含文件里设置如下目录d:/Program Files/Microsoft DirectX SDK (August 2009)/Include,库文件里设置d:/Program Files/Microsoft DirectX SDK (August 2009)/Lib/x86,这是你装directx sdk时,你所装的安装目录。设置完这些,才可以正常的运行。然后就是写directx程序了,在创建完窗口后,你得创建一个IDirect3D9接口,通过该接口有两个作用,一个是得到设备信息,在进行D3DPRESENT_PARAMETERS的填充,通过调用CreateDevice函数,创建IDirect3DDevice9接口。通过该接口来进行画图显示,在显示前,要进行物体坐标系->世界坐标系->摄像机坐标系->投影坐标系的转换,在对物体进行纹理,光照,阴影,这些相关设置完成后,就可以进行图形渲染,形成一个真实生动的3D场景了。
第一步:Create the main application window.
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)d3d::WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = TEXT("Direct3D9App");
if( !RegisterClass(&wc) )
{
::MessageBox(0, TEXT("RegisterClass() - FAILED"), 0, 0);
return false;
}
HWND hwnd = 0;
hwnd = ::CreateWindow(TEXT("Direct3D9App"), TEXT("Direct3D9App"),
WS_EX_TOPMOST,
0, 0, width, height,
0 /*parent hwnd*/, 0 /* menu */, hInstance, 0 /*extra*/);
if( !hwnd )
{
::MessageBox(0, TEXT("CreateWindow() - FAILED"), 0, 0);
return false;
}
::ShowWindow(hwnd, SW_SHOW);
::UpdateWindow(hwnd);
第二步:Init D3D
Step 1: Create the IDirect3D9 object.
IDirect3D9* d3d9 = 0;
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
if( !d3d9 )
{
::MessageBox(0, TEXT("Direct3DCreate9() - FAILED"), 0, 0);
return false;
}
// Step 2: Check for hardware vp.
D3DCAPS9 caps;
d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps);
int vp = 0;
if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
else
vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
// Step 3: Fill out the D3DPRESENT_PARAMETERS structure.
D3DPRESENT_PARAMETERS d3dpp;
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality = 0;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hwnd;
d3dpp.Windowed = windowed;
d3dpp.EnableAutoDepthStencil = true;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.Flags = 0;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
// Step 4: Create the device.
hr = d3d9->CreateDevice(
D3DADAPTER_DEFAULT, // primary adapter
deviceType, // device type
hwnd, // window associated with device
vp, // vertex processing
&d3dpp, // present parameters
device); // return created device
if( FAILED(hr) )
{
// try again using a 16-bit depth buffer
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
hr = d3d9->CreateDevice(
D3DADAPTER_DEFAULT,
deviceType,
hwnd,
vp,
&d3dpp,
device);
if( FAILED(hr) )
{
d3d9->Release(); // done with d3d9 object
::MessageBox(0, TEXT("CreateDevice() - FAILED"), 0, 0);
return false;
}
}
d3d9->Release(); // done with d3d9 object
return true;
}
第三步:进行相关的坐标系转换
如世界坐标系的转化接口方法Device->SetTransform(D3DTS_WORLD, &Ry);当然这里的Ry矩阵是世界矩阵
第四步:图形的显示
如果要使图形显示出来具有动画效果,将显示函数写入消息循环,经过delta时间,进行一次显示。
float currTime = (float)timeGetTime();
float timeDelta = (currTime - lastTime)*0.001f;
ptr_display(timeDelta);
lastTime = currTime;
Ptr_display是显示函数,里面可设置些矩阵的变换,形成动态的物体效果。
上面是一个directx程序的大致绘制流水线过程,这个流水线其实是比较复杂的。可以随具体个人的需要而进行相关的设置,灵活运用。形成更多效果逼真的3D图形。这是我刚学习DX程序时的一些心德,里面还有许多东西没有搞清楚的地方,还得继续学习中。。。