在Windows Phone中進行3D開發之十一天空

來源:互聯網
上載者:User

        飛船是離不了天空的,雖然上一節我們已經建好了飛船並試飛成功,但還是沒有給飛船更大的背景翱翔。在一個情境中,僅有主體還是不夠的,還需要有周圍環境的渲染。如果我們能為飛船增加藍天白雲的高遠,峰巒疊嶂的蒼翠,那一定才是更貼近現實的。

        在這個情境中,我們需要一個天空環境作為背景,不考慮地形地貌的特徵,因此,典型的做法是實現天空盒(sky-box)。天空盒就是做一個大的立方體,為立方體內部的六個面貼上連續的天空和大地的紋理,將飛船置入這個立方體內部,這樣從飛船的角度看出去,周圍就被天空和大地所包圍。

        下面,我們就來構造一個這樣的天空盒出來。


        還是先定義一個SkyBox類,繼承自DrawableGameCompenent。

        既然要使用貼圖和光線,那麼就為類添加一個成員變數box,用於定義立方體的各個頂點:

                VertexPositionNormalTexture[] box;

在Initialize()中以原點為中心,邊長為2個座標單位構造box資料,雖然有12個三角形,但這些三角形都會用到立方體的8個頂點,因此,可以先定義好頂點的座標。 

            Vector3 topLeftFront=new Vector3(-1,1,1);            Vector3 topRightFront = new Vector3(1, 1, 1);            Vector3 bottomLeftFront = new Vector3(-1, -1, 1);            Vector3 bottomRightFront = new Vector3(1, -1, 1);            Vector3 topLeftBack = new Vector3(-1, 1, -1);            Vector3 topRightBack = new Vector3(1, 1, -1);            Vector3 bottomLeftBack = new Vector3(-1, -1, -1);            Vector3 bottomRightBack = new Vector3(1, -1, -1);

        在這段代碼中,從變數名字上可以看出,這8個座標分別是立方體z軸正方向和z軸負方向兩個面的頂點。以Front為尾碼的變數代表z軸正方向上的前面,以Back為尾碼的變數代表z軸負方向上的後面。如所示。

 

然後,利用這8個座標構造立方體各個面的三角形,每個面由兩個三角形拼接而成。 

            box = new VertexPositionNormalTexture[]{                new VertexPositionNormalTexture(topLeftFront,new Vector3(0,0,-1),new Vector2(0.33f,0.25f)),  //front                new VertexPositionNormalTexture(topRightFront,new Vector3(0,0,-1),new Vector2(0.66f,0.25f)),                new VertexPositionNormalTexture(bottomLeftFront,new Vector3(0,0,-1),new Vector2(0.33f,0.5f)),                new VertexPositionNormalTexture(bottomLeftFront,new Vector3(0,0,-1),new Vector2(0.33f,0.5f)),                new VertexPositionNormalTexture(topRightFront,new Vector3(0,0,-1),new Vector2(0.66f,0.25f)),                new VertexPositionNormalTexture(bottomRightFront,new Vector3(0,0,-1),new Vector2(0.66f,0.5f)),                new VertexPositionNormalTexture(bottomRightFront,new Vector3(0,0,-1),new Vector2(0.66f,0.5f)),  //bottom                new VertexPositionNormalTexture(bottomRightBack,new Vector3(0,0,-1),new Vector2(0.66f,0.75f)),                new VertexPositionNormalTexture(bottomLeftBack,new Vector3(0,0,-1),new Vector2(0.33f,0.75f)),                new VertexPositionNormalTexture(bottomLeftBack,new Vector3(0,0,-1),new Vector2(0.33f,0.75f)),                new VertexPositionNormalTexture(bottomLeftFront,new Vector3(0,0,-1),new Vector2(0.33f,0.5f)),                new VertexPositionNormalTexture(bottomRightFront,new Vector3(0,0,-1),new Vector2(0.66f,0.5f)),        //..........

        在上述代碼中,每個頂點的貼圖座標是參照如(圖片來源於網路,解析度低,僅用於示意)所示的貼圖檔案確定的。

 

        這個貼圖如果摺疊起來正好構成一個立方體,所以各個面上三角形的UV座標照此圖進行確定即可。

        座標準備好以後,在Draw()方法中進行繪製。 

            basicEffect.TextureEnabled = true;            basicEffect.Texture = texture;            basicEffect.World = worldMatrix;            basicEffect.View = viewMatrix;            basicEffect.Projection = projectionMatrix;            foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)            {                pass.Apply();                Game.GraphicsDevice.DrawUserPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList, box, 0, box.Length/3);            }            base.Draw(gameTime);

        在這段代碼中,texture是Texture2D的執行個體變數,在Initialize()方法中從Context載入了貼圖檔案。

        basicEffect是BasicEffect的執行個體變數,用於設定渲染效果選項。

        worldMatrix、viewMatrix、projectionMatrix是三個變換矩陣,像上一節Ship類的封裝一樣用於確定變換座標,定義如下: 

        public Matrix worldMatrix {set;get;}        public Matrix viewMatrix { set; get; }        public Matrix projectionMatrix { set; get; }

        到這裡,SkyBox類就封裝好了,我們在MainScene中對其進行一下測試,看看是否符合我們的預期。

        在MainScene中加入SkyBox對象skyBox,並將其加入到Components中。 

            skyBox = new SkyBox(this);            Components.Add(skyBox);

        建立一個位於原點並指向z軸負方向的攝像機,並將skyBox的視圖矩陣和投影矩陣設定為攝像機的參數: 

            camera = new Camera(this, new Vector3(100,100,100), new Vector3(0, 0, -1), Vector3.Up, MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, 0.1f, 500);            skyBox.projectionMatrix = camera.projection;            skyBox.viewMatrix = Matrix.CreateWorld(new Vector3(0,0,0),new Vector3(0,0,-1),Vector3.Up);

        最後,為了能看到效果,給天空盒一個旋轉變換,在Update()中加入如下代碼: 

        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)                {                    skyBox.worldMatrix *= Matrix.CreateRotationY(MathHelper.ToRadians(5)); ;                }            }            base.Update(gameTime);        }

        運行程式,點擊螢幕,效果如所示(由於貼圖檔案來源於網路,解析度低,所以有些模糊,僅用來示意吧)。真是一個廣袤的世界!


——歡迎轉載,請註明出處 http://blog.csdn.net/caowenbin ——

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.