从零3D根蒂根基入门XNA 4.0(1)
2013年12月23日 作者:Admin【题外话】
比来要做一个3D动画演示的法度,因为斗劲熟悉C#说话,再加上XNA对模型的支撑斗劲好,故选择了XNA平台。不过从网上找到很多XNA的入门文章,发明大都须要一些3D根蒂根基,而我之前并没有接触过游戏以及3D相干的开辟,所以我来从另一个角度收拾下入门XNA。本文尽量少涉及3D及数学方面的常识,因为其他文章介绍的太多了。
【文章索引】
- XNA项目标布局
- XNA法度的布局
- 坐标系与摄像机
- 模型的导入与显示
【一、XNA项目标布局】
固然微软在推出了XNA 4.0之后就再也没有进级过XNA的版本,但XNA还是在.NET平台上斗劲便利的3D框架。因为我应用的是VS2013,而XNA 4.0的安装法度只认VS2010,所以须要安装一个应用VS2010 Shell的法度(比如我应用的是sql Server 2012 Management Studio,当然也可以安装VS2010 Express)才干经由过程XNA 4.0的安装。安装完后会主动在VS2010下添加相干扩大模板,但不会在更高版本添加,可以参考 http://ryan-lange.com/xna-game-studio-4-0-visual-studio-2012/ 将扩大模板添加到VS2012或2013中(VS2013须要将此中的版本号改为12.0)。
XNA 4.0相对之前的3.1做了很多批改,不仅代码长进行了很多调剂,默认创建的项目也与之前的不合。创建XNA 4.0的Windows Game项目后,默认会创建两个项目,分别是WindowsGame以及WindowsGameContent,前者存放法度的逻辑代码,而后者则存放法度所须要的资料(模型、纹理等等),与其他项目不合的是,XNA项目增长了一个Content Reference内容引用,可以将逻辑与资料拆分成不合的项目,即由逻辑代码的项目引用资料项目,当然也可以归并在一路。
【二、XNA法度的布局】
在创建的WindowsGame项目中,与其他Windows法度一样都包含一个Program.cs,除此之外同时还有一个Game.cs。须要申明的是,与通俗开辟Windows应用以基于事务的体式格式不合,开辟XNA(以及其他游戏框架)的应用是以基于轮询的体式格式。在Game.cs文件中,除了机关办法外还会生成以下几个办法,其履行次序和微软给出的申明如下:
- protected override void Initialize():须要包含加载任何非图形的资料。
- protected override void LoadContent():在Initialize之后或者在任何须要从头加载资料的时辰(比如在DeviceReset事务产生时)履行,须要包含加载游戏须要的图形资料等。
- protected override void Update(GameTime gameTime):在法度逻辑须要处理惩罚时履行,须要包含法度状况的经管、用户输入的处理惩罚以及数据的更新。
- protected override void Draw(GameTime gameTime):在须要绘制一帧画面的时辰履行,须要包含绘制图形的代码。
- protected override void UnloadContent():在法度须要开释资料时履行,须要包含开释资料的代码。
此中法度的首要项目组就是Update()和Draw()两个办法,全部法度在运行时,几乎就是这两个办法在络续反复履行。须要申明的是,对于XNA,在默认景象下,履行一次Update()和Draw()是要把握在一按时候的(默认为1/60s,即60FPS),若是履行一次Update()和Draw()的时候小于这个时候将会进行守候,若是跨越这个时候则会跳帧(不履行Draw()),当然也可以批改Game类中的Targetelapsedtime来改变这个时候,或者批改IsFixedtimestep=false使得法度帧数能多大就多大。
【三、坐标系与摄像机】
对于二维的画面,我们可以直接应用屏幕的坐标系;而对于三维的画面,我们还须要将三维世界投影到二维的屏幕上。那么,我们就须要一个策画如何将三维世界投影到二维屏幕的对象,那么摄像机就是实现这个功能的。实际上,这里的摄像机与我们日常平凡拿摄像机录像是一样的,在屏幕上显示的内容就是摄像机录下的内容。
起首须要申明的是,在XNA中应用的右手坐标系(与Direct3D中应用的左手坐标系Z轴相反),也就是说按正常标的目标去看的话,向右是X轴正标的目标,向上是Y轴正标的目标,而指向本身的(向外)是Z轴正标的目标,如下图。
在三维框架中,很多信息的存储和默示都是用四维矩阵(Matrix类)来的。所以要默示一个摄像机,凡是由两个矩阵构成,分别是 视图矩阵(View Matrix) 和 投影矩阵(Projection Matrix),此中视图矩阵默示了摄像机的地位、摄像机的朝向以及摄像机的上标的目标;而投影矩阵则默示了摄像机的视角以及视觉局限。固然听上去很错杂,然则XNA供给了直接由具体的参数创建矩阵的办法。
对于视图矩阵的创建,可以应用如下的办法:
Matrix.CreateLookAt(Vector3 cameraPosition, Vector3 cameraTarget, Vector3 cameraUpVector);
此中cameraPosition为摄像机在空间内的三维坐标;cameraTarget为摄像机所指向目标的三维坐标;cameraUpVector则注解了哪个标的目标是摄像机的向上标的目标(若是摄像机正着放的话,那么Y轴正标的目标为摄像机的向上标的目标)。
而对于投影矩阵的创建,则可以应用如下的办法:
Matrix.CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float nearPlanedistance, float farPlanedistance);
此中fieldOfView默示的是摄像机的视角弧度,局限为(0, Pi),凡是为Pi/4(45°);aspectRatio为摄像机的长宽比,凡是为屏幕的长宽比;nearPlanedistance与farPlanedistance则为当摄像机多近(远)时无法拍摄到物体。鄙人图中默示了fieldOfView与nearPlanedistance和farPlanedistance的关系,可以看到摄像机经由过程视角角度与间隔可以产生一个近剪裁面和远剪裁面,而终极能投影的项目组就是处在这两个平面之间的物体。
【四、模型的导入与显示】
对于三维模型,XNA平台支撑两种格局,分别是.x与.fbx文件,此中后者在很多软件中都支撑,比如Maya、MotionBuilder等等。对于模型的导入,只须要将模型文件拖到Content项目中即可。不过须要申明的是,为了包管效力等,XNA法度在运行时并不是调用的fbx等模型文件,而是经由过程Content Pipeline内容管道进行处理惩罚,编译成扩大名为.xnb的一种中心格局,在法度运行时法度实际调用的为这些中心格局,如下图。
Content Pipeline中首要有两个首要的项目组,分别是Importer以及Content Processor。此中Importer负责将导入的资料文件解析为XNA可以识此外XNA Game Studio Content Document Object Model (DOM)。体系已经支撑了很多的文件格局,比如三维模型支撑.fbx和.x,纹理支撑.bmp、.dds、.dib、.hdr、.jpg、.pfm、.png、.ppm、.tga等文件等,详情可以参考这里。若是须要的文件格局在XNA框架中不支撑,可以本身写新的Importer来支撑更多的格局。
而Processor则按照前者解析后的内容存储为Output Type,之后再编译成.xnb文件,在默认景象下应用体系自带的Processor已经足够了,不过当想存储XNA默认没有存储的内容时则须要本身扩大Processor。
固然上陈述了这么多,但加载资料则只须要一行代码即可解决。在上述的Game类中供给了一个ContentManager的实例,名为Content,我们可以应用其来加载我们的模型。ContentManager供给了一个名为Load的泛型办法,将资料类型以及资料的相对路径传入即可读取。比如我们将名为dude.fbx的文件拖到Content项目中,然后只需在上述提到的LoadContent办法中添加如下的一行代码(须要在Game类中定义一个名为model的Model类型):
protected override void LoadContent() { // Todo: use this.Content to load your game content here this.model = this.Content.Load<Model>("dude"); }
而若是要将模型绘制到屏幕上,只要调用Model对象的Draw办法即可。不过Draw办法须要供给 World世界矩阵 以及 View视图矩阵 和 Projection投影矩阵,对于后两个矩阵我们上文已经申明,而世界矩阵与视图矩阵类似,可以应用如下的办法创建:
Matrix.CreateWorld(Vector3 position, Vector3 forward, Vector3 up);
此中position与up均与之前的CreateLookAt类似,为模型活着界中所处的三维坐标和哪个标的目标是模型的向上标的目标;而forward则不合,为模型的朝向向量,其仅仅代表标的目标。当然我们也可以经由过程创建不合的平移、扭转等矩阵,然后相乘获得世界矩阵。
protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); // Todo: Add your drawing code here Matrix world = Matrix.CreateWorld(Vector3.Zero, Vector3.Forward, Vector3.Up); Matrix cameraview = Matrix.CreateLookAt(new Vector3(120, 120, 120), Vector3.Zero, Vector3.Up); Matrix cameraProjection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, this.GraphicsDevice.Viewport.AspectRatio, 10.0F, 10000.0F); this.model.Draw(world, cameraview, cameraProjection); base.Draw(gameTime); }
此中Vector3.Zero、Forward、Up为体系预设的几个常量,分别为(0, 0, 0)、(0, 0, -1)以及(0, 1, 0);而常用弧度值在MathHelper中也可以找到,比如Pi、PiOver2(90度弧度)、PiOver4(45度弧度)等等;GraphicsDevice.Viewport.AspectRatio为显示区域的宽高比。
如许我们就可以创建一个在(120, 120, 120)坐标上,朝向坐标原点的摄像机,并在坐标原点创建一个模型(因为dude模型的正面是朝Z轴负标的目标的,所以这里我们选用的Z轴负标的目标为模型的朝向)。
文中提到的dude.fbx从微软供给的sample中获得:http://xBox.create.msdn.com/en-US/education/catalog/sample/skinned_model
本文所有代码可以从如下地址:http://files.cnblogs.com/mayswind/XNA_Sample_1.zip
固然如今应用XNA的人越来越少了,然则这个有点类似小我进修笔记的文章还是要正式开坑了。
【相干链接】
- Game Class:http://msdn.microsoft.com/en-us/library/Microsoft.Xna.Framework.Game.aspx
- XBox LIVE Indie Games:http://xBox.create.msdn.com/en-US/education/catalog/?contenttype=4
- What is the Content Pipeline?:http://msdn.microsoft.com/en-us/library/bb447745.aspx
- Standard Importers and Processors:http://msdn.microsoft.com/zh-cn/library/bb447762
- 3D 游戏把握:http://msdn.microsoft.com/zh-cn/windowsphone/gg620050.aspx
从零3D根蒂根基入门XNA 4.0(2)——模型和BasicEffect
2014年1月6日 作者:Admin
【题外话】
上一篇文章介绍了3D开辟根蒂根基与XNA开辟法度的整体布局,以及应用Model类的Draw办法将模型绘制到屏幕上。本文接着上一篇文章持续,介绍XNA中模型的布局、BasicEffect的应用以及用户输入和界面显示的体式格式等,本文尽量把碰到的概念都解析清楚,但又避开错杂的数学方面的常识,对没有接触过3D开辟的同窗有所帮助。
【系列索引】
- 从零3D根蒂根基入门XNA 4.0(1)——3D开辟根蒂根基
- 从零3D根蒂根基入门XNA 4.0(2)——模型和BasicEffect
【文章索引】
【一、Model模型的布局】
上一篇文章应用Model自带的Draw办法实现了直接将载入的Model绘制到指定的地位上去,然则有时辰绘制出来的结果并不合适我们的预期,比如下图(下图的模型是经由过程Maya创建的一个房子):
经由过程ILSpy查看Microsoft.Xna.Framework.Graphics.Model,可以看到其Draw办法的代码如下:
1 public void Draw(Matrix world, Matrix view, Matrix projection) 2 { 3 int count = this.meshes.Count; 4 int count2 = this.bones.Count; 5 Matrix[] array = Model.sharedDrawBoneMatrices; 6 if (array == null || array.Length < count2) 7 { 8 array = new Matrix[count2]; 9 Model.sharedDrawBoneMatrices = array; 10 } 11 this.copyAbsoluteBoneTransformsTo(array); 12 for (int i = 0; i < count; i++) 13 { 14 ModelMesh modelMesh = this.meshes[i]; 15 int index = modelMesh.ParentBone.Index; 16 int count3 = modelMesh.Effects.Count; 17 for (int j = 0; j < count3; j++) 18 { 19 Effect effect = modelMesh.Effects[j]; 20 if (effect == null) 21 { 22 throw new InvalidOperationException(FrameworkResources.ModelHasNoEffect); 23 } 24 IEffectMatrices effectMatrices = effect as IEffectMatrices; 25 if (effectMatrices == null) 26 { 27 throw new InvalidOperationException(FrameworkResources.ModelHasNoIEffectMatrices); 28 } 29 effectMatrices.World = array[index] * world; 30 effectMatrices.View = view; 31 effectMatrices.Projection = projection; 32 } 33 modelMesh.Draw(); 34 } 35 }
View Code
此中可见,Draw办法经由过程遍历模型的Mesh,然后再遍历每个Mesh的Effect,并对每个Effect进行设置,最后应用Mesh的Draw办法将其绘制到屏幕上。
为了懂得Model的衬着,我们起首须要懂得Model的布局。实际上,在一个Model对象中,包含Bone凑集(model.Bones)、Mesh凑集(model.Meshes)以及根Bone(model.Root)三个属性,其布局和关系如下:
可以看到对于每个ModelMesh,包含一组ModelMeshPart与一个ParentBone。此中,
- ModelMesh默示单个可以自力移动的物理对象。例如,一个car的Model可以包含一个车体(body)的ModelMesh、四个车轮(wheel)的ModelMesh与一对门(door)的ModelMesh。
- ModelMeshPart默示单个雷同材料的部件,其代表一个零丁的绘制调用(draw call)。例如,上述车身可以包含着色的概况、应用景象映射(environment mapping)结果的挡风玻璃以及应用法线贴图(normalmap texture)结果的座椅等等。
- ModelBone默示了对应的ModelMesh如何变换,其包含一个Transform的变换矩阵。ModelBone是以树形存储的,每个ModelBone都有一个父节点以及若干个子节点。上述的每个ModelMesh都有一个ParentBone,ModelMesh可以按照ModelBone的变换来断定终极显示的地位等。例如,上述车门的ModelBone与车轮的ModelBone是车身的子节点等等。
所以遍历一个Model中所有的ModelMesh,然后遍历此中所有的ModelMeshPart,并且按照ModelMesh的ParentBone来将每一个ModelMeshPart绘制到指定的地位上就可以绘制出完全的Model。
不过对于每个ModelMeshPart,其实际衬着的结果都存在Effect的属性中,对于默认来说,Effect均为BasicEffect。此外,对于ModelBone,其变换矩阵都是相对其自身的Parent来的,不过Model类也供给了一个办法,即copyAbsoluteBoneTransformsTo(),即可将每个Bone相对于RootBone的变换矩阵复制到一个矩阵数组中,然后将其应用到Effect中即可。这种体式格式与上述提到的Model.Draw类似,不过本身写的话就可以自定义每个ModelMeshPart衬着的结果,当然也可以设置每个ModelMeshPart的衬着地位。
那么接下来就遵守这个思路去实现,同时在设置每一个Effect时,应用Effect供给的应用默认光照的办法EnableDefaultLighting(),启用后结果如下:
如许的结果就达到了我们的预期,按上述的办法实现的代码如下:
1 Matrix world = Matrix.CreateWorld(Vector3.Zero, Vector3.Forward, Vector3.Up); 2 3 Matrix[] transforms = new Matrix[model.Bones.Count]; 4 this.model.copyAbsoluteBoneTransformsTo(transforms); 5 6 foreach (ModelMesh mesh in model.Meshes) 7 { 8 Int32 boneIndex = mesh.ParentBone.Index; 9 10 foreach (ModelMeshPart part in mesh.MeshParts) 11 { 12 BasicEffect effect = part.Effect as BasicEffect; 13 14 effect.EnableDefaultLighting(); 15 effect.World = transforms[boneIndex] * world; 16 effect.View = cameraview; 17 effect.Projection = cameraProjection; 18 } 19 20 mesh.Draw(); 21 }
View Code
不过这与刚才看到的Model.Draw的代码并不雷同。实际上,XNA为了简化操纵,已经将ModelMeshPart的每个Effect放到了ModelMesh的Effects凑集中,只须要遍历这个凑集就可以,而无需再遍历ModelMeshPart,再获取Effect了。所以上述代码可以简化为如下的代码:
1 Matrix world = Matrix.CreateWorld(Vector3.Zero, Vector3.Forward, Vector3.Up); 2 3 Matrix[] transforms = new Matrix[model.Bones.Count]; 4 this.model.copyAbsoluteBoneTransformsTo(transforms); 5 6 foreach (ModelMesh mesh in model.Meshes) 7 { 8 Int32 boneIndex = mesh.ParentBone.Index; 9 10 foreach (BasicEffect effect in mesh.Effects) 11 { 12 effect.EnableDefaultLighting(); 13 effect.World = transforms[boneIndex] * world; 14 effect.View = cameraview; 15 effect.Projection = cameraProjection; 16 } 17 18 mesh.Draw(); 19 }
【二、BasicEffect结果的设置】
起首用ILSpy查看下BasicEffect的EnableDefaultLighting()的代码:
public void EnableDefaultLighting() { this.LightingEnabled = true; this.AmbientLightColor = EffectHelpers.EnableDefaultLighting(this.light0, this.light1, this.light2); }
此中this.light0-2为BasicEffect的DirectionalLight0-2,即BasicEffect可以时辰的三个光源。而EffectHelpers的EnableDefaultLighting是如许写的:
1 internal static Vector3 EnableDefaultLighting(DirectionalLight light0, DirectionalLight light1, DirectionalLight light2) 2 { 3 light0.Direction = new Vector3(-0.5265408f, -0.5735765f, -0.6275069f); 4 light0.DiffuseColor = new Vector3(1f, 0.9607844f, 0.8078432f); 5 light0.specularColor = new Vector3(1f, 0.9607844f, 0.8078432f); 6 light0.Enabled = true; 7 light1.Direction = new Vector3(0.7198464f, 0.3420201f, 0.6040227f); 8 light1.DiffuseColor = new Vector3(0.9647059f, 0.7607844f, 0.4078432f); 9 light1.specularColor = Vector3.Zero; 10 light1.Enabled = true; 11 light2.Direction = new Vector3(0.4545195f, -0.7660444f, 0.4545195f); 12 light2.DiffuseColor = new Vector3(0.3231373f, 0.3607844f, 0.3937255f); 13 light2.specularColor = new Vector3(0.3231373f, 0.3607844f, 0.3937255f); 14 light2.Enabled = true; 15 return new Vector3(0.05333332f, 0.09882354f, 0.1819608f); 16 }
View Code
可以看到在启用默认光照里实际上是给景象光AmbientLightColor以及三束定向光(包含光线的标的目标、漫反射色彩及镜面反射色彩)设置了预先定义好的色彩,并启用了这些光源,这三束定向光的色彩(Light1的漫反射光的色彩如下,但其镜面反射光的色彩为黑色)和标的目标大致如下。
下图第一个为启用了默认光照后的模型(上一篇文章中的dude),第二、三、四个为只启用默认光照的景象光及0、1、2三束定向光后的模型,第五个为没有启用默认光照的模型(如同上一篇产生的结果一样):
当然,在很多景象下(比如户外的日光等),我们仅须要一个光源,届时我们只要禁用(DirectionalLight*.Enabled = false)其他两个定向光即可,当然我们可能还须要批改光源的色彩等等。
除了应用EnableDefaultLighting,BasicEffect还供给了斗劲雄厚的参数可以设置。起首来看下上述例子中Effect默认的属性:
此中与光线有关的:
- LightingEnabled:是否开启光照(默认为false)。
- PreferPerPixelLighting:是否开启逐像素的光照(默认为false,为逐顶点光照),逐像素光拍照对于逐点光照结果更好,但速度也更慢,同时还须要显卡支撑Pixel Shader Model 2.0,若是显卡不支撑的话会主动应用逐顶点光照庖代。
- AmbientLightColor:景象光色彩(默认为Vector3.Zero)。为了在局部光照模型(模型间的光照互不影响)中加强真实感,引入了景象光的概念。景象光不依附任何光源,但其影响所有物体。
- DiffuseColor:漫反射色彩(默认为Vector3.One)。光线照到物体后,物体进行漫反射,其色彩与光线的标的目标有关。
- specularColor:镜面反射色彩。光线照到物体后,物体进行全反射,其色彩不仅与光线的标的目标有关,还与调查(相机)的标的目标有关。
- EmissiveColor:放射色彩(默认为Vector3.Zero)。放射光是指物体发出的光线,但在局部光照模型中,实际上不会对其他物体产生影响。
- DirectionalLight0、DirectionalLight1、DirectionalLight2:三束定向光(每束都包含光线的标的目标、漫反射色彩与镜面反射色彩)。
此中须要重视的是,在XNA中,色彩的存储并不是应用的Color(ARGB或ABGR),而是应用的Vector3(或Vector4)。对于Vector3,其x、y、z三个分量存储的分别是R、G、B分别除以255的浮点值(Vector4的w分量存储的是Alpha通道除以255的浮点值),所以Vector3.Zero即为黑色,而Vector3.One为白色。当然XNA也供给了一个Color类,并且Color也供给了供给了直接转换为Vector3(或Vector4)的办法ToVector3()(或ToVector4())。
除此之外,BasicEffect还支撑设置雾的结果:
- FogEnabled:是否开启雾的结果(默认为false)。
- FogColor:雾的色彩(默认为Vector3.Zero)。
- FogStart:雾间隔相机的开端(比来)值(默认为0.0F),这个间隔之内的器材不受雾的影响。
- FogEnd:雾间隔相机的停止(最远)值(默认为1.0F),这个间隔之外的器材完全看不清。
也就是说,雾将会在间隔相机(FogStart - FogEnd)的处所产生,这个间隔须要按照物体地点的地位决意。设distance为物体间隔相机的间隔,则distance<FogStart<FogEnd时,物体不受雾的影响,与没有雾时一样;当FogStart<FogEnd<distance时,物体完全看不清(即物体全部为雾的色彩);当FogStart<distance<FogEnd时,物体受雾的影响,物体离FogEnd越近则越看不清。
例如当人的模型在(0, 0, 0),相机在(120, 120, 120)处,雾的色彩为Gray。下图第一个为没有加雾的结果,第二个为FogStart - FogEnd为200 - 300,第三个为1 - 300,第四个为1 - 100。
【三、XNA的用户输入】
在默认生成XNA法度中的Update办法里,有一个获取GamePad的状况,当用户1的GamePad按下了“Back”键后将会退出法度。微软对用户输入的支撑都在Microsoft.Xna.Framework.Input中,除了GamePad之外,微软还支撑获取Keyboard、Mouse这两种的状况。此外在Microsoft.Xna.Framework.Input.Touch中,还有TouchPanel可以获取触摸的状况。与GamePad雷同,其他的这些状况也都是经由过程微软供给给类中的GetState()办法进行获取。
KeyboardState kbState = Keyboard.GetState();
MouseState mouseState = Mouse.GetState();
对于断定键盘的按键,可以经由过程如下的体式格式获取是否按下了指定按键:
而对于鼠标的按键,则须要断定按键的ButtonState才可以,例如断定鼠标左键是否按下:
除此之外,若是要断定鼠标是否在法度区域内,可以经由过程如下的体式格式断定
固然在大多半景象下,若是让用户操纵鼠标的话会在法度内显示一个自定义的指针。但有时辰写个小法度,为了简单直接应用体系的指针,我们可以在法度的随便率性地位(机关办法、Initialize甚至Update也可)写如下的代码,就可以显示鼠标指针了,反之则可以隐蔽:
this.IsMouseVisible = true;
【四、XNA界面的显示体式格式】
默认景象下,运行XNA的法度会主动以800*480的辨别率显示,若要批改显示的辨别率,其实很是简单,仅须要在Game的机关办法中添加如下代码即可:
graphics.PreferredBackBufferWidth = 1024; graphics.PreferredBackBufferHeight = 768;
如许XNA的法度就能遵守我们设定的辨别率显示了。除此之外,若是我们XNA的法度能全屏显示,我们还可以添加如下的代码:
graphics.IsFullScreen = true;
当然我们还可以让用户来切换全屏与窗口化,然则这行代码写在Update()中是不起感化的,不过XNA供给别的一个办法,就是graphics.ToggleFullScreen()。例如我们须要按F键进行全屏与窗口化的切换,可以编写如下的代码:
KeyboardState kbState = Keyboard.GetState(); if (kbState.IsKeyDown(Keys.F)) { graphics.ToggleFullScreen(); }
【相干链接】
- Model Class:http://msdn.microsoft.com/en-us/library/Microsoft.Xna.Framework.Graphics.Model.aspx
- Models, meshes, parts, and bones:http://blogs.msdn.com/b/shawnhar/archive/2006/11/20/models-meshes-parts-and-bones.aspx
- What Is a Model Bone?:http://msdn.microsoft.com/en-us/library/dd904249.aspx
- BasicEffect Lighting:http://rbwhitaker.wikidot.com/basic-effect-lighting
- BasicEffect Fog:http://rbwhitaker.wikidot.com/basic-effect-fog
- 一路学WP7 XNA游戏开辟(七. 3d根蒂根基光源):http://www.cnblogs.com/randylee/archive/2011/03/09/1978312.html
- 【D3D11游戏编程】进修笔记十二:光照模型:http://blog.csdn.net/bonchoix/article/details/8430561
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。