在Windows Phone中进行3D开发之七纹理

经过前几节内容的学习,我们已经让物体具有了平移、缩放、旋转的三大运动能力,通过组合使用,可以形成复杂的物体运动模型。

接下来,我们要给物体增加些颜色了,改变灰濛濛的世界。

还记得我们之前定义的三角形数据吗?当初定义的时候是这样的:

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;

运行一下,绚丽的三角形就出来了。


不过,仅用颜色显然不能制作更逼真的物体,比如说木头的三角形,用颜色就不能准确表达了。这时,我们需要的是使用纹理,即使用木纹的图片贴到三角形上,最终看上去成为想要的效果。

在Windows Phone中,纹理是使用Texture2D类来表示的,最常用的就是代表资源中的一张图片。具体的实现是在Content工程中添加一张图片,比如在HelloContent中添加一张wood.jpg图片,然后在LoadContent()方法中就可以使用如下语句将图片表示为Texture2D对象了。

texture =Content.Load<Texture2D>(@"wood");

有了纹理,还要有正确的贴图坐标,这里我们称为UV坐标,一个纹理图片的UV坐标规定为:

这样我们就可以指定不同顶点的贴图位置了。比如我们的三角形最上边的点的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;

运行程序,可以得到带木纹的三角形了。


附本节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 ——

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值