赞
踩
本篇文章里,我们对Direct3D之中几种几何体的简洁绘制方法进行了详细的剖析,最后依旧是提供文章配套的详细注释的demo源代码的欣赏,并在文章末尾提供了源代码下载。(这标题有些歧义的,这个几种是修饰几何体的,而绘制的方法只有一种 :D)
首先需要跟大家道声歉,上个周末因为浅墨个人的原因。没把想写的内容的思路整理好,所以就停更了一次。
好了,别的废话咱不说了,下面直奔本周主题~
一、D3D中内置的几何体概述
通过前面的讲解大家应该会发现,使用顶点缓存和索引缓存通过绘制三角形单元来绘制图形还是有一点复杂的,需要一定的想象力和大量顶点和索引的设置,我们一般很少去这样通过逐个设置顶点缓存和索引缓存来进行画面上几何体的绘制的。而比较人性化的是,Direct3D为我们提供了几种特殊的生成简单3D几何体的网格数据的方法。可以说是在我们学习从文件载入网格数据之前,为我们提供了很多便利,丰富了我们的学习时的图形素材。下面我们就来看看这几个快捷的几何体绘制函数,他们分别是立方体(Cube),圆环体(Torus),多边形(Polygon),球面体(Sphere),茶壶(Teapot)和圆柱体(Cylinder)。
我们可以在DirectX SDK(以目前最新的Microsoft DirectX SDK (June 2010)为例)的Windows DirectX Graphics.chm文档中依次展开【Windows DirectX Graphics Documentation】->【Direct3D 9 Graphics】->【Reference for Direct3D 9】->【D3DX Reference】->【D3DX Functions】->【Shape Drawing Functions】找到这些函数的说明文档,这是这些函数最官方最原始的参考地址了。
不过显然这些DirectX SDK Document都是纯英文的,和大众之间的距离还是比较疏远。
先给大家看看这几个函数的全家福,后面我们会全部详细介绍使用方法的:
D3DXCreateBox 用于创建一个盒子,立方体
D3DXCreateSphere 用于创建一个球面体
D3DXCreateCylinder 用于创建一个柱体
D3DXCreateTeapot 用于创建一个茶壶
D3DXCreatePolygon 用于创建一个多边形
D3DXCreateTorus 用于创建一个圆环体
我们可以看到这些函数的名字取的都非常的憨厚老实,一开始是D3DX,然后紧跟其后一个Create,表示是在创建某东西,最后跟上对应的几何体名,比如Teapot茶壶,这样连起来就非常好记忆了,D3DXCreateTeapot。
二、D3D中几种内置的几何体绘制四步曲
首先需要说明的是下面提到的ID3DXMesh接口类型是后面我们在讲解网格相关知识的时候重点讲解的内容,这里大家先对其有一个大概的印象就可以了。
想要通过这几个函数快捷绘制出一个几何体,需要以下几步:
1.定义一个ID3DXMesh接口类型的对象。
2.调用这六个函数的其中一个对我们在第一步里面定义的这个对象进行初始化,也就是把创建好的网格存储在我们定义好的ID3DXMesh类型的对象中
3.在Direct3D渲染五步曲的第三步,也就是在BeginScene之后调用DrawSubset方法进行网格图形的绘制,即是拿着第二步里面初始化好的ID3DXMesh接口类型的对象指一下DrawSubset(0)方法就好了
4.绘制完成之后,调用ID3DMesh接口的Release方法,或者我们自定义的COM接口释放宏进行资源的释放。
总结起来也就简明扼要八个字:
定义,创建,绘制,释放
方便大家理解各个过程,给出一个配套的注释好的代码:
三、D3D中几种内置几何体的创建详细剖析
这一小节里面讲解的都是上文我们提到的几何体绘制四步曲的第二步里面的具体创建方法,但是配套的调用实例都包含了四步曲里面的前三步,大家需要注意下。
1. 立方体的创建——D3DXCreateBox方法
D3DXCreateBox方法用于创建一个立方体,或者说是一个盒子。
█ 第一个参数,LPDIRECT3DDEVICE9类型的pDevice,指向IDirect3DDevice9接口的指针,这样一般就填我们在初始化四步曲里面创建的有效的Direct3D绘制”金钥匙”——Direct3D设备对象g_pd3dDevice。表示Direct3D设备对象和我们创建的这个盒子网格之间关联起来了。
█第二个参数,FLOAT类型的Width,表示我们创建的盒子沿着X轴的宽度。
█第三个参数,FLOAT类型的Height,表示我们创建的盒子沿着Y轴的高度。
█第四个参数 , FLOAT类型的Depth,表示我们创建的盒子沿着Z轴的深度。
█第五个参数,LPD3DXMESH类型的*ppMesh,一个存储着我们创建的形状的指针的地址,也就是绘制用D3DXCreateBox函数创建的网格的金钥匙,后面需要绘制我们用这个函数创建的盒子网格的话,拿这个指针指一下DrawSubset方法,也就是这样写g_box->DrawSubset(0);
█第六个参数,LPD3DXBUFFER类型的*ppAdjacency,它存储着我们在这里绘制的网格的三角形索引的指针,我们不用他的话,设为0就可以了。
下面是一个调用实例,创建一个长方体:
2. 柱体的创建——D3DXCreateCylinder方法
D3DXCreateCylinder方法用于创建柱体。
█ 第一个参数,LPDIRECT3DDEVICE9类型的pDevice,指向IDirect3DDevice9接口的指针,这样一般就填我们在初始化四步曲里面创建的有效的Direct3D绘制”金钥匙”——Direct3D设备对象g_pd3dDevice。表示Direct3D设备对象和我们创建的这个柱体网格之间关联起来了。
█ 第二个参数,FLOAT类型的Radius1,表示我们创建的柱体沿Z轴负方向的半径大小,这个参数显然必须大于等于0.0f。
█ 第三个参数,FLOAT Radius2, 表示我们创建的柱体沿Z轴正方向的半径大小,这个参数显然必须大于等于0.0f。
█ 第四个参数,FLOAT类型的Length,表示我们创建的柱体沿Z轴的长度。
█ 第五个参数,UINT类型的Slices,表示柱体的外围有几个面,举个例子,如果设为8的话,我们创建的就是八角柱了。
█ 第六个参数,UINT类型的Stacks,表示柱体的两端间共有几段,这个后面光照效果的时候需要要用到的。
█ 第七个参数,LPD3DXMESH类型的*ppMesh,一个存储着我们创建的形状的指针的地址,也就是绘制用D3DXCreateCylinder函数创建的网格的金钥匙,后面需要绘制我们用这个函数创建的柱体网格的话,拿这个指针指一下DrawSubset方法,也就是这样写g_Cylinder->DrawSubset(0);
█ 第八个参数,LPD3DXBUFFER类型的*ppAdjacency,它存储着我们在这里绘制的网格的三角形索引的指针,我们不用他的话,设为0就可以了。
3. 2D 多边形的创建——D3DXCreatePolygon方法
D3DXCreatePolygon方法用于快速创建一个2D多边形。
█ 第一个参数,LPDIRECT3DDEVICE9类型的pDevice,指向IDirect3DDevice9接口的指针,这样一般就填我们在初始化四步曲里面创建的有效的Direct3D绘制”金钥匙”——Direct3D设备对象g_pd3dDevice。表示Direct3D设备对象和我们创建的这个2D 多边形网格之间关联起来了。
█ 第二个参数,UINT类型的Sides,表示我们创建的多边形每条边的长度。
█ 第三个参数,FLOAT Radius2, 表示我们创建的多边形的包含几个三角形。
█ 第四个参数,LPD3DXMESH类型的*ppMesh,一个存储着我们创建的形状的指针的地址,也就是绘制用D3DXCreateCylinder函数创建的网格的金钥匙,后面需要绘制我们用这个函数创建的2D多边形网格的话,拿这个指针指一下DrawSubset方法,也就是这样写g_Polygon->DrawSubset(0);
█ 第五个参数,LPD3DXBUFFER类型的*ppAdjacency,它存储着我们在这里绘制的网格的三角形索引的指针,我们不用他的话,设为0就可以了。
下面是一个调用实例
4. 球面体创建——D3DXCreateSphere方法
D3DXCreateSphere方法用于创建一个球面体。
█ 第一个参数,LPDIRECT3DDEVICE9类型的pDevice,指向IDirect3DDevice9接口的指针,这样一般就填我们在初始化四步曲里面创建的有效的Direct3D绘制”金钥匙”——Direct3D设备对象g_pd3dDevice。表示Direct3D设备对象和我们创建的这个2D 多边形网格之间关联起来了。(浅墨在这里是复制粘贴上面的介绍,因为这个参数在本篇文章里介绍的几个创建几何体函数中都是一样的)
█ 第二个参数,UINT类型的Sides,表示我们创建的多边形每条边的长度。
█ 第三个参数,UINT类型的Slices, 表示我们创建的球面体绕主轴线切片数,也就是用几条经线来进行绘制。
█ 第四个参数,UINT类型的Stacks,表示我们创建的球面体绕主轴线的纬线数,也就是用几条纬线来进行绘制。
█ 第五个参数,LPD3DXMESH类型的*ppMesh,一个存储着我们创建的形状的指针的地址,也就是绘制用D3DXCreateCylinder函数创建的网格的金钥匙,后面需要绘制我们用这个函数创建的球面体网格的话,拿这个指针指一下DrawSubset方法,也就是这样写g_Polygon->DrawSubset(0);
█ 第六个参数,LPD3DXBUFFER类型的*ppAdjacency,它存储着我们在这里绘制的网格的三角形索引的指针,我们不用他的话,设为0就可以了。
依然是一个调用实例:
看到这里如果大家觉得累了,来看几幅游戏美图吧,今天浅墨给大家准备的是2012年8月份刚上市的游戏大作《暗黑血统2》的桌面壁纸,这款游戏浅墨最近在玩,感觉还不错:
是不是很酷呢?上面的第二张图片浅墨可是做了很长时间的壁纸的呢。
好了,下面我们继续来讲解。
五 茶壶的创建——D3DXCreateTeapot方法
D3DXCreateTeapot方法用于创建一个茶壶。
这个函数相对来说参数很少,他并没有给我们提供茶壶具体参数的设置。
█ 第一个参数,LPDIRECT3DDEVICE9类型的pDevice,指向IDirect3DDevice9接口的指针,这样一般就填我们在初始化四步曲里面创建的有效的Direct3D绘制”金钥匙”——Direct3D设备对象g_pd3dDevice。表示Direct3D设备对象和我们创建的这个2D 多边形网格之间关联起来了。(浅墨在这里是复制粘贴上面的介绍,因为这个参数在本篇文章里介绍的几个创建几何体函数中都是一样的)
█ 第二个参数,LPD3DXMESH类型的*ppMesh,一个存储着我们创建的形状的指针的地址,也就是绘制用D3DXCreateCylinder
函数创建的网格的金钥匙,后面需要绘制我们用这个函数创建的茶壶网格的话,拿这个指针指一下DrawSubset方法,也就是这样写g_Polygon
->DrawSubset(0);
█ 第三个参数,LPD3DXBUFFER类型的*ppAdjacency,它存储着我们在这里绘制的网格的三角形索引的指针,我们不用他的话,设为0就可以了。
依然是一个调用实例:
六、圆环的创建——D3DXCreateTorus方法
D3DXCreateTorus方法用于创建一个圆环体。
█ 第一个参数,LPDIRECT3DDEVICE9类型的pDevice,指向IDirect3DDevice9接口的指针,这样一般就填我们在初始化四步曲里面创建的有效的Direct3D绘制”金钥匙”——Direct3D设备对象g_pd3dDevice。表示Direct3D设备对象和我们创建的这个2D 多边形网格之间关联起来了。(浅墨在这里是复制粘贴上面的介绍,因为这个参数在本篇文章里介绍的几个创建几何体函数中都是一样的)
█ 第二个参数,FLOAT类型的InnerRadius,表示我们创建的圆环的內圈半径。
█ 第三个参数,FLOAT类型的OuterRadius, 表示我们创建的圆环的外圈半径。
█ 第四个参数,UINT类型的Sides,表示我们创建的圆环的外圈有几个面,也就是大圆的轮廓是几边形,这个值显然要大于等于3.
█ 第五个参数,UINT类型的Rings,表示我们创建的圆环的内圈与外圈之间有几个面。
█ 第六个参数,LPD3DXMESH类型的*ppMesh,一个存储着我们创建的形状的指针的地址,也就是绘制用D3DXCreateCylinder函数创建的网格的金钥匙,后面需要绘制我们用这个函数创建的圆环体网格的话,拿这个指针指一下DrawSubset方法,也就是这样写g_Polygon->DrawSubset(0);
█ 第七个参数,LPD3DXBUFFER类型的*ppAdjacency,它存储着我们在这里绘制的网格的三角形索引的指针,我们不用他的话,设为0就可以了。
依然是一个调用实例:
讲解最后做下总结,首先,我们可以发现这些方法的第一个参数和最后两个参数都是相同的。然后,这些函数的使用方法不用去强行记忆,用到的时候按D3DX+Create+几何体名字的命名方法去查一下SDK文档或者稍微看一下这篇博文就可以了。
四,详细注释的源代码讲解及欣赏
这里依旧是通过一个小程序,来把本篇文章所学的知识融会贯通。本篇文章里面我们介绍了Direct3D中立方体(Cube),圆环体(Torus),多边形(Polygon),球面体(Sphere),茶壶(Teapot)和圆柱体(Cylinder)这几种几何体的简洁绘制法,而下面就是一个通过本篇文章里介绍的方法绘制出四个几何体的程序的源代码。在贴出详细注释的源代码之前,我们先讲解一下写这个演示程序中的几个要点。
首先,我们定义了几个全局的ID3DXMesh对象,以及几个D3DXMATRIX矩阵类型。这里定义ID3DXMesh对象就是我们本节介绍的几何体绘制四步曲的第一步,而矩阵类型是为了后面给绘制的每个几何体不同的世界坐标位置以及做出旋转的镜头效果。相关代码如下:
然后,我们在Objects_Init()方法中进行了几何体绘制四步曲的第二步,创建几何体的过程(我们准备绘制立方体,茶壶,球面体,茶壶这四个几何体,就在这一步当中进行了创建),以及调用了一些SetRenderState关闭了光照,开启了背面消隐,以及将填充模式默认设置为线框填充。因为Objects_Init()方法我们整个程序运行过程中只会运行一次,所以默认的渲染模式的设置都可以在这里进行。相关代码如下:
接着,就是在Direct3D_Render()函数中进行绘制了,需要注意的是,四大矩阵变换我们原先都是封装在Matrix_Set()方法中进行的,而这里我们为了绘制的方便,我们把世界变换从Matrix_Set()方法中拿出来,放到了Direct3D_Render()之中。另外需要注意的一点是,制作出镜头旋转的方法,我们先用D3DXMatrixRotationY方法制作一个根据系统时间绕Y轴旋转的矩阵R出来,就是这样写:
然后在设置好物体的世界矩阵坐标后,右乘一下我们制作好的矩阵R,然后把结果矩阵设置为当前的世界矩阵,再进行绘制就可以了。
关于这一步的完整代码由于比较长,就在讲解中不贴出来了,因为下面全部代码之中有的,其实就是Direct3D_Render()的函数的实现方法。
最后,绘制完成之后,在程序准备退出的时候就是几何体绘制四步曲的第四步——释放了。其实就是Direct3D_CleanUp()函数的实现代码:
好了,讲解完成,最后我们贴出详细注释的源代码:
编译并运行上面的源代码,我们就可以得到如下四个排列规则的几何体,且这些几何体都在不停地绕着Y轴不停地旋转着,按按键盘上数字键“1”键和“2”键可以在线框填充模式和实体填充模式之间切换:
按下数字键“2”,我们可以看到这些几何体的实体填充模式:
因为我们关闭了光照,而且材质也没给我们的几何体设置,所以在实体填充模式下这些几何体白得有些惨不忍睹,立体感全无,没关系,敬请期待浅墨下篇讲解光照和材质的文章。
文章最后,依旧是放出本篇文章配套源代码的下载:
本节笔记配套源代码请点击这里下载:
其中图标素材取自的游戏大作 波斯王子:时之沙
以上就是本节笔记的全部内容,更多精彩内容,且听下回分解。
浅墨在这里,希望喜欢游戏开发系列文章的朋友们能留下你们的评论,每次浅墨登陆博客看到大家的留言的时候都会非常开心,感觉自己正在传递一种信仰,一种精神。
文章最后,依然是【每文一语】栏目,今天是来自张爱玲的句子:
在这个光怪陆离的人间,没有谁可以将日子过得行云流水。但我始终相信,走过平湖烟雨,岁月山河,那些历尽劫数、尝遍百味的人,会更加生动而干净。时间永远是旁观者,所有的过程和结果,都需要我们自己承担。
下周一,让我们离游戏开发的梦想更近一步。
下周一,游戏开发笔记,我们,不见不散。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。