ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
经过前几节内容的学习,我们已经让物体具有了平移、缩放、旋转的三大运动能力,通过组合使用,可以形成复杂的物体运动模型。 接下来,我们要给物体增加些颜色了,改变灰濛濛的世界。 还记得我们之前定义的三角形数据吗?当初定义的时候是这样的: ~~~           triangle = new VertexPositionColor[]{               new VertexPositionColor(new Vector3(0, 1, 0), Color.Red),               new VertexPositionColor(new Vector3(1, -1, 0), Color.Green),               new VertexPositionColor(new Vector3(-1,-1, 0), Color.Blue)            }; ~~~ 我们使用了VertexPositionColor对象数组,该类型使用坐标和颜色值来表示一个顶点,但在此之前,该颜色值一直没起到作用,我们看到的都是白色的三角形,其实想让颜色生效非常简单,只要在Draw()方法添加下句即可: basicEffect.VertexColorEnabled= true; 运行一下,绚丽的三角形就出来了。 ![](https://box.kancloud.cn/2016-04-08_570727fad2952.gif) 不过,仅用颜色显然不能制作更逼真的物体,比如说木头的三角形,用颜色就不能准确表达了。这时,我们需要的是使用纹理,即使用木纹的图片贴到三角形上,最终看上去成为想要的效果。 在Windows Phone中,纹理是使用Texture2D类来表示的,最常用的就是代表资源中的一张图片。具体的实现是在Content工程中添加一张图片,比如在HelloContent中添加一张wood.jpg图片,然后在LoadContent()方法中就可以使用如下语句将图片表示为Texture2D对象了。 texture =Content.Load<Texture2D>(@"wood"); 有了纹理,还要有正确的贴图坐标,这里我们称为UV坐标,一个纹理图片的UV坐标规定为: ![](https://box.kancloud.cn/2016-04-08_570727faedc83.gif) 这样我们就可以指定不同顶点的贴图位置了。比如我们的三角形最上边的点的UV坐标就是(0.5,0),左下角点是(0,1),右下角点是(1,1)。对于需要使用纹理坐标的三角形,前文用到的VertexPositionColor类型已经不够了,我们需要使用VertexPositionTexture类型,即每个顶点使用坐标和纹理坐标来描述,而不再是坐标和颜色来描述了。对应的三角形数据如下: ~~~            triangle = newVertexPositionTexture[]{                new VertexPositionTexture(newVector3(0, 1, 0), new Vector2(0.5f,0)),                new VertexPositionTexture(newVector3(1, -1, 0), new Vector2(1,1)),                new VertexPositionTexture(newVector3(-1,-1, 0), new Vector2(0,1))            }; ~~~ 最后,要想得到渲染结果,修改Draw()方法,调整basicEffect的纹理属性为: ~~~            basicEffect.TextureEnabled = true;            basicEffect.Texture = texture; ~~~ 运行程序,可以得到带木纹的三角形了。 ![](https://box.kancloud.cn/2016-04-08_570727fb0a667.gif) 附本节Game1类的完整源码: ~~~ public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; Camera camera; Matrix world = Matrix.Identity; BasicEffect basicEffect; VertexPositionTexture[] triangle; Matrix translateMatrix=Matrix.Identity; Matrix scaleMatrix = Matrix.CreateScale(0.5f); Matrix rotateMatrix = Matrix.Identity; Texture2D texture; public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; // Frame rate is 30 fps by default for Windows Phone. TargetElapsedTime = TimeSpan.FromTicks(333333); // Extend battery life under lock. InactiveSleepTime = TimeSpan.FromSeconds(1); graphics.IsFullScreen = true; } /// <summary> /// Allows the game to perform any initialization it needs to before starting to run. /// This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well. /// </summary> protected override void Initialize() { // TODO: Add your initialization logic here base.Initialize(); } /// <summary> /// LoadContent will be called once per game and is the place to load /// all of your content. /// </summary> protected override void LoadContent() { camera = new Camera(this, new Vector3(0, 0, 5), Vector3.Zero, Vector3.Up, MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, 1.0f, 50.0f); Components.Add(camera); basicEffect = new BasicEffect(GraphicsDevice); triangle = new VertexPositionTexture[]{ new VertexPositionTexture(new Vector3(0, 1, 0), new Vector2(0.5f,0)), new VertexPositionTexture(new Vector3(1, -1, 0), new Vector2(1,1)), new VertexPositionTexture(new Vector3(-1,-1, 0), new Vector2(0,1)) }; texture = Content.Load<Texture2D>(@"wood"); } /// <summary> /// UnloadContent will be called once per game and is the place to unload /// all content. /// </summary> protected override void UnloadContent() { // TODO: Unload any non ContentManager content here } /// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); TouchPanel.EnabledGestures = GestureType.Tap; if (TouchPanel.IsGestureAvailable) { GestureSample gestureSample = TouchPanel.ReadGesture(); if (gestureSample.GestureType == GestureType.Tap) { translateMatrix *= Matrix.CreateTranslation(0.3f, 0, 0); //scaleMatrix = Matrix.CreateScale(0.9f); rotateMatrix *= Matrix.CreateRotationY(MathHelper.ToRadians(10)); } } base.Update(gameTime); } /// <summary> /// This is called when the game should draw itself. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); RasterizerState rasterizerState = new RasterizerState(); rasterizerState.CullMode = CullMode.None; GraphicsDevice.RasterizerState = rasterizerState; basicEffect.World = scaleMatrix * translateMatrix * rotateMatrix; basicEffect.View = camera.view; basicEffect.Projection = camera.projection; basicEffect.TextureEnabled = true; basicEffect.Texture = texture; GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes) { pass.Apply(); GraphicsDevice.DrawUserPrimitives<VertexPositionTexture>(PrimitiveType.TriangleStrip, triangle, 0, 1); } base.Draw(gameTime); } } ~~~ ——欢迎转载,请注明出处 [http://blog.csdn.net/caowenbin](http://blog.csdn.net/caowenbin) ——