經過前幾節內容的學習,我們已經讓物體具有了平移、縮放、旋轉的三大運動能力,通過組合使用,可以形成複雜的物體運動模型。
接下來,我們要給物體增加些顏色了,改變灰濛濛的世界。
還記得我們之前定義的三角形資料嗎?當初定義的時候是這樣的:
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 ——