D3D初步知识分析

D3D初步知识分析

D3D是一个十分繁琐的工具,尽管Microsoft已经尽可能地简化了,但是为了实现一个效果,你还是不得不做许多的工作,其中就包括对各种复杂的结构的赋值;这些赋值很重要,它直接关系到程序的最终效果。

这个部分,是我初学D3D时的一个总结。

首先,获取一个D3D设备:

LPDIRECT3DDEVICE9 pd3dDevice;

LPDIRECT3D9 pD3D = Direct3DCreate9( D3D_SDK_VERSION );

D3DPRESENT_PARAMETERS d3dpp;

ZeroMemory( &d3dpp, sizeof( d3dpp ) );

d3dpp.Windowed = TRUE;

d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;

pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,

D3DCREATE_SOFTWARE_VERTEXPROCESSING,

&d3dpp, &pd3dDevice );

pd3dDevice 就是我们需要的D3D设备。这个设备是为一个窗口应用程序写的,如果你是想要一个全屏的D3D程序的话,必须要改的就是d3dpp.Windowed 这个属性的设为FALSE。至于其他参数的含义,你最好还是安装DXSDK之后,仔细阅读它的帮助文档中的内容,那是一份最权威的资料,而且锻炼你的英文阅读,4级没过的同学可以同时学习英语和编程,一举两得啊,不过,先奉劝一句,冷静,不要企图破坏显示器。我在上面的示例中使用的基本是默认参数,它足够让你建立起你的第一个D3D程序。

其次,顶点信息:

关于3D的知识我想大家都有一些,在很多游戏里面,反应得相当明显;例如CS是一款很优秀的FPS游戏,在3D的处理上也是很出色,不过,我们仍然能够看到人物身上的棱角;大宇的《轩辕剑4》也是这样。这就是3D图形的真正面目——三角形。一个3D对象就是有N个多边形(其实就是三角形)组成的,多边形的数量越多,对象就越圆滑,反之,则越粗糙。不过,更多的多边形将会导致,计算量增加,性能下降。这就需要我们更好的平衡性能与质量之间的关系。我个人倾向于对性能的优化,像WOW中的人物,其实它的多边形数量并不高,一方面满足了性能需求,一方面又通过一些光影效果和算法弥补了质量上的下降。好像扯远了…..

一个三角形在3D空间里就是由3个顶点组成的。由于3D空间还存在点、线等元素。所以顶点可以认为是D3D中最基本的元素。在D3D中,顶点包含的信息是很多的;但是并不是每次都会用到所有的信息。所以,我们一般会在程序中自定义顶点结构。在一个程序中是可以存在很多个顶点结构的。

struct CUSTOMVERTEX

{

FLOAT x, y, z;

DOWRD color;

};

#define D3DFVF_CUSTOMVERTEX ( D3DFVF_XYZ | D3DFVF_DIFFUSE )

struct CUSTOMVERTEX1

{

D3DXVECTOR3 position;

FLOAT tu, tv;

};

#define D3DFVF_CUSTOMVERTEX1 ( D3DFVF_XYZ | D3DFVF_TEX1 )

struct CUSTOMVERTEX2

{

D3DXVECTOR3 position;

D3DXVECTOR3 normal;

};

#define D3DFVF_CUSTOMVERTEX2 ( D3DFVF_XYZ | D3DFVF_NORMAL )

以上定义的几个顶点结构还可以合并在一起,定义成一个新的顶点结构。要注意的是每个自定义的顶点结构后面都应该有一个D3DFVF 与之相对应,对顶点结构进行说明,否则D3D是不会知道你定义的顶点到底是什么意思的。D3DFVF_XYZ代表顶点的坐标,D3DFVF_DIFFUSE代表顶点的漫反射颜色,D3DFVF_TEX1代表顶点的贴图坐标,D3DFVF_NORMAL代表顶点的法线向量。position 在顶点信息中是必须,连坐标都不知道的点对我们来说说明都不是。color 存储的是顶点的颜色信息,用一个32bit的值表示,就像 0xffff0000 表示的是不透明的红色。

第三,基本图形(图元):

在绘图软件中,都存在基本图形这一个说法;D3D同样也有基本图形,这些图元只需要提供顶点信息,便可以由D3D通过硬件迅速地绘制出来。包括有点表(Point List)、线表(Line List)、线带(List Strip)、三角形表(Triangle List)、三角形带(Triangle Strip)、三角形扇(Triangle Fan)。

示例:说明如果绘制6个单独的顶点。

CUSTOMVERTEX Vertices[] =

{

{ -5.0, -5.0, 0.0 },

{ 0.0, 5.0, 0.0 },

{ 5.0, -5.0, 0.0 },

{10.0, 5.0, 0.0},

{15.0, -5.0, 0.0 },

{20.0, 5.0, 0.0 }

};

pd3dDevice->DrawPrimitive( D3DPT_POINTLIST, 0, 6 );

在帮助文档中对每个图元有具体说明。

第四,矩阵:

哈哈哈,终于等到这一章了,其实在写上一章的时候我就已经开始迫不及待了。Matrix 听起来总是那么COOLHi, Neo. Wake up …”陷入美好的回忆中,把DVD拿出来温习一遍。

OK,我回来了。矩阵是D3D重要的一个组成部分,如果你要说“废话,哪个不重要!”那么,它就是最重要的部分。没有矩阵,你的对象就没有生存的空间,重要吗?另外,矩阵对于新接触D3D的人来说,又是不太好理解的,当然,如果你的线代非常好的话,我当然没有话说,我当年可是吐出来了不少。

大家还记得左手坐标系吗?我还毕业就已经忘记了,自己去看书吧。这里只是告诉你,左手坐标系对于电脑屏幕来说,x轴的正方向是右,y轴的正方向是上,z轴的正方向是指向屏幕的。

D3D中需要设定的矩阵有3个。

I、 世界矩阵(World Matrix

世界矩阵控制对象在3D世界中的位置偏移,偏转角度。这里要引进一个新的概念,Viewport,视口(翻译好像很土,不过大家都是这样翻译的)。后面再讨论它,先告诉你视口的大小就是等于你的程序窗体大校世界矩阵的原点(0.0, 0.0, 0.0)就是视口的中央。为一个对象设定世界矩阵就是指定它在3D空间中的位置和偏转状态。

D3DXMATRIX matWorld;

D3DXMatrixIdentity( &matWorld );

pd3dDevice->SetTransForm( D3DTS_WORLD, &matWorld );

这样设定的对象在3D空间的位置就是原点,并且不带偏转。通常为了设定对象的偏移和转动,我们会定义两个辅助矩阵。

D3DXMATRIX matRotate; // Rotation

D3DXMatrixIdentity( &matRotate );

D3DXMatrixRotationAxis( &matRotate, AxisX, AxisY, fAngle ); // 某方向转动一定角度

D3DXMatrixMultiply( &matWorld, &matWorld, &matRotate );

D3DXMATRIX matTrans; // Translation

D3DXMatrixIdentity( &matTrans );

D3DXMatrixTranslation( &matTrans, fPosX, fPosY, fPosZ );

D3DXMatrixMultiply( &matWorld, &matWorld, &matTrans );

通过上面两个矩阵乘法得到的matWorld 就是得到了偏移量的对象的世界矩阵。

II、 观察矩阵(View Matrix

观察矩阵说得明白一点就是,眼睛在什么地方,在看什么地方,上方是哪个方向。很简单吧。在D3D中,大家要习惯用矢量思考和计算。

D3DVECTOR3 vEyePt( fPosX, fPosY, fPosZ );

D3DVECTOR3 vLookatPt( fPosX, fPosY, fPosZ );

D3DVECTOR3 vUpVec( fX, fY, fZ );

D3DXMATRIX matView;

D3DXMatrixIdentity( &matView );

D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );

pd3dDevice->SetTransForm( D3DTS_VIEW, &matView );

关于这个好像没有什么好说的了,地球人都知道埃

很晚了,洗澡,睡觉,明天在写吧。