在Windows Phone中進行3D開發之八光照

來源:互聯網
上載者:User

        在現實生活中,除了顏色以外,最重要的其實是光照,有了光照,才有了明暗、著色、高光等效果,在繼上節的紋理之後,這節來為情境加入光照效果。

        在XNA中,可以簡單地把光照分為兩種,一種是環境光線,一種是有向光。

        環境光線是不來自任何特殊方向的光,它有光源,但是被周圍環境的多次反射變得沒有確定的方向,物體各表面都均等受光。在使用時主要用環境光線改變情境的基本光線顏色。

        有向光是來自某個方向被物體表面反射的光,比如射燈的光等。在描述這種光線時,除了描述方向以外,還要描述散射光的顏色和物體表面高光區的顏色等其他屬性。

        在使用光線的時候,還有一個額外的參數需要指定,那就是法線方向。不妨作這樣的思考,對於任意一個平面,渲染引擎是如何計算入射光和反射光的夾角呢?是如何確定該平面哪個方向為正方向的呢?其實,這些問題的答案就是依靠法線。

        回顧一下法線的定義,簡單的說就是垂直於平面的垂線,對於曲面來說,就是垂直於曲面某點切線的線。法線在3D空間的重要作用就是確定面的正方向,通常定義由內部指向外部的方向為正方向,有了這個方向,渲染引擎在做光線運算和紋理貼圖時才能正確處理方向,從而達到預期的效果。

        在情境中如果需要光照效果,就不能簡單的用VertexPositionTexture類了,XNA提供了VertexPositionNormalTexture類,這個類提供了對法線的表示方法。下面,我們在前面的三角形定義的基礎上,改用這個新的類,代碼如下:

           triangle = new VertexPositionNormalTexture[]{

               new VertexPositionNormalTexture(new Vector3(0, 1, 0),new Vector3(0,0,1),new Vector2(0.5f,0)),

               new VertexPositionNormalTexture(new Vector3(1, -1, 0),newVector3(0,0,1), new Vector2(1,1)),

               new VertexPositionNormalTexture(new Vector3(-1,-1, 0),newVector3(0,0,1), new Vector2(0,1))

            };

        注意到每個點的法線方向都用了(0,0,1),即全部指向z軸的正方向,從而確定了整個三角形的正方向是從手機螢幕向外指向使用者。

        有了這個資料定義,就可以通過BasicEffect對象添加光照效果了。代碼如下:

           basicEffect.LightingEnabled = true;

           basicEffect.AmbientLightColor = new Vector3(0.1f, 0.1f, 0.1f);

           basicEffect.DirectionalLight0.DiffuseColor = Color.Red.ToVector3();

           basicEffect.DirectionalLight0.Direction = Vector3.Normalize(newVector3(-0.5f, 0.5f, -1));

           basicEffect.DirectionalLight0.SpecularColor = Color.White.ToVector3();

           basicEffect.DirectionalLight0.Enabled = true;

        通過LightingEnabled=true可以啟動光照效果,只有該變數的值為true,後續語句中設定的光照才會得到渲染。

        AmbientLightColor指定的是環境光線的顏色。

        通過BasicEffect可以設定環境光線、漫反射光、高光以及3個有向光的效果。在上述的代碼中,通過對DirectionalLight0的設定,就是確定了一個有向光的屬性。這些屬性中,DiffuseColor是其漫反射光的顏色,Direction是一個歸一化的三維向量,用於指定光線的方向,SpecularColor是定義高光的顏色,Enabled是啟用該有向光的效果渲染。

        最終的運行結果。光源的方向是從右下角到左上方並指向螢幕內部,因此右下角的高光效果較明顯。而且整個物體被漫反射光映成了紅色,像是被夕陽照射的一樣。


        其餘的光照效果需要在實踐中不斷的積累,相信有了上述的學習,在運用時能夠達到目標效果。

附本節Game1類的完整源碼:

    public class Game1 : Microsoft.Xna.Framework.Game    {        GraphicsDeviceManager graphics;        Camera camera;        Matrix world = Matrix.Identity;        BasicEffect basicEffect;        VertexPositionNormalTexture[] triangle;        Matrix translateMatrix=Matrix.Identity;        Matrix scaleMatrix = Matrix.Identity;        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 VertexPositionNormalTexture[]{                new VertexPositionNormalTexture(new Vector3(0, 1, 0),new Vector3(0,0,1), new Vector2(0.5f,0)),                new VertexPositionNormalTexture(new Vector3(1, -1, 0),new Vector3(0,0,1), new Vector2(1,1)),                new VertexPositionNormalTexture(new Vector3(-1,-1, 0),new Vector3(0,0,1), new Vector2(0,1))            };            texture = Content.Load<Texture2D>(@"Tulips");        }        /// <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;            basicEffect.LightingEnabled = true;            basicEffect.AmbientLightColor = new Vector3(0.1f, 0.1f, 0.1f);            basicEffect.DirectionalLight0.DiffuseColor = Color.Red.ToVector3();            basicEffect.DirectionalLight0.Direction = Vector3.Normalize(new Vector3(-0.5f, 0.5f, -1));            basicEffect.DirectionalLight0.SpecularColor = Color.White.ToVector3();            basicEffect.DirectionalLight0.Enabled = true;                        foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)            {                pass.Apply();                GraphicsDevice.DrawUserPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleStrip, triangle, 0, 1);            }            base.Draw(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.