3D游戏从入门到精通Word格式.docx

上传人:b****2 文档编号:1391154 上传时间:2023-04-30 格式:DOCX 页数:36 大小:46.14KB
下载 相关 举报
3D游戏从入门到精通Word格式.docx_第1页
第1页 / 共36页
3D游戏从入门到精通Word格式.docx_第2页
第2页 / 共36页
3D游戏从入门到精通Word格式.docx_第3页
第3页 / 共36页
3D游戏从入门到精通Word格式.docx_第4页
第4页 / 共36页
3D游戏从入门到精通Word格式.docx_第5页
第5页 / 共36页
3D游戏从入门到精通Word格式.docx_第6页
第6页 / 共36页
3D游戏从入门到精通Word格式.docx_第7页
第7页 / 共36页
3D游戏从入门到精通Word格式.docx_第8页
第8页 / 共36页
3D游戏从入门到精通Word格式.docx_第9页
第9页 / 共36页
3D游戏从入门到精通Word格式.docx_第10页
第10页 / 共36页
3D游戏从入门到精通Word格式.docx_第11页
第11页 / 共36页
3D游戏从入门到精通Word格式.docx_第12页
第12页 / 共36页
3D游戏从入门到精通Word格式.docx_第13页
第13页 / 共36页
3D游戏从入门到精通Word格式.docx_第14页
第14页 / 共36页
3D游戏从入门到精通Word格式.docx_第15页
第15页 / 共36页
3D游戏从入门到精通Word格式.docx_第16页
第16页 / 共36页
3D游戏从入门到精通Word格式.docx_第17页
第17页 / 共36页
3D游戏从入门到精通Word格式.docx_第18页
第18页 / 共36页
3D游戏从入门到精通Word格式.docx_第19页
第19页 / 共36页
3D游戏从入门到精通Word格式.docx_第20页
第20页 / 共36页
亲,该文档总共36页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

3D游戏从入门到精通Word格式.docx

《3D游戏从入门到精通Word格式.docx》由会员分享,可在线阅读,更多相关《3D游戏从入门到精通Word格式.docx(36页珍藏版)》请在冰点文库上搜索。

3D游戏从入门到精通Word格式.docx

D3DXVECTOR3类有很多方法,使用起来非常方便。

因而在程序里,主要使用它来定义变量,这样就有很函数可以使用了。

比如赋值,相加,相减等等。

它的定义如下:

typedefstructD3DXVECTOR3:

publicD3DVECTOR

{

public:

D3DXVECTOR3(){};

D3DXVECTOR3(CONSTFLOAT*);

D3DXVECTOR3(CONSTD3DVECTOR&

);

D3DXVECTOR3(CONSTD3DXFLOAT16*);

D3DXVECTOR3(FLOATx,FLOATy,FLOATz);

//casting

operatorFLOAT*();

operatorCONSTFLOAT*()const;

//assignmentoperators

D3DXVECTOR3&

operator+=(CONSTD3DXVECTOR3&

operator-=(CONSTD3DXVECTOR3&

operator*=(FLOAT);

operator/=(FLOAT);

//unaryoperators

D3DXVECTOR3operator+()const;

D3DXVECTOR3operator-()const;

//binaryoperators

D3DXVECTOR3operator+(CONSTD3DXVECTOR3&

)const;

D3DXVECTOR3operator-(CONSTD3DXVECTOR3&

D3DXVECTOR3operator*(FLOAT)const;

D3DXVECTOR3operator/(FLOAT)const;

friendD3DXVECTOR3operator*(FLOAT,CONSTstructD3DXVECTOR3&

BOOLoperator==(CONSTD3DXVECTOR3&

BOOLoperator!

=(CONSTD3DXVECTOR3&

}D3DXVECTOR3,*LPD3DXVECTOR3;

在这里已经实现向量的加减、数乘、数除,也许你发现这里有没有点积和叉积运算。

它们是通过其它公共函数实现的。

说到这里,如果你对点积和叉积运算不是很懂,看来又需要去看看《向量代数》了。

在游戏里,要表示一个人沿着OA的方向行走,那么只需要对着OA向量数乘,就可以了。

有了这样的向量类型定义,就可像下面那样方便使用:

D3DXVECTOR3vOA(1.0f,1.0f,1.0f);

2.10.1平面的表示

3D空间里的物体都是实体的,主要由平面组成。

比如正方体,就有6个平面。

在D3D里组成三维物体的基本平面是三角形,无论是多么复杂的物体,都是有三角形组成的。

并且D3D里支持显示最小的图形也是三角形,它是没有点和直线显示的。

因此,要显示正方体,就需要把每个平面分成两个三角形,才能显示。

如下图所示:

为什么选择三角形作为D3D里最小的平面呢?

由于三个点组成的平面,肯定是共面的,是平坦的,并且显示效率是最高的。

如果选择其它多边形的话,就存在点不共面的情况,这样变得非常复杂,所以目前显示卡也是针对三角形进行优化显示的。

要在D3D里显示物体,就是显示很多的三角形,让这些三角形连接起来,就组成游戏里的人体,动物,武器等等。

在几何里就知道每个三角形都有三个顶点组成,那么只要设置了三个顶点的值,就可以在D3D里显示三角形出来了。

用D3D里的向量表示三个顶点就是:

A:

D3DXVECTOR3(-1.0f,-1.0f,0.0f);

B:

D3DXVECTOR3(0.0f,1.0f,0.0f);

C:

D3DXVECTOR3(1.0f,-1.0f,0.0f);

只要把所有三角形的顶点,都按上面格式设置到顶点缓冲区里,就可以显示一个三角形出来。

但这个三角形又可分为两个表面:

前表面和后表面。

在D3D缺省情况下,只会显示前表面。

那么怎么样来区别前表面和后表面呢?

由于D3D是采用左手坐标系,正对着平面看去是顺时针方向的顶点顺序就是前表面。

如果不小心把顶点的顺序搞反,就会看不到表面显示。

并且还会关系到后面的灯光显示,纹理显示。

其实,前表面就是平面的法向量指向的表面。

只要认识到组成平面的顶点以及顶点排列顺序,就可以用平面构成三维物体了。

不管多么复杂的物体,都可以由顶点组成平面,再有平面组成物体。

不管是圆的物体,还是方的物体,都可以使用三角形去组成。

其实这种三维物体是数字化的,永远都是尽可能逼近,不可能是完全相同的。

比如要显示一个足球,它是圆的,需要非常多的三角形去构成它,但不可能完全一样的。

并且使用过多的三角形,就会导致CPU或者GPU处理不过来。

在目前的个人电脑里,虽然处理三角形的速度快了很多,但真的要显示大量三角形,还是不行的。

 

21使用Direct3D

2.11.1最简单三角形显示

前面已经学习了顶点、平面以及平面的法向量。

接着下面就带你进入奇幻的3D世界,由你去创造这个美好的3D世界。

任何美好的事物都是简单的东西组成的,所以也需要从最简单的物体构造开始。

这里主要显示一个三角形,其它关于窗口和初始化D3D的设备都已经由MM3D引擎做好了,目前只要设置顶点、世界坐标变换矩阵、观察变换矩阵、投影变换矩阵,然后渲染这个三角形,就可以显示屏幕里了。

最终显示效果如下图:

1、顶点格式

顶点格式是可变的,是灵活的。

由前面可知,顶点肯定是有三个值的,就是三个坐标轴的值。

下面先来看看最简单的顶点格式,它定义如下:

//定义顶点缓冲区里用到的顶点格式。

structVT_CAITRIANGLE

D3DXVECTOR3vPosition;

//顶点位置。

staticconstDWORDdwFVF=D3DFVF_XYZ;

};

这里使用一个结构来定义顶点的格式,后面就可使用这个结构来定义顶点了。

看到这个结构里第一个成员vPosition是很熟悉的吧,前面已经说明过使用一个向量来表示一个顶点的。

最简单的顶点格式,就是只有一个向量值,其它什么也没有。

后面一个成员dwFVF是说明顶点的有什么样数据,这里只有顶点的坐标,所使用了宏定义D3DFVF_XYZ。

其实顶点还可以有其它数据在里面的,比如要表示这个顶点的法向量,就需要加入法向量的成员,比如要显示纹理在这个表面上,就需要设置纹理坐标。

1、顶点缓冲区

顶点的数据是怎么样保存在内存里的呢?

由于渲染需要,就要把顶点保存在内存缓冲区里。

最简单的方法就是使用D3D提供的顶点缓冲区,即是使用IDirect3DVertexBuffer9接口的顶点缓冲区管理,它是通过D3D的设备来创建。

这个接口实现顶点的资源管理,使用起来非常方便,由于它管理内存分配,这样就省了内存管理。

下面就是通过IDirect3DDevice9:

:

CreateVertexBuffer函数来创建一个顶点缓冲区:

HRESULThr;

//创建顶点缓冲区。

if(FAILED(hr=m_pd3dDevice->

CreateVertexBuffer(3*2*sizeof(VT_CAITRIANGLE),

0,VT_CAITRIANGLE:

dwFVF,

D3DPOOL_MANAGED,&

m_pVB,NULL)))

//创建顶点缓冲区失败。

returnDXTRACE_ERR("

CreateVertexBuffer"

hr);

}

上面这段代码,就是创建6个顶点的缓冲区。

指定的格式为VT_CAITRIANGLE:

dwFVF,这个在前面已经定义过,只包括顶点向量数据。

D3DPOOL_MANAGED指明了创建的缓冲区在系统内存里,并且需要时就拷贝到显示卡内存里。

我们知道显示卡内存越来越大了,如果把很多变化不大的物体放到显示卡内存里,就可以加速显示,减少占用系统局部总线的带宽。

像NV新出来的显示卡,都有1G显示内存,显然可以放更多物体在那里,以便显示的速度更快。

由于显示卡内存和系统内存的复杂性,而通过这个接口可以方便地使用了。

由于它是还一个内存池,所以产生内存碎片的机会就更加少了。

创建顶点缓冲区之后,就需要往里面填充顶点数据,先来看看下面的代码:

//用两个三角形填充顶点缓冲区。

VT_CAITRIANGLE*pVertices;

if(FAILED(hr=m_pVB->

Lock(0,0,(VOID**)&

pVertices,0)))

//锁住顶点缓冲区。

Lock"

//前面三角形。

pVertices[0].vPosition=D3DXVECTOR3(-1.0f,-1.0f,0.0f);

pVertices[1].vPosition=D3DXVECTOR3(0.0f,1.0f,0.0f);

pVertices[2].vPosition=D3DXVECTOR3(1.0f,-1.0f,0.0f);

//后面三角形。

pVertices[3].vPosition=D3DXVECTOR3(-1.0f,-1.0f,0.0f);

pVertices[4].vPosition=D3DXVECTOR3(1.0f,-1.0f,0.0f);

pVertices[5].vPosition=D3DXVECTOR3(0.0f,1.0f,0.0f);

//解锁顶点缓冲区。

m_pVB->

Unlock();

这段代码是通过IDirect3DVertexBuffer9:

Lock方法来获取到顶点缓冲区的指针,然后把6个顶点赋值。

最后调用IDirect3DVertexBuffer9:

Unlock方法解锁,如果不解锁,D3D显示不了这个缓冲区里的数据,就会出错的,所以一定要小心地操作。

1、世界坐标变换矩阵

在设置顶点缓冲区之后,就需要设置物体的世界坐标变换矩阵。

从解析几何里可以知道,无论二维还是三维的图像都可以通过齐次坐标来变换的。

目前在三维里的变换,采用的矩阵是4×

4的矩阵来实现变换处理。

在D3D里定义D3DXMATRIX类型,使用它来表达一个矩阵,并且定义一系列的函数可以实现矩阵的运算。

typedefstruct_D3DMATRIX{

union{

struct{

float_11,_12,_13,_14;

float_21,_22,_23,_24;

float_31,_32,_33,_34;

float_41,_42,_43,_44;

floatm[4][4];

}D3DMATRIX;

上面代码定义了4×

4矩阵的四个元素,全部使用浮点数运算。

接着还添加了一些操作方法,如下:

typedefstructD3DXMATRIX:

publicD3DMATRIX

D3DXMATRIX(){};

D3DXMATRIX(CONSTFLOAT*);

D3DXMATRIX(CONSTD3DMATRIX&

D3DXMATRIX(CONSTD3DXFLOAT16*);

D3DXMATRIX(FLOAT_11,FLOAT_12,FLOAT_13,FLOAT_14,

FLOAT_21,FLOAT_22,FLOAT_23,FLOAT_24,

FLOAT_31,FLOAT_32,FLOAT_33,FLOAT_34,

FLOAT_41,FLOAT_42,FLOAT_43,FLOAT_44);

//accessgrants

FLOAT&

operator()(UINTRow,UINTCol);

FLOAToperator()(UINTRow,UINTCol)const;

//castingoperators

D3DXMATRIX&

operator*=(CONSTD3DXMATRIX&

operator+=(CONSTD3DXMATRIX&

operator-=(CONSTD3DXMATRIX&

D3DXMATRIXoperator+()const;

D3DXMATRIXoperator-()const;

D3DXMATRIXoperator*(CONSTD3DXMATRIX&

D3DXMATRIXoperator+(CONSTD3DXMATRIX&

D3DXMATRIXoperator-(CONSTD3DXMATRIX&

D3DXMATRIXoperator*(FLOAT)const;

D3DXMATRIXoperator/(FLOAT)const;

friendD3DXMATRIXoperator*(FLOAT,CONSTD3DXMATRIX&

BOOLoperator==(CONSTD3DXMATRIX&

=(CONSTD3DXMATRIX&

}D3DXMATRIX,*LPD3DXMATRIX;

上面的方法,都是对这个矩阵的运算,使用起来更加方便。

有了矩阵的定义,还有了矩阵的运算,那么构造一个从模型坐标到世界坐标变换的矩阵,就是很容易的事情了。

由于我不需要变换它,直接使用一个单位矩阵,就可以了。

由单位矩阵可知,任何数据乘以单位矩阵都不变会改变。

代码如下:

//设置世界坐标矩阵。

D3DXMATRIXmatIdentity;

D3DXMatrixIdentity(&

matIdentity);

m_pd3dDevice->

SetTransform(D3DTS_WORLD,&

这段代码里先定义一个矩阵,然后调用函数D3DXMatrixIdentity初始化这个矩阵为单位矩阵,最后通过函数SetTransform设置为世界坐标变换矩阵。

这样显示的三角形就是按模型坐标系显示到世界坐标系里,也就是在世界坐标系的原点位置显示。

在游戏里,所有3D模型都是在外面做好的,因此都是模型坐标系,也就是局部坐标系,要把它们显示到世界坐标系里,一般是需要通过变换的。

因为所有模型坐标系都是相同的,都是原点在世界坐标系的原点。

如果不通过变换就显示的话,所有的物体都是重叠在原点位置,这样就分不清楚它们的显示。

比如显示一个足球场,两个球门就是分别显示的。

一个球门在原点,一个球门就在离原点一段距离再显示,还需要通过合适旋转变换才能显示。

由于两个球门是同一个局部坐标系的物体构成,必须通过世界坐标变换矩阵才能显示出来。

1、视图变换矩阵

视图变换矩阵是做什么用的呢?

为什么需要视图变换矩阵呢?

其实这个问题很好回答和理解的。

在3D世界里,所有东西都是跟现实中的实物一样的,当用人的眼睛去观看现实中的实物时,总是从某一方向去观察的,这样就看到实物组成的图像。

就像你拿着照相去照相是一样的,首先要调好焦距,对准物体。

在D3D里也需要调好焦距,对准物体,否则什么也看不到。

因此在D3D里,就需要设置好视图变换矩阵。

也就是相机的位置和焦距。

在视图变换矩阵里,是使用两个点来表达相机位置和焦距,如下图所示:

在D3D里使用向量来表示相机位置,如下:

D3DXVECTOR3vFromPt=D3DXVECTOR3(0.0f,0.0f,-5.0f);

这里指明了相机所在位置是Z轴上-5的位置。

接着又需要指明焦点所有位置,如下:

D3DXVECTOR3vLookatPt=D3DXVECTOR3(0.0f,0.0f,0.0f);

这里指明了相机焦点所在位置是在世界坐标系的原点。

但还有一个因素没有考虑进去,那就是相机放置的方向。

比如人站在地球上,头顶着天去观察实物是一种方向,是一种正常的方向,侧着头去看实物又是一种方向,人倒立着看实物又是一个方向。

“横看成岭侧成峰,远近高低各不同。

”就表达了这种不同方向看东西的不同,因此在D3D里也需要设置方向,用如下向量表示:

//设置向上方向为Y轴正方向.

D3DXVECTOR3vUp(0,1,0);

有了这三个向量,就决定了相机需要经过的变换矩阵,也就是看到D3D里的物体是什么样子了。

在D3D里,就是构造一个视图变换矩阵,它是使用下面函数来计算的:

D3DXMatrixLookAtLH(&

m_mView,&

m_vEyePosition,&

m_vLookAtPosition,&

vUp);

第一个参数,就是返回来的视图变换矩阵,第二个参数是相机位置,第三个参数是焦点位置,第四个参数是相机朝向。

构造好视图变换矩阵后,就可以把它设置D3D里,通过下面的函数来实现:

//设置视变换矩阵。

constD3DXMATRIX&

mView=CCameraFirstPerson:

Instance()->

GetViewMatrix();

SetTransform(D3DTS_VIEW,&

mView);

这样就把D3D的设备视图变换矩阵设置好了。

投影变换矩阵

投影变换矩阵是做什么的呢?

这个更容易理解了。

大家都应看过照片吧,那大家又想过照片是怎么样表现原来的物体呢?

看到远处的山是小的,近处的人是大的。

并且只有在一定的范围内的物体才照得清楚,其它的就不见了。

在D3D里就需要把三维的物体空间投影到二维的屏幕空间显示,这就需要投影了。

本来人眼看现实的物体时,总是经过投影变换的,把三维的物体通通变换成二维东西,这样就在人眼上看见东西就是三维的了。

现在这个投影变换就是模拟人眼的作用,沿着光线的方向,那些能看见,那些不能看见。

那些是近的,那些是远的。

通过这样的计算,就会生成二维的图像,跟人眼看到真实的世界是相同的。

在D3D里通过设置投影前截面、后截面、视角和长宽比来构造投影矩阵,使用下面的函数来构造这个投影变换矩阵:

D3DXMatrixPerspectiveFovLH(&

m_mProjection,fFOV,fAspect,fNearPlane,fFarPlane);

第一个参数是返回的矩阵,第二参数是视角,第三个参数是长宽比,第四参数是近截面,第五参数是远截面。

构造好投影变换矩阵,就可以通过下面参数设置:

//设置投影矩阵。

mProj=CCameraFirstPerson:

GetProjectionMatrix();

SetTransform(D3DTS_PROJECTION,&

mProj);

这样就可以设置好D3D的设备投影矩阵

1、渲染物体

经过前面这么多步骤,做足了准备工作,就可以渲染物体,显示三维空间的图像了。

这时心情要兴奋起来,就看到自己辛苦的果实了。

仔细地看一下前面的代码,创建的缓冲区还没有设置给D3D设备。

下面就来做这方面的工作:

//渲染顶点缓冲区的内容。

SetStreamSource(0,m_pVB,0,sizeof(VT_CAITRIANGLE));

SetFVF(VT_CAITRIANGLE:

dwFVF);

DrawPrimitive(D3DPT_TRIANGLELIST,0,2);

上面这段代码先设置顶点缓冲区给D3D设备,第一个参数选择渲染通道,由于现在的显示卡提供多个通道显示,以便加速显示。

这个参数可以根据枚举设备的特性来知道最大的通道数。

第二个参数是上面的顶点缓冲区,就是每个顶点的坐标值。

第三个参数是指明从顶点缓冲区什么位置开始渲染,这里是从缓冲区开始位置开始,所以设置为0。

第四个参数是每个顶点占用的大小,因为每个顶点的数据,可以有三个坐标值、纹理坐标、颜色值和其它数据。

接着下来调用SetFVF函数来设置顶点的格式,这里设置为上面的定义的顶点格式VT_CAITRIANGLE:

dwFVF。

最后一行代码就是真正地画两个三角形在屏幕缓冲区里。

它的第一个参数是设置显示顶点的格式,这里按三角形列表的形

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2