Using the transformation matrix of the control ship, it is now at our mercy in the sky, but I always feel that there is something wrong with it, and the authenticity is not enough. What is missing?
Through careful observation, we can see that no matter how the sky rotates, the ship's hull does not reflect the changes in light and shade, and does not produce the necessary light reflection as the sun moves.
This seems to be a big problem. We have encapsulated the ship class in the Ship Model and rendered the output through basiceffect in the draw () method. We also encapsulate the class in the sky, and also have its own basiceffect to control the rendering effect. What we need to do now is to combine the two so that the rotation of the sky can form light changes on the ship.
Review the previously learned knowledge of light. basiceffect provides environmental light, highlight, directed light, and other light sources for processing. If you can apply a directed light to a spacecraft, and the direction of the light is the same as that of the sun in the sky box, you can first make the sun shine in the picture. The change in light turns to keep this speed in the direction of light consistent with the direction of the sky box that is too sun.
Based on this idea, we will first add the property directed to the light direction for the ship class.
Public vector3 lightdirection {set; get ;}
Then, change the draw () method in the ship class and add the directed light parameter to basiceffect. The Code is as follows:
public override void Draw(GameTime gameTime) { model.CopyAbsoluteBoneTransformsTo(modelTransforms); foreach (ModelMesh mesh in model.Meshes) { foreach (BasicEffect effect in mesh.Effects) { effect.World = modelTransforms[mesh.ParentBone.Index] * worldMatrix; effect.View = viewMatrix; effect.Projection = projectionMatrix; effect.LightingEnabled = true; effect.AmbientLightColor = new Vector3(0.35f, 0.35f, 0.35f); effect.DirectionalLight0.Enabled = true; effect.DirectionalLight0.Direction = Vector3.Normalize(lightDirection); effect.DirectionalLight0.DiffuseColor = Color.White.ToVector3(); } mesh.Draw(); } base.Draw(gameTime); }
In this way, you only need to set the direction of light for the spacecraft object, you can make the correct reflection effect on the ship.
Next, let's determine the direction of the sun. Based on the image and the vertex parameters of the sky box, when constructing vertex data for each triangle in the sky box, we assume that the box is displayed outside the box in the positive direction of the Z axis, therefore, the Sun part in the texture is attached to the observer side of the sky box, that is, the front. Now, when rendering, our observer is located in the box in the sky, and the line of sight points to the negative direction of the Z axis. Therefore, the sun is behind us, the direction of sunlight can be considered to point to the negative direction of the Z axis.
After determining the sunshine direction, modify the loadcontent () method in the mainscene code to set the light direction to (,-1) for the ship object. The Code is as follows:
protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); camera = new Camera(this, new Vector3(100,100,100), new Vector3(0, 0, 1), Vector3.Up, MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, 0.1f, 500); basicEffect = new BasicEffect(GraphicsDevice); skyBox.projectionMatrix = camera.projection; skyBox.viewMatrix = Matrix.CreateWorld(new Vector3(0,0,0),new Vector3(0,0,-1),Vector3.Up); ship.projectionMatrix = camera.projection; ship.viewMatrix = camera.view; ship.worldMatrix = Matrix.CreateScale(-0.02f) * Matrix.CreateRotationZ(MathHelper.ToRadians(180)); ship.lightDirection = skyBox.worldMatrix.Forward; ship2.projectionMatrix = camera.projection; ship2.viewMatrix = camera.view; ship2.worldMatrix = Matrix.CreateScale(-0.02f) * Matrix.CreateRotationZ(MathHelper.ToRadians(180))*Matrix.CreateTranslation(new Vector3(50, 0, 0)); ship2.lightDirection = skyBox.worldMatrix.Forward; }
Execute the program and you will see that the light on the ship's hull is already in line with the sky environment.
If the light can be changed, add the following code in the update () method.
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)); ship.lightDirection = skyBox.worldMatrix.Forward; ship2.lightDirection = skyBox.worldMatrix.Forward; } } base.Update(gameTime); }
From this code, we can see that every time the sky box rotates, we need to take the vector of the new viewpoint coordinates of the sky box as the direction of directed light, in this way, the rotation of the sky box is synchronized with the rotation of the light, and the spacecraft will render the sunlight effect in the corresponding light direction.
Running result.
So far, we have been able to initially use the 3D functions provided by xNa to develop applications. By using matrices, we can perform complex transformations and use vectors to control the direction, these are the basis of computer graphics theory. In fact, the previous changes to objects can also be applied to the camera. Applying the translation and rotation changes to the camera can form the most basic push-pull and shake Effect in a movie, so that our thoughts can fly in the sky.
-- Welcome to reprint, please indicate the source of http://blog.csdn.net/caowenbin --