初识DXUT
什么是DXUT
这个概念性的东西,不同的人不同的理解,总的来说还是比较简单的D3D小框架,对D3D的一个简单的封装,可以理解成一个类库。微软作用,可以更好的展示D3D的功能和新发布的特性;游戏开发者作用,可以更快更轻巧的展示模型结果,检验算法效果;学习者作用,可以是一个入门的精巧例子,由于D3D的例子大部分都是利用DXUT的,所以可以更快的学习D3D SDK中的例子,加速学习过程。
现在的DXUT
现在的DXUT主要有D3D9 D3D10和D3D11三个版本,可以看出来D3DX的版本是跟着SDK的,到了D3D11 的DXUT就是一个额外的部分的,不随着SDK一起发布了,这个是后话,现在一般还是有的。这篇入门级别的文章还是D3D9的。
架构浅解
dxut库
打开sdk 里面的例子可以看到DXUT,进入dxut那么就会看见两个目录,core 和optional。意思是很明白的,一个是dxut的核心部分,一个是dxut的可选部分,我们的文章现在只是关注核心的这一部分。打开core里面的工程,如果没有什么配置问题,直接编译就会生成dxut的静态库。dxut.lib这个就是牛气轰轰的dxut核心库了。我们可以在项目中加入头文件和生成的库来构建程序,也就是使用了dxut。我没有发现dxut封装到dll中的可能,因为里面的函数没有导入和导出关键字,也就是说,现在的dxut仅支持静态链接。可选库也可以这样子获得,不过这篇文章没有这样做。
dxut代码
我们也可以不用库,直接在项目中加入dxut的源代码,代价就是编译时间长一些罢了,但是,不符合库的思想而已。
dxut运行过程
dxut先配置一些回调函数,然后就是主函数的实际操作进入消息循环。就这么简单,客户要使用这些功能就是在各种回调函数里面编写代码。说的挺简单的,但是要想真的学习dxut这个类库,还是需要熟练记住一些函数的,是的,我们编程不要求死记硬背,但是你花费半个小时去背一些主要函数你就会发现自己对库的理解不仅仅一丁半点了。理解这段话需要有一定的win32和d3d基础。
应用练习
配置目录
配置d3d和dxut的头文件目录。d3d头文件目录在sdk中,dxut的头文件目录是自己创建的,将core下的头文件添加上就可以了。配置库目录,d3d库目录还是在sdk中,dxut的库目录还是自己创建的,将生成的dxut.lib加入就可以了。至于如何配置这些目录就是项目属性里面找了。
程序代码
#pragma once
//win32
#pragma comment(lib,"comctl32.lib")
//d3d
#pragma comment(lib,"dxerr.lib")
#pragma comment(lib,"d3dx9.lib")
//dxut
#pragma comment(lib,"dxut.lib")
//dxut
#include"DXUT.h"
HRESULT CALLBACK OnDeviceCreate(
IDirect3DDevice9* pd3dDevice,
const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
void* pUserContext );
void CALLBACK OnDeviceDestroyed(
void* pUserContext );
void CALLBACK OnFrameRender(
IDirect3DDevice9* pd3dDevice,
double fTime,
float fElapsedTime,
void* pUserContext );
void SetUpMatrix(
IDirect3DDevice9* pd3dDevice);
void SetupLight(
IDirect3DDevice9* pd3dDevice);
//TODO: global variables.
ID3DXMesh* g_pd3dMesh=NULL;
INT WINAPI wWinMain(
HINSTANCE,
HINSTANCE,
LPWSTR,
INT)
{
DXUTSetCallbackD3D9DeviceCreated(
OnDeviceCreate,
NULL);
DXUTSetCallbackD3D9DeviceDestroyed(
OnDeviceDestroyed,
NULL);
DXUTSetCallbackD3D9FrameRender(
OnFrameRender,
NULL);
//0.dxut init.
DXUTInit(
true,
true,
NULL,
true);
//1.create window
DXUTCreateWindow(
L"dxut window",
GetModuleHandle(NULL),
NULL,
NULL,
CW_USEDEFAULT,
CW_USEDEFAULT);
//2.create device.
DXUTCreateDevice(
true,
640,
480);
//3.main loop
DXUTMainLoop();
//exit.
return DXUTGetExitCode();
}
HRESULT CALLBACK OnDeviceCreate(
IDirect3DDevice9* pd3dDevice,
const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
void* pUserContext )
{
//TODO: create d3d device.
D3DXCreateTeapot(pd3dDevice,&g_pd3dMesh,NULL);
return S_OK;
}
void CALLBACK OnDeviceDestroyed(
void* pUserContext )
{
//TODO:destroy d3d device.
if(g_pd3dMesh!=NULL)
{
g_pd3dMesh->Release();
g_pd3dMesh=NULL;
}
}
void CALLBACK OnFrameRender(
IDirect3DDevice9* pd3dDevice,
double fTime,
float fElapsedTime,
void* pUserContext )
{
pd3dDevice->Clear(
0,
NULL,
D3DCLEAR_TARGET,
D3DCOLOR_XRGB(0,0,255),
1.0f,
0);
SetUpMatrix(pd3dDevice);
SetupLight(pd3dDevice);
if(SUCCEEDED(pd3dDevice->BeginScene()))
{
//TODO:render d3d scene.
g_pd3dMesh->DrawSubset(0);
pd3dDevice->EndScene();
}
pd3dDevice->Present(NULL,NULL,NULL,NULL);
}
void SetUpMatrix(
IDirect3DDevice9* pd3dDevice)
{
D3DXMATRIXA16 viewMatrix;
D3DXVECTOR3 vEye(0.0f,5.0f,-3.0f);
D3DXVECTOR3 vLookAt(0.0f,0.0f,0.0f);
D3DXVECTOR3 vUp(0.0f,1.0f,0.0f);
D3DXMatrixLookAtLH(&viewMatrix,&vEye,&vLookAt,&vUp);
pd3dDevice->SetTransform(D3DTS_VIEW,&viewMatrix);
D3DXMATRIXA16 projectionMatrix;
D3DXMatrixPerspectiveFovLH(&projectionMatrix,D3DX_PI/4,1.0f,1.0f,1000.0f);
pd3dDevice->SetTransform(D3DTS_PROJECTION,&projectionMatrix);
}
void SetupLight(
IDirect3DDevice9* pd3dDevice)
{
D3DMATERIAL9 mtrl;
ZeroMemory(&mtrl,sizeof(mtrl));
mtrl.Ambient.r=mtrl.Diffuse.r=1.0f;
mtrl.Ambient.g=mtrl.Diffuse.g=1.0f;
mtrl.Ambient.b=mtrl.Diffuse.b=0.0f;
mtrl.Ambient.a=mtrl.Diffuse.a=1.0f;
pd3dDevice->SetMaterial(&mtrl);
D3DLIGHT9 light;
D3DXVECTOR3 dir(1.0f,0.0f,0.0f);
D3DXCOLOR color(1.0f,1.0f,1.0f,0.0f);
ZeroMemory(&light,sizeof(light));
light.Type=D3DLIGHT_DIRECTIONAL;
light.Ambient=color*0.6f;
light.Diffuse=color;
light.Specular=color*0.6f;
light.Direction=dir;
pd3dDevice->SetLight(0,&light);
pd3dDevice->LightEnable(0,TRUE);
pd3dDevice->SetRenderState(D3DRS_LIGHTING,TRUE);
pd3dDevice->SetRenderState(D3DRS_NORMALIZENORMALS,TRUE);
}
总结
运行结果
综合
我也是新手,研究中。我觉得理解了库的思想很有帮助,图形方面的算法还没有涉及,不过会学的。对dxut的学习需要研究一段时间,将来检验模型的时候可以很快地得到结果,而且也是认识新的版本的d3d的有力帮手,你说不是么?