如何使用DXUT框架

来源:互联网 发布:淘宝品牌授权是正品吗 编辑:程序博客网 时间:2024/05/16 06:13

转自:http://blog.163.com/bingcaihuang@126/blog/static/19894212201001824828380/

DXUT是什么?

  DXUT即DirectX Utility Library

  它是微软为DirectX的Samples写的一个框架,有了这个框架,Sample的构建就方便多了,这个框架实际上抽取了所有构建Sample 都要用到的代码,比如处理窗口消息,处理设备丢失与重设等等。这样一来,我们就可以从繁重的重复代码中解脱出来,专注于编写customer code.

  其实题目本来想写如何使用DXUT中的Camera,因为我觉得camera才是本文的精华。

  下面我们就看一下如何用DXUT框架造自己的DirectX程序。在这里我使用的DirectX SDK版本是March 2008, 编译器是VSTS2008

  想要使用DXUT,必须安装DirectX SDK,这里下载

  首先,启动DirectX Sample Browser(开始菜单,DirectX目录下),在里面找到"Empty Project"工程,点击InstallProject按钮来安装它

如何使用DXUT框架 - bingcaihuang - 水雲间
 

安装提示后会提示是否打开工程目录,打开工程之后,你会看到这个空的工程已经包含了许多代码,但是这些都是框架代码,没有做任何实际的渲染,你可以编译并运行这个程序,当然你只会得到一个蓝色的窗口,里面空无一物。也很美,不是么?

如何使用DXUT框架 - bingcaihuang - 水雲间
 

不要小看这个毫无内容的窗口,实际上DUXT已经为你完成了许多棘手的工作,比如处理窗口大小变化的代码,如果自己写,是要费一番功夫的。好了,下面我们来润色一下,添加点东西进去,就像许多程序设计语言的第一课都以hello world为例一样,大多数图形学教程的第一个模型都是以teapot为例,我们也不例外,就画一个茶壶吧。

  在D3D中,绘制一个model大体要这么四步,我们就以茶壶为例,这四步搞懂了,下面就好理解了

  1. 定义mesh

  2. 创建mesh

  3. 绘制mesh

  4. 释放mesh

  说点题外话,什么是mesh

  说了如此多的mesh,那么到底什么是mesh呢?我在刚刚接触这个词的时候,也很茫然,这个词的中文译名基本是网格。在D3D中,最小的几何图元是三角形,说它最小,是因为不可再细分了,也就是说在D3D中,无论多么复杂的模型,最终都可以分解为若干个三角形,这个并不难理解,比如我想画一个正方形,就可以使用两个等腰直角三角形拼接一个,我想画个立方体,则可以用若干个正方形来拼接。即使是一个球体,也可以用若干个三角形组合而成,这么多的三角形放到一起,看起来就行成了很多网格,我想大概这就是mesh的来历吧。

如何使用DXUT框架 - bingcaihuang - 水雲间
 

对比下面两张图,你可以更清楚的明白mesh的含义

  模型

如何使用DXUT框架 - bingcaihuang - 水雲间
 

对应的网格

在OnD3D9ResetDevice函数中设置投影矩阵

1 float fAspectRatio = pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height;
2 modelCamera.SetProjParams( D3DX_PI/4, fAspectRatio, 0.1f, 1000.0f );
3 modelCamera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
4 

  注意,到这里时,上面那个自定义的SetupMatrix函数就可以不用了,因为我们使用Camera来处理矩阵了

  在OnFrameMove函数中调用camera的FrameMove函数

1 modelCamera.FrameMove(fElapsedTime);

  在MsgProc函数中调用camera的消息处理函数,这使得model camera可以处理鼠标消息

1 modelCamera.HandleMessages(hWnd, uMsg, wParam, lParam) ;

  最后,也是最重要的,是OnD3D9FrameRender函数中的代码

  在每一帧开始绘制之前,我们要取得当前的矩阵并应用到当前的Scene中

 1 // Set world matrix
 2 D3DXMATRIX world = *modelCamera.GetWorldMatrix() ;
 3 pd3dDevice->SetTransform(D3DTS_WORLD, &world) ;
 4 
 5 // Set view matrix
 6 D3DXMATRIX view  = *modelCamera.GetViewMatrix() ;
 7 pd3dDevice->SetTransform(D3DTS_VIEW, &view) ;
 8 
 9 // Set projection matrix
10 D3DXMATRIX proj  = *modelCamera.GetProjMatrix() ;
11 pd3dDevice->SetTransform(D3DTS_PROJECTION, &proj) ;
12 

如何使用DXUT框架 - bingcaihuang - 水雲间
 

  以下所提到的函数,都是EmptyProject.cpp中的代码

  好了,下面开始绘制茶壶的详细步骤。

  首先声明一个全局变量,用来保存茶壶对应的mesh

1 ID3DXMesh* mesh = 0; // mesh pointer for teapot

  然后,在OnD3D9CreateDevice函数中创建teapot

1 D3DXCreateTeapot(pd3dDevice, &mesh, NULL) ;

  在OnD3D9FrameRender函数中绘制teapot,注意,绘制代码一定要放在BeginScene和EndScene之间

1 // Render the scene
2 if( SUCCEEDED( pd3dDevice->BeginScene() ) )
3 {
4     mesh->DrawSubset(0) ; //绘制茶壶
5     V( pd3dDevice->EndScene() );
6 }
7 

  最后,当绘制结束时要清理mesh,在OnD3D9DestroyDevice函数中释放mesh

1 if(mesh != NULL)
2     mesh->Release() ;//释放mesh
3 

  好了,编译运行。

  如果不出意外的话,你肯定看不到茶壶,而是一条黑线

如何使用DXUT框架 - bingcaihuang - 水雲间
 

为什么呢?再漂亮的美女,站在你背后,你也欣赏不到美,计算机就更笨了,你得告诉它看什么,向哪里看,这就需要设置设置view matrix和projection matrix,现在来设置它们,定义一个函数SetupMatrix,如下

 1 VOID SetupMatrix(IDirect3DDevice9* pd3dDevice)   
 2 {   
 3     // Set view matrix   
 4     D3DXVECTOR3 vEyePt( 0.0f, 0.0f,-5.0f );   //眼睛的位置
 5     D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );   //视点中心
 6     D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );   //向上向量
 7     D3DXMATRIXA16 matView;   
 8     D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );   
 9     pd3dDevice->SetTransform( D3DTS_VIEW, &matView );   
10 
11     // Set projection matrix   
12     D3DXMATRIXA16 matProj;   
13     D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 1000.0f );   
14     pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );   
15 
16 }  

  并在OnD3D9FrameRender函数中调用之

1 SetupMatrix(pd3dDevice) ; // 调用自定义的SetupMatrix函数
2 
3 // Render the scene
4 if( SUCCEEDED( pd3dDevice->BeginScene() ) )
5 {
6     mesh->DrawSubset(0) ;
7     V( pd3dDevice->EndScene() );
8 }
9 

好了,再次编译并运行,哇,茶壶出现了!

如何使用DXUT框架 - bingcaihuang - 水雲间
 

  可是仍然是黑色的,黑的不好看,来个彩色的吧,OK,继续!

  要想使Model丰富多彩,就要设置材质(material)和光照,这两个属性决定了Model的最终颜色,简单解释一下这两个属性,和现实生活中的情况是一样的。同一束光照在不同的材质上效果是不同的,比如一束光在石头上和照在玻璃上效果肯定不一样。所以材质是决定光照的一个因素,也就是光的反射程度,映射到D3D中就是设置材质的漫射光属性。另一个就是关照本身了,在这里我们使用平行光。于是添加如下函数设置光照效果。diffuse表示漫射光,而ambient表示环境光,一般将他们的值设为相同r,g,b分别表示红,绿,蓝三种颜色的程度,范围是0.0-1.0,在这里r和g设置为1.0 而b设置为0.0,实际上构造了一个反射黄色光的材质,也就是我们最终看见的model颜色将是黄色。

  再将入射光定为白色,方向指向x轴正向。

  一般来说,D3D程序通常将入射光设置为白色,而通过设置材质来决定最终的反射光颜色,本例即如此。

 1 VOID SetupLight(IDirect3DDevice9* pd3dDevice)
 2 {
 3     // Set material
 4     D3DMATERIAL9 mtrl;
 5     ZeroMemory( &mtrl, sizeof(mtrl) );
 6     mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f;
 7     mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f;
 8     mtrl.Diffuse.b = mtrl.Ambient.b = 0.0f;
 9     mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;
10     pd3dDevice->SetMaterial( &mtrl );
11 
12 
13     // Set light
14     D3DXCOLOR color(1.0f, 1.0f, 1.0f, 0.0f) ;
15     D3DXVECTOR3 dir(1.0f, 0.0f, 0.0f ) ;
16 
17     D3DLIGHT9 light ;
18     ZeroMemory(&light, sizeof(light)) ;
19     light.Type = D3DLIGHT_DIRECTIONAL ;
20     light.Ambient   = color * 0.6f;
21     light.Diffuse   = color;
22     light.Specular  = color * 0.6f;
23     light.Direction = dir ;
24     pd3dDevice->SetLight(0, &light) ;            // Set light ;
25     pd3dDevice->LightEnable(0, true) ;            // Enable light
26 
27     pd3dDevice->SetRenderState(D3DRS_LIGHTING , TRUE);   
28     pd3dDevice->SetRenderState(D3DRS_NORMALIZENORMALS, true);
29 }

在OnD3D9FrameRender函数中调用之

1 SetupMatrix(pd3dDevice) ;
2 SetupLight(pd3dDevice) ;
3 

  再次编译运行,哇,经典的蓝黄配!

如何使用DXUT框架 - bingcaihuang - 水雲间
 

  但是这个茶壶是固定的,如何让它动起来呢,使之可以相应用户的输入。这就需要用到DXUT的Camera类,这里我们使用 ModelViewCamera来实现,默认情况下,生成的EmptyProject是不包含Camera类的,所以我们要手动添加,来到程序所在目录,将DXUT-Optional文件夹下的DXUTres.h,DXUTres.cpp,DXUTcamera.h和DXUTcamera.cpp四个文件加入到工程中的DXUT文件夹下

  在EmptyProject.cpp文件头部加上下面一句,以便可以使用camera类

1 #include "DXUTCamera.h"

  定义一个全局变量保存model camera

1 CModelViewerCamera modelCamera ;

  在OnD3D9CreateDevice函数中设置view matrix

  eyePt 眼睛 位于z轴的负半轴5个单位距离处,DirectX使用左手系,z轴正向指向屏幕内部。

  lookAt 视点 位于坐标原点

  通过这个设置,我们相当于在z轴负半轴5个单位距离处朝坐标原点看

  至于向上向量,camera类会为我们设置,一般是 D3DXVECTOR3 up(0.0f, 1.0f, 0.0f)

1 D3DXVECTOR3 eyePt(0.0f, 0.0f, -5.0f);
2 D3DXVECTOR3 lookAt(0.0f, 0.0f, 0.0f);
3 modelCamera.SetViewParams(&eyePt, &lookAt) ;
4 

在OnD3D9ResetDevice函数中设置投影矩阵

1 float fAspectRatio = pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height;
2 modelCamera.SetProjParams( D3DX_PI/4, fAspectRatio, 0.1f, 1000.0f );
3 modelCamera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
4 

  注意,到这里时,上面那个自定义的SetupMatrix函数就可以不用了,因为我们使用Camera来处理矩阵了

  在OnFrameMove函数中调用camera的FrameMove函数

1 modelCamera.FrameMove(fElapsedTime);

  在MsgProc函数中调用camera的消息处理函数,这使得model camera可以处理鼠标消息

1 modelCamera.HandleMessages(hWnd, uMsg, wParam, lParam) ;

  最后,也是最重要的,是OnD3D9FrameRender函数中的代码

  在每一帧开始绘制之前,我们要取得当前的矩阵并应用到当前的Scene中

 1 // Set world matrix
 2 D3DXMATRIX world = *modelCamera.GetWorldMatrix() ;
 3 pd3dDevice->SetTransform(D3DTS_WORLD, &world) ;
 4 
 5 // Set view matrix
 6 D3DXMATRIX view  = *modelCamera.GetViewMatrix() ;
 7 pd3dDevice->SetTransform(D3DTS_VIEW, &view) ;
 8 
 9 // Set projection matrix
10 D3DXMATRIX proj  = *modelCamera.GetProjMatrix() ;
11 pd3dDevice->SetTransform(D3DTS_PROJECTION, &proj) ;
12 

  好了,运行程序看看,貌似和前一次没什么区别啊?区别大了!现在你可以:

  拖动鼠标左键旋转model,注意旋转model时光照效果不变

  拖动鼠标右键旋转camera,注意旋转camera时光照会发生明暗变化,因为我们的视点变了,这就好比一束光照向茶壶的正面,茶壶不动,光的方向也不改变,而你作为观察者围着茶壶转,当你转到茶壶背面时,你将看到比较暗的一面。

  滑动鼠标滚轮,向前滑动时,是zoom in,茶壶会被放大,向后滑动时,是zoom out,茶壶会被缩小。

如何使用DXUT框架 - bingcaihuang - 水雲间
 
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 吃了螃蟹全身痒怎么办 全身痒眼睛肿了怎么办 感染了hpv病毒怎么办16 高危型hpv阳性52怎么办 腰椎盘突出腿疼怎么办 腰椎间盘突出压迫神经怎么办 疣体长到宫颈了怎么办 龟头的系带断了怎么办 龟头与系带断了怎么办 舌头下长肉芽痛怎么办 脑组织供血不足怎么办 尖锐湿锐喝酒了怎么办 快递寄错地方了怎么办 16岁掉头发严重怎么办 18岁老是掉头发怎么办 17岁头发老是掉怎么办 19岁老是掉头发怎么办 植发的了毛囊炎怎么办 长得好看不上镜怎么办 鬓角的头发总翘怎么办 戴贞洁锁硬了怎么办 欠很多钱还不了怎么办 理财平台跑路了怎么办 联通4g信号不好怎么办 老年人耳朵嗡嗡响什么原因怎么办 单侧耳朵嗡嗡响怎么办 蚊子钻到耳朵里怎么办 小飞虫进耳朵里怎么办 耳朵里飞进去虫怎么办 耳朵里进虫子了怎么办 耳朵进虫子了怎么办啊 耳朵里进了蚊子怎么办 有虫子爬进耳朵怎么办 虫子死在耳朵里怎么办 早上起床口苦口臭怎么办 耳朵被耳屎堵了怎么办 油耳朵被堵住了怎么办 棉签掏耳朵堵了怎么办 耳朵被气堵住了怎么办 掏耳朵发炎了疼怎么办 掏耳朵掏深了疼怎么办