现在的位置: 首页 > 综合 > 正文

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

2013年08月19日 ⁄ 综合 ⁄ 共 4823字 ⁄ 字号 评论关闭

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

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

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

           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 ——

抱歉!评论已关闭.